source: rtems/c/src/lib/libcpu/sh/sh7045/sci/sci.c @ df49c60

4.104.114.84.95
Last change on this file since df49c60 was df49c60, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 12, 2000 at 3:00:15 PM

Merged from 4.5.0-beta3a

  • Property mode set to 100644
File size: 10.8 KB
Line 
1/*
2 * /dev/sci[0|1] for Hitachi SH 704X
3 *
4 * The SH doesn't have a designated console device. Therefore we "alias"
5 * another device as /dev/console and revector all calls to /dev/console
6 * to this device.
7 *
8 * This approach is similar to installing a sym-link from one device to
9 * another device. If rtems once will support sym-links for devices files,
10 * this implementation could be dropped.
11 *
12 *  Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
13 *
14 *  COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
15 *
16 *  This program is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 *
21 *  COPYRIGHT (c) 1998.
22 *  On-Line Applications Research Corporation (OAR).
23 *  Copyright assigned to U.S. Government, 1994.
24 *
25 *  The license and distribution terms for this file may be
26 *  found in the file LICENSE in this distribution or at
27 *  http://www.OARcorp.com/rtems/license.html.
28 *
29 *  Modified to reflect sh7045 processor:
30 *  John M. Mills (jmills@tga.com)
31 *  TGA Technologies, Inc.
32 *  100 Pinnacle Way, Suite 140
33 *  Norcross, GA 30071 U.S.A.
34 *
35 *  This modified file may be copied and distributed in accordance
36 *  the above-referenced license. It is provided for critique and
37 *  developmental purposes without any warranty nor representation
38 *  by the authors or by TGA Technologies.
39 *
40 *  $Id$
41 */
42
43#include <rtems.h>
44
45#include <stdlib.h>
46
47#include <rtems/libio.h>
48#include <iosupp.h>
49#include <rtems/score/sh_io.h>
50#include <rtems/score/ispsh7045.h>
51#include <rtems/score/iosh7045.h>
52#include <sh/sh7_sci.h>
53#include <sh/sh7_pfc.h>
54
55#include <sh/sci.h>
56
57#ifndef STANDALONE_EVB
58#define STANDALONE_EVB 0
59#endif
60
61/*
62 * NOTE: Some SH variants have 3 sci devices
63 */
64 
65#define SCI_MINOR_DEVICES       2
66 
67/*
68 * FIXME: sh7045 register names match Hitachi data book,
69 *  but conflict with RTEMS sh7032 usage.
70 */
71
72#define SH_SCI_BASE_0   SCI_SMR0
73#define SH_SCI_BASE_1   SCI_SMR1
74
75#define SH_SCI_DEF_COMM_0   B9600 | CS8
76#define SH_SCI_DEF_COMM_1   B38400 | CS8
77/*  #define SH_SCI_DEF_COMM_1   B9600 | CS8 */
78
79struct scidev_t {
80  char *                        name ;
81  unsigned32                    addr ;
82  rtems_device_minor_number     minor ;
83  unsigned short                opened ;
84  tcflag_t                      cflags ;
85} sci_device[SCI_MINOR_DEVICES] =
86{
87  { "/dev/sci0", SH_SCI_BASE_0, 0, 0, SH_SCI_DEF_COMM_0 },
88  { "/dev/sci1", SH_SCI_BASE_1, 1, 0, SH_SCI_DEF_COMM_1 }
89} ;
90
91/*  local data structures maintain hardware configuration */
92#if UNUSED
93static sci_setup_t sio_param[2];
94#endif
95
96/*  imported from scitab.rel */
97extern int _sci_get_brparms(
98  tcflag_t      cflag,
99  unsigned char *smr,
100  unsigned char *brr );
101
102/* Translate termios' tcflag_t into sci settings */
103static int _sci_set_cflags(
104  struct scidev_t      *sci_dev,
105  tcflag_t      c_cflag )
106{
107  unsigned8     smr ;
108  unsigned8     brr ;
109 
110  if ( c_cflag & CBAUD )
111  {
112    if ( _sci_get_brparms( c_cflag, &smr, &brr ) != 0 )
113      return -1 ;
114  }
115                   
116  if ( c_cflag & CSIZE )
117  {
118    if ( c_cflag & CS8 )
119      smr &= ~SCI_SEVEN_BIT_DATA;
120    else if ( c_cflag & CS7 )
121      smr |= SCI_SEVEN_BIT_DATA;
122    else
123      return -1 ;
124  }
125
126  if ( c_cflag & CSTOPB )
127    smr |= SCI_STOP_BITS_2;
128  else
129    smr &= ~SCI_STOP_BITS_2;
130
131  if ( c_cflag & PARENB )
132    smr |= SCI_PARITY_ON ;
133  else
134    smr &= ~SCI_PARITY_ON ;
135
136  if ( c_cflag & PARODD )
137    smr |= SCI_ODD_PARITY ;
138  else
139    smr &= ~SCI_ODD_PARITY;
140   
141  write8( smr, sci_dev->addr + SCI_SMR );
142  write8( brr, sci_dev->addr + SCI_BRR );
143 
144  return 0 ;
145}
146
147/*
148 * local functions operate SCI ports 0 and 1
149 * called from polling routines or ISRs
150 */
151rtems_boolean wrtSCI0(unsigned char ch)
152{
153  unsigned8 temp;
154  rtems_boolean result=FALSE;
155
156  if ((read8(SCI_SSR0) & SCI_TDRE) != 0x00) {
157    /* Write the character to the TDR */
158    write8(ch, SCI_TDR0);
159    /* Clear the TDRE bit */
160    temp = read8(SCI_SSR0) & ~SCI_TDRE;
161    write8(temp, SCI_SSR0);
162    result = TRUE;
163  }
164  return result;
165} /* wrtSCI0 */
166
167rtems_boolean wrtSCI1(unsigned char ch)
168{
169  unsigned8 temp;
170  rtems_boolean result=FALSE;
171
172  if ((read8(SCI_SSR1) & SCI_TDRE) != 0x00) {
173     /* Write the character to the TDR */
174     write8(ch, SCI_TDR1);
175     /* Clear the TDRE bit */
176     temp = read8(SCI_SSR1) & ~SCI_TDRE;
177     write8(temp, SCI_SSR1);
178     result = TRUE;
179  }
180  return result;
181} /* wrtSCI1 */
182
183/* polled output steers byte to selected port */
184void sh_sci_outbyte_polled(
185  rtems_device_minor_number  minor,
186  char ch )
187{
188        if (minor == 0) /* blocks until port ready */
189                while (wrtSCI0(ch) != TRUE); /* SCI0*/
190        else
191                while (wrtSCI1(ch) != TRUE); /* SCI1*/
192} /* sh_sci_outbyte_polled */
193
194/*
195 * Initial version calls polled output driver and blocks
196 */
197void outbyte(
198  rtems_device_minor_number  minor,
199  char ch)
200{
201        sh_sci_outbyte_polled(minor, (unsigned char)ch);
202} /* outbyte */
203
204rtems_boolean rdSCI0(unsigned char *ch)
205{
206  unsigned8 temp;
207  rtems_boolean result=FALSE;
208
209  if ((read8(SCI_SSR0) & SCI_RDRF) != 0x00) {
210    /* read input */
211    *ch = read8(SCI_RDR0);
212    /* Clear RDRF flag */
213    temp = read8(SCI_SSR0) & ~SCI_RDRF;
214    write8(temp, SCI_SSR0);
215    result = TRUE;
216  }
217  return result;
218} /* rdSCI0 */
219
220rtems_boolean rdSCI1(unsigned char *ch)
221{
222  unsigned8 temp;
223  rtems_boolean result=FALSE;
224
225  if ((read8(SCI_SSR1) & SCI_RDRF) != 0x00) {
226    /* read input */
227    *ch = read8(SCI_RDR1);
228    /* Clear RDRF flag */
229    temp= read8(SCI_SSR1) & ~SCI_RDRF;
230    write8(temp, SCI_SSR1);
231    result = TRUE;
232    }
233  return result;
234} /* rdSCI1 */
235
236
237/* initial version pulls byte from selected port */
238char sh_sci_inbyte_polled(
239    rtems_device_minor_number  minor )
240{
241        char ch;
242       
243        if (minor == 0) /* blocks until char.ready */
244                while (rdSCI0(&ch) != TRUE); /* SCI0 */
245        else
246                while (rdSCI1(&ch) != TRUE); /* SCI1 */
247        return ch;
248} /* sh_sci_inbyte_polled */
249
250/* Initial version calls polled input driver */
251char inbyte(
252  rtems_device_minor_number  minor )
253{
254        char ch;
255
256        ch = sh_sci_inbyte_polled(minor);
257        return ch;
258} /* inbyte */
259
260
261/*  sh_sci_initialize
262 *
263 *  This routine initializes (registers) the sh_sci IO drivers.
264 *
265 *  Input parameters: ignored
266 *
267 *  Output parameters:  NONE
268 *
269 *  Return values: RTEMS_SUCCESSFUL
270 *   if all sci[...] register, else calls
271 *   rtems_fatal_error_occurred(status)
272 *
273 */
274
275rtems_device_driver sh_sci_initialize(
276  rtems_device_major_number  major,
277  rtems_device_minor_number  minor,
278  void                      *arg )
279{
280  rtems_device_driver status ;
281  rtems_device_minor_number     i;
282 
283  /*
284   * register all possible devices.
285   * the initialization of the hardware is done by sci_open
286   */
287
288  for ( i = 0 ; i < SCI_MINOR_DEVICES ; i++ )
289  {
290    status = rtems_io_register_name(
291      sci_device[i].name,
292      major,
293      sci_device[i].minor );
294    if (status != RTEMS_SUCCESSFUL)
295      rtems_fatal_error_occurred(status);
296  }
297
298  /* non-default hardware setup occurs in sh_sci_open() */
299
300  return RTEMS_SUCCESSFUL;
301}
302
303
304/*
305 *  Open entry point
306 *   Sets up port and pins for selected sci.
307 *   SCI0 setup is conditional on STANDALONE_EVB == 1
308 */
309
310rtems_device_driver sh_sci_open(
311  rtems_device_major_number major,
312  rtems_device_minor_number minor,
313  void                    * arg )
314{
315  unsigned8 temp8;
316  unsigned16 temp16;
317 
318  unsigned      a ;
319 
320 /* check for valid minor number */
321   if(( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 ))
322   {
323     return RTEMS_INVALID_NUMBER;
324   }
325 
326  /* device already opened */
327  if ( sci_device[minor].opened > 0 )
328  {
329    sci_device[minor].opened++ ;
330    return RTEMS_SUCCESSFUL ;
331  }
332   
333  /* set PFC registers to enable I/O pins */
334
335  if ((minor == 0) && (STANDALONE_EVB == 1)) {
336    temp16 = read16(PFC_PACRL2);         /* disable SCK0, DMA, IRQ */
337    temp16 &= ~(PA2MD1 | PA2MD0);
338    temp16 |= (PA_TXD0 | PA_RXD0);       /* enable pins for Tx0, Rx0 */
339    write16(temp16, PFC_PACRL2);
340   
341  } else if (minor == 1) { 
342    temp16 = read16(PFC_PACRL2);          /* disable SCK1, DMA, IRQ */
343    temp16 &= ~(PA5MD1 | PA5MD0);
344    temp16 |= (PA_TXD1 | PA_RXD1);        /* enable pins for Tx1, Rx1 */
345    write16(temp16, PFC_PACRL2);
346
347  } /* add other devices and pins as req'd. */
348
349  /* set up SCI registers */
350  if ((minor != 0) || (STANDALONE_EVB == 1)) {
351    write8(0x00, sci_device[minor].addr + SCI_SCR);      /* Clear SCR */
352                                                   /* set SMR and BRR */
353    _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags );
354
355    for(a=0; a < 10000L; a++) {                      /* Delay */
356      asm volatile ("nop");
357    }
358
359    write8((SCI_RE | SCI_TE),              /* enable async. Tx and Rx */
360           sci_device[minor].addr + SCI_SCR);
361    temp8 = read8(sci_device[minor].addr + SCI_RDR);   /* flush input */
362    /* Clear RDRF flag */
363    temp8= read8(sci_device[minor].addr + SCI_SSR) & ~SCI_RDRF;
364    write8(temp8, sci_device[minor].addr + SCI_SSR);
365    write8(0x00, sci_device[minor].addr + SCI_TDR);    /* force output */
366     /* Clear the TDRE bit */
367     temp8 = read8(sci_device[minor].addr + SCI_SSR) & ~SCI_TDRE;
368     write8(temp8, sci_device[minor].addr + SCI_SSR);
369   
370    /* add interrupt setup if required */
371
372  }
373
374  sci_device[minor].opened++ ;
375
376  return RTEMS_SUCCESSFUL ;
377}
378 
379/*
380 *  Close entry point
381 */
382
383rtems_device_driver sh_sci_close(
384  rtems_device_major_number major,
385  rtems_device_minor_number minor,
386  void                    * arg
387)
388{
389  /* FIXME: Incomplete */
390  if ( sci_device[minor].opened > 0 )
391    sci_device[minor].opened-- ;
392  else
393    return RTEMS_INVALID_NUMBER ;
394   
395  return RTEMS_SUCCESSFUL ;
396}
397
398/*
399 * read bytes from the serial port. We only have stdin.
400 */
401
402rtems_device_driver sh_sci_read(
403  rtems_device_major_number major,
404  rtems_device_minor_number minor,
405  void                    * arg
406)
407{
408  rtems_libio_rw_args_t *rw_args;
409  char *buffer;
410  int maximum;
411  int count = 0;
412 
413  rw_args = (rtems_libio_rw_args_t *) arg;
414
415  buffer = rw_args->buffer;
416  maximum = rw_args->count;
417
418  for (count = 0; count < maximum; count++) {
419    buffer[ count ] = inbyte(minor);
420    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
421      buffer[ count++ ]  = '\n';
422      break;
423    }
424  }
425
426  rw_args->bytes_moved = count;
427  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
428}
429
430/*
431 * write bytes to the serial port. Stdout and stderr are the same.
432 */
433
434rtems_device_driver sh_sci_write(
435  rtems_device_major_number major,
436  rtems_device_minor_number minor,
437  void                    * arg
438)
439{
440  int count;
441  int maximum;
442  rtems_libio_rw_args_t *rw_args;
443  char *buffer;
444
445  rw_args = (rtems_libio_rw_args_t *) arg;
446
447  buffer = rw_args->buffer;
448  maximum = rw_args->count;
449
450  for (count = 0; count < maximum; count++) {
451    if ( buffer[ count ] == '\n') {
452      outbyte(minor, '\r');
453    }
454    outbyte( minor, buffer[ count ] );
455  }
456
457  rw_args->bytes_moved = maximum;
458  return 0;
459}
460
461/*
462 *  IO Control entry point
463 */
464
465rtems_device_driver sh_sci_control(
466  rtems_device_major_number major,
467  rtems_device_minor_number minor,
468  void                    * arg
469)
470{
471  /* Not yet supported */
472  return RTEMS_SUCCESSFUL ;
473}
Note: See TracBrowser for help on using the repository browser.