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

4.115
Last change on this file since a4097fdb was 36cfb55f, checked in by Joel Sherrill <joel.sherrill@…>, on 11/09/11 at 20:51:01

2011-11-09 Jennifer Averett <jennifer.averett@…>

PR 1934/bsps

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