source: rtems/c/src/lib/libchip/serial/mc68681.c @ a5d0c7c

4.104.114.84.95
Last change on this file since a5d0c7c was a5d0c7c, checked in by Joel Sherrill <joel.sherrill@…>, on 06/23/98 at 15:54:33

Added concept of "mate" -- the other port on the same DUART. This is
needed to properly handle the interrupt mask register since it is
shared.

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