forked from Imagelibrary/rtems
bsp/gen5200: New ATA driver
This is a replacement for the ATA task. The performance is much better.
This commit is contained in:
@@ -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
|
||||
|
||||
188
c/src/lib/libbsp/powerpc/gen5200/ide/ata-dma-pio-single.c
Normal file
188
c/src/lib/libbsp/powerpc/gen5200/ide/ata-dma-pio-single.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
c/src/lib/libbsp/powerpc/gen5200/ide/ata-instance.c
Normal file
40
c/src/lib/libbsp/powerpc/gen5200/ide/ata-instance.c
Normal 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;
|
||||
}
|
||||
231
c/src/lib/libbsp/powerpc/gen5200/ide/ata.c
Normal file
231
c/src/lib/libbsp/powerpc/gen5200/ide/ata.c
Normal 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);
|
||||
}
|
||||
338
c/src/lib/libbsp/powerpc/gen5200/include/ata.h
Normal file
338
c/src/lib/libbsp/powerpc/gen5200/include/ata.h
Normal 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 */
|
||||
370
c/src/lib/libbsp/powerpc/gen5200/include/bestcomm.h
Normal file
370
c/src/lib/libbsp/powerpc/gen5200/include/bestcomm.h
Normal 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 */
|
||||
224
c/src/lib/libbsp/powerpc/gen5200/include/bestcomm_ops.h
Normal file
224
c/src/lib/libbsp/powerpc/gen5200/include/bestcomm_ops.h
Normal 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 */
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
107
c/src/lib/libbsp/powerpc/gen5200/startup/bestcomm.c
Normal file
107
c/src/lib/libbsp/powerpc/gen5200/startup/bestcomm.c
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user