source: rtems/c/src/lib/libcpu/sh/sh7750/sci/sh4uart.c @ cd53898

4.104.114.84.95
Last change on this file since cd53898 was cd53898, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 14, 2005 at 9:22:10 PM

2005-03-14 Joel Sherrill <joel@…>

  • sh7750/sci/sh4uart.c: Now compiles under gcc 4.x and reformatted.
  • Property mode set to 100644
File size: 23.7 KB
Line 
1/*
2 * Generic UART Serial driver for SH-4 processors
3 *
4 * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed.
5 * Author: Alexandra Kossovsky <sasha@oktet.ru>
6 *
7 *  COPYRIGHT (c) 1989-2000.
8 *  On-Line Applications Research Corporation (OAR).
9 *
10 *  The license and distribution terms for this file may be
11 *  found in the file LICENSE in this distribution or at
12 *
13 *  http://www.rtems.com/license/LICENSE.
14 *
15 *  $Id$
16 *
17 */
18
19#include <rtems.h>
20#include <termios.h>
21#include <rtems/libio.h>
22#include <bsp.h>
23#include "sh/sh4uart.h"
24
25#ifndef SH4_UART_INTERRUPT_LEVEL
26#define SH4_UART_INTERRUPT_LEVEL 4
27#endif
28
29/* Forward function declarations */
30static rtems_isr
31sh4uart1_interrupt_transmit(rtems_vector_number vec);
32static rtems_isr
33sh4uart1_interrupt_receive(rtems_vector_number vec);
34static rtems_isr
35sh4uart2_interrupt_transmit(rtems_vector_number vec);
36static rtems_isr
37sh4uart2_interrupt_receive(rtems_vector_number vec);
38
39/*
40 * sh4uart_init --
41 * This function verifies the input parameters and perform initialization
42 *     of the SH-4 on-chip UART descriptor structure.
43 *
44 * PARAMETERS:
45 *     uart - pointer to the UART channel descriptor structure
46 *     tty - pointer to termios structure
47 *     chn - channel number (SH4_SCI/SH4_SCIF -- 1/2)
48 *     int_driven - interrupt-driven (1) or polled (0) I/O mode
49 *
50 * RETURNS:
51 *     RTEMS_SUCCESSFUL if all parameters are valid, or error code
52 */
53rtems_status_code
54sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven)
55{
56  if (uart == NULL)
57    return RTEMS_INVALID_ADDRESS;
58
59  if ((chn != SH4_SCI) && (chn != SH4_SCIF))
60    return RTEMS_INVALID_NUMBER;
61
62  uart->chn = chn;
63  uart->tty = tty;
64  uart->int_driven = int_driven;
65
66#if 0
67  sh4uart_poll_write(uart, "init", 4);
68#endif
69  return RTEMS_SUCCESSFUL;
70}
71
72/*
73 * sh4uart_get_Pph --
74 *    Get current peripheral module clock.
75 *
76 * PARAMETERS: none;
77 *    Cpu clock is get from CPU_CLOCK_RATE_HZ marco
78 *    (defined in bspopts.h, included from bsp.h)
79 *
80 * RETURNS:
81 *    peripheral module clock in Hz.
82 */
83uint32_t
84sh4uart_get_Pph(void)
85{
86  uint16_t   frqcr = *(volatile uint16_t*)SH7750_FRQCR;
87  uint32_t   Pph = CPU_CLOCK_RATE_HZ;
88
89  switch (frqcr & SH7750_FRQCR_IFC) {
90    case SH7750_FRQCR_IFCDIV1: break;
91    case SH7750_FRQCR_IFCDIV2: Pph *= 2; break;
92    case SH7750_FRQCR_IFCDIV3: Pph *= 3; break;
93    case SH7750_FRQCR_IFCDIV4: Pph *= 4; break;
94    case SH7750_FRQCR_IFCDIV6: Pph *= 6; break;
95    case SH7750_FRQCR_IFCDIV8: Pph *= 8; break;
96    default: /* unreachable */
97      break;
98  }
99
100  switch (frqcr & SH7750_FRQCR_PFC) {
101    case SH7750_FRQCR_PFCDIV2: Pph /= 2; break;
102    case SH7750_FRQCR_PFCDIV3: Pph /= 3; break;
103    case SH7750_FRQCR_PFCDIV4: Pph /= 4; break;
104    case SH7750_FRQCR_PFCDIV6: Pph /= 6; break;
105    case SH7750_FRQCR_PFCDIV8: Pph /= 8; break;
106    default: /* unreachable */
107      break;
108  }
109
110  return Pph;
111}
112
113/*
114 * sh4uart_set_baudrate --
115 *     Program the UART timer to specified baudrate
116 *
117 * PARAMETERS:
118 *     uart - pointer to UART descriptor structure
119 *     baud - termios baud rate (B50, B9600, etc...)
120 *
121 * ALGORITHM:
122 *     see SH7750 Hardware Manual.
123 *
124 * RETURNS:
125 *     none
126 */
127static void
128sh4uart_set_baudrate(sh4uart *uart, speed_t baud)
129{
130  uint32_t   rate;
131  int16_t   div;
132  int n;
133  uint32_t   Pph = sh4uart_get_Pph();
134
135  switch (baud) {
136    case B50:     rate = 50; break;
137    case B75:     rate = 75; break;
138    case B110:    rate = 110; break;
139    case B134:    rate = 134; break;
140    case B150:    rate = 150; break;
141    case B200:    rate = 200; break;
142    case B300:    rate = 300; break;
143    case B600:    rate = 600; break;
144    case B1200:   rate = 1200; break;
145    case B2400:   rate = 2400; break;
146    case B4800:   rate = 4800; break;
147    case B9600:   rate = 9600; break;
148    case B19200:  rate = 19200; break;
149    case B38400:  rate = 38400; break;
150    case B57600:  rate = 57600; break;
151#ifdef B115200
152    case B115200: rate = 115200; break;
153#endif
154#ifdef B230400
155    case B230400: rate = 230400; break;
156#endif
157    default:      rate = 9600; break;
158  }
159
160  for (n = 0; n < 4; n++) {
161    div = Pph / (32 * (1 << (2 * n)) * rate) - 1;
162    if (div < 0x100)
163      break;
164  }
165
166  /* Set default baudrate if specified baudrate is impossible */
167  if (n >= 4)
168    sh4uart_set_baudrate(uart, B9600);
169
170  if ( uart->chn == 1 ) {
171    volatile uint8_t *smr1 = (volatile uint8_t *)SH7750_SCSMR1;
172    *smr1 &= ~SH7750_SCSMR_CKS;
173    *smr1 |= n << SH7750_SCSMR_CKS_S;
174  } else { 
175    volatile uint16_t *smr2 = (volatile uint16_t *)SH7750_SCSMR2;
176    *smr2 &= ~SH7750_SCSMR_CKS;
177    *smr2 |= n << SH7750_SCSMR_CKS_S;
178  }
179
180  SCBRR(uart->chn) = div;
181  /* Wait at least 1 bit interwal */
182  rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));
183}
184
185/*
186 * sh4uart_reset --
187 *     This function perform the hardware initialization of SH-4
188 *     on-chip UART controller using parameters
189 *     filled by the sh4uart_init function.
190 *
191 * PARAMETERS:
192 *     uart - pointer to UART channel descriptor structure
193 *
194 * RETURNS:
195 *     RTEMS_SUCCESSFUL if channel is initialized successfully, error
196 *     code in other case
197 */
198rtems_status_code
199sh4uart_reset(sh4uart *uart)
200{
201  register int chn;
202  register int int_driven;
203  rtems_status_code rc;
204  uint16_t tmp;
205
206  if (uart == NULL)
207    return RTEMS_INVALID_ADDRESS;
208
209  chn = uart->chn;
210  int_driven = uart->int_driven;
211
212  if ( chn == 1 ) {
213    volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
214    volatile uint8_t *smr1 = (volatile uint8_t *)SH7750_SCSMR1;
215    *scr1 = 0x0;       /* Is set properly at the end of this function */
216    *smr1 = 0x0;       /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
217  } else {
218    volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
219    volatile uint16_t *smr2 = (volatile uint16_t *)SH7750_SCSMR2;
220    *scr2 = 0x0;       /* Is set properly at the end of this function */
221    *smr2 = 0x0;       /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
222  }
223
224  if (chn == SH4_SCIF)
225    SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST |
226             SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4;
227
228  if (chn == SH4_SCI)
229    SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO;
230  else
231    SCSPTR2 = SH7750_SCSPTR2_RTSDT;
232
233  if (int_driven) {
234    uint16_t   ipr;
235
236    if (chn == SH4_SCI) {
237      ipr = IPRB;
238      ipr &= ~SH7750_IPRB_SCI1;
239      ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S;
240      IPRB = ipr;
241
242      rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit,
243                                 SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI),
244                                 &uart->old_handler_transmit);
245      if (rc != RTEMS_SUCCESSFUL)
246        return rc;
247
248      rc = rtems_interrupt_catch(sh4uart1_interrupt_receive,
249                                 SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI),
250                                 &uart->old_handler_receive);
251      if (rc != RTEMS_SUCCESSFUL)
252        return rc;
253    } else {
254      ipr = IPRC;
255      ipr &= ~SH7750_IPRC_SCIF;
256      ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S;
257      IPRC = ipr;
258
259      rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit,
260                                 SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI),
261                                 &uart->old_handler_transmit);
262      if (rc != RTEMS_SUCCESSFUL)
263        return rc;
264      rc = rtems_interrupt_catch(sh4uart2_interrupt_receive,
265                                 SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI),
266                                 &uart->old_handler_receive);
267      if (rc != RTEMS_SUCCESSFUL)
268        return rc;
269    }
270    uart->tx_buf = NULL;
271    uart->tx_ptr = uart->tx_buf_len = 0;
272  }
273
274  sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately,
275                                         it is differ to termios default */
276
277  tmp = SH7750_SCSCR_TE | SH7750_SCSCR_RE |
278          (chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) |
279          (int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0);
280
281  if ( chn == 1 ) {
282    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
283    *scr = tmp;
284  } else {
285    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
286    *scr = tmp;
287  }
288
289  return RTEMS_SUCCESSFUL;
290}
291
292/*
293 * sh4uart_disable --
294 *     This function disable the operations on SH-4 UART controller
295 *
296 * PARAMETERS:
297 *     uart - pointer to UART channel descriptor structure
298 *     disable_port - disable receive and transmit on the port
299 *
300 * RETURNS:
301 *     RTEMS_SUCCESSFUL if UART closed successfuly, or error code in
302 *     other case
303 */
304rtems_status_code
305sh4uart_disable(sh4uart *uart, int disable_port)
306{
307  rtems_status_code rc;
308
309  if (disable_port) {
310    if ( uart->chn == 1 ) {
311      volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
312      *scr &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
313    } else {
314      volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
315      *scr &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
316    }
317  }
318
319  if (uart->int_driven) {
320    rc = rtems_interrupt_catch(uart->old_handler_transmit,
321           uart->chn == SH4_SCI ?  SH7750_EVT_SCI_TXI : SH7750_EVT_SCIF_TXI,
322           NULL);
323    if (rc != RTEMS_SUCCESSFUL)
324      return rc;
325    rc = rtems_interrupt_catch(uart->old_handler_receive,
326           uart->chn == SH4_SCI ?  SH7750_EVT_SCI_RXI : SH7750_EVT_SCIF_RXI,
327           NULL);
328    if (rc != RTEMS_SUCCESSFUL)
329      return rc;
330  }
331
332  return RTEMS_SUCCESSFUL;
333}
334
335/*
336 * sh4uart_set_attributes --
337 *     This function parse the termios attributes structure and perform
338 *     the appropriate settings in hardware.
339 *
340 * PARAMETERS:
341 *     uart - pointer to the UART descriptor structure
342 *     t - pointer to termios parameters
343 *
344 * RETURNS:
345 *     RTEMS_SUCCESSFUL
346 */
347rtems_status_code
348sh4uart_set_attributes(sh4uart *uart, const struct termios *t)
349{
350  int level;
351  speed_t baud;
352  uint16_t   smr;
353
354  smr = (uint16_t)(*(uint8_t*)SH7750_SCSMR(uart->chn));
355
356  baud = cfgetospeed(t);
357
358  /* Set flow control XXX*/
359  if ((t->c_cflag & CRTSCTS) != 0) {
360  }
361
362  /* Set character size -- only 7 or 8 bit */
363  switch (t->c_cflag & CSIZE) {
364    case CS5:
365    case CS6:
366    case CS7: smr |= SH7750_SCSMR_CHR_7; break;
367    case CS8: smr &= ~SH7750_SCSMR_CHR_7; break;
368  }
369
370    /* Set number of stop bits */
371  if ((t->c_cflag & CSTOPB) != 0)
372    smr |= SH7750_SCSMR_STOP_2;
373  else
374    smr &= ~SH7750_SCSMR_STOP_2;
375
376  /* Set parity mode */
377  if ((t->c_cflag & PARENB) != 0) {
378    smr |= SH7750_SCSMR_PE;
379    if ((t->c_cflag & PARODD) != 0)
380       smr |= SH7750_SCSMR_PM_ODD;
381    else
382       smr &= ~SH7750_SCSMR_PM_ODD;
383  } else
384    smr &= ~SH7750_SCSMR_PE;
385
386  rtems_interrupt_disable(level);
387  /* wait untill all data is transmitted */
388  /* XXX JOEL says this is broken -- interrupts are OFF so NO ticks  */
389  rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(100));
390
391  if ( uart->chn == 1 ) {
392    volatile uint8_t *scrP = (volatile uint8_t *)SH7750_SCSCR1;
393    volatile uint8_t *smrP = (volatile uint8_t *)SH7750_SCSMR1;
394
395    *scrP &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); /* disable operations */
396    sh4uart_set_baudrate(uart, baud);
397    *smrP = (uint8_t)smr;
398    *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;    /* enable operations */
399  } else {
400    volatile uint16_t *scrP = (volatile uint16_t *)SH7750_SCSCR2;
401    volatile uint16_t *smrP = (volatile uint16_t *)SH7750_SCSMR2;
402
403    *scrP &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); /* disable operations */
404    sh4uart_set_baudrate(uart, baud);
405    *smrP = (uint8_t)smr;
406    *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;    /* enable operations */
407  }
408
409  rtems_interrupt_enable(level);
410
411  return RTEMS_SUCCESSFUL;
412}
413
414/*
415 * sh4uart_handle_error --
416 *     Perfoms error (Overrun, Framing & Parity) handling
417 *
418 * PARAMETERS:
419 *     uart - pointer to UART descriptor structure
420 *
421 * RETURNS:
422 *     nothing
423 */
424void
425sh4uart_handle_error(sh4uart *uart)
426{
427  if (uart->chn == SH4_SCI) {
428    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
429    *scr &= ~(SH7750_SCSSR1_ORER | SH7750_SCSSR1_FER | SH7750_SCSSR1_PER);
430  } else {
431    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
432    *scr &= ~(SH7750_SCSSR2_ER | SH7750_SCSSR2_BRK | SH7750_SCSSR2_FER);
433    *scr &= ~(SH7750_SCLSR2_ORER);
434  }
435}
436
437/*
438 * sh4uart_poll_read --
439 *     This function tried to read character from SH-4 UART and perform
440 *     error handling. When parity or framing error occured, return
441 *     value dependent on termios input mode flags:
442 *         - received character, if IGNPAR == 1
443 *         - 0, if IGNPAR == 0 and PARMRK == 0
444 *         - 0xff and 0x00 on next poll_read invocation, if IGNPAR == 0 and
445 *           PARMRK == 1
446 *
447 * PARAMETERS:
448 *     uart - pointer to UART descriptor structure
449 *
450 * RETURNS:
451 *     code of received character or -1 if no characters received.
452 */
453int
454sh4uart_poll_read(sh4uart *uart)
455{
456  int chn = uart->chn;
457  int error_occured = 0;
458  int parity_error = 0;
459  int break_occured = 0;
460  int ch;
461
462  if (uart->parerr_mark_flag == 1) {
463    uart->parerr_mark_flag = 0;
464    return 0;
465  }
466
467  if (chn == SH4_SCI) {
468    if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
469                 SH7750_SCSSR1_ORER)) != 0) {
470      error_occured = 1;
471      if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
472        parity_error = 1;
473      sh4uart_handle_error(uart);
474    }
475    if ((SCSSR1 & SH7750_SCSSR1_RDRF) == 0)
476      return -1;
477  } else {
478    if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
479                 SH7750_SCSSR2_BRK)) != 0 ||
480            (SCLSR2 & SH7750_SCLSR2_ORER) != 0) {
481      error_occured = 1;
482      if (SCSSR2 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
483        parity_error = 1;
484      if (SCSSR2 & SH7750_SCSSR2_BRK)
485        break_occured = 1;
486      sh4uart_handle_error(uart);
487    }
488    if ((SCSSR2 & SH7750_SCSSR2_RDF) == 0)
489      return -1;
490  }
491
492  if (parity_error && !(uart->c_iflag & IGNPAR)) {
493    if (uart->c_iflag & PARMRK) {
494      uart->parerr_mark_flag = 1;
495      return 0xff;
496    } else
497      return 0;
498  }
499
500  if (break_occured && !(uart->c_iflag & BRKINT)) {
501    if (uart->c_iflag & IGNBRK)
502      return 0;
503    else
504      return 0;   /* XXX -- SIGINT */
505  }
506
507  ch = SCRDR(chn);
508
509  if (uart->chn == SH4_SCI) {
510    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
511    *scr &= ~SH7750_SCSSR1_RDRF;
512  } else {
513    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
514    *scr &= ~SH7750_SCSSR2_RDF;
515  }
516
517  return ch;
518}
519
520/*
521 * sh4uart_poll_write --
522 *     This function transmit buffer byte-by-byte in polling mode.
523 *
524 * PARAMETERS:
525 *     uart - pointer to the UART descriptor structure
526 *     buf - pointer to transmit buffer
527 *     len - transmit buffer length
528 *
529 * RETURNS:
530 *     0
531 */
532int
533sh4uart_poll_write(sh4uart *uart, const char *buf, int len)
534{
535  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
536  volatile uint16_t *ssr2 = (volatile uint16_t *)SH7750_SCSSR2;
537
538  while (len) {
539    if (uart->chn == SH4_SCI) {
540      while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0) {
541          SCTDR1 = *buf++;
542          len--;
543          *ssr1 &= ~SH7750_SCSSR1_TDRE;
544      }
545    } else {
546      while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) {
547        int i;
548        for (i = 0;
549                i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 &
550                    SH7750_SCFCR2_TTRG);
551                i++) {
552            SCTDR2 = *buf++;
553            len--;
554        }
555        while ((SCSSR2 & SH7750_SCSSR2_TDFE) == 0 ||
556                (SCSSR2 & SH7750_SCSSR2_TEND) == 0);
557            *ssr2 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
558      }
559    }
560  }
561  return 0;
562}
563
564/**********************************
565 * Functions to handle interrupts *
566 **********************************/
567/* sh4uart1_interrupt_receive --
568 *     UART interrupt handler routine -- SCI
569 *     Receiving data
570 *
571 * PARAMETERS:
572 *     vec - interrupt vector number
573 *
574 * RETURNS:
575 *     none
576 */
577static rtems_isr
578sh4uart1_interrupt_receive(rtems_vector_number vec)
579{
580  register int bp = 0;
581  char buf[32];
582  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
583
584
585  /* Find UART descriptor from vector number */
586  sh4uart *uart = &sh4_uarts[0];
587
588  while (1) {
589    if ((bp < sizeof(buf) - 1) && ((SCSSR1 & SH7750_SCSSR1_RDRF) != 0)) {
590      /* Receive character and handle frame/parity errors */
591      if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
592                      SH7750_SCSSR1_ORER)) != 0) {
593        if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER)) {
594            if (!(uart->c_iflag & IGNPAR)) {
595              if (uart->c_iflag & PARMRK) {
596                buf[bp++] = 0xff;
597                buf[bp++] = 0x00;
598              } else
599                buf[bp++] = 0x00;
600            } else
601              buf[bp++] = SCRDR1;
602          }
603          sh4uart_handle_error(uart);
604      } else
605          buf[bp++] = SCRDR1;
606      *ssr1 &= ~SH7750_SCSSR1_RDRF;
607    } else {
608      if (bp != 0)
609        rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
610      break;
611    }
612  }
613}
614
615/* sh4uart2_interrupt_receive --
616 *     UART interrupt handler routine -- SCIF
617 *     Receiving data
618 *
619 * PARAMETERS:
620 *     vec - interrupt vector number
621 *
622 * RETURNS:
623 *     none
624 */
625static rtems_isr
626sh4uart2_interrupt_receive(rtems_vector_number vec)
627{
628  register int bp = 0;
629  char buf[32];
630  volatile uint16_t *ssr2 = (volatile uint16_t *)SH7750_SCSSR2;
631
632
633  /* Find UART descriptor from vector number */
634  sh4uart *uart = &sh4_uarts[1];
635
636  while (1) {
637    if ((bp < sizeof(buf) - 1) && ((SCSSR2 & SH7750_SCSSR2_RDF) != 0)) {
638      if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
639                      SH7750_SCSSR2_BRK)) != 0 ||
640              (SH7750_SCLSR2 & SH7750_SCLSR2_ORER) != 0) {
641        if (SCSSR2 & SH7750_SCSSR2_ER) {
642          if (!(uart->c_iflag & IGNPAR)) {
643            if (uart->c_iflag & PARMRK) {
644              buf[bp++] = 0xff;
645              buf[bp++] = 0x00;
646            } else
647              buf[bp++] = 0x00;
648          } else
649              buf[bp++] = SCRDR1;
650        }
651
652        if (SCSSR2 & SH7750_SCSSR2_BRK) {
653          if (uart->c_iflag & IGNBRK)
654            buf[bp++] = 0x00;
655          else
656            buf[bp++] = 0x00;   /* XXX -- SIGINT */
657        }
658
659        sh4uart_handle_error(uart);
660      } else
661        buf[bp++] = SCRDR1;
662      *ssr2 &= ~SH7750_SCSSR2_RDF;
663    } else {
664      if (bp != 0)
665        rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
666      break;
667    }
668  }
669}
670
671
672/* sh4uart1_interrupt_transmit --
673 *     UART interrupt handler routine -- SCI
674 *     It continues transmit data when old part of data is transmitted
675 *
676 * PARAMETERS:
677 *     vec - interrupt vector number
678 *
679 * RETURNS:
680 *     none
681 */
682static rtems_isr
683sh4uart1_interrupt_transmit(rtems_vector_number vec)
684{
685  volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
686  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
687
688  /* Find UART descriptor from vector number */
689  sh4uart *uart = &sh4_uarts[0];
690
691  if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) {
692    while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0 &&
693            uart->tx_ptr < uart->tx_buf_len) {
694        SCTDR1 = uart->tx_buf[uart->tx_ptr++];
695        *ssr1 &= ~SH7750_SCSSR1_TDRE;
696    }
697  } else {
698    register int dequeue = uart->tx_buf_len;
699
700    uart->tx_buf = NULL;
701    uart->tx_ptr = uart->tx_buf_len = 0;
702
703    /* Disable interrupts while we do not have any data to transmit */
704    *scr1 &= ~SH7750_SCSCR_TIE;
705
706    rtems_termios_dequeue_characters(uart->tty, dequeue);
707  }
708}
709
710/* sh4uart2_interrupt_transmit --
711 *     UART interrupt handler routine -- SCI
712 *     It continues transmit data when old part of data is transmitted
713 *
714 * PARAMETERS:
715 *     vec - interrupt vector number
716 *
717 * RETURNS:
718 *     none
719 */
720static rtems_isr
721sh4uart2_interrupt_transmit(rtems_vector_number vec)
722{
723  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
724  volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
725
726  /* Find UART descriptor from vector number */
727  sh4uart *uart = &sh4_uarts[1];
728
729  if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) {
730    while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) {
731        int i;
732        for (i = 0;
733             i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 & SH7750_SCFCR2_TTRG);
734             i++)
735          SCTDR2 = uart->tx_buf[uart->tx_ptr++];
736        while ((SCSSR1 & SH7750_SCSSR1_TDRE) == 0 ||
737                (SCSSR1 & SH7750_SCSSR1_TEND) == 0);
738        *ssr1 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
739    }
740  } else {
741    register int dequeue = uart->tx_buf_len;
742
743    uart->tx_buf = NULL;
744    uart->tx_ptr = uart->tx_buf_len = 0;
745
746    /* Disable interrupts while we do not have any data to transmit */
747    *scr2 &= ~SH7750_SCSCR_TIE;
748
749    rtems_termios_dequeue_characters(uart->tty, dequeue);
750  }
751}
752
753/* sh4uart_interrupt_write --
754 *     This function initiate transmitting of the buffer in interrupt mode.
755 *
756 * PARAMETERS:
757 *     uart - pointer to the UART descriptor structure
758 *     buf - pointer to transmit buffer
759 *     len - transmit buffer length
760 *
761 * RETURNS:
762 *     0
763 */
764rtems_status_code
765sh4uart_interrupt_write(sh4uart *uart, const char *buf, int len)
766{
767  volatile uint8_t  *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
768  volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
769  int level;
770
771  while ((SCSSR1 & SH7750_SCSSR1_TEND) == 0);
772
773  rtems_interrupt_disable(level);
774
775  uart->tx_buf = buf;
776  uart->tx_buf_len = len;
777  uart->tx_ptr = 0;
778
779  if (uart->chn == SH4_SCI)
780    *scr1 |= SH7750_SCSCR_TIE;
781  else
782    *scr2 |= SH7750_SCSCR_TIE;
783
784  rtems_interrupt_enable(level);
785
786  return RTEMS_SUCCESSFUL;
787}
788
789/* sh4uart_stop_remote_tx --
790 *     This function stop data flow from remote device.
791 *
792 * PARAMETERS:
793 *     uart - pointer to the UART descriptor structure
794 *
795 * RETURNS:
796 *     RTEMS_SUCCESSFUL
797 */
798rtems_status_code
799sh4uart_stop_remote_tx(sh4uart *uart)
800{
801  if ( uart->chn == 1 ) {
802    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
803    *scr &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
804  } else {
805    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
806    *scr &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
807  }
808
809  return RTEMS_SUCCESSFUL;
810}
811
812/* sh4uart_start_remote_tx --
813 *     This function resume data flow from remote device.
814 *
815 * PARAMETERS:
816 *     uart - pointer to the UART descriptor structure
817 *
818 * RETURNS:
819 *     RTEMS_SUCCESSFUL
820 */
821rtems_status_code
822sh4uart_start_remote_tx(sh4uart *uart)
823{
824  if ( uart->chn == 1 ) {
825    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
826    *scr |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
827  } else {
828    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
829    *scr |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
830  }
831
832  return RTEMS_SUCCESSFUL;
833}
834
835#ifdef SH4_WITH_IPL
836/*********************************
837 * Functions for SH-IPL gdb stub *
838 *********************************/
839
840/*
841 * ipl_finish --
842 *     Says gdb that program finished to get out from it.
843 */
844extern void ipl_finish(void);
845asm(
846"   .global _ipl_finish\n"
847"_ipl_finish:\n"
848"   mov.l   __ipl_finish_value, r0\n"
849"   trapa   #0x3f\n"
850"   nop\n"
851"   rts\n"
852"   nop\n"
853"   .align 4\n"
854"__ipl_finish_value:\n"
855"   .long   255"
856);
857
858extern int ipl_serial_input(int poll_count);
859asm(
860"    .global _ipl_serial_input\n"
861"_ipl_serial_input:\n"
862"    mov  #1,r0\n"
863"    trapa #0x3f\n"
864"    nop\n"
865"    rts\n"
866"    nop\n");
867
868extern void ipl_serial_output(const char *buf, int len);
869asm (
870"    .global _ipl_serial_output\n"
871"_ipl_serial_output:\n"
872"    mov  #0,r0\n"
873"    trapa #0x3f\n"
874"    nop\n"
875"    rts\n"
876"    nop\n");
877
878/* ipl_console_poll_read --
879 *     poll read operation for simulator console through ipl mechanism.
880 *
881 * PARAMETERS:
882 *     minor - minor device number
883 *
884 * RETURNS:
885 *     character code red from UART, or -1 if there is no characters
886 *     available
887 */
888int
889ipl_console_poll_read(int minor)
890{
891    unsigned char buf;
892    buf = ipl_serial_input(0x100000);
893    return buf;
894}
895
896/* ipl_console_poll_write --
897 *     wrapper for polling mode write function
898 *
899 * PARAMETERS:
900 *     minor - minor device number
901 *     buf - output buffer
902 *     len - output buffer length
903 *
904 * RETURNS:
905 *     result code (0)
906 */
907int
908ipl_console_poll_write(int minor, const char *buf, int len)
909{
910  int c;
911  while (len > 0) {
912    c = (len < 64 ? len : 64);
913    ipl_serial_output(buf, c);
914    len -= c;
915    buf += c;
916  }
917  return 0;
918}
919#endif
Note: See TracBrowser for help on using the repository browser.