source: rtems/c/src/libchip/serial/mc68681.c @ 693b5b88

4.104.114.84.95
Last change on this file since 693b5b88 was 693b5b88, checked in by Joel Sherrill <joel.sherrill@…>, on 07/09/98 at 23:30:02

Switched to default probe routine.

  • Property mode set to 100644
File size: 22.9 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  libchip_serial_default_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  libchip_serial_default_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_baud_rate
68 *
69 *  This routine returns the proper ACR bit and baud rate field values
70 *  based on the requested baud rate.  The baud rate set to be used
71 *  must be configured by the user.
72 */
73
74/* major index of 0 : ACR[7] = 0, X = 0 -- 68c681 only has these */
75/* major index of 1 : ACR[7] = 1, X = 0 -- 68c681 only has these */
76/* major index of 2 : ACR[7] = 0, X = 1 */
77/* major index of 3 : ACR[7] = 1, X = 1 */
78
79/* mc68681_baud_table_t mc68681_baud_rate_table[4] = { */
80mc68681_baud_t mc68681_baud_rate_table[4][RTEMS_TERMIOS_NUMBER_BAUD_RATES] = {
81  { /* ACR[7] = 0, X = 0 */
82    MC68681_BAUD_NOT_VALID,    /* B0 */
83    0x00,                      /* B50 */
84    MC68681_BAUD_NOT_VALID,    /* B75 */
85    0x01,                      /* B110 */
86    0x02,                      /* B134 */
87    MC68681_BAUD_NOT_VALID,    /* B150 */
88    0x03,                      /* B200 */
89    0x04,                      /* B300 */
90    0x05,                      /* B600 */
91    0x06,                      /* B1200 */
92    MC68681_BAUD_NOT_VALID,    /* B1800 */
93    0x08,                      /* B2400 */
94    0x09,                      /* B4800 */
95    0x0B,                      /* B9600 */
96    MC68681_BAUD_NOT_VALID,    /* B19200 */
97    0x0C,                      /* B38400 */
98    MC68681_BAUD_NOT_VALID,    /* B57600 */
99    MC68681_BAUD_NOT_VALID,    /* B115200 */
100    MC68681_BAUD_NOT_VALID,    /* B230400 */
101    MC68681_BAUD_NOT_VALID     /* B460800 */
102  },
103  { /* ACR[7] = 1, X = 0 */
104    MC68681_BAUD_NOT_VALID,    /* B0 */
105    MC68681_BAUD_NOT_VALID,    /* B50 */
106    0x00,                      /* B75 */
107    0x01,                      /* B110 */
108    0x02,                      /* B134 */
109    0x03,                      /* B150 */
110    MC68681_BAUD_NOT_VALID,    /* B200 */
111    0x04,                      /* B300 */
112    0x05,                      /* B600 */
113    0x06,                      /* B1200 */
114    0x0A,                      /* B1800 */
115    0x08,                      /* B2400 */
116    0x09,                      /* B4800 */
117    0x0B,                      /* B9600 */
118    0x0C,                      /* B19200 */
119    MC68681_BAUD_NOT_VALID,    /* B38400 */
120    MC68681_BAUD_NOT_VALID,    /* B57600 */
121    MC68681_BAUD_NOT_VALID,    /* B115200 */
122    MC68681_BAUD_NOT_VALID,    /* B230400 */
123    MC68681_BAUD_NOT_VALID     /* B460800 */
124  },
125  { /* ACR[7] = 0, X = 1 */
126    MC68681_BAUD_NOT_VALID,    /* B0 */
127    MC68681_BAUD_NOT_VALID,    /* B50 */
128    0x00,                      /* B75 */
129    0x01,                      /* B110 */
130    0x02,                      /* B134 */
131    0x03,                      /* B150 */
132    MC68681_BAUD_NOT_VALID,    /* B200 */
133    MC68681_BAUD_NOT_VALID,    /* B300 */
134    MC68681_BAUD_NOT_VALID,    /* B600 */
135    MC68681_BAUD_NOT_VALID,    /* B1200 */
136    0x0A,                      /* B1800 */
137    MC68681_BAUD_NOT_VALID,    /* B2400 */
138    0x08,                      /* B4800 */
139    0x0B,                      /* B9600 */
140    0x0C,                      /* B19200 */
141    MC68681_BAUD_NOT_VALID,    /* B38400 */
142    0x07,                      /* B57600 */
143    0x08,                      /* B115200 */
144    MC68681_BAUD_NOT_VALID,    /* B230400 */
145    MC68681_BAUD_NOT_VALID     /* B460800 */
146  },
147  { /* ACR[7] = 1, X = 1 */
148    MC68681_BAUD_NOT_VALID,    /* B0 */
149    0x00,                      /* B50 */
150    MC68681_BAUD_NOT_VALID,    /* B75 */
151    0x01,                      /* B110 */
152    0x02,                      /* B134 */
153    MC68681_BAUD_NOT_VALID,    /* B150 */
154    0x03,                      /* B200 */
155    MC68681_BAUD_NOT_VALID,    /* B300 */
156    MC68681_BAUD_NOT_VALID,    /* B600 */
157    MC68681_BAUD_NOT_VALID,    /* B1200 */
158    MC68681_BAUD_NOT_VALID,    /* B1800 */
159    MC68681_BAUD_NOT_VALID,    /* B2400 */
160    0x09,                      /* B4800 */
161    0x0B,                      /* B9600 */
162    MC68681_BAUD_NOT_VALID,    /* B19200 */
163    0x0C,                      /* B38400 */
164    0x07,                      /* B57600 */
165    0x08,                      /* B115200 */
166    MC68681_BAUD_NOT_VALID,    /* B230400 */
167    MC68681_BAUD_NOT_VALID     /* B460800 */
168  },
169};
170
171MC68681_STATIC int mc68681_baud_rate(
172  int           minor,
173  int           baud,
174  unsigned int *baud_mask_p,
175  unsigned int *acr_bit_p,
176  unsigned int *command
177);
178
179/*
180 *  mc68681_set_attributes
181 *
182 *  This function sets the DUART channel to reflect the requested termios
183 *  port settings.
184 */
185
186MC68681_STATIC int mc68681_set_attributes(
187  int minor,
188  const struct termios *t
189)
190{
191  unsigned32             pMC68681_port;
192  unsigned32             pMC68681;
193  unsigned int           mode1;
194  unsigned int           mode2;
195  unsigned int           baud_mask;
196  unsigned int           acr_bit;
197  unsigned int           cmd;
198  setRegister_f          setReg;
199  rtems_interrupt_level  Irql;
200
201  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
202  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
203  setReg        = Console_Port_Tbl[minor].setRegister;
204
205  /*
206   *  Set the baud rate
207   */
208
209  if (mc68681_baud_rate( minor, t->c_cflag, &baud_mask, &acr_bit, &cmd ) == -1)
210    return -1;
211
212  baud_mask |=  baud_mask << 4;
213  acr_bit   <<= 7;
214
215  /*
216   *  Parity
217   */
218
219  mode1 = 0;
220  mode2 = 0;
221
222  if (t->c_cflag & PARENB) {
223    if (t->c_cflag & PARODD)
224      mode1 |= 0x04;
225    else
226      mode1 |= 0x04;
227  } else {
228   mode1 |= 0x10;
229  }
230
231  /*
232   *  Character Size
233   */
234
235  if (t->c_cflag & CSIZE) {
236    switch (t->c_cflag & CSIZE) {
237      case CS5:  break;
238      case CS6:  mode1 |= 0x01;  break;
239      case CS7:  mode1 |= 0x02;  break;
240      case CS8:  mode1 |= 0x03;  break;
241    }
242  } else {
243    mode1 |= 0x03;       /* default to 9600,8,N,1 */
244  }
245
246  /*
247   *  Stop Bits
248   */
249 
250  if (t->c_cflag & CSTOPB) {
251    mode2 |= 0x07;                      /* 2 stop bits */
252  } else {
253    if ((t->c_cflag & CSIZE) == CS5)    /* CS5 and 2 stop bits not supported */
254      return -1;
255    mode2 |= 0x0F;                      /* 1 stop bit */
256  }
257
258  rtems_interrupt_disable(Irql);
259    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit );
260    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud_mask );
261    if ( cmd ) {
262      (*setReg)( pMC68681_port, MC68681_COMMAND, cmd );         /* RX */
263      (*setReg)( pMC68681_port, MC68681_COMMAND, cmd | 0x20 );  /* TX */
264    }
265    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
266    (*setReg)( pMC68681_port, MC68681_MODE, mode1 );
267    (*setReg)( pMC68681_port, MC68681_MODE, mode2 );
268  rtems_interrupt_enable(Irql);
269  return 0;
270}
271
272/*
273 *  mc68681_initialize_context
274 *
275 *  This function sets the default values of the per port context structure.
276 */
277
278MC68681_STATIC void mc68681_initialize_context(
279  int               minor,
280  mc68681_context  *pmc68681Context
281)
282{
283  int          port;
284  unsigned int pMC68681;
285 
286  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
287
288  pmc68681Context->mate = -1;
289
290  for (port=0 ; port<Console_Port_Count ; port++ ) {
291    if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 ) {
292      pmc68681Context->mate = port;
293      break;
294    }
295  }
296
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
307MC68681_STATIC unsigned int mc68681_build_imr(
308  int  minor,
309  int  enable_flag
310)
311{
312  int              mate;
313  unsigned int     mask;
314  unsigned int     mate_mask;
315  unsigned int     pMC68681;
316  unsigned int     pMC68681_port;
317  mc68681_context *pmc68681Context;
318 
319  pMC68681       = Console_Port_Tbl[minor].ulCtrlPort1;
320  pMC68681_port  = Console_Port_Tbl[minor].ulCtrlPort2;
321  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
322  mate            = pmc68681Context->mate;
323
324  mate_mask = 0;
325
326  /*
327   *  Decide if the other port on this DUART is using interrupts
328   */
329
330  if ( mate != -1 ) {
331    if ( Console_Port_Tbl[mate].pDeviceFns->deviceOutputUsesInterrupts )
332      mate_mask = 0x03;
333
334    /*
335     *  If equal, then minor is A so the mate must be B
336     */
337
338    if ( pMC68681 == pMC68681_port )
339      mate_mask <<= 4;
340  }
341
342  /*
343   *  Add in minor's mask
344   */
345
346  mask = 0;
347  if ( enable_flag ) {
348    if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) {
349      if ( pMC68681 == pMC68681_port )
350         mask = 0x03;
351      else
352         mask = 0x30;
353    }
354  }
355
356#if 0
357  return mask | mate_mask;
358#endif
359
360  return 0;
361}
362
363/*
364 *  mc68681_init
365 *
366 *  This function initializes the DUART to a quiecsent state.
367 */
368
369MC68681_STATIC void mc68681_init(int minor)
370{
371  unsigned32              pMC68681_port;
372  unsigned32              pMC68681;
373  mc68681_context        *pmc68681Context;
374  setRegister_f           setReg;
375  getRegister_f           getReg;
376
377  pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context));
378
379  Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context;
380
381  mc68681_initialize_context( minor, pmc68681Context );
382
383  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
384  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
385  setReg        = Console_Port_Tbl[minor].setRegister;
386  getReg        = Console_Port_Tbl[minor].getRegister;
387
388  /*
389   *  Reset everything and leave this port disabled.
390   */
391
392  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
393  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
394  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
395  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
396  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
397  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
398  (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
399
400
401  (*setReg)( pMC68681, MC68681_MODE_REG_1A, 0x00 );
402  (*setReg)( pMC68681, MC68681_MODE_REG_2A, 0x02 );
403
404  /*
405   *  Disable interrupts on RX and TX for this port
406   */
407
408  (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 0));
409}
410
411/*
412 *  mc68681_open
413 *
414 *  This function opens a port for communication.
415 *
416 *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
417 */
418
419MC68681_STATIC int mc68681_open(
420  int      major,
421  int      minor,
422  void    *arg
423)
424{
425  unsigned32             pMC68681;
426  unsigned32             pMC68681_port;
427  unsigned int           baud;
428  unsigned int           acr;
429  unsigned int           vector;
430  unsigned int           command;
431  rtems_interrupt_level  Irql;
432  setRegister_f          setReg;
433
434  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
435  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
436  setReg        = Console_Port_Tbl[minor].setRegister;
437  vector        = Console_Port_Tbl[minor].ulIntVector;
438
439  /* XXX default baud rate should be from configuration table */
440
441  (void) mc68681_baud_rate( minor, B9600, &baud, &acr, &command );
442
443  /*
444   *  Set the DUART channel to a default useable state
445   */
446
447  rtems_interrupt_disable(Irql);
448    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr );
449    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud );
450    if ( command ) {
451      (*setReg)( pMC68681_port, MC68681_COMMAND, command );         /* RX */
452      (*setReg)( pMC68681_port, MC68681_COMMAND, command | 0x20 );  /* TX */
453    }
454    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
455    (*setReg)( pMC68681_port, MC68681_MODE, 0x13 );
456    (*setReg)( pMC68681_port, MC68681_MODE, 0x07 );
457  rtems_interrupt_enable(Irql);
458
459  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX );
460  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX );
461
462  (*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector );
463
464  return RTEMS_SUCCESSFUL;
465}
466
467/*
468 *  mc68681_close
469 *
470 *  This function shuts down the requested port.
471 */
472
473MC68681_STATIC int mc68681_close(
474  int      major,
475  int      minor,
476  void    *arg
477)
478{
479  unsigned32      pMC68681;
480  unsigned32      pMC68681_port;
481  setRegister_f   setReg;
482
483  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;
484  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
485  setReg        = Console_Port_Tbl[minor].setRegister;
486
487  /*
488   *  Disable interrupts from this channel and then disable it totally.
489   */
490
491  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
492  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
493
494  return(RTEMS_SUCCESSFUL);
495}
496
497/*
498 *  mc68681_write_polled
499 *
500 *  This routine polls out the requested character.
501 */
502
503MC68681_STATIC void mc68681_write_polled(
504  int   minor,
505  char  cChar
506)
507{
508  unsigned32              pMC68681_port;
509  unsigned char           ucLineStatus;
510  int                     iTimeout;
511  getRegister_f           getReg;
512  setRegister_f           setReg;
513
514  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
515  getReg        = Console_Port_Tbl[minor].getRegister;
516  setReg        = Console_Port_Tbl[minor].setRegister;
517
518  /*
519   * wait for transmitter holding register to be empty
520   */
521  iTimeout = 1000;
522  ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
523  while ((ucLineStatus & (MC68681_TX_READY|MC68681_TX_EMPTY)) == 0) {
524
525    if ((ucLineStatus & 0xF0))
526      (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
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  unsigned 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_extended;
846  int              baud_requested;
847  mc68681_baud_table_t  *baud_tbl;
848
849  baud_mask = 0;
850  acr_bit = 0;
851  status = 0;
852
853  if ( !(Console_Port_Tbl[minor].ulDataPort & MC68681_DATA_BAUD_RATE_SET_1) )
854    acr_bit = 1;
855
856  is_extended = 0;
857
858  switch (Console_Port_Tbl[minor].ulDataPort & MC68681_XBRG_MASK) {
859    case MC68681_XBRG_IGNORED:
860      *command = 0x00;
861      break;
862    case MC68681_XBRG_ENABLED:
863      *command = 0x80;
864      is_extended = 1;
865      break;
866    case MC68681_XBRG_DISABLED:
867      *command = 0x90;
868      break;
869  }
870
871  baud_requested = baud & CBAUD;
872  if (!baud_requested)
873    baud_requested = B9600;              /* default to 9600 baud */
874 
875  baud_requested = termios_baud_to_index( baud_requested );
876
877  baud_tbl = (mc68681_baud_table_t *) Console_Port_Tbl[minor].ulClock;
878  if (!baud_tbl)
879    baud_tbl = (mc68681_baud_table_t *)mc68681_baud_rate_table;
880
881  if ( is_extended )
882    baud_mask = (unsigned int)baud_tbl[ acr_bit + 2 ][ baud_requested ];
883  else
884    baud_mask = baud_tbl[ acr_bit ][ baud_requested ];
885
886  if ( baud_mask == MC68681_BAUD_NOT_VALID )
887    status = -1;
888
889  /*
890   *  upper nibble is receiver and lower nibble is transmitter
891   */
892
893  *baud_mask_p = (baud_mask << 4) | baud_mask;
894  *acr_bit_p   = acr_bit;
895  return status;
896}
897
Note: See TracBrowser for help on using the repository browser.