source: soft/giet_vm/giet_drivers/tty_driver.c @ 295

Last change on this file since 295 was 295, checked in by alain, 11 years ago

Introducing a major release, to suppoort the tsar_generic_leti platform
and the various (external or internal) peripherals configurations.
The map.xml format has been modified, in order to support the new
vci_iopic componentand a new policy for peripherals initialisation.
The IRQs are nom described in the XICU and IOPIC components
(and not anymore in the processors).
To enforce this major change, the map.xml file signature changed:
The signature value must be: 0xDACE2014

This new release has been tested on the tsar_generic_leti platform
for the following mappings:

  • 4c_4p_sort_leti
  • 4c_4p_sort_leti_ext
  • 4c_4p_transpose_leti
  • 4c_4p_transpose_leti_ext
  • 4c_1p_four_leti_ext
File size: 9.7 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : tty_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The tty_driver.c and tty_drivers.h files are part ot the GIET-VM kernel.
8// This driver supports the SocLib vci_multi_tty component.
9//
10// The total number of TTY terminals must be defined by the configuration
11// parameter NB_TTY_CHANNELS in the hard_config.h file.
12//
13// The "system" terminal is TTY[0].
14// The "user" TTYs are allocated to applications by the GIET in the boot phase,
15// as defined in the mapping_info data structure. The corresponding tty_id must
16// be stored in the context of the task by the boot code.
17//
[295]18// The seg_tty_base must be defined in giet_vsegs.ld file.
[258]19///////////////////////////////////////////////////////////////////////////////////
[295]20// Implementation note:
21//
22// All physical accesses to device registers are done by the two
23// _tty_get_register(), _tty_set_register() low-level functions,
24// that are handling virtual / physical addressing.
25///////////////////////////////////////////////////////////////////////////////////
[258]26
27#include <giet_config.h>
28#include <tty_driver.h>
[295]29#include <xcu_driver.h>
[258]30#include <ctx_handler.h>
31#include <utils.h>
32
33#if !defined(NB_TTY_CHANNELS)
34# error: You must define NB_TTY_CHANNELS in the hard_config.h file
35#endif
36
37#if (NB_TTY_CHANNELS < 1)
38# error: NB_TTY_CHANNELS cannot be smaller than 1!
39#endif
40
41#define in_unckdata __attribute__((section (".unckdata")))
42
[295]43//////////////////////////////////////////////////////////////////////////////
44//   TTY global variables
45//////////////////////////////////////////////////////////////////////////////
46
47in_unckdata volatile unsigned int _tty_rx_buf[NB_TTY_CHANNELS];
48in_unckdata volatile unsigned int _tty_rx_full[NB_TTY_CHANNELS] 
[258]49                                     = { [0 ... NB_TTY_CHANNELS - 1] = 0 };
50
[295]51//////////////////////////////////////////////////////////////////////////////
52// This low level function returns the value of register (channel / index)
53//////////////////////////////////////////////////////////////////////////////
54unsigned int _tty_get_register( unsigned int channel,
55                                unsigned int index )
56{
57    unsigned int* vaddr = (unsigned int*)&seg_tty_base + channel*TTY_SPAN + index;
58    return _io_extended_read( vaddr );
59}
60
61//////////////////////////////////////////////////////////////////////////////
62// This low level function set a new value in register (channel / index) 
63//////////////////////////////////////////////////////////////////////////////
64void _tty_set_register( unsigned int channel,
65                        unsigned int index,
66                        unsigned int value )
67{
68    unsigned int* vaddr = (unsigned int*)&seg_tty_base + channel*TTY_SPAN + index;
69    _io_extended_write( vaddr, value );
70}
71
[258]72/////////////////////////////////////////////////////////////////////////////////
73// This non-blocking function writes a character string from a fixed-length
[295]74// buffer to a TTY terminal identified by the channel argument.
75// This function is intended to be used to handle a system call, and should
76// not be used by the kernel for log messages on TTY 0.
77// protecting exclusive access to the selected terminal.
78// If channel argument is 0xFFFFFFFF, the TTY index is found in the task context.
[258]79// This is a non blocking call: it tests the TTY_STATUS register, and stops
80// the transfer as soon as the TTY_STATUS[WRITE] bit is set.
81/////////////////////////////////////////////////////////////////////////////////
82// Returns  the number of characters that have been written.
83/////////////////////////////////////////////////////////////////////////////////
84unsigned int _tty_write( const char*  buffer,   
85                         unsigned int length,    // number of characters
86                         unsigned int channel)   // channel index
87{
[295]88    unsigned int  nwritten;
[258]89
[295]90    // compute and check tty channel
91    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
92    if( channel >= NB_TTY_CHANNELS ) return -1;
[258]93
94    // write string to TTY channel
95    for (nwritten = 0; nwritten < length; nwritten++) 
96    {
97        // check tty's status
[295]98        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
99
100        // write one byte
101        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
[258]102    }
[295]103   
[258]104    return nwritten;
105}
106
107//////////////////////////////////////////////////////////////////////////////
108// This non-blocking function fetches one character from the
109// terminal identified by the channel argument. If the channel argument
110// is 0xFFFFFFFF, the channel index is obtained from the current task context.
111// It uses the TTY_GET_IRQ[tty_id] interrupt and the buffer must have been
112// filled by the TTY_ISR.
[295]113// It test the _tty_rx_full[tty_id] variable, read the _tty_rx_buf[tty_id]
[258]114// buffer, writes this character to the target buffer, and resets the
[295]115// _tty_rx_full[tty_id] register.
[258]116// The length argument is not used.
117//////////////////////////////////////////////////////////////////////////////
118// Returns  the number of characters that have been read (0/1).
119//////////////////////////////////////////////////////////////////////////////
120unsigned int _tty_read( char*        buffer, 
121                        unsigned int length,    // unused
122                        unsigned int channel)   // channel index
123{
[295]124    // compute and check tty channel
125    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
126    if( channel >= NB_TTY_CHANNELS ) return -1;
[258]127
128    // read one character from TTY channel
[295]129    if (_tty_rx_full[channel] == 0) 
[258]130    {
131        return 0;
132    }
133    else 
134    {
[295]135        *buffer = _tty_rx_buf[channel];
136        _tty_rx_full[channel] = 0;
[258]137        return 1;
138    }
139}
140
141//////////////////////////////////////////////////////////////////////////////
[295]142// This function try to take the hardwired lock protecting
143// exclusive access to TTY terminal identified by the "channel" argument.
144// It enters a critical section before taking the lock, and save the SR value
145// at address defined by the "save_sr_ptr" argument.
[258]146// It returns only when the lock has been successfully taken.
147//////////////////////////////////////////////////////////////////////////////
[295]148void _tty_get_lock( unsigned int   channel,
149                    unsigned int * save_sr_ptr )
[258]150{
[295]151    if( channel >= NB_TTY_CHANNELS ) _exit();
152    _it_disable( save_sr_ptr );
153    while ( _tty_get_register( channel, TTY_CONFIG ) ); // busy waiting
[258]154}
155
156//////////////////////////////////////////////////////////////////////////////
[295]157// This function releases the hardwired lock protecting
158// exclusive access to TTY terminal identified by the channel argument.
159// It exit the critical section after lock release, and restore SR value
160// from address defined by the "save_sr_ptr" argument.
[258]161//////////////////////////////////////////////////////////////////////////////
[295]162void _tty_release_lock( unsigned int   channel,
163                        unsigned int * save_sr_ptr )
[258]164{
[295]165    if( channel >= NB_TTY_CHANNELS ) _exit();
[258]166
[295]167    _tty_set_register( channel, TTY_CONFIG, 0 );
168    _it_restore( save_sr_ptr );
[258]169}
170
[295]171///////////////////////////////////////////////////////////////////////////////////
172// This ISR handles the IRQ signaling that the RX buffer is full.
173// IT can be an HWI or an SWI.
174// There is one single multi_tty component controling all channels.
175// There is one communication buffer _tty_rx_buf[i] and one synchronisation
176// variable _tty_rx_full[i] per channel.
177// A character is lost if the buffer is full when the ISR is executed.
178///////////////////////////////////////////////////////////////////////////////////
179void _tty_rx_isr( unsigned int irq_type,   // HWI / WTI
180                  unsigned int irq_id,     // index returned by XCU
181                  unsigned int channel )   // TTY channel
[258]182{
[295]183    unsigned int cluster_xy = _get_procid() / NB_PROCS_MAX;
[258]184
[295]185    if ( irq_type == IRQ_TYPE_WTI )   // reset SWI in XCU if required
[258]186    {
[295]187        unsigned int value;
188        _xcu_get_wti_value( cluster_xy, irq_id, &value );
[258]189    }
[295]190     
191    // get character and reset TTY IRQ
192    _tty_rx_buf[channel] = _tty_get_register( channel, TTY_READ ); 
[258]193
[295]194#if GIET_DEBUG_IRQS  // we don't take the TTY lock to avoid deadlock
195unsigned int x              = cluster_xy >> Y_WIDTH;
196unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
197unsigned int lpid           = _get_procid() % NB_PROCS_MAX;
198_puts("\n[IRQS DEBUG] Processor[");
199_putd(x );
200_puts(",");
201_putd(y );
202_puts(",");
203_putd(lpid );
204_puts("] enters _tty_rx_isr() at cycle ");
205_putd(_get_proctime() );
206_puts("\n  read byte = ");
207_putx(_tty_rx_buf[channel] );
208_puts("\n");
209#endif
[258]210
[295]211    // signals character available
212    _tty_rx_full[channel] = 1;
[258]213}
214
[295]215///////////////////////////////////////////////////////////////////////////////////
216// This ISR handles the IRQ signaling that the TX buffer is empty.
217// IT can be an HWI or an SWI.
218// There is one single multi_tty component controling all channels.
219// There is one communication buffer _tty_rx_buf[i] and one synchronisation
220// variable _tty_rx_full[i] per channel.
221// A character is lost if the buffer is full when the ISR is executed.
222///////////////////////////////////////////////////////////////////////////////////
223void _tty_tx_isr( unsigned int irq_type,   // HWI / WTI
224                  unsigned int irq_id,     // index returned by XCU
225                  unsigned int channel )   // TTY channel
[258]226{
[295]227    _puts("\n[GIET ERROR] the _tty_tx_isr() is not implemented\n");
228    _exit();
[258]229}
230
231// Local Variables:
232// tab-width: 4
233// c-basic-offset: 4
234// c-file-offsets:((innamespace . 0)(inline-open . 0))
235// indent-tabs-mode: nil
236// End:
237// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
238
Note: See TracBrowser for help on using the repository browser.