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

4.104.114.84.95
Last change on this file since 2c5ea01 was 2c5ea01, checked in by Joel Sherrill <joel.sherrill@…>, on 07/09/98 at 22:16:27

Properly handle extended baud rate set commands.

Temporarily "if 0" of code which enables interrupts.

Moved setting of command registers at open but the current implementation
is questionable.

Added reset of RX errors while polling TX.

Read polled character as unsigned.

Baud rate mask must be in upper and lower nibble.

  • Property mode set to 100644
File size: 23.0 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    if ( cmd ) {
277      (*setReg)( pMC68681_port, MC68681_COMMAND, cmd );         /* RX */
278      (*setReg)( pMC68681_port, MC68681_COMMAND, cmd | 0x20 );  /* TX */
279    }
280    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
281    (*setReg)( pMC68681_port, MC68681_MODE, mode1 );
282    (*setReg)( pMC68681_port, MC68681_MODE, mode2 );
283  rtems_interrupt_enable(Irql);
284  return 0;
285}
286
287/*
288 *  mc68681_initialize_context
289 *
290 *  This function sets the default values of the per port context structure.
291 */
292
293MC68681_STATIC void mc68681_initialize_context(
294  int               minor,
295  mc68681_context  *pmc68681Context
296)
297{
298  int          port;
299  unsigned int pMC68681;
300 
301  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
302
303  pmc68681Context->mate = -1;
304
305  for (port=0 ; port<Console_Port_Count ; port++ ) {
306    if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 ) {
307      pmc68681Context->mate = port;
308      break;
309    }
310  }
311
312}
313
314/*
315 *  mc68681_build_imr
316 *
317 *  This function returns the value for the interrupt mask register for this
318 *  DUART.  Since this is a shared register, we must look at the other port
319 *  on this chip to determine whether or not it is using interrupts.
320 */
321
322MC68681_STATIC unsigned int mc68681_build_imr(
323  int  minor,
324  int  enable_flag
325)
326{
327  int              mate;
328  unsigned int     mask;
329  unsigned int     mate_mask;
330  unsigned int     pMC68681;
331  unsigned int     pMC68681_port;
332  mc68681_context *pmc68681Context;
333 
334  pMC68681       = Console_Port_Tbl[minor].ulCtrlPort1;
335  pMC68681_port  = Console_Port_Tbl[minor].ulCtrlPort2;
336  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
337  mate            = pmc68681Context->mate;
338
339  mate_mask = 0;
340
341  /*
342   *  Decide if the other port on this DUART is using interrupts
343   */
344
345  if ( mate != -1 ) {
346    if ( Console_Port_Tbl[mate].pDeviceFns->deviceOutputUsesInterrupts )
347      mate_mask = 0x03;
348
349    /*
350     *  If equal, then minor is A so the mate must be B
351     */
352
353    if ( pMC68681 == pMC68681_port )
354      mate_mask <<= 4;
355  }
356
357  /*
358   *  Add in minor's mask
359   */
360
361  mask = 0;
362  if ( enable_flag ) {
363    if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) {
364      if ( pMC68681 == pMC68681_port )
365         mask = 0x03;
366      else
367         mask = 0x30;
368    }
369  }
370
371#if 0
372  return mask | mate_mask;
373#endif
374
375  return 0;
376}
377
378/*
379 *  mc68681_init
380 *
381 *  This function initializes the DUART to a quiecsent state.
382 */
383
384MC68681_STATIC void mc68681_init(int minor)
385{
386  unsigned32              pMC68681_port;
387  unsigned32              pMC68681;
388  mc68681_context        *pmc68681Context;
389  setRegister_f           setReg;
390  getRegister_f           getReg;
391
392  pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context));
393
394  Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context;
395
396  mc68681_initialize_context( minor, pmc68681Context );
397
398  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
399  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
400  setReg        = Console_Port_Tbl[minor].setRegister;
401  getReg        = Console_Port_Tbl[minor].getRegister;
402
403  /*
404   *  Reset everything and leave this port disabled.
405   */
406
407  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
408  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
409  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
410  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
411  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
412  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
413  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
414
415
416  (*setReg)( pMC68681, MC68681_MODE_REG_1A, 0x00 );
417  (*setReg)( pMC68681, MC68681_MODE_REG_2A, 0x02 );
418
419  /*
420   *  Disable interrupts on RX and TX for this port
421   */
422
423  (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 0));
424}
425
426/*
427 *  mc68681_open
428 *
429 *  This function opens a port for communication.
430 *
431 *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
432 */
433
434MC68681_STATIC int mc68681_open(
435  int      major,
436  int      minor,
437  void    *arg
438)
439{
440  unsigned32             pMC68681;
441  unsigned32             pMC68681_port;
442  unsigned int           baud;
443  unsigned int           acr;
444  unsigned int           vector;
445  unsigned int           command;
446  rtems_interrupt_level  Irql;
447  setRegister_f          setReg;
448
449  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
450  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
451  setReg        = Console_Port_Tbl[minor].setRegister;
452  vector        = Console_Port_Tbl[minor].ulIntVector;
453
454  (void) mc68681_baud_rate( minor, B9600, &baud, &acr, &command );
455
456  /*
457   *  Set the DUART channel to a default useable state
458   */
459
460  rtems_interrupt_disable(Irql);
461    (*setReg)( pMC68681, MC68681_COMMAND, command );
462    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr );
463    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud );
464    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
465    (*setReg)( pMC68681_port, MC68681_MODE, 0x13 );
466    (*setReg)( pMC68681_port, MC68681_MODE, 0x07 );
467  rtems_interrupt_enable(Irql);
468
469  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX );
470  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX );
471
472  (*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector );
473
474  return RTEMS_SUCCESSFUL;
475}
476
477/*
478 *  mc68681_close
479 *
480 *  This function shuts down the requested port.
481 */
482
483MC68681_STATIC int mc68681_close(
484  int      major,
485  int      minor,
486  void    *arg
487)
488{
489  unsigned32      pMC68681;
490  unsigned32      pMC68681_port;
491  setRegister_f   setReg;
492
493  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
494  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
495  setReg        = Console_Port_Tbl[minor].setRegister;
496
497  /*
498   *  Disable interrupts from this channel and then disable it totally.
499   */
500
501  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
502  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
503
504  return(RTEMS_SUCCESSFUL);
505}
506
507/*
508 *  mc68681_write_polled
509 *
510 *  This routine polls out the requested character.
511 */
512
513MC68681_STATIC void mc68681_write_polled(
514  int   minor,
515  char  cChar
516)
517{
518  unsigned32              pMC68681_port;
519  unsigned char           ucLineStatus;
520  int                     iTimeout;
521  getRegister_f           getReg;
522  setRegister_f           setReg;
523
524  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
525  getReg        = Console_Port_Tbl[minor].getRegister;
526  setReg        = Console_Port_Tbl[minor].setRegister;
527
528  /*
529   * wait for transmitter holding register to be empty
530   */
531  iTimeout = 1000;
532  ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
533  while ((ucLineStatus & (MC68681_TX_READY|MC68681_TX_EMPTY)) == 0) {
534
535    if ((ucLineStatus & 0xF0))
536      (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
537
538    /*
539     * Yield while we wait
540     */
541
542     if(_System_state_Is_up(_System_state_Get())) {
543       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
544     }
545     ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
546     if(!--iTimeout) {
547       break;
548     }
549  }
550
551  /*
552   * transmit character
553   */
554
555  (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);
556}
557
558/*
559 *  mc68681_process
560 *
561 *  This routine is the per port console interrupt handler.
562 */
563
564MC68681_STATIC void mc68681_process(
565  int  minor
566)
567{
568  unsigned32              pMC68681;
569  unsigned32              pMC68681_port;
570  volatile unsigned8      ucLineStatus;
571  char                    cChar;
572  getRegister_f           getReg;
573  setRegister_f           setReg;
574
575  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
576  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
577  getReg        = Console_Port_Tbl[minor].getRegister;
578  setReg        = Console_Port_Tbl[minor].setRegister;
579
580  /*
581   * Deal with any received characters
582   */
583  while(TRUE) {
584    ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
585    if(!(ucLineStatus & MC68681_RX_READY)) {
586      break;
587    }
588    /*
589     *  If there is a RX error, then dump all the data.
590     */
591    if ( ucLineStatus & MC68681_RX_ERRORS ) {
592      do {
593        cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
594        ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
595      } while ( ucLineStatus & MC68681_RX_READY );
596      continue;
597    }
598    cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
599    rtems_termios_enqueue_raw_characters(
600      Console_Port_Data[minor].termios_data,
601      &cChar,
602      1
603    );
604  }
605
606  /*
607   *  Deal with the transmitter
608   */
609
610  while(TRUE) {
611    if(Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
612      Console_Port_Data[minor].bActive = FALSE;
613
614      /*
615       * There is no data to transmit
616       */
617      break;
618    }
619
620    ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
621    if(!(ucLineStatus & (MC68681_TX_EMPTY|MC68681_TX_READY))) {
622      /*
623       *  We'll get another interrupt when the TX can take another character.
624       */
625      break;
626    }
627
628    Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar);
629    /*
630     * transmit character
631     */
632    (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);
633  }
634
635}
636
637/*
638 *  mc68681_isr
639 *
640 *  This is the single interrupt entry point which parcels interrupts
641 *  out to the various ports.
642 */
643
644MC68681_STATIC rtems_isr mc68681_isr(
645  rtems_vector_number vector
646)
647{
648  int     minor;
649
650  for(minor=0 ; minor<Console_Port_Count ; minor++) {
651    if(vector == Console_Port_Tbl[minor].ulIntVector) {
652      mc68681_process(minor);
653    }
654  }
655}
656
657/*
658 *  mc68681_flush
659 *
660 *  This routine waits before all output is completed before closing
661 *  the requested port.
662 *
663 *  NOTE:  This is the "interrupt mode" close entry point.
664 */
665
666MC68681_STATIC int mc68681_flush(int major, int minor, void *arg)
667{
668  while(!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
669    /*
670     * Yield while we wait
671     */
672    if(_System_state_Is_up(_System_state_Get())) {
673      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
674    }
675  }
676
677  mc68681_close(major, minor, arg);
678
679  return(RTEMS_SUCCESSFUL);
680}
681
682/*
683 *  mc68681_enable_interrupts
684 *
685 *  This function initializes the hardware for this port to use interrupts.
686 */
687
688MC68681_STATIC void mc68681_enable_interrupts(
689  int minor
690)
691{
692  unsigned32            pMC68681;
693  setRegister_f         setReg;
694
695  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
696  setReg   = Console_Port_Tbl[minor].setRegister;
697
698  /*
699   *  Enable interrupts on RX and TX -- not break
700   */
701
702  (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 1));
703}
704
705/*
706 *  mc68681_initialize_interrupts
707 *
708 *  This routine initializes the console's receive and transmit
709 *  ring buffers and loads the appropriate vectors to handle the interrupts.
710 */
711
712MC68681_STATIC void mc68681_initialize_interrupts(int minor)
713{
714  mc68681_init(minor);
715
716  Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
717
718  Console_Port_Data[minor].bActive = FALSE;
719
720  set_vector(mc68681_isr, Console_Port_Tbl[minor].ulIntVector, 1);
721
722  mc68681_enable_interrupts(minor);
723}
724
725/*
726 *  mc68681_write_support_int
727 *
728 *  Console Termios output entry point when using interrupt driven output.
729 */
730
731MC68681_STATIC int mc68681_write_support_int(
732  int   minor,
733  const char *buf,
734  int   len
735)
736{
737  int i;
738  unsigned32 Irql;
739
740  for(i=0 ; i<len ;) {
741    if(Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
742      if(!Console_Port_Data[minor].bActive) {
743        /*
744         * Wake up the device
745         */
746        rtems_interrupt_disable(Irql);
747        Console_Port_Data[minor].bActive = TRUE;
748        mc68681_process(minor);
749        rtems_interrupt_enable(Irql);
750      } else {
751        /*
752         * Yield
753         */
754        rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
755      }
756
757      /*
758       * Wait for ring buffer to empty
759       */
760      continue;
761    }
762    else {
763      Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
764      i++;
765    }
766  }
767
768  /*
769   * Ensure that characters are on the way
770   */
771
772  if(!Console_Port_Data[minor].bActive) {
773    /*
774     * Wake up the device
775     */
776    rtems_interrupt_disable(Irql);
777    Console_Port_Data[minor].bActive = TRUE;
778    mc68681_process(minor);
779    rtems_interrupt_enable(Irql);
780  }
781
782  return (len);
783}
784
785/*
786 *  mc68681_write_support_polled
787 *
788 *  Console Termios output entry point when using polled output.
789 *
790 */
791
792MC68681_STATIC int mc68681_write_support_polled(
793  int         minor,
794  const char *buf,
795  int         len
796)
797{
798  int nwrite = 0;
799
800  /*
801   * poll each byte in the string out of the port.
802   */
803  while (nwrite < len) {
804    /*
805     * transmit character
806     */
807    mc68681_write_polled(minor, *buf++);
808    nwrite++;
809  }
810
811  /*
812   * return the number of bytes written.
813   */
814  return nwrite;
815}
816
817/*
818 *  mc68681_inbyte_nonblocking_polled
819 *
820 *  Console Termios polling input entry point.
821 */
822
823MC68681_STATIC int mc68681_inbyte_nonblocking_polled(
824  int minor
825)
826{
827  unsigned32           pMC68681_port;
828  unsigned char        ucLineStatus;
829  unsigned char        cChar;
830  getRegister_f        getReg;
831
832  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
833  getReg        = Console_Port_Tbl[minor].getRegister;
834
835  ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
836  if(ucLineStatus & MC68681_RX_READY) {
837    cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
838    return (int)cChar;
839  } else {
840    return -1;
841  }
842}
843
844MC68681_STATIC int mc68681_baud_rate(
845  int           minor,
846  int           baud,
847  unsigned int *baud_mask_p,
848  unsigned int *acr_bit_p,
849  unsigned int *command
850)
851{
852  unsigned int     baud_mask;
853  unsigned int     acr_bit;
854  int              status;
855  int              is_extended;
856  int              baud_requested;
857  mc68681_baud_table_t  *baud_tbl;
858
859  baud_mask = 0;
860  acr_bit = 0;
861  status = 0;
862
863  if ( !(Console_Port_Tbl[minor].ulDataPort & MC68681_DATA_BAUD_RATE_SET_1) )
864    acr_bit = 1;
865
866  is_extended = 0;
867
868  switch (Console_Port_Tbl[minor].ulDataPort & MC68681_XBRG_MASK) {
869    case MC68681_XBRG_IGNORED:
870      *command = 0x00;
871      break;
872    case MC68681_XBRG_ENABLED:
873      *command = 0x80;
874      is_extended = 1;
875      break;
876    case MC68681_XBRG_DISABLED:
877      *command = 0x90;
878      break;
879  }
880
881  baud_requested = baud & CBAUD;
882  if (!baud_requested)
883    baud_requested = B9600;              /* default to 9600 baud */
884 
885  baud_requested = termios_baud_to_index( baud_requested );
886
887  baud_tbl = (mc68681_baud_table_t *) Console_Port_Tbl[minor].ulClock;
888  if (!baud_tbl)
889    baud_tbl = (mc68681_baud_table_t *)mc68681_baud_rate_table;
890
891  if ( is_extended )
892    baud_mask = (unsigned int)baud_tbl[ acr_bit + 2 ][ baud_requested ];
893  else
894    baud_mask = baud_tbl[ acr_bit ][ baud_requested ];
895
896  if ( baud_mask == MC68681_BAUD_NOT_VALID )
897    status = -1;
898
899  /*
900   *  upper nibble is receiver and lower nibble is transmitter
901   */
902
903  *baud_mask_p = (baud_mask << 4) | baud_mask;
904  *acr_bit_p   = acr_bit;
905  return status;
906}
907
Note: See TracBrowser for help on using the repository browser.