source: rtems/c/src/libchip/serial/mc68681.c @ ab2dbd7

4.104.114.84.95
Last change on this file since ab2dbd7 was ab2dbd7, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 22, 1998 at 11:09:32 AM

Added mc68681 stuff to the makefile.

Added numerous constants to mc68681_p.h.

Changed spacing.

At this point the polled support is in but nothing else is right except the
structure.

  • Property mode set to 100644
File size: 14.7 KB
Line 
1/*
2 *  This file contains the termios TTY driver for the Motorola MC68681.
3 *
4 *  This part is available from a number of secondary sources.
5 *  In particular, we know about the following:
6 *
7 *     + Exar 88c681 and 68c681
8 *
9 *  COPYRIGHT (c) 1989-1998.
10 *  On-Line Applications Research Corporation (OAR).
11 *  Copyright assigned to U.S. Government, 1994.
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.OARcorp.com/rtems/license.html.
16 *
17 *  $Id$
18 */
19
20#include <rtems.h>
21#include <rtems/libio.h>
22#include <stdlib.h>
23#include <ringbuf.h>
24
25#include <libchip/serial.h>
26#include "mc68681_p.h"
27#include "mc68681.h"
28
29/*
30 * Flow control is only supported when using interrupts
31 */
32
33console_flow mc68681_flow_RTSCTS =
34{
35  mc68681_negate_RTS,             /* deviceStopRemoteTx */
36  mc68681_assert_RTS              /* deviceStartRemoteTx */
37};
38
39console_flow mc68681_flow_DTRCTS =
40{
41  mc68681_negate_DTR,             /* deviceStopRemoteTx */
42  mc68681_assert_DTR              /* deviceStartRemoteTx */
43};
44
45console_fns mc68681_fns =
46{
47  mc68681_probe,                  /* deviceProbe */
48  mc68681_open,                   /* deviceFirstOpen */
49  mc68681_flush,                  /* deviceLastClose */
50  NULL,                           /* deviceRead */
51  mc68681_write_support_int,      /* deviceWrite */
52  mc68681_initialize_interrupts,  /* deviceInitialize */
53  mc68681_write_polled,           /* deviceWritePolled */
54  FALSE,                          /* deviceOutputUsesInterrupts */
55};
56
57console_fns mc68681_fns_polled =
58{
59  mc68681_probe,                       /* deviceProbe */
60  mc68681_open,                        /* deviceFirstOpen */
61  mc68681_close,                       /* deviceLastClose */
62  mc68681_inbyte_nonblocking_polled,   /* deviceRead */
63  mc68681_write_support_polled,        /* deviceWrite */
64  mc68681_init,                        /* deviceInitialize */
65  mc68681_write_polled,                /* deviceWritePolled */
66  FALSE,                               /* deviceOutputUsesInterrupts */
67};
68
69extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
70
71/*
72 *  Console Device Driver Entry Points
73 */
74
75static boolean mc68681_probe(int minor)
76{
77  /*
78   * If the configuration dependent probe has located the device then
79   * assume it is there
80   */
81  return(TRUE);
82}
83
84static void mc68681_init(int minor)
85{
86/* XXX */
87  unsigned32              pMC68681;
88  unsigned8               ucTrash;
89  unsigned8               ucDataByte;
90  unsigned32              ulBaudDivisor;
91  mc68681_context        *pmc68681Context;
92  setRegister_f           setReg;
93  getRegister_f           getReg;
94
95#if 1
96ulBaudDivisor = ucDataByte = ucTrash =  0;
97#endif
98  pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context));
99
100  Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context;
101#if 0
102  pmc68681Context->ucModemCtrl = SP_MODEM_IRQ;
103#endif
104
105  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
106  setReg   = Console_Port_Tbl[minor].setRegister;
107  getReg   = Console_Port_Tbl[minor].getRegister;
108
109#if 0
110  /* Clear the divisor latch, clear all interrupt enables,
111   * and reset and
112   * disable the FIFO's.
113   */
114
115  (*setReg)(pMC68681, MC68681_LINE_CONTROL, 0x0);
116  (*setReg)(pMC68681, MC68681_INTERRUPT_ENABLE, 0x0);
117
118  /* Set the divisor latch and set the baud rate. */
119
120  ulBaudDivisor=MC68681_Baud((unsigned32)Console_Port_Tbl[minor].pDeviceParams);
121  ucDataByte = SP_LINE_DLAB;
122  (*setReg)(pMC68681, MC68681_LINE_CONTROL, ucDataByte);
123  (*setReg)(pMC68681, MC68681_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
124  (*setReg)(pMC68681, MC68681_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
125
126  /* Clear the divisor latch and set the character size to eight bits */
127  /* with one stop bit and no parity checking. */
128  ucDataByte = EIGHT_BITS;
129  (*setReg)(pMC68681, MC68681_LINE_CONTROL, ucDataByte);
130
131  /* Enable and reset transmit and receive FIFOs. TJA     */
132  ucDataByte = SP_FIFO_ENABLE;
133  (*setReg)(pMC68681, MC68681_FIFO_CONTROL, ucDataByte);
134
135  ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
136  (*setReg)(pMC68681, MC68681_FIFO_CONTROL, ucDataByte);
137
138  /*
139   * Disable interrupts
140   */
141  ucDataByte = 0;
142  (*setReg)(pMC68681, MC68681_INTERRUPT_ENABLE, ucDataByte);
143
144  /* Set data terminal ready. */
145  /* And open interrupt tristate line */
146  (*setReg)(pMC68681, MC68681_MODEM_CONTROL,pmc68681Context->ucModemCtrl);
147
148  ucTrash = (*getReg)(pMC68681, MC68681_LINE_STATUS );
149  ucTrash = (*getReg)(pMC68681, MC68681_RECEIVE_BUFFER );
150#endif
151}
152
153static int mc68681_open(
154  int      major,
155  int      minor,
156  void    * arg
157)
158{
159/* XXX */
160  /*
161   * Assert DTR
162   */
163
164  if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_DTRCTS) {
165    mc68681_assert_DTR(minor);
166  }
167
168  return(RTEMS_SUCCESSFUL);
169}
170
171static int mc68681_close(
172  int      major,
173  int      minor,
174  void    * arg
175)
176{
177/* XXX */
178  /*
179   * Negate DTR
180   */
181  if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_DTRCTS) {
182    mc68681_negate_DTR(minor);
183  }
184
185  return(RTEMS_SUCCESSFUL);
186}
187
188/*
189 *  mc68681_write_polled
190 */
191
192static void mc68681_write_polled(
193  int   minor, 
194  char  cChar
195)
196{
197  unsigned32              pMC68681;
198  unsigned char           ucLineStatus;
199  int                     iTimeout;
200  getRegister_f           getReg;
201  setData_f               setData;
202
203  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
204  getReg   = Console_Port_Tbl[minor].getRegister;
205  setData  = Console_Port_Tbl[minor].setData;
206
207  /*
208   * wait for transmitter holding register to be empty
209   */
210  iTimeout = 1000;
211  ucLineStatus = (*getReg)(pMC68681, MC68681_STATUS_REG);
212  while ((ucLineStatus & MC68681_TX_READY) == 0) {
213
214    /*
215     * Yield while we wait
216     */
217
218     if(_System_state_Is_up(_System_state_Get())) {
219       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
220     }
221     ucLineStatus = (*getReg)(pMC68681, MC68681_STATUS_REG);
222     if(!--iTimeout) {
223       break;
224     }
225  }
226
227  /*
228   * transmit character
229   */
230
231  (*setData)(pMC68681, cChar);
232}
233
234/*
235 * These routines provide control of the RTS and DTR lines
236 */
237
238/*
239 *  mc68681_assert_RTS
240 */
241
242static int mc68681_assert_RTS(int minor)
243{
244/* XXX */
245
246  unsigned32              pMC68681;
247  unsigned32              Irql;
248  mc68681_context        *pmc68681Context;
249  setRegister_f           setReg;
250
251
252  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
253
254  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
255  setReg   = Console_Port_Tbl[minor].setRegister;
256
257  /*
258   * Assert RTS
259   */
260  rtems_interrupt_disable(Irql);
261#if 0
262  pmc68681Context->ucModemCtrl |= SP_MODEM_RTS;
263  (*setReg)(pMC68681, MC68681_MODEM_CONTROL, pmc68681Context->ucModemCtrl);
264#endif
265  rtems_interrupt_enable(Irql);
266  return 0;
267}
268
269/*
270 *  mc68681_negate_RTS
271 */
272static int mc68681_negate_RTS(int minor)
273{
274/* XXX */
275  unsigned32              pMC68681;
276  unsigned32              Irql;
277  mc68681_context        *pmc68681Context;
278  setRegister_f           setReg;
279
280  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
281
282  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
283  setReg   = Console_Port_Tbl[minor].setRegister;
284
285  /*
286   * Negate RTS
287   */
288  rtems_interrupt_disable(Irql);
289#if 0
290  pmc68681Context->ucModemCtrl &= ~SP_MODEM_RTS;
291  (*setReg)(pMC68681, MC68681_MODEM_CONTROL, pmc68681Context->ucModemCtrl);
292#endif
293  rtems_interrupt_enable(Irql);
294  return 0;
295}
296
297/*
298 * These flow control routines utilise a connection from the local DTR
299 * line to the remote CTS line
300 */
301
302/*
303 *  mc68681_assert_DTR
304 */
305
306static int mc68681_assert_DTR(int minor)
307{
308/* XXX */
309  unsigned32              pMC68681;
310  unsigned32              Irql;
311  mc68681_context        *pmc68681Context;
312  setRegister_f           setReg;
313
314  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
315
316  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
317  setReg   = Console_Port_Tbl[minor].setRegister;
318
319  /*
320   * Assert DTR
321   */
322  rtems_interrupt_disable(Irql);
323#if 0
324  pmc68681Context->ucModemCtrl |= SP_MODEM_DTR;
325  (*setReg)(pMC68681, MC68681_MODEM_CONTROL, pmc68681Context->ucModemCtrl);
326#endif
327  rtems_interrupt_enable(Irql);
328  return 0;
329}
330
331/*
332 *  mc68681_negate_DTR
333 */
334
335static int mc68681_negate_DTR(int minor)
336{
337/* XXX */
338  unsigned32              pMC68681;
339  unsigned32              Irql;
340  mc68681_context        *pmc68681Context;
341  setRegister_f           setReg;
342
343  pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
344
345  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
346  setReg   = Console_Port_Tbl[minor].setRegister;
347
348  /*
349   * Negate DTR
350   */
351  rtems_interrupt_disable(Irql);
352#if 0
353  pmc68681Context->ucModemCtrl &= ~SP_MODEM_DTR;
354  (*setReg)(pMC68681, MC68681_MODEM_CONTROL,pmc68681Context->ucModemCtrl);
355#endif
356  rtems_interrupt_enable(Irql);
357  return 0;
358}
359
360/*
361 *  mc68681_isr
362 *
363 *  This routine is the console interrupt handler.
364 *
365 *  Input parameters:
366 *    vector - vector number
367 *
368 *  Output parameters: NONE
369 *
370 *  Return values:     NONE
371 */
372
373static void mc68681_process(
374        int             minor
375)
376{
377/* XXX */
378  unsigned32              pMC68681;
379  volatile unsigned8      ucLineStatus; 
380  volatile unsigned8      ucInterruptId;
381  char                    cChar;
382  getRegister_f           getReg;
383  setRegister_f           setReg;
384
385#if 1
386cChar = ucInterruptId = ucLineStatus = 0;
387#endif
388  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
389  getReg   = Console_Port_Tbl[minor].getRegister;
390  setReg   = Console_Port_Tbl[minor].setRegister;
391
392#if 0
393  do {
394    /*
395     * Deal with any received characters
396     */
397    while(TRUE) {
398      ucLineStatus = (*getReg)(pMC68681, MC68681_LINE_STATUS);
399      if(~ucLineStatus & SP_LSR_RDY) {
400        break;
401      }
402      cChar = (*getReg)(pMC68681, MC68681_RECEIVE_BUFFER);
403      rtems_termios_enqueue_raw_characters(
404        Console_Port_Data[minor].termios_data,
405        &cChar,
406        1
407      );
408    }
409
410    while(TRUE) {
411      if(Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
412        Console_Port_Data[minor].bActive = FALSE;
413        if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_RTSCTS) {
414          mc68681_negate_RTS(minor);
415        }
416
417        /*
418         * There is no data to transmit
419         */
420        break;
421      }
422
423      ucLineStatus = (*getReg)(pMC68681, MC68681_LINE_STATUS);
424      if(~ucLineStatus & SP_LSR_THOLD) {
425        /*
426         * We'll get another interrupt when
427         * the transmitter holding reg. becomes
428         * free again
429         */
430        break;
431      }
432
433      Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar);
434      /*
435       * transmit character
436       */
437      (*setReg)(pMC68681, MC68681_TRANSMIT_BUFFER, cChar);
438    }
439
440    ucInterruptId = (*getReg)(pMC68681, MC68681_INTERRUPT_ID);
441  }
442  while((ucInterruptId&0xf) != 0x1);
443#endif
444}
445
446static rtems_isr mc68681_isr(
447  rtems_vector_number vector
448)
449{
450  int     minor;
451
452  for(minor=0 ; minor<Console_Port_Count ; minor++) {
453    if(vector == Console_Port_Tbl[minor].ulIntVector) {
454      mc68681_process(minor);
455    }
456  }
457}
458
459/*
460 *  mc68681_flush
461 */
462
463static int mc68681_flush(int major, int minor, void *arg)
464{
465  while(!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
466    /*
467     * Yield while we wait
468     */
469    if(_System_state_Is_up(_System_state_Get())) {
470      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
471    }
472  }
473
474  mc68681_close(major, minor, arg);
475
476  return(RTEMS_SUCCESSFUL);
477}
478
479/*
480 *  mc68681_initialize_interrupts
481 *
482 *  This routine initializes the console's receive and transmit
483 *  ring buffers and loads the appropriate vectors to handle the interrupts.
484 *
485 *  Input parameters:  NONE
486 *
487 *  Output parameters: NONE
488 *
489 *  Return values:     NONE
490 */
491
492static void mc68681_enable_interrupts(
493  int minor
494)
495{
496/* XXX */
497  unsigned32            pMC68681;
498  unsigned8             ucDataByte;
499  setRegister_f         setReg;
500
501#if 1
502ucDataByte = 0;
503#endif
504  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
505  setReg   = Console_Port_Tbl[minor].setRegister;
506
507#if 0
508  /*
509   * Enable interrupts
510   */
511  ucDataByte = SP_INT_RX_ENABLE | SP_INT_TX_ENABLE;
512  (*setReg)(pMC68681, MC68681_INTERRUPT_ENABLE, ucDataByte);
513#endif
514}
515
516static void mc68681_initialize_interrupts(int minor)
517{
518  mc68681_init(minor);
519
520  Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
521
522  Console_Port_Data[minor].bActive = FALSE;
523
524  set_vector(mc68681_isr, Console_Port_Tbl[minor].ulIntVector, 1);
525
526  mc68681_enable_interrupts(minor);
527}
528
529/*
530 *  mc68681_write_support_int
531 *
532 *  Console Termios output entry point.
533 */
534
535static int mc68681_write_support_int(
536  int   minor, 
537  const char *buf, 
538  int   len
539)
540{
541  int i;
542  unsigned32 Irql;
543
544  for(i=0 ; i<len ;) {
545    if(Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
546      if(!Console_Port_Data[minor].bActive) {
547        /*
548         * Wake up the device
549         */
550        rtems_interrupt_disable(Irql);
551        Console_Port_Data[minor].bActive = TRUE;
552        if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_RTSCTS) {
553          mc68681_assert_RTS(minor);
554        }
555        mc68681_process(minor);
556        rtems_interrupt_enable(Irql);
557      } else {
558        /*
559         * Yield
560         */
561        rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
562      }
563
564      /*
565       * Wait for ring buffer to empty
566       */
567      continue;
568    }
569    else {
570      Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
571      i++;
572    }
573  }
574
575  /*
576   * Ensure that characters are on the way
577   */
578
579  if(!Console_Port_Data[minor].bActive) {
580    /*
581     * Wake up the device
582     */
583    rtems_interrupt_disable(Irql);
584    Console_Port_Data[minor].bActive = TRUE;
585    if(Console_Port_Tbl[minor].pDeviceFlow != &mc68681_flow_RTSCTS) {
586      mc68681_assert_RTS(minor);
587    }
588    mc68681_process(minor);
589    rtems_interrupt_enable(Irql);
590  }
591
592  return (len);
593}
594
595/*
596 *  mc68681_write_support_polled
597 *
598 *  Console Termios output entry point.
599 *
600 */
601
602static int mc68681_write_support_polled(
603  int         minor, 
604  const char *buf, 
605  int         len
606)
607{
608  int nwrite = 0;
609
610  /*
611   * poll each byte in the string out of the port.
612   */
613  while (nwrite < len) {
614    /*
615     * transmit character
616     */
617    mc68681_write_polled(minor, *buf++);
618    nwrite++;
619  }
620
621  /*
622   * return the number of bytes written.
623   */
624  return nwrite;
625}
626
627/*
628 *  mc68681_inbyte_nonblocking_polled
629 *
630 *  Console Termios polling input entry point.
631 */
632
633static int mc68681_inbyte_nonblocking_polled( 
634  int minor
635)
636{
637  unsigned32           pMC68681;
638  unsigned char        ucLineStatus;
639  char                 cChar;
640  getRegister_f        getReg;
641  getData_f            getData;
642
643  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
644  getReg   = Console_Port_Tbl[minor].getRegister;
645  getData  = Console_Port_Tbl[minor].getData;
646
647  ucLineStatus = (*getReg)(pMC68681, MC68681_STATUS_REG);
648  if(ucLineStatus & MC68681_RX_READY) {
649    cChar = (*getData)(pMC68681);
650    return (int)cChar;
651  } else {
652    return(-1);
653  }
654}
Note: See TracBrowser for help on using the repository browser.