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

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

This is a major release, including a deep restructuration of code.
The main evolutions are

  • use of the Tsar preloader to load the GIET boot-loader from disk
  • introduction of a FAT32 file system library,
  • use of this fat32 library by the boot-loader to load the map.bin data structure, and the various .elf files
  • reorganisation of drivers (one file per peripheral).
  • introduction of drivers for new peripherals: vci_chbuf_dma and vci_multi_ahci.
  • introduction of a new physical memory allocator in the boot code.

This release has been tested on the tsar_generic_iob architecture,
for the two following mappings: 4c_1p_iob_four.xml and 4c_1p_iob_sort.xml

File size: 8.2 KB
Line 
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// It can exist only one multi_tty controler in the architecture.
11//
12// The total number of TTY terminals must be defined by the configuration
13// parameter NB_TTY_CHANNELS in the hard_config.h file.
14//
15// The register offsets must be defined in the hwr_mapping.h file.
16//
17// The "system" terminal is TTY[0].
18// The "user" TTYs are allocated to applications by the GIET in the boot phase,
19// as defined in the mapping_info data structure. The corresponding tty_id must
20// be stored in the context of the task by the boot code.
21///////////////////////////////////////////////////////////////////////////////////
22// The virtual base address of the segment associated to a channel is:
23//
24//                  seg_tty_base  + TTY_SPAN * channel_id
25//
26// The seg_tty_base virtual base addresses must be defined in giet_vsegs.ld file.
27///////////////////////////////////////////////////////////////////////////////////
28
29#include <giet_config.h>
30#include <tty_driver.h>
31#include <ctx_handler.h>
32#include <utils.h>
33
34#if !defined(NB_TTY_CHANNELS)
35# error: You must define NB_TTY_CHANNELS in the hard_config.h file
36#endif
37
38#if (NB_TTY_CHANNELS < 1)
39# error: NB_TTY_CHANNELS cannot be smaller than 1!
40#endif
41
42#define in_unckdata __attribute__((section (".unckdata")))
43
44/////////////////   TTY global variables
45in_unckdata volatile unsigned char _tty_get_buf[NB_TTY_CHANNELS];
46in_unckdata volatile unsigned char _tty_get_full[NB_TTY_CHANNELS] 
47                                     = { [0 ... NB_TTY_CHANNELS - 1] = 0 };
48
49/////////////////////////////////////////////////////////////////////////////////
50// This non-blocking function writes a character string from a fixed-length
51// buffer to the TTY_WRITE register of a TTY terminal identified by the
52// channel argument. If the channel argument is 0xFFFFFFFF, the channel
53// index is obtained from the current taxk context.
54// It doesn't use any interrupt.
55// This is a non blocking call: it tests the TTY_STATUS register, and stops
56// the transfer as soon as the TTY_STATUS[WRITE] bit is set.
57/////////////////////////////////////////////////////////////////////////////////
58// Returns  the number of characters that have been written.
59/////////////////////////////////////////////////////////////////////////////////
60unsigned int _tty_write( const char*  buffer,   
61                         unsigned int length,    // number of characters
62                         unsigned int channel)   // channel index
63{
64    unsigned int nwritten;
65    unsigned int tty_id;
66    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
67
68    // compute tty channel
69    if( channel == 0xFFFFFFFF )
70    {
71        tty_id = _get_context_slot(CTX_TTY_ID);
72    }
73    else
74    {
75        tty_id = (unsigned int)channel;
76    }
77
78    // write string to TTY channel
79    for (nwritten = 0; nwritten < length; nwritten++) 
80    {
81        // check tty's status
82        if ((tty_address[tty_id * TTY_SPAN + TTY_STATUS] & 0x2) == 0x2) break;
83        _tty_write_data( tty_id, buffer[nwritten] );
84    }
85    return nwritten;
86}
87
88//////////////////////////////////////////////////////////////////////////////
89// This non-blocking function fetches one character from the
90// terminal identified by the channel argument. If the channel argument
91// is 0xFFFFFFFF, the channel index is obtained from the current task context.
92// It uses the TTY_GET_IRQ[tty_id] interrupt and the buffer must have been
93// filled by the TTY_ISR.
94// It test the _tty_get_full[tty_id] register, read the _tty_get_buf[tty_id]
95// buffer, writes this character to the target buffer, and resets the
96// _tty_get_full[tty_id] register.
97// The length argument is not used.
98//////////////////////////////////////////////////////////////////////////////
99// Returns  the number of characters that have been read (0/1).
100//////////////////////////////////////////////////////////////////////////////
101unsigned int _tty_read( char*        buffer, 
102                        unsigned int length,    // unused
103                        unsigned int channel)   // channel index
104{
105   
106    unsigned int tty_id;
107
108    // compute tty channel
109    if( channel == 0xFFFFFFFF )
110    {
111        tty_id = _get_context_slot(CTX_TTY_ID);
112    }
113    else
114    {
115        tty_id = (unsigned int)channel;
116    }
117
118    // read one character from TTY channel
119    if (_tty_get_full[tty_id] == 0) 
120    {
121        return 0;
122    }
123    else 
124    {
125        *buffer = _tty_get_buf[tty_id];
126        _tty_get_full[tty_id] = 0;
127        return 1;
128    }
129}
130//////////////////////////////////////////////////////////////////////////////
131
132//////////////////////////////////////////////////////////////////////////////
133// This function try to take the hardwired lock protecting exclusive access
134// to TTY terminal identified by the channel argument.
135// It returns only when the lock has been successfully taken.
136//////////////////////////////////////////////////////////////////////////////
137void _tty_get_lock( unsigned int channel )
138{
139    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
140
141    if( channel >= NB_TTY_CHANNELS )
142    {
143        _puts("[GIET ERROR] in _tty_get_lock() : illegal TTY index\n");
144        _exit();       
145    }
146
147    while ( tty_address[channel * TTY_SPAN + TTY_CONFIG] );
148}
149
150//////////////////////////////////////////////////////////////////////////////
151// This function releases the hardwired lock protecting exclusive access
152// to TTY terminal identified by the channel argument.
153//////////////////////////////////////////////////////////////////////////////
154void _tty_release_lock( unsigned int channel )
155{
156    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
157
158    if( channel >= NB_TTY_CHANNELS )
159    {
160        _puts("[GIET ERROR] in _tty_release_lock() : illegal TTY index\n");
161        _exit();       
162    }
163
164    tty_address[channel * TTY_SPAN + TTY_CONFIG] = 0;
165}
166
167//////////////////////////////////////////////////////////////////////////////
168// This function returns the content of the TTY_READ register in the
169// TTY terminal identified by the channel argument.
170//////////////////////////////////////////////////////////////////////////////
171unsigned int _tty_read_data( unsigned int channel )
172{
173    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
174
175    if( channel >= NB_TTY_CHANNELS )
176    {
177        _puts("[GIET ERROR] in _tty_read_data() : illegal TTY index\n");
178        _exit();       
179    }
180
181    return tty_address[channel * TTY_SPAN + TTY_READ];
182}
183
184//////////////////////////////////////////////////////////////////////////////
185// This function returns the content of the TTY_STATUS register in the
186// TTY terminal identified by the channel argument.
187//////////////////////////////////////////////////////////////////////////////
188unsigned int _tty_get_status( unsigned int channel )
189{
190    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
191
192    if( channel >= NB_TTY_CHANNELS )
193    {
194        _puts("[GIET ERROR] in _tty_get_status() : illegal TTY index\n");
195        _exit();       
196    }
197
198    return tty_address[channel * TTY_SPAN + TTY_STATUS];
199}
200
201//////////////////////////////////////////////////////////////////////////////
202// This function writes one character in the TTY_WRITE register in the
203// TTY terminal identified by the channel argument.
204//////////////////////////////////////////////////////////////////////////////
205void _tty_write_data( unsigned int channel,
206                      char         byte )
207{
208    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
209
210    if( channel >= NB_TTY_CHANNELS )
211    {
212        _puts("[GIET ERROR] in _tty_write_data() : illegal TTY index\n");
213        _exit();       
214    }
215
216    tty_address[channel * TTY_SPAN + TTY_WRITE] = (unsigned int) byte;
217}
218
219
220// Local Variables:
221// tab-width: 4
222// c-basic-offset: 4
223// c-file-offsets:((innamespace . 0)(inline-open . 0))
224// indent-tabs-mode: nil
225// End:
226// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
227
Note: See TracBrowser for help on using the repository browser.