source: rtems/c/src/libchip/serial/mc68681.c @ 1c6926c1

5
Last change on this file since 1c6926c1 was 1c6926c1, checked in by Kevin Kirspel <kevin-kirspel@…>, on 03/21/17 at 19:39:48

termios: Synchronize with latest FreeBSD headers

Adding modified FreeBSD headers to synchronize RTEMS termios with
FreeBSD. Modify termios to support dedicated input and output baud for
termios structure. Updated BSPs to use dedicated input and output baud
in termios structure. Updated tools to use dedicated input and output
baud in termios structure. Updated termios testsuites to use dedicated
input and output baud in termios structure.

Close #2897.

  • Property mode set to 100644
File size: 18.8 KB
RevLine 
[cd58d82]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 *
[08311cc3]9 *  COPYRIGHT (c) 1989-1999.
[cd58d82]10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
[c499856]14 *  http://www.rtems.org/license/LICENSE.
[cd58d82]15 */
16
17#include <rtems.h>
18#include <rtems/libio.h>
[39046f7]19#include <rtems/score/sysstate.h>
[cd58d82]20#include <stdlib.h>
21
22#include <libchip/serial.h>
[a6f441b]23#include <libchip/mc68681.h>
[7e05b53]24#include <libchip/sersupp.h>
[cd58d82]25#include "mc68681_p.h"
26
27/*
28 * Flow control is only supported when using interrupts
29 */
[424e23ee]30
[c8bd3cd]31const console_fns mc68681_fns =
[cd58d82]32{
[693b5b88]33  libchip_serial_default_probe,   /* deviceProbe */
[cd58d82]34  mc68681_open,                   /* deviceFirstOpen */
[198d851]35  NULL,                           /* deviceLastClose */
[cd58d82]36  NULL,                           /* deviceRead */
37  mc68681_write_support_int,      /* deviceWrite */
38  mc68681_initialize_interrupts,  /* deviceInitialize */
39  mc68681_write_polled,           /* deviceWritePolled */
[25c3ff91]40  mc68681_set_attributes,         /* deviceSetAttributes */
[6640459d]41  true                            /* deviceOutputUsesInterrupts */
[cd58d82]42};
43
[c8bd3cd]44const console_fns mc68681_fns_polled =
[cd58d82]45{
[693b5b88]46  libchip_serial_default_probe,        /* deviceProbe */
[cd58d82]47  mc68681_open,                        /* deviceFirstOpen */
48  mc68681_close,                       /* deviceLastClose */
49  mc68681_inbyte_nonblocking_polled,   /* deviceRead */
50  mc68681_write_support_polled,        /* deviceWrite */
51  mc68681_init,                        /* deviceInitialize */
52  mc68681_write_polled,                /* deviceWritePolled */
[25c3ff91]53  mc68681_set_attributes,              /* deviceSetAttributes */
[6640459d]54  false,                               /* deviceOutputUsesInterrupts */
[cd58d82]55};
56
[a29909cb]57
58#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE)
59  extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
60#endif
[cd58d82]61
62/*
63 *  Console Device Driver Entry Points
64 */
[424e23ee]65
[beaaf49f]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
[2d8e51aa]74MC68681_STATIC int mc68681_baud_rate(
[25c3ff91]75  int           minor,
76  int           baud,
77  unsigned int *baud_mask_p,
[2d8e51aa]78  unsigned int *acr_bit_p,
79  unsigned int *command
80);
[25c3ff91]81
[beaaf49f]82/*
83 *  mc68681_set_attributes
84 *
85 *  This function sets the DUART channel to reflect the requested termios
86 *  port settings.
87 */
88
[a3d3d9a]89MC68681_STATIC int mc68681_set_attributes(
[25c3ff91]90  int minor,
91  const struct termios *t
92)
93{
[ee4f57d]94  uint32_t               pMC68681_port;
95  uint32_t               pMC68681;
[25c3ff91]96  unsigned int           mode1;
97  unsigned int           mode2;
98  unsigned int           baud_mask;
99  unsigned int           acr_bit;
[b7acc4ad]100  unsigned int           cmd = 0;
[25c3ff91]101  setRegister_f          setReg;
102  rtems_interrupt_level  Irql;
[cd58d82]103
[229bcca8]104  pMC68681      = Console_Port_Tbl[minor]->ulCtrlPort1;
105  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
106  setReg        = Console_Port_Tbl[minor]->setRegister;
[7deeb16]107
108  /*
[25c3ff91]109   *  Set the baud rate
[7deeb16]110   */
111
[2d8e51aa]112  if (mc68681_baud_rate( minor, t->c_cflag, &baud_mask, &acr_bit, &cmd ) == -1)
[25c3ff91]113    return -1;
114
115  baud_mask |=  baud_mask << 4;
116  acr_bit   <<= 7;
[7deeb16]117
118  /*
[25c3ff91]119   *  Parity
[7deeb16]120   */
121
[25c3ff91]122  mode1 = 0;
123  mode2 = 0;
[7deeb16]124
[25c3ff91]125  if (t->c_cflag & PARENB) {
126    if (t->c_cflag & PARODD)
127      mode1 |= 0x04;
[5ca5a54]128    /* else
129                mode1 |= 0x04; */
[25c3ff91]130  } else {
131   mode1 |= 0x10;
132  }
[cd58d82]133
[25c3ff91]134  /*
135   *  Character Size
[cd58d82]136   */
137
[25c3ff91]138  if (t->c_cflag & CSIZE) {
139    switch (t->c_cflag & CSIZE) {
140      case CS5:  break;
141      case CS6:  mode1 |= 0x01;  break;
142      case CS7:  mode1 |= 0x02;  break;
143      case CS8:  mode1 |= 0x03;  break;
144    }
145  } else {
146    mode1 |= 0x03;       /* default to 9600,8,N,1 */
147  }
[cd58d82]148
[25c3ff91]149  /*
150   *  Stop Bits
151   */
[a3d3d9a]152
[25c3ff91]153  if (t->c_cflag & CSTOPB) {
[5ca5a54]154    mode2 |= 0x0F;                      /* 2 stop bits */
[25c3ff91]155  } else {
[5ca5a54]156    if ((t->c_cflag & CSIZE) == CS5)    /* CS5 and 1 stop bits not supported */
[25c3ff91]157      return -1;
[5ca5a54]158    mode2 |= 0x07;                      /* 1 stop bit */
[25c3ff91]159  }
[cd58d82]160
[5ca5a54]161 /*
162  *   Hardware Flow Control
163  */
164
165  if(t->c_cflag & CRTSCTS) {
166          mode1 |= 0x80; /* Enable Rx RTS Control */
167          mode2 |= 0x10; /* Enable CTS Enable Tx */
168  }
169
170
[25c3ff91]171  rtems_interrupt_disable(Irql);
172    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit );
173    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud_mask );
[2c5ea01]174    if ( cmd ) {
175      (*setReg)( pMC68681_port, MC68681_COMMAND, cmd );         /* RX */
176      (*setReg)( pMC68681_port, MC68681_COMMAND, cmd | 0x20 );  /* TX */
177    }
[25c3ff91]178    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
179    (*setReg)( pMC68681_port, MC68681_MODE, mode1 );
180    (*setReg)( pMC68681_port, MC68681_MODE, mode2 );
181  rtems_interrupt_enable(Irql);
182  return 0;
183}
[cd58d82]184
[beaaf49f]185/*
186 *  mc68681_initialize_context
187 *
188 *  This function sets the default values of the per port context structure.
189 */
190
[2d8e51aa]191MC68681_STATIC void mc68681_initialize_context(
[a5d0c7c]192  int               minor,
193  mc68681_context  *pmc68681Context
194)
195{
196  int          port;
197  unsigned int pMC68681;
[be8cbbf]198  unsigned int pMC68681_port;
[a3d3d9a]199
[229bcca8]200  pMC68681      = Console_Port_Tbl[minor]->ulCtrlPort1;
201  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
[a5d0c7c]202
203  pmc68681Context->mate = -1;
204
205  for (port=0 ; port<Console_Port_Count ; port++ ) {
[229bcca8]206    if ( Console_Port_Tbl[port]->ulCtrlPort1 == pMC68681 &&
207         Console_Port_Tbl[port]->ulCtrlPort2 != pMC68681_port ) {
[a5d0c7c]208      pmc68681Context->mate = port;
[198d851]209      pmc68681Context->imr  = 0;
[a5d0c7c]210      break;
211    }
212  }
213
214}
215
[beaaf49f]216/*
217 *  mc68681_init
218 *
219 *  This function initializes the DUART to a quiecsent state.
220 */
221
[2d8e51aa]222MC68681_STATIC void mc68681_init(int minor)
[25c3ff91]223{
[ee4f57d]224  uint32_t                pMC68681_port;
[25c3ff91]225  mc68681_context        *pmc68681Context;
226  setRegister_f           setReg;
227
228  pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context));
[cd58d82]229
[25c3ff91]230  Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context;
[a5d0c7c]231
232  mc68681_initialize_context( minor, pmc68681Context );
[cd58d82]233
[229bcca8]234  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
235  setReg        = Console_Port_Tbl[minor]->setRegister;
[cd58d82]236
237  /*
[25c3ff91]238   *  Reset everything and leave this port disabled.
[cd58d82]239   */
240
[198d851]241  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
242  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
243  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
244  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
245  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
246  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
247  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
[cd58d82]248
[25c3ff91]249
[198d851]250  (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 );
251  (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 );
[4f0ffa57]252
253  /*
254   *  Disable interrupts on RX and TX for this port
255   */
256
[198d851]257  mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL );
[cd58d82]258}
259
[25c3ff91]260/*
[beaaf49f]261 *  mc68681_open
262 *
263 *  This function opens a port for communication.
264 *
265 *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
[25c3ff91]266 */
267
[2d8e51aa]268MC68681_STATIC int mc68681_open(
[cd58d82]269  int      major,
270  int      minor,
[25c3ff91]271  void    *arg
[cd58d82]272)
273{
[ee4f57d]274  uint32_t               pMC68681;
275  uint32_t               pMC68681_port;
[25c3ff91]276  unsigned int           baud;
[5ca5a54]277  unsigned int           acr_bit;
[25c3ff91]278  unsigned int           vector;
[48b8259]279  unsigned int           command = 0;
[25c3ff91]280  rtems_interrupt_level  Irql;
281  setRegister_f          setReg;
[2186f401]282  int                    status;
[a3d3d9a]283
284
[229bcca8]285  pMC68681      = Console_Port_Tbl[minor]->ulCtrlPort1;
286  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
287  setReg        = Console_Port_Tbl[minor]->setRegister;
288  vector        = Console_Port_Tbl[minor]->ulIntVector;
[a3d3d9a]289
[e78c474b]290  /* XXX default baud rate should be from configuration table */
291
[5ca5a54]292  status = mc68681_baud_rate( minor, B9600, &baud, &acr_bit, &command );
293  if (status < 0) rtems_fatal_error_occurred (RTEMS_NOT_DEFINED);
[25c3ff91]294
[b7ebcea3]295  /*
296   *  Set the DUART channel to a default useable state
297   */
298
[25c3ff91]299  rtems_interrupt_disable(Irql);
[5ca5a54]300    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit << 7 );
[25c3ff91]301    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud );
[e78c474b]302    if ( command ) {
303      (*setReg)( pMC68681_port, MC68681_COMMAND, command );         /* RX */
304      (*setReg)( pMC68681_port, MC68681_COMMAND, command | 0x20 );  /* TX */
305    }
[25c3ff91]306    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
307    (*setReg)( pMC68681_port, MC68681_MODE, 0x13 );
308    (*setReg)( pMC68681_port, MC68681_MODE, 0x07 );
309  rtems_interrupt_enable(Irql);
310
311  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX );
312  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX );
313
314  (*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector );
315
[4f0ffa57]316  return RTEMS_SUCCESSFUL;
[cd58d82]317}
318
[beaaf49f]319/*
320 *  mc68681_close
321 *
322 *  This function shuts down the requested port.
323 */
324
[2d8e51aa]325MC68681_STATIC int mc68681_close(
[cd58d82]326  int      major,
327  int      minor,
[25c3ff91]328  void    *arg
[cd58d82]329)
330{
[ee4f57d]331  uint32_t        pMC68681_port;
[b7ebcea3]332  setRegister_f   setReg;
333
[229bcca8]334  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
335  setReg        = Console_Port_Tbl[minor]->setRegister;
[b7ebcea3]336
337  /*
338   *  Disable interrupts from this channel and then disable it totally.
339   */
340  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
341  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
342
[cd58d82]343  return(RTEMS_SUCCESSFUL);
344}
345
[a3d3d9a]346/*
[cd58d82]347 *  mc68681_write_polled
[beaaf49f]348 *
349 *  This routine polls out the requested character.
[cd58d82]350 */
[424e23ee]351
[2d8e51aa]352MC68681_STATIC void mc68681_write_polled(
[a3d3d9a]353  int   minor,
[cd58d82]354  char  cChar
355)
356{
[ee4f57d]357  uint32_t                pMC68681_port;
[cd58d82]358  unsigned char           ucLineStatus;
359  int                     iTimeout;
360  getRegister_f           getReg;
[25c3ff91]361  setRegister_f           setReg;
[cd58d82]362
[229bcca8]363  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
364  getReg        = Console_Port_Tbl[minor]->getRegister;
365  setReg        = Console_Port_Tbl[minor]->setRegister;
[cd58d82]366
367  /*
368   * wait for transmitter holding register to be empty
369   */
[ab2dbd7]370  iTimeout = 1000;
[25c3ff91]371  ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
[2c5ea01]372  while ((ucLineStatus & (MC68681_TX_READY|MC68681_TX_EMPTY)) == 0) {
373
374    if ((ucLineStatus & 0xF0))
375      (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
[ab2dbd7]376
[cd58d82]377    /*
378     * Yield while we wait
379     */
[ab2dbd7]380
[0eb85ae]381#if 0
[cd58d82]382     if(_System_state_Is_up(_System_state_Get())) {
383       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
384     }
[0eb85ae]385#endif
[25c3ff91]386     ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
[cd58d82]387     if(!--iTimeout) {
388       break;
389     }
390  }
391
392  /*
393   * transmit character
394   */
[ab2dbd7]395
[25c3ff91]396  (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);
[cd58d82]397}
398
[4f0ffa57]399/*
400 *  mc68681_isr
401 *
402 *  This is the single interrupt entry point which parcels interrupts
403 *  out to the various ports.
404 */
405
[2d8e51aa]406MC68681_STATIC rtems_isr mc68681_isr(
[cd58d82]407  rtems_vector_number vector
408)
409{
410  int     minor;
411
[ab2dbd7]412  for(minor=0 ; minor<Console_Port_Count ; minor++) {
[229bcca8]413    if(Console_Port_Tbl[minor]->ulIntVector == vector &&
414       Console_Port_Tbl[minor]->deviceType == SERIAL_MC68681 ) {
[cd58d82]415      mc68681_process(minor);
416    }
417  }
418}
419
[beaaf49f]420/*
421 *  mc68681_initialize_interrupts
422 *
423 *  This routine initializes the console's receive and transmit
424 *  ring buffers and loads the appropriate vectors to handle the interrupts.
425 */
426
[2d8e51aa]427MC68681_STATIC void mc68681_initialize_interrupts(int minor)
[cd58d82]428{
429  mc68681_init(minor);
430
431  Console_Port_Data[minor].bActive = FALSE;
432
[a29909cb]433#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE)
[229bcca8]434  set_vector(mc68681_isr, Console_Port_Tbl[minor]->ulIntVector, 1);
[a29909cb]435#endif
[cd58d82]436
[198d851]437  mc68681_enable_interrupts(minor,MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
[cd58d82]438}
439
[a3d3d9a]440/*
[cd58d82]441 *  mc68681_write_support_int
442 *
[beaaf49f]443 *  Console Termios output entry point when using interrupt driven output.
[cd58d82]444 */
[ab2dbd7]445
[3ed964f9]446MC68681_STATIC ssize_t mc68681_write_support_int(
[a3d3d9a]447  int         minor,
448  const char *buf,
[3ed964f9]449  size_t      len
[cd58d82]450)
451{
[ee4f57d]452  uint32_t        Irql;
453  uint32_t        pMC68681_port;
[198d851]454  setRegister_f   setReg;
455
[229bcca8]456  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
457  setReg        = Console_Port_Tbl[minor]->setRegister;
[cd58d82]458
459  /*
[b070d69a]460   *  We are using interrupt driven output and termios only sends us
461   *  one character at a time.
[cd58d82]462   */
[ab2dbd7]463
[198d851]464  if ( !len )
465    return 0;
[cd58d82]466
[198d851]467  /*
[b070d69a]468   *  Put the character out and enable interrupts if necessary.
[198d851]469   */
[b070d69a]470
[198d851]471  rtems_interrupt_disable(Irql);
[c68b990]472    if ( Console_Port_Data[minor].bActive == FALSE ) {
473      Console_Port_Data[minor].bActive = TRUE;
474      mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL);
475    }
[198d851]476    (*setReg)(pMC68681_port, MC68681_TX_BUFFER, *buf);
477  rtems_interrupt_enable(Irql);
[b070d69a]478
[3ed964f9]479  return 0;
[cd58d82]480}
481
[a3d3d9a]482/*
[cd58d82]483 *  mc68681_write_support_polled
484 *
[beaaf49f]485 *  Console Termios output entry point when using polled output.
[cd58d82]486 *
487 */
[ab2dbd7]488
[3ed964f9]489MC68681_STATIC ssize_t mc68681_write_support_polled(
[a3d3d9a]490  int         minor,
491  const char *buf,
[3ed964f9]492  size_t      len
[cd58d82]493)
494{
495  int nwrite = 0;
496
497  /*
498   * poll each byte in the string out of the port.
499   */
500  while (nwrite < len) {
501    /*
502     * transmit character
503     */
504    mc68681_write_polled(minor, *buf++);
505    nwrite++;
506  }
507
508  /*
509   * return the number of bytes written.
510   */
511  return nwrite;
512}
513
[a3d3d9a]514/*
515 *  mc68681_inbyte_nonblocking_polled
[cd58d82]516 *
517 *  Console Termios polling input entry point.
518 */
519
[a3d3d9a]520MC68681_STATIC int mc68681_inbyte_nonblocking_polled(
521  int minor
[cd58d82]522)
523{
[ee4f57d]524  uint32_t             pMC68681_port;
[cd58d82]525  unsigned char        ucLineStatus;
[2c5ea01]526  unsigned char        cChar;
[cd58d82]527  getRegister_f        getReg;
528
[229bcca8]529  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
530  getReg        = Console_Port_Tbl[minor]->getRegister;
[cd58d82]531
[25c3ff91]532  ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
[ab2dbd7]533  if(ucLineStatus & MC68681_RX_READY) {
[25c3ff91]534    cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
[ab2dbd7]535    return (int)cChar;
[cd58d82]536  } else {
[25c3ff91]537    return -1;
[cd58d82]538  }
539}
[2d8e51aa]540
[749c54e]541/*
542 *  mc68681_baud_rate
543 */
544
[2d8e51aa]545MC68681_STATIC int mc68681_baud_rate(
546  int           minor,
547  int           baud,
548  unsigned int *baud_mask_p,
549  unsigned int *acr_bit_p,
550  unsigned int *command
551)
552{
[dd5d2f04]553  unsigned int           baud_mask;
554  unsigned int           acr_bit;
555  int                    status;
556  int                    is_extended;
557  int                    baud_requested;
[2d8e51aa]558  mc68681_baud_table_t  *baud_tbl;
559
560  baud_mask = 0;
561  acr_bit = 0;
562  status = 0;
563
[229bcca8]564  if (Console_Port_Tbl[minor]->ulDataPort & MC68681_DATA_BAUD_RATE_SET_2)
[5ca5a54]565  {
[2d8e51aa]566    acr_bit = 1;
[5ca5a54]567  }
[2d8e51aa]568
569  is_extended = 0;
570
[229bcca8]571  switch (Console_Port_Tbl[minor]->ulDataPort & MC68681_XBRG_MASK) {
[2d8e51aa]572    case MC68681_XBRG_IGNORED:
573      *command = 0x00;
574      break;
575    case MC68681_XBRG_ENABLED:
[2c5ea01]576      *command = 0x80;
[2d8e51aa]577      is_extended = 1;
578      break;
579    case MC68681_XBRG_DISABLED:
[2c5ea01]580      *command = 0x90;
[2d8e51aa]581      break;
582  }
583
[1c6926c1]584  baud_requested = baud;
[2d8e51aa]585  if (!baud_requested)
[2c5ea01]586    baud_requested = B9600;              /* default to 9600 baud */
[a3d3d9a]587
[64a1529]588  baud_requested = rtems_termios_baud_to_index( baud_requested );
[17d1aa7]589  if (baud_requested == -1)
590    return -1;
[2d8e51aa]591
[642c500]592  baud_tbl = (mc68681_baud_table_t *)
[229bcca8]593     ((uintptr_t)Console_Port_Tbl[minor]->ulClock);
[2d8e51aa]594  if (!baud_tbl)
[a6f441b]595    rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS);
[2d8e51aa]596
597  if ( is_extended )
598    baud_mask = (unsigned int)baud_tbl[ acr_bit + 2 ][ baud_requested ];
599  else
600    baud_mask = baud_tbl[ acr_bit ][ baud_requested ];
601
602  if ( baud_mask == MC68681_BAUD_NOT_VALID )
603    status = -1;
604
[2c5ea01]605  /*
606   *  upper nibble is receiver and lower nibble is transmitter
607   */
608
609  *baud_mask_p = (baud_mask << 4) | baud_mask;
[2d8e51aa]610  *acr_bit_p   = acr_bit;
611  return status;
612}
613
[be8cbbf]614/*
615 *  mc68681_process
616 *
617 *  This routine is the per port console interrupt handler.
618 */
619
620MC68681_STATIC void mc68681_process(
621  int  minor
622)
623{
[ee4f57d]624  uint32_t                pMC68681;
625  uint32_t                pMC68681_port;
[a3d3d9a]626  volatile uint8_t        ucLineStatus;
627  volatile uint8_t        ucISRStatus;
[e11bf43]628  char                    cChar;
[be8cbbf]629  getRegister_f           getReg;
630
[229bcca8]631  pMC68681      = Console_Port_Tbl[minor]->ulCtrlPort1;
632  pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
633  getReg        = Console_Port_Tbl[minor]->getRegister;
[be8cbbf]634
[a3d3d9a]635  /* Get ISR at the beginning of the IT routine */
[5ca5a54]636  ucISRStatus = (*getReg)(pMC68681, MC68681_INTERRUPT_STATUS_REG);
[a3d3d9a]637
[5ca5a54]638  /* Get good ISR a or b channel */
639  if (pMC68681 != pMC68681_port){
640    ucISRStatus >>= 4;
641  }
[a3d3d9a]642
[5ca5a54]643  /* See if is usefull to call rtems_termios_dequeue */
644  if(Console_Port_Data[minor].bActive == FALSE) {
645                ucISRStatus = ucISRStatus & ~MC68681_IR_TX_READY;
646  }
647
[be8cbbf]648  /*
649   * Deal with any received characters
650   */
[6640459d]651  while(true) {
[be8cbbf]652    ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
653    if(!(ucLineStatus & MC68681_RX_READY)) {
654      break;
655    }
656    /*
657     *  If there is a RX error, then dump all the data.
658     */
659    if ( ucLineStatus & MC68681_RX_ERRORS ) {
660      do {
661        cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
662        ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
663      } while ( ucLineStatus & MC68681_RX_READY );
664      continue;
665    }
666    cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
[a3d3d9a]667    rtems_termios_enqueue_raw_characters(
[be8cbbf]668      Console_Port_Data[minor].termios_data,
[a3d3d9a]669      &cChar,
670      1
[be8cbbf]671    );
672  }
673
674  /*
675   *  Deal with the transmitter
676   */
677
[5ca5a54]678  if (ucISRStatus & MC68681_IR_TX_READY) {
679    if (!rtems_termios_dequeue_characters(
680          Console_Port_Data[minor].termios_data, 1)) {
681          /* If no more char to send, disable TX interrupt */
[c68b990]682      Console_Port_Data[minor].bActive = FALSE;
683      mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
684    }
[be8cbbf]685  }
686}
687
688/*
689 *  mc68681_build_imr
690 *
691 *  This function returns the value for the interrupt mask register for this
692 *  DUART.  Since this is a shared register, we must look at the other port
693 *  on this chip to determine whether or not it is using interrupts.
694 */
695
696MC68681_STATIC unsigned int mc68681_build_imr(
697  int  minor,
698  int  enable_flag
699)
700{
701  int              mate;
[198d851]702  int              is_a;
[be8cbbf]703  unsigned int     mask;
704  unsigned int     mate_mask;
705  unsigned int     pMC68681;
706  unsigned int     pMC68681_port;
707  mc68681_context *pmc68681Context;
[198d851]708  mc68681_context *mateContext;
[a3d3d9a]709
[229bcca8]710  pMC68681        = Console_Port_Tbl[minor]->ulCtrlPort1;
711  pMC68681_port   = Console_Port_Tbl[minor]->ulCtrlPort2;
[be8cbbf]712  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
713  mate            = pmc68681Context->mate;
714
[198d851]715  mask = 0;
[be8cbbf]716  mate_mask = 0;
717
[198d851]718  is_a = (pMC68681 == pMC68681_port);
[a3d3d9a]719
[be8cbbf]720  /*
[198d851]721   *  If there is a mate for this port, get its IMR mask.
[be8cbbf]722   */
723
724  if ( mate != -1 ) {
[198d851]725    mateContext = Console_Port_Data[mate].pDeviceContext;
[a3d3d9a]726
[198d851]727    if (mateContext)
728      mate_mask = mateContext->imr;
729  }
[be8cbbf]730
[198d851]731  /*
732   *  Calculate this port's IMR mask and save it in the context area.
733   */
[be8cbbf]734
[229bcca8]735  if ( Console_Port_Tbl[minor]->pDeviceFns->deviceOutputUsesInterrupts )
[198d851]736    mask = enable_flag;
737
738  pmc68681Context->imr = mask;
[be8cbbf]739
740  /*
[198d851]741   *  Now return the full IMR value
[be8cbbf]742   */
743
[198d851]744  if (is_a)
745    return (mate_mask << 4) | mask;
746
747  return (mask << 4) | mate_mask;
748}
749
750/*
751 *  mc68681_enable_interrupts
752 *
[70502bc4]753 *  This function enables specific interrupt sources on the DUART.
[198d851]754 */
755
756MC68681_STATIC void mc68681_enable_interrupts(
757  int minor,
758  int imr_mask
759)
760{
[ee4f57d]761  uint32_t              pMC68681;
[198d851]762  setRegister_f         setReg;
763
[229bcca8]764  pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
765  setReg   = Console_Port_Tbl[minor]->setRegister;
[198d851]766
767  /*
768   *  Enable interrupts on RX and TX -- not break
769   */
[be8cbbf]770
[198d851]771  (*setReg)(
772     pMC68681,
773     MC68681_INTERRUPT_MASK_REG,
774     mc68681_build_imr(minor, imr_mask)
775  );
[be8cbbf]776}
Note: See TracBrowser for help on using the repository browser.