bsp/gen5200: New ATA driver

This is a replacement for the ATA task.  The performance is much better.
This commit is contained in:
Sebastian Huber
2013-02-18 17:00:28 +01:00
parent c7a56564a0
commit 57bcb88ef5
10 changed files with 1565 additions and 44 deletions

View File

@@ -83,20 +83,27 @@ libbsp_a_SOURCES += console/console.c
libbsp_a_SOURCES += i2c/i2c.c i2c/i2cdrv.c i2c/mpc5200mbus.c i2c/mpc5200mbus.h
# ide
libbsp_a_SOURCES += ide/idecfg.c ide/pcmcia_ide.c ide/pcmcia_ide.h
libbsp_a_SOURCES += ide/ata.c
libbsp_a_SOURCES += ide/ata-instance.c
libbsp_a_SOURCES += ide/ata-dma-pio-single.c
include_bsp_HEADERS = ../../shared/include/irq-generic.h \
../../shared/include/irq-info.h \
../../shared/include/utility.h \
../../shared/include/bootcard.h \
../../shared/include/u-boot.h \
../shared/include/u-boot-board-info.h \
include/irq.h \
include/i2cdrv.h \
include/i2c.h \
include/mpc5200.h \
include/mscan-base.h \
include/u-boot-config.h \
mscan/mscan.h
include_bsp_HEADERS =
include_bsp_HEADERS += ../../shared/include/bootcard.h
include_bsp_HEADERS += ../../shared/include/irq-generic.h
include_bsp_HEADERS += ../../shared/include/irq-info.h
include_bsp_HEADERS += ../../shared/include/u-boot.h
include_bsp_HEADERS += ../../shared/include/utility.h
include_bsp_HEADERS += ../shared/include/u-boot-board-info.h
include_bsp_HEADERS += include/ata.h
include_bsp_HEADERS += include/bestcomm.h
include_bsp_HEADERS += include/bestcomm_ops.h
include_bsp_HEADERS += include/i2cdrv.h
include_bsp_HEADERS += include/i2c.h
include_bsp_HEADERS += include/irq.h
include_bsp_HEADERS += include/mpc5200.h
include_bsp_HEADERS += include/mscan-base.h
include_bsp_HEADERS += include/u-boot-config.h
include_bsp_HEADERS += mscan/mscan.h
# irq
libbsp_a_SOURCES += include/irq.h \
@@ -123,25 +130,26 @@ libbsp_a_SOURCES += tod/todcfg.c tod/pcf8563.c tod/pcf8563.h \
../../shared/tod.c
# startup
libbsp_a_SOURCES += ../../shared/bootcard.c \
../../shared/bsplibc.c \
../../shared/bsppost.c \
../../shared/bsppretaskinghook.c \
../../shared/bsppredriverhook.c \
../../shared/gnatinstallhandler.c \
../../shared/sbrk.c \
../../shared/src/bsp-uboot-board-info.c \
../shared/showbats.c \
../shared/uboot_dump_bdinfo.c \
../shared/uboot_getenv.c \
../../shared/bspclean.c \
startup/bspreset.c \
../../shared/bspgetworkarea.c \
../shared/startup/bspidle.c \
../shared/src/memcpy.c \
startup/bspstart.c \
startup/cpuinit.c \
startup/uboot_support.c
libbsp_a_SOURCES += ../../shared/bootcard.c
libbsp_a_SOURCES += ../../shared/bspclean.c
libbsp_a_SOURCES += ../../shared/bspgetworkarea.c
libbsp_a_SOURCES += ../../shared/bsplibc.c
libbsp_a_SOURCES += ../../shared/bsppost.c
libbsp_a_SOURCES += ../../shared/bsppredriverhook.c
libbsp_a_SOURCES += ../../shared/bsppretaskinghook.c
libbsp_a_SOURCES += ../../shared/gnatinstallhandler.c
libbsp_a_SOURCES += ../../shared/sbrk.c
libbsp_a_SOURCES += ../../shared/src/bsp-uboot-board-info.c
libbsp_a_SOURCES += ../shared/showbats.c
libbsp_a_SOURCES += ../shared/src/memcpy.c
libbsp_a_SOURCES += ../shared/startup/bspidle.c
libbsp_a_SOURCES += ../shared/uboot_dump_bdinfo.c
libbsp_a_SOURCES += ../shared/uboot_getenv.c
libbsp_a_SOURCES += startup/bspreset.c
libbsp_a_SOURCES += startup/bspstart.c
libbsp_a_SOURCES += startup/cpuinit.c
libbsp_a_SOURCES += startup/uboot_support.c
libbsp_a_SOURCES += startup/bestcomm.c
if HAS_NETWORKING
libbsp_a_SOURCES += network_5200/network.c

View File

@@ -0,0 +1,188 @@
/*
* Copyright (c) 2011-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.
*/
#define NDEBUG
#include <bsp/ata.h>
#include <libcpu/powerpc-utility.h>
#include <bsp.h>
#include <bsp/irq.h>
typedef enum {
DATA_CURRENT = 0,
DATA_END,
DATA_REG
} variables;
typedef enum {
INC_0_NE = 0,
INC_2_NE
} increments;
/*
* for
* idx0 = DATA_CURRENT, idx1 = DATA_REG
* idx0 != DATA_END
* idx0 += 2, idx1 += 0
* do
* *idx0 = *idx1 [INT, 16 bit] OR *idx1 = *idx0 [INT, 16 bit]
*/
static const uint32_t ops[] = {
LCD(0, VAR(DATA_CURRENT), 0, VAR(DATA_REG), TERM_FIRST, VAR(DATA_END), INC_2_NE, INC_0_NE),
0, /* Transfer opcode, see transfer() */
};
static bool is_last_transfer(const ata_driver_dma_pio_single *self)
{
return self->transfer_current + 1 == self->transfer_end;
}
static void start_sector_transfer(ata_driver_dma_pio_single *self)
{
uint16_t *current = ata_sg_get_sector_data_begin(&self->sg_context, self->transfer_current);
bestcomm_task_set_variable(&self->task, DATA_CURRENT, (uint32_t) current);
bestcomm_task_set_variable(&self->task, DATA_END, (uint32_t) ata_sg_get_sector_data_end(&self->sg_context, current));
bestcomm_task_start(&self->task);
bool last = is_last_transfer(self);
++self->transfer_current;
if (!last) {
ata_flush_sector(ata_sg_get_sector_data_begin(&self->sg_context, self->transfer_current));
}
}
static void dma_pio_single_interrupt_handler(void *arg)
{
ata_driver_dma_pio_single *self = arg;
bool ok = ata_check_status();
bool send_event = false;
if (ok && self->transfer_current != self->transfer_end) {
bool enable_dma_interrupt = self->read && is_last_transfer(self);
if (enable_dma_interrupt) {
bestcomm_task_irq_clear(&self->task);
bestcomm_task_irq_enable(&self->task);
}
start_sector_transfer(self);
} else {
send_event = true;
}
if (send_event) {
bestcomm_task_wakeup_event_task(&self->task);
}
}
static bool transfer_dma_pio_single(ata_driver *super, bool read, rtems_blkdev_sg_buffer *sg, size_t sg_count)
{
bool ok = true;
ata_driver_dma_pio_single *self = (ata_driver_dma_pio_single *) super;
self->read = read;
ata_sg_reset(&self->sg_context, sg, sg_count);
rtems_blkdev_bnum start_sector = ata_sg_get_start_sector(&self->sg_context);
rtems_blkdev_bnum sector_count = ata_sg_get_sector_count(&self->sg_context);
rtems_blkdev_bnum relative_sector = 0;
ata_flush_sector(ata_sg_get_sector_data_begin(&self->sg_context, relative_sector));
uint8_t command = ata_read_or_write_sectors_command(read);
uint32_t opcode;
if (read) {
opcode = DRD1A(INT, INIT_ALWAYS, DEST_DEREF_IDX(0), SZ_16, SRC_DEREF_IDX(1), SZ_16);
} else {
opcode = DRD1A(INT, INIT_ALWAYS, DEST_DEREF_IDX(1), SZ_16, SRC_DEREF_IDX(0), SZ_16);
}
bestcomm_task_irq_disable(&self->task);
bestcomm_task_associate_with_current_task(&self->task);
size_t transfer_opcode_index = 1; /* See ops */
bestcomm_task_set_opcode(&self->task, transfer_opcode_index, opcode);
while (ok && relative_sector < sector_count) {
rtems_blkdev_bnum remaining_sectors = sector_count - relative_sector;
rtems_blkdev_bnum transfer_count = ata_max_transfer_count(remaining_sectors);
self->transfer_current = relative_sector;
self->transfer_end = relative_sector + transfer_count;
ok = ata_execute_io_command(command, start_sector + relative_sector, transfer_count);
if (ok) {
if (!read) {
ok = ata_wait_for_data_request();
assert(ok);
rtems_interrupt_level level;
rtems_interrupt_disable(level);
start_sector_transfer(self);
rtems_interrupt_enable(level);
}
bestcomm_task_wait(&self->task);
ok = ata_check_status();
relative_sector += ATA_PER_TRANSFER_SECTOR_COUNT_MAX;
}
}
return ok;
}
static int io_control_dma_pio_single(
rtems_disk_device *dd,
uint32_t cmd,
void *arg
)
{
return ata_driver_io_control(dd, cmd, arg, transfer_dma_pio_single);
}
void ata_driver_dma_pio_single_create(ata_driver_dma_pio_single *self, const char *device_file_path, TaskId task_index)
{
ata_driver_create(&self->super, device_file_path, io_control_dma_pio_single);
self->read = false;
if (ata_driver_is_card_present(&self->super)) {
bestcomm_task_create_and_load(&self->task, task_index, ops, sizeof(ops));
bestcomm_task_set_variable(&self->task, DATA_REG, (uint32_t) &ATA->write.data);
bestcomm_task_set_increment_and_condition(&self->task, INC_0_NE, 0, COND_NE);
bestcomm_task_set_increment_and_condition(&self->task, INC_2_NE, 2, COND_NE);
bestcomm_task_enable_combined_write(&self->task, true);
bestcomm_task_enable_read_buffer(&self->task, true);
bestcomm_task_enable_speculative_read(&self->task, true);
ata_clear_interrupts();
rtems_status_code sc = rtems_interrupt_handler_install(
BSP_SIU_IRQ_ATA,
"ATA",
RTEMS_INTERRUPT_UNIQUE,
dma_pio_single_interrupt_handler,
self
);
if (sc != RTEMS_SUCCESSFUL) {
mpc5200_fatal(MPC5200_FATAL_ATA_DMA_SINGLE_IRQ_INSTALL);
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2011-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.
*/
#include <bsp/ata.h>
#include <libchip/ata.h>
#include <bsp.h>
static ata_driver_dma_pio_single ata_driver_instance;
rtems_status_code rtems_ata_initialize(
rtems_device_major_number major,
rtems_device_minor_number minor_arg,
void *arg
)
{
rtems_status_code sc = rtems_disk_io_initialize();
if (sc == RTEMS_SUCCESSFUL) {
bestcomm_glue_init();
ata_driver_dma_pio_single_create(&ata_driver_instance, "/dev/hda", TASK_PCI_TX);
} else {
mpc5200_fatal(MPC5200_FATAL_ATA_DISK_IO_INIT);
}
return sc;
}

View File

@@ -0,0 +1,231 @@
/*
* 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.
*/
#define NDEBUG
#include <bsp/ata.h>
#include <bsp.h>
#include <bsp/mpc5200.h>
bool ata_execute_io_command(uint8_t command, uint32_t lba, uint32_t sector_count_32)
{
assert(sector_count_32 >= 1);
assert(sector_count_32 <= 256);
assert(ata_is_drive_ready_for_selection());
ATA->write.head = (uint8_t) (0xe0 | ((lba >> 24) & 0x0f));
ata_wait_400_nano_seconds();
ata_wait_for_drive_ready();
/*
* It seems that the write to the ATA device registers is sometimes not
* successful. The write is retried until the read back values are all right
* or a timeout is reached.
*/
bool ok = false;
uint8_t sector = (uint8_t) lba;
uint8_t cylinder_low = (uint8_t) (lba >> 8);
uint8_t cylinder_high = (uint8_t) (lba >> 16);
uint8_t sector_count = (uint8_t) sector_count_32;
int i;
for (i = 0; !ok && i < 100; ++i) {
ATA->write.sector = sector;
ATA->write.cylinder_low = cylinder_low;
ATA->write.cylinder_high = cylinder_high;
ATA->write.sector_count = sector_count;
uint8_t actual_sector = ATA->read.sector;
uint8_t actual_cylinder_low = ATA->read.cylinder_low;
uint8_t actual_cylinder_high = ATA->read.cylinder_high;
uint8_t actual_sector_count = ATA->read.sector_count;
ok = actual_cylinder_high == cylinder_high
&& actual_cylinder_low == cylinder_low
&& actual_sector == sector
&& actual_sector_count == sector_count;
}
if (ok) {
ATA->write.command = command;
}
return ok;
}
void ata_reset_device(void)
{
ATA->write.control = DCTRL_SRST;
rtems_task_wake_after(1);
ATA->write.control = 0;
rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(2));
ata_wait_for_not_busy();
}
bool ata_set_transfer_mode(uint8_t mode)
{
assert(ata_is_drive_ready_for_selection());
ATA->write.head = 0xe0;
ata_wait_400_nano_seconds();
ata_wait_for_drive_ready();
ATA->write.feature = 0x3;
ATA->write.sector_count = mode;
ATA->write.command = 0xef;
ata_wait_for_not_busy();
return ata_check_status();
}
static bool probe()
{
bool card_present = true;
#ifdef BRS5L
volatile struct mpc5200_::mpc5200_gpt *gpt = &mpc5200.gpt[GPT2];
/* Enable card detection on GPT2 */
gpt->emsel = (GPT_EMSEL_GPIO_IN | GPT_EMSEL_TIMER_MS_GPIO);
/* Check for card detection (-CD0) */
if ((gpt->status & GPT_STATUS_PIN) != 0) {
card_present = false;
}
#endif
return card_present;
}
static void create_lock(ata_driver *self)
{
rtems_status_code sc = rtems_semaphore_create(
rtems_build_name('A', 'T', 'A', ' '),
1,
RTEMS_LOCAL | RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
0,
&self->lock
);
assert(sc == RTEMS_SUCCESSFUL);
}
static void destroy_lock(const ata_driver *self)
{
rtems_status_code sc = rtems_semaphore_delete(self->lock);
assert(sc == RTEMS_SUCCESSFUL);
}
void ata_driver_create(ata_driver *self, const char *device_file_path, rtems_block_device_ioctl io_control)
{
self->card_present = probe();
if (ata_driver_is_card_present(self)) {
create_lock(self);
ata_reset_device();
uint16_t sector_buffer[256];
ata_dev_t ata_device;
rtems_status_code sc = ata_identify_device(0, 0, sector_buffer, &ata_device);
if (sc == RTEMS_SUCCESSFUL && ata_device.lba_avaible) {
sc = ide_controller_config_io_speed(0, ata_device.modes_available);
if (sc == RTEMS_SUCCESSFUL) {
sc = rtems_blkdev_create(
device_file_path,
ATA_SECTOR_SIZE,
ata_device.lba_sectors,
io_control,
self
);
if (sc != RTEMS_SUCCESSFUL) {
mpc5200_fatal(MPC5200_FATAL_ATA_DISK_CREATE);
}
}
}
}
}
void ata_driver_destroy(ata_driver *self)
{
destroy_lock(self);
/* TODO */
assert(0);
}
static bool transfer_pio_polled(ata_driver *self, bool read, rtems_blkdev_sg_buffer *sg, size_t sg_count)
{
bool ok = true;
ata_sg_context sg_context;
ata_sg_create(&sg_context, sg, sg_count);
rtems_blkdev_bnum start_sector = ata_sg_get_start_sector(&sg_context);
rtems_blkdev_bnum sector_count = ata_sg_get_sector_count(&sg_context);
rtems_blkdev_bnum relative_sector = 0;
uint8_t command = ata_read_or_write_sectors_command(read);
while (ok && relative_sector < sector_count) {
rtems_blkdev_bnum remaining_sectors = sector_count - relative_sector;
rtems_blkdev_bnum transfer_count = ata_max_transfer_count(remaining_sectors);
rtems_blkdev_bnum transfer_end = relative_sector + transfer_count;
ok = ata_execute_io_command(command, start_sector + relative_sector, transfer_count);
rtems_blkdev_bnum transfer;
for (transfer = relative_sector; ok && transfer < transfer_end; ++transfer) {
uint16_t *current = ata_sg_get_sector_data_begin(&sg_context, transfer);
uint16_t *end = ata_sg_get_sector_data_end(&sg_context, current);
ok = ata_wait_for_data_request();
if (ok) {
if (read) {
while (current != end) {
*current = ATA->read.data;
++current;
}
} else {
while (current != end) {
ATA->write.data = *current;
++current;
}
}
}
}
if (ok) {
ata_wait_for_not_busy();
ok = ata_check_status();
}
relative_sector += ATA_PER_TRANSFER_SECTOR_COUNT_MAX;
}
return ok;
}
int ata_driver_io_control_pio_polled(
rtems_disk_device *dd,
uint32_t cmd,
void *arg
)
{
return ata_driver_io_control(dd, cmd, arg, transfer_pio_polled);
}

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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;

View File

@@ -157,6 +157,10 @@ $(PROJECT_INCLUDE)/bsp/bestcomm/task_api/bestcomm_api_mem.h: bestcomm/task_api/b
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bestcomm/task_api/bestcomm_api_mem.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bestcomm/task_api/bestcomm_api_mem.h
$(PROJECT_INCLUDE)/bsp/bootcard.h: ../../shared/include/bootcard.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bootcard.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bootcard.h
$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
@@ -165,25 +169,29 @@ $(PROJECT_INCLUDE)/bsp/irq-info.h: ../../shared/include/irq-info.h $(PROJECT_INC
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h
$(PROJECT_INCLUDE)/bsp/utility.h: ../../shared/include/utility.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/utility.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/utility.h
$(PROJECT_INCLUDE)/bsp/bootcard.h: ../../shared/include/bootcard.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bootcard.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bootcard.h
$(PROJECT_INCLUDE)/bsp/u-boot.h: ../../shared/include/u-boot.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/u-boot.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/u-boot.h
$(PROJECT_INCLUDE)/bsp/utility.h: ../../shared/include/utility.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/utility.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/utility.h
$(PROJECT_INCLUDE)/bsp/u-boot-board-info.h: ../shared/include/u-boot-board-info.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/u-boot-board-info.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/u-boot-board-info.h
$(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
$(PROJECT_INCLUDE)/bsp/ata.h: include/ata.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/ata.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/ata.h
$(PROJECT_INCLUDE)/bsp/bestcomm.h: include/bestcomm.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bestcomm.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bestcomm.h
$(PROJECT_INCLUDE)/bsp/bestcomm_ops.h: include/bestcomm_ops.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bestcomm_ops.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bestcomm_ops.h
$(PROJECT_INCLUDE)/bsp/i2cdrv.h: include/i2cdrv.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2cdrv.h
@@ -193,6 +201,10 @@ $(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h
$(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
$(PROJECT_INCLUDE)/bsp/mpc5200.h: include/mpc5200.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/mpc5200.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/mpc5200.h

View File

@@ -0,0 +1,107 @@
/*
* 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.
*/
#define NDEBUG
#include <bsp/bestcomm.h>
#include <string.h>
#include <bsp/mpc5200.h>
static void bestcomm_irq_handler(void *arg)
{
bestcomm_irq *self = arg;
bestcomm_irq_clear(self);
bestcomm_irq_wakeup_event_task(self);
}
void bestcomm_irq_create(bestcomm_irq *self, int task_index)
{
assert(task_index >= 0 && task_index <= 15);
self->task_index = task_index;
self->event_task_id = rtems_task_self();
bestcomm_glue_irq_install(task_index, bestcomm_irq_handler, self);
}
void bestcomm_irq_destroy(const bestcomm_irq *self)
{
bestcomm_glue_irq_install(self->task_index, NULL, NULL);
}
void bestcomm_task_create(bestcomm_task *self, TaskId task_index)
{
self->task_control_register = &mpc5200.sdma.tcr[task_index];
self->variable_table = BESTCOMM_TASK_ENTRY_TABLE[task_index].var_table;
self->task_index = task_index;
self->tdt_begin = NULL;
self->tdt_opcode_count = 0;
bestcomm_task_stop(self);
bestcomm_irq_create(&self->irq, task_index);
}
void bestcomm_task_create_and_load(
bestcomm_task *self,
TaskId task_index,
const uint32_t *tdt_source_begin,
size_t tdt_size
)
{
bestcomm_task_create(self, task_index);
bestcomm_task_load(self, tdt_source_begin, tdt_size);
}
void bestcomm_task_destroy(bestcomm_task *self)
{
bestcomm_task_stop(self);
bestcomm_task_free_tdt(self);
}
void bestcomm_task_load(bestcomm_task *self, const uint32_t *tdt_source_begin, size_t tdt_size)
{
assert(tdt_size % 4 == 0);
bestcomm_task_irq_disable(self);
bestcomm_task_stop(self);
bestcomm_task_irq_clear(self);
bestcomm_task_irq_enable(self);
bestcomm_task_free_tdt(self);
bestcomm_task_clear_variables(self);
self->tdt_opcode_count = tdt_size / 4;
self->tdt_begin = bestcomm_malloc(tdt_size);
assert(self->tdt_begin != NULL);
uint32_t *tdt_last = self->tdt_begin + self->tdt_opcode_count - 1;
memcpy(self->tdt_begin, tdt_source_begin, tdt_size);
volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self);
entry->tdt_begin = self->tdt_begin;
entry->tdt_last = tdt_last;
bestcomm_task_clear_pragmas(self);
bestcomm_task_set_priority(self, 0);
}
void bestcomm_task_clear_variables(const bestcomm_task *self)
{
int i;
for (i = 0; i < 32; ++i) {
(*self->variable_table)[i] = 0;
}
}