//========================================================================== // // synthserial.c // // Serial device driver for the synthetic target // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 2003 Savin Zlobec. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): savin // Contributors: // Date: 2003-03-27 // //####DESCRIPTIONEND#### // //========================================================================== #include #include #include #include #include #include #include #include #include #include // Protocol between this driver and the auxiliary #define SYNTH_SERIAL_TX 0x01 // send char #define SYNTH_SERIAL_RX 0x02 // receive char #define SYNTH_SERIAL_GETPARAMS 0x03 // get init parameters typedef struct synth_serial_info { int synth_id; // Device id within the auxiliary cyg_vector_t interrupt; // Interrupt number allocated by the auxiliary cyg_handle_t interrupt_handle; // Interrupt handle cyg_interrupt interrupt_data; // Interrupt data } synth_serial_info; static bool synth_serial_init(struct cyg_devtab_entry *tab); static bool synth_serial_putc(serial_channel *chan, unsigned char c); static Cyg_ErrNo synth_serial_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name); static unsigned char synth_serial_getc(serial_channel *chan); static Cyg_ErrNo synth_serial_set_config(serial_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len); static void synth_serial_start_xmit(serial_channel *chan); static void synth_serial_stop_xmit(serial_channel *chan); static cyg_uint32 synth_serial_ISR(cyg_vector_t vector, cyg_addrword_t data); static void synth_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); static SERIAL_FUNS(synth_serial_funs, synth_serial_putc, synth_serial_getc, synth_serial_set_config, synth_serial_start_xmit, synth_serial_stop_xmit ); #define SYNTH_SERIAL_INSTANCE(_number_) \ static synth_serial_info synth_serial_info##_number_ = { \ synth_id: -1, \ interrupt: 0, \ interrupt_handle: 0 \ }; \ static unsigned char synth_serial_out_buf##_number_[CYGNUM_IO_SERIAL_ECOSYNTH_SERIAL##_number_##_BUFSIZE]; \ static unsigned char synth_serial_in_buf##_number_[CYGNUM_IO_SERIAL_ECOSYNTH_SERIAL##_number_##_BUFSIZE]; \ static SERIAL_CHANNEL_USING_INTERRUPTS(synth_serial_channel##_number_, \ synth_serial_funs, \ synth_serial_info##_number_, \ CYGNUM_SERIAL_BAUD_MIN, \ CYG_SERIAL_STOP_DEFAULT, \ CYG_SERIAL_PARITY_DEFAULT, \ CYG_SERIAL_WORD_LENGTH_DEFAULT, \ CYG_SERIAL_FLAGS_DEFAULT, \ &synth_serial_out_buf##_number_[0], sizeof(synth_serial_out_buf##_number_), \ &synth_serial_in_buf##_number_[0], sizeof(synth_serial_in_buf##_number_) \ ); \ DEVTAB_ENTRY(synth_serial_io##_number_, \ CYGDAT_IO_SERIAL_ECOSYNTH_SERIAL##_number_##_NAME, \ 0, \ &cyg_io_serial_devio, \ synth_serial_init, \ synth_serial_lookup, \ &synth_serial_channel##_number_ \ ); #ifdef CYGVAR_DEVS_SERIAL_ECOSYNTH_SERIAL0 SYNTH_SERIAL_INSTANCE(0); #endif static bool synth_serial_init(struct cyg_devtab_entry *tab) { bool result = false; serial_channel *chan = (serial_channel *)tab->priv; synth_serial_info *synth_info = (synth_serial_info *)chan->dev_priv; if (synth_auxiliary_running) { synth_info->synth_id = synth_auxiliary_instantiate("devs/serial/synth/ecosynth", SYNTH_MAKESTRING(CYGPKG_DEVS_SERIAL_ECOSYNTH), "serial", tab->name, (const char*) 0); if (-1 != synth_info->synth_id) { result = true; synth_auxiliary_xchgmsg(synth_info->synth_id, SYNTH_SERIAL_GETPARAMS, 0, 0, 0, 0, &(synth_info->interrupt), 0, 0, 0); cyg_drv_interrupt_create(synth_info->interrupt, 0, (CYG_ADDRWORD)chan, &synth_serial_ISR, &synth_serial_DSR, &(synth_info->interrupt_handle), &(synth_info->interrupt_data)); cyg_drv_interrupt_attach(synth_info->interrupt_handle); cyg_drv_interrupt_unmask(synth_info->interrupt); } } (chan->callbacks->serial_init)(chan); return result; } static Cyg_ErrNo synth_serial_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name) { serial_channel *chan = (serial_channel *)(*tab)->priv; (chan->callbacks->serial_init)(chan); return ENOERR; } static bool synth_serial_putc(serial_channel *chan, unsigned char c) { synth_serial_info *synth_info = (synth_serial_info *)chan->dev_priv; if (-1 != synth_info->synth_id) { synth_auxiliary_xchgmsg(synth_info->synth_id, SYNTH_SERIAL_TX, 0, 0, &c, 1, 0, 0, 0, 0); return true; } return false; } static unsigned char synth_serial_getc(serial_channel *chan) { synth_serial_info *synth_info = (synth_serial_info *)chan->dev_priv; if (-1 != synth_info->synth_id) { char c; int l; do { synth_auxiliary_xchgmsg(synth_info->synth_id, SYNTH_SERIAL_RX, 0, 0, 0, 0, &l, &c, 0, 1); } while (l < 0); return c; } return 0; } static Cyg_ErrNo synth_serial_set_config(serial_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) { switch (key) { case CYG_IO_SET_CONFIG_SERIAL_INFO: { if ( *len < sizeof(cyg_serial_info_t) ) { return -EINVAL; } *len = sizeof(cyg_serial_info_t); return ENOERR; } break; default: return -EINVAL; } return ENOERR; } static void synth_serial_start_xmit(serial_channel *chan) { (chan->callbacks->xmt_char)(chan); } static void synth_serial_stop_xmit(serial_channel *chan) { } static cyg_uint32 synth_serial_ISR(cyg_vector_t vector, cyg_addrword_t data) { cyg_drv_interrupt_mask(vector); cyg_drv_interrupt_acknowledge(vector); return CYG_ISR_CALL_DSR; } static void synth_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) { serial_channel *chan = (serial_channel *)data; synth_serial_info *synth_info = (synth_serial_info *)chan->dev_priv; if (-1 != synth_info->synth_id) { char c; int l; synth_auxiliary_xchgmsg(synth_info->synth_id, SYNTH_SERIAL_RX, 0, 0, 0, 0, &l, &c, 0, 1); (chan->callbacks->rcv_char)(chan, c); } cyg_drv_interrupt_unmask(vector); } // ---------------------------------------------------------------------------- // EOF synthserial.c