source: rtems/c/src/libchip/serial/ns16550.c @ 69be08ee

4.104.115
Last change on this file since 69be08ee was 69be08ee, checked in by Ralf Corsepius <ralf.corsepius@…>, on 12/17/08 at 12:48:04

2008-12-17 Ralf Corsépius <ralf.corsepius@…>

  • libchip/serial/ns16550.c: Add CVS-Id. Fix #define mess.
  • Property mode set to 100644
File size: 17.5 KB
RevLine 
[0737710]1/*
[aa0da6b]2 *  This file contains the TTY driver for the National Semiconductor NS16550.
3 *
[a3d3d9a]4 *  This part is widely cloned and second sourced.  It is found in a number
[aa0da6b]5 *  of "Super IO" controllers.
[0737710]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 */
[69be08ee]22 
23/*
24 * $Id$
25 */
[0737710]26
[e97e0e0]27#include <stdlib.h>
28
[0737710]29#include <rtems.h>
30#include <rtems/libio.h>
[4caeb10]31#include <rtems/ringbuf.h>
[e97e0e0]32#include <rtems/bspIo.h>
[0737710]33
[ee3b242b]34#include <libchip/serial.h>
[7e05b53]35#include <libchip/sersupp.h>
[e97e0e0]36
[8c0cab0]37#include <bsp.h>
[0737710]38
[8c0cab0]39#include "ns16550_p.h"
[fc9cbcf3]40
[e97e0e0]41#ifdef BSP_FEATURE_IRQ_EXTENSION
[8c0cab0]42  #include <bsp/irq.h>
[e97e0e0]43#elif defined BSP_FEATURE_IRQ_LEGACY
[8c0cab0]44  #include <bsp/irq.h>
[e97e0e0]45#elif defined __PPC__
[8c0cab0]46  #include <bsp/irq.h>
[e97e0e0]47  #define BSP_FEATURE_IRQ_LEGACY
48  #ifdef BSP_SHARED_HANDLER_SUPPORT
49    #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
50  #endif
51#endif
52
[0737710]53/*
54 * Flow control is only supported when using interrupts
55 */
[cae0504]56
57console_flow ns16550_flow_RTSCTS = {
[0737710]58  ns16550_negate_RTS,             /* deviceStopRemoteTx */
59  ns16550_assert_RTS              /* deviceStartRemoteTx */
60};
61
[cae0504]62console_flow ns16550_flow_DTRCTS = {
[0737710]63  ns16550_negate_DTR,             /* deviceStopRemoteTx */
64  ns16550_assert_DTR              /* deviceStartRemoteTx */
65};
66
[cae0504]67console_fns ns16550_fns = {
[064b9be]68  libchip_serial_default_probe,   /* deviceProbe */
[0737710]69  ns16550_open,                   /* deviceFirstOpen */
[70a9451]70  NULL,                           /* deviceLastClose */
[0737710]71  NULL,                           /* deviceRead */
72  ns16550_write_support_int,      /* deviceWrite */
73  ns16550_initialize_interrupts,  /* deviceInitialize */
74  ns16550_write_polled,           /* deviceWritePolled */
[8739322]75  ns16550_set_attributes,         /* deviceSetAttributes */
[6640459d]76  true                            /* deviceOutputUsesInterrupts */
[0737710]77};
78
[cae0504]79console_fns ns16550_fns_polled = {
[064b9be]80  libchip_serial_default_probe,        /* deviceProbe */
[0737710]81  ns16550_open,                        /* deviceFirstOpen */
82  ns16550_close,                       /* deviceLastClose */
83  ns16550_inbyte_nonblocking_polled,   /* deviceRead */
84  ns16550_write_support_polled,        /* deviceWrite */
85  ns16550_init,                        /* deviceInitialize */
86  ns16550_write_polled,                /* deviceWritePolled */
[8739322]87  ns16550_set_attributes,              /* deviceSetAttributes */
[6640459d]88  false                                /* deviceOutputUsesInterrupts */
[0737710]89};
90
[cae0504]91/*
92 *  ns16550_init
93 */
94
[27045a82]95NS16550_STATIC void ns16550_init(int minor)
[0737710]96{
[ee4f57d]97  uint32_t                pNS16550;
98  uint8_t                 ucTrash;
99  uint8_t                 ucDataByte;
100  uint32_t                ulBaudDivisor;
[0737710]101  ns16550_context        *pns16550Context;
102  setRegister_f           setReg;
103  getRegister_f           getReg;
104
105  pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));
106
[e97e0e0]107  if (pns16550Context == NULL) {
108    printk( "%s: Error: Not enough memory\n", __func__);
109    rtems_fatal_error_occurred( 0xdeadbeef);
110  }
111
[0737710]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);
[70a9451]125  ns16550_enable_interrupts(minor, NS16550_DISABLE_ALL_INTR);
[0737710]126
127  /* Set the divisor latch and set the baud rate. */
128
[df49c60]129  ulBaudDivisor = NS16550_Baud(
[509fec9c]130    (uint32_t) Console_Port_Tbl[minor].ulClock,
131    (uint32_t) Console_Port_Tbl[minor].pDeviceParams
[df49c60]132  );
[0737710]133  ucDataByte = SP_LINE_DLAB;
134  (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
[70a9451]135
136  /* XXX */
[e97e0e0]137  (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, (uint8_t) (ulBaudDivisor & 0xffU));
138  (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (uint8_t) ((ulBaudDivisor >> 8) & 0xffU));
[0737710]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
[70a9451]152  ns16550_enable_interrupts(minor, NS16550_DISABLE_ALL_INTR);
[0737710]153
154  /* Set data terminal ready. */
155  /* And open interrupt tristate line */
156  (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
157
158  ucTrash = (*getReg)(pNS16550, NS16550_LINE_STATUS );
159  ucTrash = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER );
160}
161
[cae0504]162/*
163 *  ns16550_open
164 */
165
[27045a82]166NS16550_STATIC int ns16550_open(
[0737710]167  int      major,
168  int      minor,
169  void    * arg
170)
171{
172  /*
173   * Assert DTR
174   */
175
176  if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) {
177    ns16550_assert_DTR(minor);
178  }
179
180  return(RTEMS_SUCCESSFUL);
181}
182
[cae0504]183/*
184 *  ns16550_close
185 */
186
[27045a82]187NS16550_STATIC int ns16550_close(
[0737710]188  int      major,
189  int      minor,
190  void    * arg
191)
192{
193  /*
194   * Negate DTR
195   */
196  if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) {
197    ns16550_negate_DTR(minor);
198  }
199
200  return(RTEMS_SUCCESSFUL);
201}
202
[9151ec6]203/**
204 * @brief Polled write for NS16550.
[0737710]205 */
[9151ec6]206NS16550_STATIC void ns16550_write_polled( int minor, char c)
[0737710]207{
[9151ec6]208  uint32_t port = Console_Port_Tbl [minor].ulCtrlPort1;
209  getRegister_f get = Console_Port_Tbl [minor].getRegister;
210  setRegister_f set = Console_Port_Tbl [minor].setRegister;
211  uint32_t status;
212  rtems_interrupt_level level;
213
214  while (1) {
215    /* Try to transmit the character in a critical section */
216    rtems_interrupt_disable( level);
217
218    /* Read the transmitter holding register and check it */
219    status = get( port, NS16550_LINE_STATUS);
220    if ((status & SP_LSR_THOLD) != 0) {
221      /* Transmit character */
222      set( port, NS16550_TRANSMIT_BUFFER, c);
223
224      /* Finished */
225      rtems_interrupt_enable( level);
226      break;
227    } else {
228      rtems_interrupt_enable( level);
229    }
230
231    /* Wait for transmitter holding register to be empty */
232    do {
233      status = get( port, NS16550_LINE_STATUS);
234    } while ((status & SP_LSR_THOLD) == 0);
[0737710]235  }
236}
237
238/*
239 * These routines provide control of the RTS and DTR lines
240 */
[cae0504]241
[0737710]242/*
243 *  ns16550_assert_RTS
244 */
[cae0504]245
[27045a82]246NS16550_STATIC int ns16550_assert_RTS(int minor)
[0737710]247{
[ee4f57d]248  uint32_t                pNS16550;
249  uint32_t                Irql;
[0737710]250  ns16550_context        *pns16550Context;
251  setRegister_f           setReg;
252
253  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
254
255  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
256  setReg   = Console_Port_Tbl[minor].setRegister;
257
258  /*
259   * Assert RTS
260   */
261  rtems_interrupt_disable(Irql);
262  pns16550Context->ucModemCtrl|=SP_MODEM_RTS;
263  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
264  rtems_interrupt_enable(Irql);
265  return 0;
266}
267
268/*
269 *  ns16550_negate_RTS
270 */
[cae0504]271
[27045a82]272NS16550_STATIC int ns16550_negate_RTS(int minor)
[0737710]273{
[ee4f57d]274  uint32_t                pNS16550;
275  uint32_t                Irql;
[0737710]276  ns16550_context        *pns16550Context;
277  setRegister_f           setReg;
278
279  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
280
281  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
282  setReg   = Console_Port_Tbl[minor].setRegister;
283
284  /*
285   * Negate RTS
286   */
287  rtems_interrupt_disable(Irql);
288  pns16550Context->ucModemCtrl&=~SP_MODEM_RTS;
289  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
290  rtems_interrupt_enable(Irql);
291  return 0;
292}
293
294/*
295 * These flow control routines utilise a connection from the local DTR
296 * line to the remote CTS line
297 */
[cae0504]298
[0737710]299/*
300 *  ns16550_assert_DTR
301 */
[cae0504]302
[27045a82]303NS16550_STATIC int ns16550_assert_DTR(int minor)
[0737710]304{
[ee4f57d]305  uint32_t                pNS16550;
306  uint32_t                Irql;
[0737710]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   * Assert DTR
317   */
318  rtems_interrupt_disable(Irql);
319  pns16550Context->ucModemCtrl|=SP_MODEM_DTR;
320  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
321  rtems_interrupt_enable(Irql);
322  return 0;
323}
324
325/*
326 *  ns16550_negate_DTR
327 */
[8739322]328
[27045a82]329NS16550_STATIC int ns16550_negate_DTR(int minor)
[0737710]330{
[ee4f57d]331  uint32_t                pNS16550;
332  uint32_t                Irql;
[0737710]333  ns16550_context        *pns16550Context;
334  setRegister_f           setReg;
335
336  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
337
338  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
339  setReg   = Console_Port_Tbl[minor].setRegister;
340
341  /*
342   * Negate DTR
343   */
344  rtems_interrupt_disable(Irql);
345  pns16550Context->ucModemCtrl&=~SP_MODEM_DTR;
346  (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
347  rtems_interrupt_enable(Irql);
348  return 0;
349}
350
[8739322]351/*
352 *  ns16550_set_attributes
353 *
354 *  This function sets the channel to reflect the requested termios
355 *  port settings.
356 */
357
358NS16550_STATIC int ns16550_set_attributes(
359  int                   minor,
360  const struct termios *t
361)
362{
[ee4f57d]363  uint32_t                pNS16550;
364  uint32_t                ulBaudDivisor;
365  uint8_t                 ucLineControl;
366  uint32_t                baud_requested;
[8739322]367  setRegister_f           setReg;
368  getRegister_f           getReg;
[ee4f57d]369  uint32_t                Irql;
[8739322]370
371  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
372  setReg   = Console_Port_Tbl[minor].setRegister;
373  getReg   = Console_Port_Tbl[minor].getRegister;
374
375  /*
376   *  Calculate the baud rate divisor
377   */
378
379  baud_requested = t->c_cflag & CBAUD;
380  if (!baud_requested)
381    baud_requested = B9600;              /* default to 9600 baud */
382
[df49c60]383  ulBaudDivisor = NS16550_Baud(
[509fec9c]384    (uint32_t) Console_Port_Tbl[minor].ulClock,
[df49c60]385    termios_baud_to_number(baud_requested)
386  );
[8739322]387
388  ucLineControl = 0;
389
390  /*
391   *  Parity
392   */
393
394  if (t->c_cflag & PARENB) {
395    ucLineControl |= SP_LINE_PAR;
396    if (!(t->c_cflag & PARODD))
397      ucLineControl |= SP_LINE_ODD;
398  }
399
400  /*
401   *  Character Size
402   */
403
404  if (t->c_cflag & CSIZE) {
405    switch (t->c_cflag & CSIZE) {
406      case CS5:  ucLineControl |= FIVE_BITS;  break;
407      case CS6:  ucLineControl |= SIX_BITS;   break;
408      case CS7:  ucLineControl |= SEVEN_BITS; break;
409      case CS8:  ucLineControl |= EIGHT_BITS; break;
410    }
411  } else {
412    ucLineControl |= EIGHT_BITS;               /* default to 9600,8,N,1 */
413  }
414
415  /*
416   *  Stop Bits
417   */
418
419  if (t->c_cflag & CSTOPB) {
420    ucLineControl |= SP_LINE_STOP;              /* 2 stop bits */
421  } else {
422    ;                                           /* 1 stop bit */
423  }
424
425  /*
426   *  Now actually set the chip
427   */
428
429  rtems_interrupt_disable(Irql);
430
431    /*
[a3d3d9a]432     *  Set the baud rate
[8739322]433     */
434
435    (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
436    /* XXX are these registers right? */
437    (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
438    (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
439
440    /*
441     *  Now write the line control
442     */
443    (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
444
445  rtems_interrupt_enable(Irql);
446
[07a3253d]447  return 0;
[8739322]448}
449
[69be08ee]450#if defined(BSP_FEATURE_IRQ_EXTENSION)
[0737710]451/*
[cae0504]452 *  ns16550_process
[0737710]453 *
[cae0504]454 *  This routine is the console interrupt handler for A port.
[0737710]455 */
456
[e97e0e0]457NS16550_STATIC void ns16550_process( int minor)
[0737710]458{
[e97e0e0]459  console_tbl *c = &Console_Port_Tbl [minor];
460  console_data *d = &Console_Port_Data [minor];
461
[ee4f57d]462  uint32_t                pNS16550;
[a3d3d9a]463  volatile uint8_t        ucLineStatus;
[ee4f57d]464  volatile uint8_t        ucInterruptId;
[e11bf43]465  char                    cChar;
[0737710]466  getRegister_f           getReg;
467  setRegister_f           setReg;
468
[e97e0e0]469  pNS16550 = c->ulCtrlPort1;
470  getReg   = c->getRegister;
471  setReg   = c->setRegister;
[0737710]472
473  do {
474    /*
475     * Deal with any received characters
476     */
[e97e0e0]477    while (true) {
[0737710]478      ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
[e97e0e0]479      if (~ucLineStatus & SP_LSR_RDY) {
[0737710]480        break;
481      }
482      cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
[a3d3d9a]483      rtems_termios_enqueue_raw_characters(
[e97e0e0]484        d->termios_data,
[a3d3d9a]485        &cChar,
486        1
[0737710]487      );
488    }
489
[70a9451]490    /*
491     *  TX all the characters we can
492     */
493
[e97e0e0]494    while (true) {
495      ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
496      if (~ucLineStatus & SP_LSR_THOLD) {
497        /*
498         * We'll get another interrupt when
499         * the transmitter holding reg. becomes
500         * free again
501         */
502        break;
503      }
[70a9451]504
[e97e0e0]505      if (rtems_termios_dequeue_characters( d->termios_data, 1) == 0) {
506        if (c->pDeviceFlow != &ns16550_flow_RTSCTS) {
[70a9451]507          ns16550_negate_RTS(minor);
508        }
[e97e0e0]509        d->bActive = false;
[70a9451]510        ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
[0737710]511        break;
512      }
513    }
[c163605f]514
[e97e0e0]515    ucInterruptId = (*getReg)(pNS16550, NS16550_INTERRUPT_ID);
516  } while((ucInterruptId&0xf)!=0x1);
[c163605f]517}
518
[0737710]519/*
[70a9451]520 *  ns16550_enable_interrupts
[0737710]521 *
[70a9451]522 *  This routine initializes the port to have the specified interrupts masked.
[0737710]523 */
[69be08ee]524#endif
[0737710]525
[27045a82]526NS16550_STATIC void ns16550_enable_interrupts(
[70a9451]527  int minor,
528  int mask
[0737710]529)
530{
[ee4f57d]531  uint32_t       pNS16550;
[70a9451]532  setRegister_f  setReg;
[0737710]533
534  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
535  setReg   = Console_Port_Tbl[minor].setRegister;
536
[70a9451]537  (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);
[0737710]538}
539
[e97e0e0]540#ifdef BSP_FEATURE_IRQ_EXTENSION
541  NS16550_STATIC void ns16550_isr( rtems_vector_number vector, void *arg)
542  {
543    int minor = (int) arg;
544
545    ns16550_process( minor);
546  }
547#elif defined BSP_FEATURE_IRQ_LEGACY
548  NS16550_STATIC rtems_isr ns16550_isr( void *arg)
549  {
550    int minor = (int) arg;
551
552    ns16550_process( minor);
553  }
554#endif
555
[70a9451]556/*
557 *  ns16550_initialize_interrupts
558 *
559 *  This routine initializes the port to operate in interrupt driver mode.
[a3d3d9a]560 */
[e97e0e0]561NS16550_STATIC void ns16550_initialize_interrupts( int minor)
[0737710]562{
[69be08ee]563#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
[e97e0e0]564  console_tbl *c = &Console_Port_Tbl [minor];
[69be08ee]565#endif
[e97e0e0]566  console_data *d = &Console_Port_Data [minor];
567
568  ns16550_init( minor);
569
570  d->bActive = false;
571
572  #ifdef BSP_FEATURE_IRQ_EXTENSION
573    {
574      rtems_status_code sc = RTEMS_SUCCESSFUL;
575      sc = rtems_interrupt_handler_install(
576        c->ulIntVector,
577        "NS16550",
578        RTEMS_INTERRUPT_SHARED,
579        ns16550_isr,
580        (void *) minor
581      );
582      if (sc != RTEMS_SUCCESSFUL) {
583        /* FIXME */
584        printk( "%s: Error: Install interrupt handler\n", __func__);
585        rtems_fatal_error_occurred( 0xdeadbeef);
586      }
587    }
[69be08ee]588  #elif defined(BSP_FEATURE_IRQ_LEGACY)
[e97e0e0]589    {
590      int rv = 0;
591      #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
592        rtems_irq_connect_data cd = {
593          c->ulIntVector,
594          ns16550_isr,
[95ef82c]595          (void *) minor,
[e97e0e0]596          NULL,
597          NULL,
598          NULL,
599          NULL
600        };
601        rv = BSP_install_rtems_shared_irq_handler( &cd);
602      #else
603        rtems_irq_connect_data cd = {
604          c->ulIntVector,
605          ns16550_isr,
[0fbd231]606          (void *) minor,
[e97e0e0]607          NULL,
608          NULL,
609          NULL
610        };
611        rv = BSP_install_rtems_irq_handler( &cd);
612      #endif
613      if (rv == 0) {
614        /* FIXME */
615        printk( "%s: Error: Install interrupt handler\n", __func__);
616        rtems_fatal_error_occurred( 0xdeadbeef);
617      }
618    }
619  #endif
[c163605f]620 
[e97e0e0]621  ns16550_enable_interrupts( minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
[0737710]622}
623
[a3d3d9a]624/*
[0737710]625 *  ns16550_write_support_int
626 *
627 *  Console Termios output entry point.
628 */
[70a9451]629
[27045a82]630NS16550_STATIC int ns16550_write_support_int(
[a3d3d9a]631  int   minor,
632  const char *buf,
[0737710]633  int   len
634)
635{
[ee4f57d]636  uint32_t       Irql;
637  uint32_t       pNS16550;
[70a9451]638  setRegister_f  setReg;
[0737710]639
[70a9451]640  setReg   = Console_Port_Tbl[minor].setRegister;
641  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
[0737710]642
643  /*
[70a9451]644   *  We are using interrupt driven output and termios only sends us
645   *  one character at a time.
[0737710]646   */
[70a9451]647
648  if ( !len )
649    return 0;
650
651  if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {
652    ns16550_assert_RTS(minor);
[0737710]653  }
654
[70a9451]655  rtems_interrupt_disable(Irql);
[e97e0e0]656    if ( Console_Port_Data[minor].bActive == false) {
657      Console_Port_Data[minor].bActive = true;
[70a9451]658      ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
659    }
660    (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, *buf);
661  rtems_interrupt_enable(Irql);
662
663  return 1;
[0737710]664}
665
[a3d3d9a]666/*
[0737710]667 *  ns16550_write_support_polled
668 *
669 *  Console Termios output entry point.
670 *
671 */
[70a9451]672
[27045a82]673NS16550_STATIC int ns16550_write_support_polled(
[a3d3d9a]674  int         minor,
675  const char *buf,
[0737710]676  int         len
677)
678{
679  int nwrite = 0;
680
681  /*
682   * poll each byte in the string out of the port.
683   */
684  while (nwrite < len) {
685    /*
686     * transmit character
687     */
688    ns16550_write_polled(minor, *buf++);
689    nwrite++;
690  }
691
692  /*
693   * return the number of bytes written.
694   */
695  return nwrite;
696}
697
[a3d3d9a]698/*
699 *  ns16550_inbyte_nonblocking_polled
[0737710]700 *
701 *  Console Termios polling input entry point.
702 */
703
[a3d3d9a]704NS16550_STATIC int ns16550_inbyte_nonblocking_polled(
705  int minor
[0737710]706)
707{
[ee4f57d]708  uint32_t             pNS16550;
[0737710]709  unsigned char        ucLineStatus;
710  char                 cChar;
711  getRegister_f        getReg;
712
713  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
714  getReg   = Console_Port_Tbl[minor].getRegister;
715
716  ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
717  if(ucLineStatus & SP_LSR_RDY) {
718    cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
[8a2d4f2b]719    return (int)cChar;
[0737710]720  } else {
[8a2d4f2b]721    return -1;
[0737710]722  }
723}
Note: See TracBrowser for help on using the repository browser.