/** * @file * * @ingroup QorIQUartBridge * * @brief UART bridge master implementation. */ /* * Copyright (c) 2011 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Obere Lagerstr. 30 * 82178 Puchheim * Germany * * * 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 #include #include #include #include #include #include #include #define TRANSMIT_EVENT RTEMS_EVENT_13 static void serial_settings(int fd) { struct termios term; int rv = tcgetattr(fd, &term); assert(rv == 0); term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); term.c_oflag &= ~OPOST; term.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); term.c_cflag &= ~(CSIZE | PARENB); term.c_cflag |= CS8; term.c_cc [VMIN] = 1; term.c_cc [VTIME] = 1; rv = tcsetattr(fd, TCSANOW, &term); assert(rv == 0); } static void uart_bridge_master_service(intercom_packet *packet, void *arg) { rtems_status_code sc = RTEMS_SUCCESSFUL; uart_bridge_master_control *control = arg; sc = rtems_chain_append_with_notification( &control->transmit_fifo, &packet->glue.node, control->transmit_task, TRANSMIT_EVENT ); assert(sc == RTEMS_SUCCESSFUL); } static void receive_task(rtems_task_argument arg) { uart_bridge_master_control *control = (uart_bridge_master_control *) arg; intercom_type type = control->type; int fd = open(control->device_path, O_RDONLY); assert(fd >= 0); serial_settings(fd); while (true) { intercom_packet *packet = qoriq_intercom_allocate_packet( type, INTERCOM_SIZE_64 ); ssize_t in = read(fd, packet->data, packet->size - 1); if (in > 0) { packet->size = (size_t) in; qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_SLAVE_CORE, packet); } else { qoriq_intercom_free_packet(packet); } } } static void transmit_task(rtems_task_argument arg) { rtems_status_code sc = RTEMS_SUCCESSFUL; uart_bridge_master_control *control = (uart_bridge_master_control *) arg; rtems_chain_control *fifo = &control->transmit_fifo; int fd = open(control->device_path, O_WRONLY); assert(fd >= 0); serial_settings(fd); while (true) { intercom_packet *packet = NULL; sc = rtems_chain_get_with_wait( fifo, TRANSMIT_EVENT, RTEMS_NO_TIMEOUT, (rtems_chain_node **) &packet ); assert(sc == RTEMS_SUCCESSFUL); write(fd, packet->data, packet->size); qoriq_intercom_free_packet(packet); } } static rtems_id create_task( char name, rtems_task_entry entry, uart_bridge_master_control *control ) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_id task = RTEMS_ID_NONE; char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0); sc = rtems_task_create( rtems_build_name('U', 'B', name, index), QORIQ_UART_BRIDGE_TASK_PRIORITY, 0, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &task ); assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_start( task, entry, (rtems_task_argument) control ); assert(sc == RTEMS_SUCCESSFUL); return task; } static void initialize(int minor) { console_tbl *ct = Console_Port_Tbl [minor]; uart_bridge_master_control *control = ct->pDeviceParams; intercom_type type = control->type; qoriq_intercom_service_install(type, uart_bridge_master_service, control); create_task('R', receive_task, control); control->transmit_task = create_task('T', transmit_task, control); } static int first_open(int major, int minor, void *arg) { return -1; } static int last_close(int major, int minor, void *arg) { return -1; } static int read_polled(int minor) { return -1; } static void write_polled(int minor, char c) { /* Do nothing */ } static int set_attributes(int minor, const struct termios *term) { return -1; } const console_fns qoriq_uart_bridge_master = { .deviceProbe = libchip_serial_default_probe, .deviceFirstOpen = first_open, .deviceLastClose = last_close, .deviceRead = read_polled, .deviceWrite = NULL, .deviceInitialize = initialize, .deviceWritePolled = write_polled, .deviceSetAttributes = set_attributes, .deviceOutputUsesInterrupts = false };