source: rtems/c/src/libchip/serial/ns16550.c @ 9e162be9

4.115
Last change on this file since 9e162be9 was 229bcca8, checked in by Jennifer Averett <Jennifer.Averett@…>, on 10/18/11 at 18:40:27

2011-10-18 Jennifer Averett <Jennifer.Averett@…>

PR 1917/bsps

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