source: rtems/c/src/libchip/serial/mc68681.c @ beaaf49f

4.104.114.84.95
Last change on this file since beaaf49f was beaaf49f, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 23, 1998 at 4:02:52 PM

Added numerous comments.

  • Property mode set to 100644
File size: 22.1 KB
Line 
1/*
2 *  This file contains the termios TTY driver for the Motorola MC68681.
3 *
4 *  This part is available from a number of secondary sources.
5 *  In particular, we know about the following:
6 *
7 *     + Exar 88c681 and 68c681
8 *
9 *  COPYRIGHT (c) 1989-1998.
10 *  On-Line Applications Research Corporation (OAR).
11 *  Copyright assigned to U.S. Government, 1994.
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.OARcorp.com/rtems/license.html.
16 *
17 *  $Id$
18 */
19
20#include <rtems.h>
21#include <rtems/libio.h>
22#include <stdlib.h>
23#include <ringbuf.h>
24
25#include <libchip/serial.h>
26#include "mc68681_p.h"
27#include "mc68681.h"
28
29/*
30 * Flow control is only supported when using interrupts
31 */
32
33console_flow mc68681_flow_RTSCTS =
34{
35  mc68681_negate_RTS,             /* deviceStopRemoteTx */
36  mc68681_assert_RTS              /* deviceStartRemoteTx */
37};
38
39console_flow mc68681_flow_DTRCTS =
40{
41  mc68681_negate_DTR,             /* deviceStopRemoteTx */
42  mc68681_assert_DTR              /* deviceStartRemoteTx */
43};
44
45console_fns mc68681_fns =
46{
47  mc68681_probe,                  /* deviceProbe */
48  mc68681_open,                   /* deviceFirstOpen */
49  mc68681_flush,                  /* deviceLastClose */
50  NULL,                           /* deviceRead */
51  mc68681_write_support_int,      /* deviceWrite */
52  mc68681_initialize_interrupts,  /* deviceInitialize */
53  mc68681_write_polled,           /* deviceWritePolled */
54  mc68681_set_attributes,         /* deviceSetAttributes */
55  FALSE,                          /* deviceOutputUsesInterrupts */
56};
57
58console_fns mc68681_fns_polled =
59{
60  mc68681_probe,                       /* deviceProbe */
61  mc68681_open,                        /* deviceFirstOpen */
62  mc68681_close,                       /* deviceLastClose */
63  mc68681_inbyte_nonblocking_polled,   /* deviceRead */
64  mc68681_write_support_polled,        /* deviceWrite */
65  mc68681_init,                        /* deviceInitialize */
66  mc68681_write_polled,                /* deviceWritePolled */
67  mc68681_set_attributes,              /* deviceSetAttributes */
68  FALSE,                               /* deviceOutputUsesInterrupts */
69};
70
71extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
72
73/*
74 *  Console Device Driver Entry Points
75 */
76
77/*
78 *  mc68681_probe
79 *
80 *  Default probe routine which simply say the port is present.
81 */
82
83static boolean mc68681_probe(int minor)
84{
85  /*
86   * If the configuration dependent probe has located the device then
87   * assume it is there
88   */
89  return(TRUE);
90}
91
92/*
93 *  mc68681_baud_rate
94 *
95 *  This routine returns the proper ACR bit and baud rate field values
96 *  based on the requested baud rate.  The baud rate set to be used
97 *  must be configured by the user.
98 */
99
100static int mc68681_baud_rate(
101  int           minor,
102  int           baud,
103  unsigned int *baud_mask_p,
104  unsigned int *acr_bit_p
105)
106{
107  unsigned int baud_mask;
108  unsigned int acr_bit;
109  int          status;
110
111  baud_mask = 0;
112  acr_bit = 0;
113  status = 0;
114
115  if ( !(Console_Port_Tbl[minor].ulDataPort & MC68681_DATA_BAUD_RATE_SET_1) )
116    acr_bit = 1;
117
118  if (!(baud & CBAUD)) {
119    *baud_mask_p = 0x0B;     /* default to 9600 baud */
120    *acr_bit_p   = acr_bit;
121    return status;
122  }
123
124  if ( !acr_bit ) {
125    switch (baud & CBAUD) {
126      case B50:    baud_mask = 0x00; break;
127      case B110:   baud_mask = 0x01; break;
128      case B134:   baud_mask = 0x02; break;
129      case B200:   baud_mask = 0x03; break;
130      case B300:   baud_mask = 0x04; break;
131      case B600:   baud_mask = 0x05; break;
132      case B1200:  baud_mask = 0x06; break;
133      case B2400:  baud_mask = 0x08; break;
134      case B4800:  baud_mask = 0x09; break;
135      case B9600:  baud_mask = 0x0B; break;
136      case B38400: baud_mask = 0x0C; break;
137
138      case B0:
139      case B75:
140      case B150:
141      case B1800:
142      case B19200:
143      case B57600:
144      case B115200:
145      case B230400:
146      case B460800:
147        status = -1;
148        break;
149    }
150  } else {
151    switch (baud & CBAUD) {
152      case B75:    baud_mask = 0x00; break;
153      case B110:   baud_mask = 0x01; break;
154      case B134:   baud_mask = 0x02; break;
155      case B150:   baud_mask = 0x03; break;
156      case B300:   baud_mask = 0x04; break;
157      case B600:   baud_mask = 0x05; break;
158      case B1200:  baud_mask = 0x06; break;
159      case B1800:  baud_mask = 0x0A; break;
160      case B2400:  baud_mask = 0x08; break;
161      case B4800:  baud_mask = 0x09; break;
162      case B9600:  baud_mask = 0x0B; break;
163      case B19200: baud_mask = 0x0C; break;
164
165      case B0:
166      case B50:
167      case B200:
168      case B38400:
169      case B57600:
170      case B115200:
171      case B230400:
172      case B460800:
173        status = -1;
174        break;
175    }
176  }
177
178  *baud_mask_p = baud_mask;
179  *acr_bit_p   = acr_bit;
180  return status;
181}
182
183/*
184 *  mc68681_set_attributes
185 *
186 *  This function sets the DUART channel to reflect the requested termios
187 *  port settings.
188 */
189
190static int mc68681_set_attributes( 
191  int minor,
192  const struct termios *t
193)
194{
195  unsigned32             pMC68681_port;
196  unsigned32             pMC68681;
197  unsigned int           mode1;
198  unsigned int           mode2;
199  unsigned int           baud_mask;
200  unsigned int           acr_bit;
201  setRegister_f          setReg;
202  rtems_interrupt_level  Irql;
203
204  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort1;
205  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort2;
206  setReg        = Console_Port_Tbl[minor].setRegister;
207
208  /*
209   *  Set the baud rate
210   */
211
212  if ( mc68681_baud_rate( minor, t->c_cflag, &baud_mask, &acr_bit ) == -1 )
213    return -1;
214
215  baud_mask |=  baud_mask << 4;
216  acr_bit   <<= 7;
217
218  /*
219   *  Parity
220   */
221
222  mode1 = 0;
223  mode2 = 0;
224
225  if (t->c_cflag & PARENB) {
226    if (t->c_cflag & PARODD)
227      mode1 |= 0x04;
228    else
229      mode1 |= 0x04;
230  } else {
231   mode1 |= 0x10;
232  }
233
234  /*
235   *  Character Size
236   */
237
238  if (t->c_cflag & CSIZE) {
239    switch (t->c_cflag & CSIZE) {
240      case CS5:  break;
241      case CS6:  mode1 |= 0x01;  break;
242      case CS7:  mode1 |= 0x02;  break;
243      case CS8:  mode1 |= 0x03;  break;
244    }
245  } else {
246    mode1 |= 0x03;       /* default to 9600,8,N,1 */
247  }
248
249  /*
250   *  Stop Bits
251   */
252 
253  if (t->c_cflag & CSTOPB) {
254    mode2 |= 0x07;                      /* 2 stop bits */
255  } else {
256    if ((t->c_cflag & CSIZE) == CS5)    /* CS5 and 2 stop bits not supported */
257      return -1;
258    mode2 |= 0x0F;                      /* 1 stop bit */
259  }
260
261  rtems_interrupt_disable(Irql);
262    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit );
263    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud_mask );
264    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
265    (*setReg)( pMC68681_port, MC68681_MODE, mode1 );
266    (*setReg)( pMC68681_port, MC68681_MODE, mode2 );
267  rtems_interrupt_enable(Irql);
268  return 0;
269}
270
271/*
272 *  mc68681_initialize_context
273 *
274 *  This function sets the default values of the per port context structure.
275 */
276
277static void mc68681_initialize_context(
278  int               minor,
279  mc68681_context  *pmc68681Context
280)
281{
282  int          port;
283  unsigned int pMC68681;
284 
285  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
286
287  pmc68681Context->mate = -1;
288
289  for (port=0 ; port<Console_Port_Count ; port++ ) {
290    if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 ) {
291      pmc68681Context->mate = port;
292      break;
293    }
294  }
295
296  pmc68681Context->ucModemCtrl = 0x00;   /* XXX */
297}
298
299/*
300 *  mc68681_build_imr
301 *
302 *  This function returns the value for the interrupt mask register for this
303 *  DUART.  Since this is a shared register, we must look at the other port
304 *  on this chip to determine whether or not it is using interrupts.
305 */
306
307static unsigned int mc68681_build_imr(
308  int minor
309)
310{
311  int              mate;
312  unsigned int     mask;
313  unsigned int     mate_mask;
314  unsigned int     pMC68681;
315  unsigned int     pMC68681_port;
316  mc68681_context *pmc68681Context;
317 
318  pMC68681       = Console_Port_Tbl[minor].ulCtrlPort1;
319  pMC68681_port  = Console_Port_Tbl[minor].ulCtrlPort2;
320  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
321  mate            = pmc68681Context->mate;
322
323  mate_mask = 0;
324
325  /*
326   *  Decide if the other port on this DUART is using interrupts
327   */
328
329  if ( mate != -1 ) {
330    if ( Console_Port_Tbl[mate].pDeviceFns->deviceOutputUsesInterrupts )
331      mate_mask = 0x03;
332
333    /*
334     *  If equal, then minor is A so the mate must be B
335     */
336
337    if ( pMC68681 == pMC68681_port )
338      mate_mask <<= 4;
339  }
340
341  /*
342   *  Add in minor's mask
343   */
344
345  mask = 0;
346  if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) {
347    if ( pMC68681 == pMC68681_port )
348       mask = 0x03;
349    else
350       mask = 0x30;
351  }
352
353  return mask | mate_mask;
354}
355
356/*
357 *  mc68681_init
358 *
359 *  This function initializes the DUART to a quiecsent state.
360 */
361
362static void mc68681_init(int minor)
363{
364  unsigned32              pMC68681_port;
365  unsigned32              pMC68681;
366  mc68681_context        *pmc68681Context;
367  setRegister_f           setReg;
368  getRegister_f           getReg;
369
370  pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context));
371
372  Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context;
373
374  mc68681_initialize_context( minor, pmc68681Context );
375
376  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort1;
377  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort2;
378  setReg        = Console_Port_Tbl[minor].setRegister;
379  getReg        = Console_Port_Tbl[minor].getRegister;
380
381  /*
382   *  Reset everything and leave this port disabled.
383   */
384
385  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
386  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
387  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
388  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
389  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
390  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
391  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
392
393
394  (*setReg)( pMC68681, MC68681_MODE_REG_1A, 0x00 );
395  (*setReg)( pMC68681, MC68681_MODE_REG_2A, 0x02 );
396}
397
398/*
399 *  mc68681_open
400 *
401 *  This function opens a port for communication.
402 *
403 *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
404 */
405
406static int mc68681_open(
407  int      major,
408  int      minor,
409  void    *arg
410)
411{
412  unsigned32             pMC68681;
413  unsigned32             pMC68681_port;
414  unsigned int           baud;
415  unsigned int           acr;
416  unsigned int           vector;
417  rtems_interrupt_level  Irql;
418  setRegister_f          setReg;
419
420  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
421  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
422  setReg        = Console_Port_Tbl[minor].setRegister;
423  vector        = Console_Port_Tbl[minor].ulIntVector;
424
425  (void) mc68681_baud_rate( minor, B9600, &baud, &acr );
426
427  /*
428   *  Set the DUART channel to a default useable state
429   */
430
431  rtems_interrupt_disable(Irql);
432    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr );
433    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud );
434    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
435    (*setReg)( pMC68681_port, MC68681_MODE, 0x13 );
436    (*setReg)( pMC68681_port, MC68681_MODE, 0x07 );
437  rtems_interrupt_enable(Irql);
438
439  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX );
440  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX );
441
442  (*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector );
443
444  /*
445   * Assert DTR
446   */
447
448  if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_DTRCTS) {
449    mc68681_assert_DTR(minor);
450  }
451
452  return(RTEMS_SUCCESSFUL);
453}
454
455/*
456 *  mc68681_close
457 *
458 *  This function shuts down the requested port.
459 */
460
461static int mc68681_close(
462  int      major,
463  int      minor,
464  void    *arg
465)
466{
467  unsigned32      pMC68681;
468  unsigned32      pMC68681_port;
469  setRegister_f   setReg;
470
471  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
472  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
473  setReg        = Console_Port_Tbl[minor].setRegister;
474
475  /*
476   *  Disable interrupts from this channel and then disable it totally.
477   */
478
479  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
480  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
481
482  /*
483   * Negate DTR
484   */
485
486  if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_DTRCTS) {
487    mc68681_negate_DTR(minor);
488  }
489
490  return(RTEMS_SUCCESSFUL);
491}
492
493/*
494 *  mc68681_write_polled
495 *
496 *  This routine polls out the requested character.
497 */
498
499static void mc68681_write_polled(
500  int   minor, 
501  char  cChar
502)
503{
504  unsigned32              pMC68681_port;
505  unsigned char           ucLineStatus;
506  int                     iTimeout;
507  getRegister_f           getReg;
508  setRegister_f           setReg;
509
510  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
511  getReg        = Console_Port_Tbl[minor].getRegister;
512  setReg        = Console_Port_Tbl[minor].setRegister;
513
514  /*
515   * wait for transmitter holding register to be empty
516   */
517  iTimeout = 1000;
518  ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
519  while ((ucLineStatus & MC68681_TX_READY) == 0) {
520
521    /*
522     * Yield while we wait
523     */
524
525     if(_System_state_Is_up(_System_state_Get())) {
526       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
527     }
528     ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
529     if(!--iTimeout) {
530       break;
531     }
532  }
533
534  /*
535   * transmit character
536   */
537
538  (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);
539}
540
541/*
542 * These routines provide control of the RTS and DTR lines
543 */
544
545/*
546 *  mc68681_assert_RTS
547 */
548
549static int mc68681_assert_RTS(int minor)
550{
551/* XXX */
552
553  unsigned32              pMC68681;
554  unsigned32              Irql;
555  mc68681_context        *pmc68681Context;
556  setRegister_f           setReg;
557
558
559  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
560
561  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
562  setReg   = Console_Port_Tbl[minor].setRegister;
563
564  /*
565   * Assert RTS
566   */
567  rtems_interrupt_disable(Irql);
568#if 0
569  pmc68681Context->ucModemCtrl |= SP_MODEM_RTS;
570  (*setReg)(pMC68681, MC68681_MODEM_CONTROL, pmc68681Context->ucModemCtrl);
571#endif
572  rtems_interrupt_enable(Irql);
573  return 0;
574}
575
576/*
577 *  mc68681_negate_RTS
578 */
579
580static int mc68681_negate_RTS(int minor)
581{
582/* XXX */
583  unsigned32              pMC68681;
584  unsigned32              Irql;
585  mc68681_context        *pmc68681Context;
586  setRegister_f           setReg;
587
588  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
589
590  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
591  setReg   = Console_Port_Tbl[minor].setRegister;
592
593  /*
594   * Negate RTS
595   */
596  rtems_interrupt_disable(Irql);
597#if 0
598  pmc68681Context->ucModemCtrl &= ~SP_MODEM_RTS;
599  (*setReg)(pMC68681, MC68681_MODEM_CONTROL, pmc68681Context->ucModemCtrl);
600#endif
601  rtems_interrupt_enable(Irql);
602  return 0;
603}
604
605/*
606 * These flow control routines utilize a connection from the local DTR
607 * line to the remote CTS line
608 */
609
610/*
611 *  mc68681_assert_DTR
612 */
613
614static int mc68681_assert_DTR(int minor)
615{
616/* XXX */
617  unsigned32              pMC68681;
618  unsigned32              Irql;
619  mc68681_context        *pmc68681Context;
620  setRegister_f           setReg;
621
622  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
623
624  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
625  setReg   = Console_Port_Tbl[minor].setRegister;
626
627  /*
628   * Assert DTR
629   */
630  rtems_interrupt_disable(Irql);
631#if 0
632  pmc68681Context->ucModemCtrl |= SP_MODEM_DTR;
633  (*setReg)(pMC68681, MC68681_MODEM_CONTROL, pmc68681Context->ucModemCtrl);
634#endif
635  rtems_interrupt_enable(Irql);
636  return 0;
637}
638
639/*
640 *  mc68681_negate_DTR
641 */
642
643static int mc68681_negate_DTR(int minor)
644{
645/* XXX */
646  unsigned32              pMC68681;
647  unsigned32              Irql;
648  mc68681_context        *pmc68681Context;
649  setRegister_f           setReg;
650
651  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
652
653  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
654  setReg   = Console_Port_Tbl[minor].setRegister;
655
656  /*
657   * Negate DTR
658   */
659  rtems_interrupt_disable(Irql);
660#if 0
661  pmc68681Context->ucModemCtrl &= ~SP_MODEM_DTR;
662  (*setReg)(pMC68681, MC68681_MODEM_CONTROL,pmc68681Context->ucModemCtrl);
663#endif
664  rtems_interrupt_enable(Irql);
665  return 0;
666}
667
668/*
669 *  mc68681_isr
670 *
671 *  This routine is the console interrupt handler.
672 */
673
674static void mc68681_process(
675        int             minor
676)
677{
678/* XXX */
679  unsigned32              pMC68681;
680  volatile unsigned8      ucLineStatus; 
681  volatile unsigned8      ucInterruptId;
682  char                    cChar;
683  getRegister_f           getReg;
684  setRegister_f           setReg;
685
686#if 1
687cChar = ucInterruptId = ucLineStatus = 0;
688#endif
689  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
690  getReg   = Console_Port_Tbl[minor].getRegister;
691  setReg   = Console_Port_Tbl[minor].setRegister;
692
693#if 0
694  do {
695    /*
696     * Deal with any received characters
697     */
698    while(TRUE) {
699      ucLineStatus = (*getReg)(pMC68681, MC68681_LINE_STATUS);
700      if(~ucLineStatus & SP_LSR_RDY) {
701        break;
702      }
703      cChar = (*getReg)(pMC68681, MC68681_RECEIVE_BUFFER);
704      rtems_termios_enqueue_raw_characters(
705        Console_Port_Data[minor].termios_data,
706        &cChar,
707        1
708      );
709    }
710
711    while(TRUE) {
712      if(Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
713        Console_Port_Data[minor].bActive = FALSE;
714        if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_RTSCTS) {
715          mc68681_negate_RTS(minor);
716        }
717
718        /*
719         * There is no data to transmit
720         */
721        break;
722      }
723
724      ucLineStatus = (*getReg)(pMC68681, MC68681_LINE_STATUS);
725      if(~ucLineStatus & SP_LSR_THOLD) {
726        /*
727         * We'll get another interrupt when
728         * the transmitter holding reg. becomes
729         * free again
730         */
731        break;
732      }
733
734      Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar);
735      /*
736       * transmit character
737       */
738      (*setReg)(pMC68681, MC68681_TRANSMIT_BUFFER, cChar);
739    }
740
741    ucInterruptId = (*getReg)(pMC68681, MC68681_INTERRUPT_ID);
742  }
743  while((ucInterruptId&0xf) != 0x1);
744#endif
745}
746
747static rtems_isr mc68681_isr(
748  rtems_vector_number vector
749)
750{
751  int     minor;
752
753  for(minor=0 ; minor<Console_Port_Count ; minor++) {
754    if(vector == Console_Port_Tbl[minor].ulIntVector) {
755      mc68681_process(minor);
756    }
757  }
758}
759
760/*
761 *  mc68681_flush
762 *
763 *  This routine waits before all output is completed before closing
764 *  the requested port.
765 *
766 *  NOTE:  This is the "interrupt mode" close entry point.
767 */
768
769static int mc68681_flush(int major, int minor, void *arg)
770{
771  while(!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
772    /*
773     * Yield while we wait
774     */
775    if(_System_state_Is_up(_System_state_Get())) {
776      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
777    }
778  }
779
780  mc68681_close(major, minor, arg);
781
782  return(RTEMS_SUCCESSFUL);
783}
784
785/*
786 *  mc68681_enable_interrupts
787 *
788 *  This function initializes the hardware for this port to use interrupts.
789 */
790
791static void mc68681_enable_interrupts(
792  int minor
793)
794{
795  unsigned32            pMC68681;
796  setRegister_f         setReg;
797
798  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
799  setReg   = Console_Port_Tbl[minor].setRegister;
800
801  /*
802   *  Enable interrupts on RX and TX -- not break
803   */
804
805  (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr( minor ));
806}
807
808/*
809 *  mc68681_initialize_interrupts
810 *
811 *  This routine initializes the console's receive and transmit
812 *  ring buffers and loads the appropriate vectors to handle the interrupts.
813 */
814
815static void mc68681_initialize_interrupts(int minor)
816{
817  mc68681_init(minor);
818
819  Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
820
821  Console_Port_Data[minor].bActive = FALSE;
822
823  set_vector(mc68681_isr, Console_Port_Tbl[minor].ulIntVector, 1);
824
825  mc68681_enable_interrupts(minor);
826}
827
828/*
829 *  mc68681_write_support_int
830 *
831 *  Console Termios output entry point when using interrupt driven output.
832 */
833
834static int mc68681_write_support_int(
835  int   minor, 
836  const char *buf, 
837  int   len
838)
839{
840  int i;
841  unsigned32 Irql;
842
843  for(i=0 ; i<len ;) {
844    if(Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
845      if(!Console_Port_Data[minor].bActive) {
846        /*
847         * Wake up the device
848         */
849        rtems_interrupt_disable(Irql);
850        Console_Port_Data[minor].bActive = TRUE;
851        if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_RTSCTS) {
852          mc68681_assert_RTS(minor);
853        }
854        mc68681_process(minor);
855        rtems_interrupt_enable(Irql);
856      } else {
857        /*
858         * Yield
859         */
860        rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
861      }
862
863      /*
864       * Wait for ring buffer to empty
865       */
866      continue;
867    }
868    else {
869      Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
870      i++;
871    }
872  }
873
874  /*
875   * Ensure that characters are on the way
876   */
877
878  if(!Console_Port_Data[minor].bActive) {
879    /*
880     * Wake up the device
881     */
882    rtems_interrupt_disable(Irql);
883    Console_Port_Data[minor].bActive = TRUE;
884    if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_RTSCTS) {
885      mc68681_assert_RTS(minor);
886    }
887    mc68681_process(minor);
888    rtems_interrupt_enable(Irql);
889  }
890
891  return (len);
892}
893
894/*
895 *  mc68681_write_support_polled
896 *
897 *  Console Termios output entry point when using polled output.
898 *
899 */
900
901static int mc68681_write_support_polled(
902  int         minor, 
903  const char *buf, 
904  int         len
905)
906{
907  int nwrite = 0;
908
909  /*
910   * poll each byte in the string out of the port.
911   */
912  while (nwrite < len) {
913    /*
914     * transmit character
915     */
916    mc68681_write_polled(minor, *buf++);
917    nwrite++;
918  }
919
920  /*
921   * return the number of bytes written.
922   */
923  return nwrite;
924}
925
926/*
927 *  mc68681_inbyte_nonblocking_polled
928 *
929 *  Console Termios polling input entry point.
930 */
931
932static int mc68681_inbyte_nonblocking_polled( 
933  int minor
934)
935{
936  unsigned32           pMC68681_port;
937  unsigned char        ucLineStatus;
938  char                 cChar;
939  getRegister_f        getReg;
940
941  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
942  getReg        = Console_Port_Tbl[minor].getRegister;
943
944  ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
945  if(ucLineStatus & MC68681_RX_READY) {
946    cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
947    return (int)cChar;
948  } else {
949    return -1;
950  }
951}
Note: See TracBrowser for help on using the repository browser.