source: rtems/c/src/libchip/serial/ns16550.c @ ae55da72

4.115
Last change on this file since ae55da72 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 19.4 KB
Line 
1/**
2 *  @file
3 * 
4 *  This file contains the TTY driver for the National Semiconductor NS16550.
5 *
6 *  This part is widely cloned and second sourced.  It is found in a number
7 *  of "Super IO" controllers.
8 *
9 *  This driver uses the termios pseudo driver.
10 */
11
12/*
13 *  COPYRIGHT (c) 1998 by Radstone Technology
14 *
15 *  THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
16 *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
17 *  IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
18 *  AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
19 *
20 *  You are hereby granted permission to use, copy, modify, and distribute
21 *  this file, provided that this notice, plus the above copyright notice
22 *  and disclaimer, appears in all copies. Radstone Technology will provide
23 *  no support for this code.
24 *
25 *  COPYRIGHT (c) 1989-2012.
26 *  On-Line Applications Research Corporation (OAR).
27 *
28 *  The license and distribution terms for this file may be
29 *  found in the file LICENSE in this distribution or at
30 *  http://www.rtems.com/license/LICENSE.
31 */
32
33#include <stdlib.h>
34
35#include <rtems.h>
36#include <rtems/libio.h>
37#include <rtems/ringbuf.h>
38#include <rtems/bspIo.h>
39#include <rtems/termiostypes.h>
40
41#include <libchip/serial.h>
42#include <libchip/sersupp.h>
43
44#include <bsp.h>
45
46#include "ns16550_p.h"
47
48#if defined(BSP_FEATURE_IRQ_EXTENSION)
49  #include <bsp/irq.h>
50#elif defined(BSP_FEATURE_IRQ_LEGACY)
51  #include <bsp/irq.h>
52#elif defined(__PPC__) || defined(__i386__)
53  #include <bsp/irq.h>
54  #define BSP_FEATURE_IRQ_LEGACY
55  #ifdef BSP_SHARED_HANDLER_SUPPORT
56    #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
57  #endif
58#endif
59
60/*
61 * Flow control is only supported when using interrupts
62 */
63
64console_flow ns16550_flow_RTSCTS = {
65  ns16550_negate_RTS,             /* deviceStopRemoteTx */
66  ns16550_assert_RTS              /* deviceStartRemoteTx */
67};
68
69console_flow ns16550_flow_DTRCTS = {
70  ns16550_negate_DTR,             /* deviceStopRemoteTx */
71  ns16550_assert_DTR              /* deviceStartRemoteTx */
72};
73
74console_fns ns16550_fns = {
75  libchip_serial_default_probe,   /* deviceProbe */
76  ns16550_open,                   /* deviceFirstOpen */
77  ns16550_close,                  /* deviceLastClose */
78  NULL,                           /* deviceRead */
79  ns16550_write_support_int,      /* deviceWrite */
80  ns16550_init,                   /* deviceInitialize */
81  ns16550_write_polled,           /* deviceWritePolled */
82  ns16550_set_attributes,         /* deviceSetAttributes */
83  true                            /* deviceOutputUsesInterrupts */
84};
85
86console_fns ns16550_fns_polled = {
87  libchip_serial_default_probe,        /* deviceProbe */
88  ns16550_open,                        /* deviceFirstOpen */
89  ns16550_close,                       /* deviceLastClose */
90  ns16550_inbyte_nonblocking_polled,   /* deviceRead */
91  ns16550_write_support_polled,        /* deviceWrite */
92  ns16550_init,                        /* deviceInitialize */
93  ns16550_write_polled,                /* deviceWritePolled */
94  ns16550_set_attributes,              /* deviceSetAttributes */
95  false                                /* deviceOutputUsesInterrupts */
96};
97
98/*
99 *  ns16550_init
100 */
101
102NS16550_STATIC void ns16550_init(int minor)
103{
104  uintptr_t               pNS16550;
105  uint8_t                 ucDataByte;
106  uint32_t                ulBaudDivisor;
107  ns16550_context        *pns16550Context;
108  setRegister_f           setReg;
109  getRegister_f           getReg;
110  console_tbl             *c = Console_Port_Tbl [minor];
111
112  pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));
113
114  if (pns16550Context == NULL) {
115    printk( "%s: Error: Not enough memory\n", __func__);
116    rtems_fatal_error_occurred( 0xdeadbeef);
117  }
118
119  Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context;
120  pns16550Context->ucModemCtrl=SP_MODEM_IRQ;
121
122  pNS16550 = c->ulCtrlPort1;   
123  setReg   = c->setRegister;
124  getReg   = c->getRegister;
125
126  /* Clear the divisor latch, clear all interrupt enables,
127   * and reset and
128   * disable the FIFO's.
129   */
130
131  (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0);
132  ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR );
133
134  /* Set the divisor latch and set the baud rate. */
135
136  ulBaudDivisor = NS16550_Baud(
137    (uint32_t) c->ulClock,
138    (uint32_t) ((uintptr_t)c->pDeviceParams)
139  );
140  ucDataByte = SP_LINE_DLAB;
141  (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
142
143  /* XXX */
144  (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU));
145  (*setReg)(
146    pNS16550,NS16550_INTERRUPT_ENABLE,
147    (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU )
148  );
149
150  /* Clear the divisor latch and set the character size to eight bits */
151  /* with one stop bit and no parity checking. */
152  ucDataByte = EIGHT_BITS;
153  (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
154
155  /* Enable and reset transmit and receive FIFOs. TJA     */
156  ucDataByte = SP_FIFO_ENABLE;
157  (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
158
159  ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
160  (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
161
162  ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR);
163
164  /* Set data terminal ready. */
165  /* And open interrupt tristate line */
166  (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
167
168  (*getReg)(pNS16550, NS16550_LINE_STATUS );
169  (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER );
170}
171
172/*
173 *  ns16550_open
174 */
175
176NS16550_STATIC int ns16550_open(
177  int major,
178  int minor,
179  void *arg
180)
181{
182  rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
183  struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
184  console_tbl *c = Console_Port_Tbl [minor];
185  console_data *d = &Console_Port_Data [minor];
186
187  d->termios_data = tty;
188
189  /* Assert DTR */
190  if (c->pDeviceFlow != &ns16550_flow_DTRCTS) {
191    ns16550_assert_DTR( minor);
192  }
193
194  /* Set initial baud */
195  rtems_termios_set_initial_baud( tty, (intptr_t) c->pDeviceParams);
196
197  if (c->pDeviceFns->deviceOutputUsesInterrupts) {
198    ns16550_initialize_interrupts( minor);
199    ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
200  }
201
202  return RTEMS_SUCCESSFUL;
203}
204
205/*
206 *  ns16550_close
207 */
208
209NS16550_STATIC int ns16550_close(
210  int      major,
211  int      minor,
212  void    * arg
213)
214{
215  console_tbl *c = Console_Port_Tbl [minor];
216
217  /*
218   * Negate DTR
219   */
220  if (c->pDeviceFlow != &ns16550_flow_DTRCTS) {
221    ns16550_negate_DTR(minor);
222  }
223
224  ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR);
225
226  if (c->pDeviceFns->deviceOutputUsesInterrupts) {
227    ns16550_cleanup_interrupts(minor);
228  }
229
230  return(RTEMS_SUCCESSFUL);
231}
232
233/**
234 * @brief Polled write for NS16550.
235 */
236void ns16550_outch_polled(console_tbl *c, char out)
237{
238  uintptr_t port = c->ulCtrlPort1;
239  getRegister_f get = c->getRegister;
240  setRegister_f set = c->setRegister;
241  uint32_t status = 0;
242  rtems_interrupt_level level;
243
244  /* Save port interrupt mask */
245  uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE);
246
247  /* Disable port interrupts */
248  ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR);
249
250  while (true) {
251    /* Try to transmit the character in a critical section */
252    rtems_interrupt_disable( level);
253
254    /* Read the transmitter holding register and check it */
255    status = get( port, NS16550_LINE_STATUS);
256    if ((status & SP_LSR_THOLD) != 0) {
257      /* Transmit character */
258      set( port, NS16550_TRANSMIT_BUFFER, out);
259
260      /* Finished */
261      rtems_interrupt_enable( level);
262      break;
263    } else {
264      rtems_interrupt_enable( level);
265    }
266
267    /* Wait for transmitter holding register to be empty */
268    do {
269      status = get( port, NS16550_LINE_STATUS);
270    } while ((status & SP_LSR_THOLD) == 0);
271  }
272
273  /* Restore port interrupt mask */
274  set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask);
275}
276
277NS16550_STATIC void ns16550_write_polled(int minor, char out)
278{
279  console_tbl *c = Console_Port_Tbl [minor];
280 
281  ns16550_outch_polled( c, out );
282}
283
284/*
285 * These routines provide control of the RTS and DTR lines
286 */
287
288/*
289 *  ns16550_assert_RTS
290 */
291
292NS16550_STATIC int ns16550_assert_RTS(int minor)
293{
294  uint32_t                pNS16550;
295  uint32_t                Irql;
296  ns16550_context        *pns16550Context;
297  setRegister_f           setReg;
298
299  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
300
301  pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
302  setReg   = Console_Port_Tbl[minor]->setRegister;
303
304  /*
305   * Assert RTS
306   */
307  rtems_interrupt_disable(Irql);
308  pns16550Context->ucModemCtrl|=SP_MODEM_RTS;
309  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
310  rtems_interrupt_enable(Irql);
311  return 0;
312}
313
314/*
315 *  ns16550_negate_RTS
316 */
317
318NS16550_STATIC int ns16550_negate_RTS(int minor)
319{
320  uint32_t                pNS16550;
321  uint32_t                Irql;
322  ns16550_context        *pns16550Context;
323  setRegister_f           setReg;
324
325  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
326
327  pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
328  setReg   = Console_Port_Tbl[minor]->setRegister;
329
330  /*
331   * Negate RTS
332   */
333  rtems_interrupt_disable(Irql);
334  pns16550Context->ucModemCtrl&=~SP_MODEM_RTS;
335  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
336  rtems_interrupt_enable(Irql);
337  return 0;
338}
339
340/*
341 * These flow control routines utilise a connection from the local DTR
342 * line to the remote CTS line
343 */
344
345/*
346 *  ns16550_assert_DTR
347 */
348
349NS16550_STATIC int ns16550_assert_DTR(int minor)
350{
351  uint32_t                pNS16550;
352  uint32_t                Irql;
353  ns16550_context        *pns16550Context;
354  setRegister_f           setReg;
355
356  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
357
358  pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
359  setReg   = Console_Port_Tbl[minor]->setRegister;
360
361  /*
362   * Assert DTR
363   */
364  rtems_interrupt_disable(Irql);
365  pns16550Context->ucModemCtrl|=SP_MODEM_DTR;
366  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
367  rtems_interrupt_enable(Irql);
368  return 0;
369}
370
371/*
372 *  ns16550_negate_DTR
373 */
374
375NS16550_STATIC int ns16550_negate_DTR(int minor)
376{
377  uint32_t                pNS16550;
378  uint32_t                Irql;
379  ns16550_context        *pns16550Context;
380  setRegister_f           setReg;
381
382  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
383
384  pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
385  setReg   = Console_Port_Tbl[minor]->setRegister;
386
387  /*
388   * Negate DTR
389   */
390  rtems_interrupt_disable(Irql);
391  pns16550Context->ucModemCtrl&=~SP_MODEM_DTR;
392  (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
393  rtems_interrupt_enable(Irql);
394  return 0;
395}
396
397/*
398 *  ns16550_set_attributes
399 *
400 *  This function sets the channel to reflect the requested termios
401 *  port settings.
402 */
403
404NS16550_STATIC int ns16550_set_attributes(
405  int                   minor,
406  const struct termios *t
407)
408{
409  uint32_t                pNS16550;
410  uint32_t                ulBaudDivisor;
411  uint8_t                 ucLineControl;
412  uint32_t                baud_requested;
413  setRegister_f           setReg;
414  getRegister_f           getReg;
415  uint32_t                Irql;
416
417  pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
418  setReg   = Console_Port_Tbl[minor]->setRegister;
419  getReg   = Console_Port_Tbl[minor]->getRegister;
420
421  /*
422   *  Calculate the baud rate divisor
423   */
424
425  baud_requested = t->c_cflag & CBAUD;
426  if (!baud_requested)
427    baud_requested = B9600;              /* default to 9600 baud */
428
429  ulBaudDivisor = NS16550_Baud(
430    (uint32_t) Console_Port_Tbl[minor]->ulClock,
431    rtems_termios_baud_to_number(baud_requested)
432  );
433
434  ucLineControl = 0;
435
436  /*
437   *  Parity
438   */
439
440  if (t->c_cflag & PARENB) {
441    ucLineControl |= SP_LINE_PAR;
442    if (!(t->c_cflag & PARODD))
443      ucLineControl |= SP_LINE_ODD;
444  }
445
446  /*
447   *  Character Size
448   */
449
450  if (t->c_cflag & CSIZE) {
451    switch (t->c_cflag & CSIZE) {
452      case CS5:  ucLineControl |= FIVE_BITS;  break;
453      case CS6:  ucLineControl |= SIX_BITS;   break;
454      case CS7:  ucLineControl |= SEVEN_BITS; break;
455      case CS8:  ucLineControl |= EIGHT_BITS; break;
456    }
457  } else {
458    ucLineControl |= EIGHT_BITS;               /* default to 9600,8,N,1 */
459  }
460
461  /*
462   *  Stop Bits
463   */
464
465  if (t->c_cflag & CSTOPB) {
466    ucLineControl |= SP_LINE_STOP;              /* 2 stop bits */
467  } else {
468    ;                                           /* 1 stop bit */
469  }
470
471  /*
472   *  Now actually set the chip
473   */
474
475  rtems_interrupt_disable(Irql);
476
477    /*
478     *  Set the baud rate
479     */
480
481    (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
482    /* XXX are these registers right? */
483    (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
484    (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
485
486    /*
487     *  Now write the line control
488     */
489    (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
490
491  rtems_interrupt_enable(Irql);
492
493  return 0;
494}
495
496#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
497
498/**
499 * @brief Process interrupt.
500 */
501NS16550_STATIC void ns16550_process( int minor)
502{
503  console_tbl *c = Console_Port_Tbl [minor];
504  console_data *d = &Console_Port_Data [minor];
505  ns16550_context *ctx = d->pDeviceContext;
506  uint32_t port = c->ulCtrlPort1;
507  getRegister_f get = c->getRegister;
508  int i = 0;
509  char buf [SP_FIFO_SIZE];
510
511  /* Iterate until no more interrupts are pending */
512  do {
513    /* Fetch received characters */
514    for (i = 0; i < SP_FIFO_SIZE; ++i) {
515      if ((get( port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) {
516        buf [i] = (char) get(port, NS16550_RECEIVE_BUFFER);
517      } else {
518        break;
519      }
520    }
521
522    /* Enqueue fetched characters */
523    rtems_termios_enqueue_raw_characters( d->termios_data, buf, i);
524
525    /* Check if we can dequeue transmitted characters */
526    if (ctx->transmitFifoChars > 0
527        && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) {
528      unsigned chars = ctx->transmitFifoChars;
529
530      /*
531       * We finished the transmission, so clear the number of characters in the
532       * transmit FIFO.
533       */
534      ctx->transmitFifoChars = 0;
535
536      /* Dequeue transmitted characters */
537      if (rtems_termios_dequeue_characters( d->termios_data, chars) == 0) {
538        /* Nothing to do */
539        d->bActive = false;
540        ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
541      }
542    }
543  } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
544}
545#endif
546
547/**
548 * @brief Transmits up to @a len characters from @a buf.
549 *
550 * This routine is invoked either from task context with disabled interrupts to
551 * start a new transmission process with exactly one character in case of an
552 * idle output state or from the interrupt handler to refill the transmitter.
553 *
554 * Returns always zero.
555 */
556NS16550_STATIC ssize_t ns16550_write_support_int(
557  int minor,
558  const char *buf,
559  size_t len
560)
561{
562  console_tbl *c = Console_Port_Tbl [minor];
563  console_data *d = &Console_Port_Data [minor];
564  ns16550_context *ctx = d->pDeviceContext;
565  uint32_t port = c->ulCtrlPort1;
566  setRegister_f set = c->setRegister;
567  int i = 0;
568  int out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len;
569
570  for (i = 0; i < out; ++i) {
571    set( port, NS16550_TRANSMIT_BUFFER, buf [i]);
572  }
573
574  if (len > 0) {
575    ctx->transmitFifoChars = out;
576    d->bActive = true;
577    ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR);
578  }
579
580  return 0;
581}
582
583/*
584 *  ns16550_enable_interrupts
585 *
586 *  This routine initializes the port to have the specified interrupts masked.
587 */
588NS16550_STATIC void ns16550_enable_interrupts(
589  console_tbl *c,
590  int         mask
591)
592{
593  uint32_t       pNS16550;
594  setRegister_f  setReg;
595
596  pNS16550 = c->ulCtrlPort1;
597  setReg   = c->setRegister;
598
599  (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);
600}
601
602#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
603  NS16550_STATIC rtems_isr ns16550_isr(void *arg)
604  {
605    int minor = (int) arg;
606
607    ns16550_process( minor);
608  }
609#endif
610
611/*
612 *  ns16550_initialize_interrupts
613 *
614 *  This routine initializes the port to operate in interrupt driver mode.
615 */
616NS16550_STATIC void ns16550_initialize_interrupts( int minor)
617{
618#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
619  console_tbl *c = Console_Port_Tbl [minor];
620#endif
621  console_data *d = &Console_Port_Data [minor];
622
623  d->bActive = false;
624
625  #ifdef BSP_FEATURE_IRQ_EXTENSION
626    {
627      rtems_status_code sc = RTEMS_SUCCESSFUL;
628      sc = rtems_interrupt_handler_install(
629        c->ulIntVector,
630        "NS16550",
631        RTEMS_INTERRUPT_SHARED,
632        ns16550_isr,
633        (void *) minor
634      );
635      if (sc != RTEMS_SUCCESSFUL) {
636        /* FIXME */
637        printk( "%s: Error: Install interrupt handler\n", __func__);
638        rtems_fatal_error_occurred( 0xdeadbeef);
639      }
640    }
641  #elif defined(BSP_FEATURE_IRQ_LEGACY)
642    {
643      int rv = 0;
644      #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
645        rtems_irq_connect_data cd = {
646          c->ulIntVector,
647          ns16550_isr,
648          (void *) minor,
649          NULL,
650          NULL,
651          NULL,
652          NULL
653        };
654        rv = BSP_install_rtems_shared_irq_handler( &cd);
655      #else
656        rtems_irq_connect_data cd = {
657          c->ulIntVector,
658          ns16550_isr,
659          (void *) minor,
660          NULL,
661          NULL,
662          NULL
663        };
664        rv = BSP_install_rtems_irq_handler( &cd);
665      #endif
666      if (rv == 0) {
667        /* FIXME */
668        printk( "%s: Error: Install interrupt handler\n", __func__);
669        rtems_fatal_error_occurred( 0xdeadbeef);
670      }
671    }
672  #endif
673}
674
675NS16550_STATIC void ns16550_cleanup_interrupts(int minor)
676{
677  #if defined(BSP_FEATURE_IRQ_EXTENSION)
678    rtems_status_code sc = RTEMS_SUCCESSFUL;
679    console_tbl *c = Console_Port_Tbl [minor];
680    sc = rtems_interrupt_handler_remove(
681      c->ulIntVector,
682      ns16550_isr,
683      (void *) minor
684    );
685    if (sc != RTEMS_SUCCESSFUL) {
686      /* FIXME */
687      printk("%s: Error: Remove interrupt handler\n", __func__);
688      rtems_fatal_error_occurred(0xdeadbeef);
689    }
690  #elif defined(BSP_FEATURE_IRQ_LEGACY)
691    int rv = 0;
692    console_tbl *c = Console_Port_Tbl [minor];
693    rtems_irq_connect_data cd = {
694      .name = c->ulIntVector,
695      .hdl = ns16550_isr,
696      .handle = (void *) minor
697    };
698    rv = BSP_remove_rtems_irq_handler(&cd);
699    if (rv == 0) {
700      /* FIXME */
701      printk("%s: Error: Remove interrupt handler\n", __func__);
702      rtems_fatal_error_occurred(0xdeadbeef);
703    }
704  #endif
705}
706
707/*
708 *  ns16550_write_support_polled
709 *
710 *  Console Termios output entry point.
711 *
712 */
713
714NS16550_STATIC ssize_t ns16550_write_support_polled(
715  int         minor,
716  const char *buf,
717  size_t      len
718)
719{
720  int nwrite = 0;
721
722  /*
723   * poll each byte in the string out of the port.
724   */
725  while (nwrite < len) {
726    /*
727     * transmit character
728     */
729    ns16550_write_polled(minor, *buf++);
730    nwrite++;
731  }
732
733  /*
734   * return the number of bytes written.
735   */
736  return nwrite;
737}
738
739/*
740 *  Debug gets() support
741 */
742int ns16550_inch_polled(
743  console_tbl *c
744)
745{
746  uint32_t             pNS16550;
747  unsigned char        ucLineStatus;
748  uint8_t              cChar;
749  getRegister_f        getReg;
750
751  pNS16550 = c->ulCtrlPort1;
752  getReg   = c->getRegister;
753
754  ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
755  if (ucLineStatus & SP_LSR_RDY) {
756    cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
757    return (int)cChar;
758  }
759  return -1;
760}
761
762/*
763 *  ns16550_inbyte_nonblocking_polled
764 *
765 *  Console Termios polling input entry point.
766 */
767NS16550_STATIC int ns16550_inbyte_nonblocking_polled(int minor)
768{
769  console_tbl *c = Console_Port_Tbl [minor];
770 
771  return ns16550_inch_polled( c );
772}
Note: See TracBrowser for help on using the repository browser.