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

4.104.114.84.95
Last change on this file since b4f92a9 was b4f92a9, checked in by Joel Sherrill <joel.sherrill@…>, on 02/03/03 at 23:55:48

2003-02-03 Joel Sherrill <joel@…>

PR 338/filesystem

  • sci/sci.c: Side-effect of fixing reentrancy problem with rtems_io_lookup_name() (API change).
  • Property mode set to 100644
File size: 13.5 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 *
24 *  The license and distribution terms for this file may be
25 *  found in the file LICENSE in this distribution or at
26 *  http://www.OARcorp.com/rtems/license.html.
27 *
28 *  Modified to reflect sh7045 processor:
29 *  John M. Mills (jmills@tga.com)
30 *  TGA Technologies, Inc.
31 *  100 Pinnacle Way, Suite 140
32 *  Norcross, GA 30071 U.S.A.
33 *
34 *  This modified file may be copied and distributed in accordance
35 *  the above-referenced license. It is provided for critique and
36 *  developmental purposes without any warranty nor representation
37 *  by the authors or by TGA Technologies.
38 *
39 *  $Id$
40 */
41
42#include <rtems.h>
43
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    /* Check for transmission errors */
216    if(temp & (SCI_ORER | SCI_FER | SCI_PER)){
217        /* TODO: report to RTEMS transmission error */
218
219        /* clear error flags*/
220        temp &= ~(SCI_ORER | SCI_FER | SCI_PER);
221        write8(temp, SCI_SSR0);
222    }
223    result = TRUE;
224  }
225  return result;
226} /* rdSCI0 */
227
228rtems_boolean rdSCI1(unsigned char *ch)
229{
230  unsigned8 temp;
231  rtems_boolean result=FALSE;
232
233  if ((read8(SCI_SSR1) & SCI_RDRF) != 0x00) {
234    /* read input */
235    *ch = read8(SCI_RDR1);
236    /* Clear RDRF flag */
237    temp= read8(SCI_SSR1) & ~SCI_RDRF;
238    write8(temp, SCI_SSR1);
239    /* Check for transmission errors */
240    if(temp & (SCI_ORER | SCI_FER | SCI_PER)){
241        /* TODO: report to RTEMS transmission error */
242
243        /* clear error flags*/
244        temp &= ~(SCI_ORER | SCI_FER | SCI_PER);
245        write8(temp, SCI_SSR1);
246    }
247    result = TRUE;
248  }
249  return result;
250} /* rdSCI1 */
251
252
253/* initial version pulls byte from selected port */
254char sh_sci_inbyte_polled(
255    rtems_device_minor_number  minor )
256{
257        char ch;
258       
259        if (minor == 0) /* blocks until char.ready */
260                while (rdSCI0(&ch) != TRUE); /* SCI0 */
261        else
262                while (rdSCI1(&ch) != TRUE); /* SCI1 */
263        return ch;
264} /* sh_sci_inbyte_polled */
265
266/* Initial version calls polled input driver */
267char inbyte(
268  rtems_device_minor_number  minor )
269{
270        char ch;
271
272        ch = sh_sci_inbyte_polled(minor);
273        return ch;
274} /* inbyte */
275
276
277/*  sh_sci_initialize
278 *
279 *  This routine initializes (registers) the sh_sci IO drivers.
280 *
281 *  Input parameters: ignored
282 *
283 *  Output parameters:  NONE
284 *
285 *  Return values: RTEMS_SUCCESSFUL
286 *   if all sci[...] register, else calls
287 *   rtems_fatal_error_occurred(status)
288 *
289 */
290
291rtems_device_driver sh_sci_initialize(
292  rtems_device_major_number  major,
293  rtems_device_minor_number  minor,
294  void                      *arg )
295{
296  rtems_device_driver status;
297  rtems_device_minor_number i;
298  rtems_driver_name_t driver;
299 
300 
301  /*
302   * register all possible devices.
303   * the initialization of the hardware is done by sci_open
304   *
305   * One of devices could be previously registered by console
306   * initialization therefore we check it everytime
307   */
308
309  for ( i = 0 ; i < SCI_MINOR_DEVICES ; i++ )
310  {
311    status = rtems_io_lookup_name(
312        sci_device[i].name,
313        &driver);
314    if( status != RTEMS_SUCCESSFUL )
315    {
316        /* OK. We assume it is not registered yet. */
317        status = rtems_io_register_name(
318            sci_device[i].name,
319            major,
320            sci_device[i].minor );
321        if (status != RTEMS_SUCCESSFUL)
322            rtems_fatal_error_occurred(status);
323    }
324  }
325
326  /* non-default hardware setup occurs in sh_sci_open() */
327
328  return RTEMS_SUCCESSFUL;
329}
330
331
332/*
333 *  Open entry point
334 *   Sets up port and pins for selected sci.
335 */
336
337rtems_device_driver sh_sci_open(
338  rtems_device_major_number major,
339  rtems_device_minor_number minor,
340  void                    * arg )
341{
342  unsigned8 temp8;
343  unsigned16 temp16;
344 
345  unsigned      a ;
346 
347 /* check for valid minor number */
348   if(( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 ))
349   {
350     return RTEMS_INVALID_NUMBER;
351   }
352 
353  /* device already opened */
354  if ( sci_device[minor].opened > 0 )
355  {
356    sci_device[minor].opened++ ;
357    return RTEMS_SUCCESSFUL ;
358  }
359   
360  /* set PFC registers to enable I/O pins */
361
362  if ((minor == 0)) {
363    temp16 = read16(PFC_PACRL2);         /* disable SCK0, DMA, IRQ */
364    temp16 &= ~(PA2MD1 | PA2MD0);
365    temp16 |= (PA_TXD0 | PA_RXD0);       /* enable pins for Tx0, Rx0 */
366    write16(temp16, PFC_PACRL2);
367   
368  } else if (minor == 1) { 
369    temp16 = read16(PFC_PACRL2);          /* disable SCK1, DMA, IRQ */
370    temp16 &= ~(PA5MD1 | PA5MD0);
371    temp16 |= (PA_TXD1 | PA_RXD1);        /* enable pins for Tx1, Rx1 */
372    write16(temp16, PFC_PACRL2);
373
374  } /* add other devices and pins as req'd. */
375
376  /* set up SCI registers */
377      write8(0x00, sci_device[minor].addr + SCI_SCR);    /* Clear SCR */
378                                                   /* set SMR and BRR */
379    _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags );
380
381    for(a=0; a < 10000L; a++) {                      /* Delay */
382      asm volatile ("nop");
383    }
384
385    write8((SCI_RE | SCI_TE),              /* enable async. Tx and Rx */
386           sci_device[minor].addr + SCI_SCR);
387
388    /* clear error flags */
389    temp8 = read8(sci_device[minor].addr + SCI_SSR);
390    while(temp8 & (SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER)){
391        temp8 = read8(sci_device[minor].addr + SCI_RDR);   /* flush input */
392        temp8 = read8(sci_device[minor].addr + SCI_SSR); /* clear some flags */
393        write8(temp8 & ~(SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER),
394               sci_device[minor].addr + SCI_SSR);
395        temp8 = read8(sci_device[minor].addr + SCI_SSR); /* check if everything is OK */
396    }   
397    /* Clear RDRF flag */
398    write8(0x00, sci_device[minor].addr + SCI_TDR);    /* force output */
399     /* Clear the TDRE bit */
400     temp8 = read8(sci_device[minor].addr + SCI_SSR) & ~SCI_TDRE;
401     write8(temp8, sci_device[minor].addr + SCI_SSR);
402   
403    /* add interrupt setup if required */
404
405 
406  sci_device[minor].opened++ ;
407
408  return RTEMS_SUCCESSFUL ;
409}
410 
411/*
412 *  Close entry point
413 */
414
415rtems_device_driver sh_sci_close(
416  rtems_device_major_number major,
417  rtems_device_minor_number minor,
418  void                    * arg
419)
420{
421  /* FIXME: Incomplete */
422  if ( sci_device[minor].opened > 0 )
423    sci_device[minor].opened-- ;
424  else
425    return RTEMS_INVALID_NUMBER ;
426   
427  return RTEMS_SUCCESSFUL ;
428}
429
430/*
431 * read bytes from the serial port. We only have stdin.
432 */
433
434rtems_device_driver sh_sci_read(
435  rtems_device_major_number major,
436  rtems_device_minor_number minor,
437  void                    * arg
438)
439{
440  rtems_libio_rw_args_t *rw_args;
441  char *buffer;
442  int maximum;
443  int count = 0;
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    buffer[ count ] = inbyte(minor);
452    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
453      buffer[ count++ ]  = '\n';
454      break;
455    }
456  }
457
458  rw_args->bytes_moved = count;
459  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
460}
461
462/*
463 * write bytes to the serial port. Stdout and stderr are the same.
464 */
465
466rtems_device_driver sh_sci_write(
467  rtems_device_major_number major,
468  rtems_device_minor_number minor,
469  void                    * arg
470)
471{
472  int count;
473  int maximum;
474  rtems_libio_rw_args_t *rw_args;
475  char *buffer;
476
477  rw_args = (rtems_libio_rw_args_t *) arg;
478
479  buffer = rw_args->buffer;
480  maximum = rw_args->count;
481
482  for (count = 0; count < maximum; count++) {
483    if ( buffer[ count ] == '\n') {
484      outbyte(minor, '\r');
485    }
486    outbyte( minor, buffer[ count ] );
487  }
488
489  rw_args->bytes_moved = maximum;
490  return 0;
491}
492
493/*
494 *  IO Control entry point
495 */
496
497rtems_device_driver sh_sci_control(
498  rtems_device_major_number major,
499  rtems_device_minor_number minor,
500  void                    * arg
501)
502{
503  /* Not yet supported */
504  return RTEMS_SUCCESSFUL ;
505}
506
507/*
508 * Termios polled first open
509 */
510static int _sh_sci_poll_first_open(int major, int minor, void *arg)
511{
512    return sh_sci_open(major, minor, arg);
513}
514
515/*
516 * Termios general last close
517 */
518static int _sh_sci_last_close(int major, int minor, void *arg)
519{
520    return sh_sci_close(major, minor, arg);
521}
522
523/*
524 * Termios polled read
525 */
526static int _sh_sci_poll_read(int minor)
527{
528    int value = -1;
529    char ch;
530   
531    if( minor == 0 ){
532        if( rdSCI0( &ch ) )
533            value = (int) ch;
534    }else if( minor == 1 ){
535        if( rdSCI1( &ch ) )
536            value = (int) ch;
537    }
538    return value;
539}
540
541/*
542 * Termios polled write
543 */
544static int _sh_sci_poll_write(int minor, const char *buf, int len)
545{
546    int count;
547   
548    for(count = 0; count < len; count++)
549        outbyte( minor, buf[count] );
550    return count;
551}
552
553/*
554 * Termios set attributes
555 */
556static int _sh_sci_set_attributes( int minor, const struct termios *t)
557{
558    return _sci_set_cflags( &sci_device[ minor ], t->c_cflag);
559}
560
561
562const rtems_termios_callbacks sci_poll_callbacks = {
563    _sh_sci_poll_first_open,    /* FirstOpen*/
564    _sh_sci_last_close,         /* LastClose*/
565    _sh_sci_poll_read,          /* PollRead  */
566    _sh_sci_poll_write,         /* Write */
567    _sh_sci_set_attributes,     /* setAttributes */
568    NULL,                       /* stopRemoteTX */
569    NULL,                       /* StartRemoteTX */
570    0                           /* outputUsesInterrupts */
571};
572
573/* FIXME: not yet supported */
574const rtems_termios_callbacks sci_interrupt_callbacks;
575
576const rtems_termios_callbacks* sh_sci_get_termios_handlers( rtems_boolean poll )
577{
578    return poll ?
579        &sci_poll_callbacks :
580        &sci_interrupt_callbacks;
581}
Note: See TracBrowser for help on using the repository browser.