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

4.104.114.84.95
Last change on this file since 2d8e51aa was 2d8e51aa, checked in by Joel Sherrill <joel.sherrill@…>, on 07/09/98 at 18:45:28

Changed static to MC68681_STATIC to make all data and routines
globally visiable to ease debugging.

Added support for mc68681 "2 column" style baud rate table as
well as the Exar 88681 "4 column" style baud rate table.

Added support for user override of the default baud rate table.

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