source: rtems/c/src/libchip/serial/z85c30.c @ dd5d2f04

4.104.114.84.95
Last change on this file since dd5d2f04 was 991a1ab4, checked in by Joel Sherrill <joel.sherrill@…>, on 07/15/98 at 23:21:55

Added check for proper deviceType to interrupt processing code.

  • Property mode set to 100644
File size: 21.0 KB
Line 
1/*
2 *  This file contains the console driver chip level routines for the
3 *  Zilog z85c30 chip.
4 *
5 *  The Zilog Z8530 is also available as:
6 *
7 *    + Intel 82530
8 *    + AMD ???
9 *
10 *  COPYRIGHT (c) 1998 by Radstone Technology
11 *
12 *
13 * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
14 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
16 * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
17 *
18 * You are hereby granted permission to use, copy, modify, and distribute
19 * this file, provided that this notice, plus the above copyright notice
20 * and disclaimer, appears in all copies. Radstone Technology will provide
21 * no support for this code.
22 *
23 *  COPYRIGHT (c) 1989-1997.
24 *  On-Line Applications Research Corporation (OAR).
25 *  Copyright assigned to U.S. Government, 1994.
26 *
27 *  The license and distribution terms for this file may be
28 *  found in the file LICENSE in this distribution or at
29 *  http://www.OARcorp.com/rtems/license.html.
30 *
31 *  $Id$
32 */
33
34#include <rtems.h>
35#include <rtems/libio.h>
36#include <stdlib.h>
37
38#include <libchip/serial.h>
39#include "z85c30_p.h"
40#include "sersupp.h"
41
42/*
43 * Flow control is only supported when using interrupts
44 */
45
46console_flow z85c30_flow_RTSCTS =
47{
48  z85c30_negate_RTS,    /* deviceStopRemoteTx */
49  z85c30_assert_RTS     /* deviceStartRemoteTx */
50};
51
52console_flow z85c30_flow_DTRCTS =
53{
54  z85c30_negate_DTR,    /* deviceStopRemoteTx */
55  z85c30_assert_DTR     /* deviceStartRemoteTx */
56};
57
58/*
59 * Exported driver function table
60 */
61
62console_fns z85c30_fns =
63{
64  libchip_serial_default_probe,  /* deviceProbe */
65  z85c30_open,                   /* deviceFirstOpen */
66  z85c30_flush,                  /* deviceLastClose */
67  NULL,                          /* deviceRead */
68  z85c30_write_support_int,      /* deviceWrite */
69  z85c30_initialize_interrupts,  /* deviceInitialize */
70  z85c30_write_polled,           /* deviceWritePolled */
71  NULL,                          /* deviceSetAttributes */
72  TRUE                           /* deviceOutputUsesInterrupts */
73};
74
75console_fns z85c30_fns_polled =
76{
77  libchip_serial_default_probe,      /* deviceProbe */
78  z85c30_open,                       /* deviceFirstOpen */
79  z85c30_close,                      /* deviceLastClose */
80  z85c30_inbyte_nonblocking_polled,  /* deviceRead */
81  z85c30_write_support_polled,       /* deviceWrite */
82  z85c30_init,                       /* deviceInitialize */
83  z85c30_write_polled,               /* deviceWritePolled */
84  NULL,                              /* deviceSetAttributes */
85  FALSE,                             /* deviceOutputUsesInterrupts */
86};
87
88extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
89
90
91
92/*
93 * z85c30_initialize_port
94 *
95 * initialize a z85c30 Port
96 */
97
98Z85C30_STATIC void z85c30_initialize_port(
99  int minor
100)
101{
102  unsigned32      ulCtrlPort;
103  unsigned32      ulBaudDivisor;
104  setRegister_f   setReg;
105
106  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
107  setReg   = Console_Port_Tbl[minor].setRegister;
108
109  /*
110   * Using register 4
111   * Set up the clock rate is 16 times the data
112   * rate, 8 bit sync char, 1 stop bit, no parity
113   */
114
115  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, SCC_WR4_1_STOP | SCC_WR4_16_CLOCK );
116
117  /*
118   * Set up for 8 bits/character on receive with
119   * receiver disable via register 3
120   */
121  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS );
122
123  /*
124   * Set up for 8 bits/character on transmit
125   * with transmitter disable via register 5
126   */
127  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS );
128
129  /*
130   * Clear misc control bits
131   */
132  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR10, 0x00 );
133
134  /*
135   * Setup the source of the receive and xmit
136   * clock as BRG output and the transmit clock
137   * as the output source for TRxC pin via register 11
138   */
139  (*setReg)(
140    ulCtrlPort,
141    SCC_WR0_SEL_WR11,
142    SCC_WR11_OUT_BR_GEN | SCC_WR11_TRXC_OI |
143      SCC_WR11_TX_BR_GEN | SCC_WR11_RX_BR_GEN
144  );
145
146  ulBaudDivisor = Z85C30_Baud(
147    (unsigned32) Console_Port_Tbl[minor].ulClock,
148    (unsigned32) Console_Port_Tbl[minor].pDeviceParams
149  );
150
151  /*
152   * Setup the lower 8 bits time constants=1E.
153   * If the time constans=1E, then the desire
154   * baud rate will be equilvalent to 9600, via register 12.
155   */
156  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
157
158  /*
159   * using register 13
160   * Setup the upper 8 bits time constant
161   */
162  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );
163           
164  /*
165   * Enable the baud rate generator enable with clock from the
166   * SCC's PCLK input via register 14.
167   */
168  (*setReg)(
169    ulCtrlPort,
170    SCC_WR0_SEL_WR14,
171    SCC_WR14_BR_EN | SCC_WR14_BR_SRC | SCC_WR14_NULL
172  );
173
174  /*
175   * We are only interested in CTS state changes
176   */
177  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR15, SCC_WR15_CTS_IE );
178
179  /*
180   * Reset errors
181   */
182  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT );
183
184  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_ERR_RST );
185
186  /*
187   * Enable the receiver via register 3
188   */
189  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS | SCC_WR3_RX_EN );
190
191  /*
192   * Enable the transmitter pins set via register 5.
193   */
194  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN );
195
196  /*
197   * Disable interrupts
198   */
199  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR1, 0 );
200
201  /*
202   * Reset TX CRC
203   */
204  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_CRC );
205
206  /*
207   * Reset interrupts
208   */
209  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT );
210}
211
212Z85C30_STATIC int z85c30_open(
213  int   major,
214  int   minor,
215  void *arg
216)
217{
218  /*
219   * Assert DTR
220   */
221
222  if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_DTRCTS) {
223    z85c30_assert_DTR(minor);
224  }
225
226  return(RTEMS_SUCCESSFUL);
227}
228
229Z85C30_STATIC int z85c30_close(
230  int   major,
231  int   minor,
232  void *arg
233)
234{
235  /*
236   * Negate DTR
237   */
238
239  if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_DTRCTS) {
240    z85c30_negate_DTR(minor);
241  }
242
243  return(RTEMS_SUCCESSFUL);
244}
245
246/*
247 *  z85c30_write_polled
248 *
249 *  This routine transmits a character using polling.
250 */
251
252Z85C30_STATIC void z85c30_write_polled(
253  int   minor,
254  char  cChar
255)
256{
257  volatile unsigned8 z85c30_status;
258  unsigned32         ulCtrlPort;
259  getRegister_f      getReg;
260  setData_f          setData;
261
262  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
263  getReg     = Console_Port_Tbl[minor].getRegister;
264  setData    = Console_Port_Tbl[minor].setData;
265
266  /*
267   * Wait for the Transmit buffer to indicate that it is empty.
268   */
269
270  z85c30_status = (*getReg)( ulCtrlPort, SCC_WR0_SEL_RD0 );
271
272  while (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
273    /*
274     * Yield while we wait
275     */
276    if (_System_state_Is_up(_System_state_Get())) {
277      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
278    }
279    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
280  }
281
282  /*
283   * Write the character.
284   */
285
286  (*setData)(Console_Port_Tbl[minor].ulDataPort, cChar);
287}
288
289/*
290 *  Console Device Driver Entry Points
291 */
292
293Z85C30_STATIC void z85c30_init(int minor)
294{
295  unsigned32       ulCtrlPort;
296  unsigned8        dummy;
297  z85c30_context  *pz85c30Context;
298  setRegister_f    setReg;
299  getRegister_f    getReg;
300
301  setReg = Console_Port_Tbl[minor].setRegister;
302  getReg   = Console_Port_Tbl[minor].getRegister;
303
304  pz85c30Context = (z85c30_context *)malloc(sizeof(z85c30_context));
305
306  Console_Port_Data[minor].pDeviceContext=(void *)pz85c30Context;
307
308  pz85c30Context->ucModemCtrl = SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN;
309
310  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
311  if (ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort2) {
312    /*
313     * This is channel A
314     */
315    /*
316     * Ensure port state machine is reset
317     */
318    dummy = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
319
320    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_A_RST);
321
322  } else {
323    /*
324     * This is channel B
325     */
326    /*
327     * Ensure port state machine is reset
328     */
329    dummy = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
330
331    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_B_RST);
332  }
333
334  z85c30_initialize_port(minor);
335}
336
337/*
338 * These routines provide control of the RTS and DTR lines
339 */
340
341/*
342 *  z85c30_assert_RTS
343 */
344
345Z85C30_STATIC int z85c30_assert_RTS(int minor)
346{
347  rtems_interrupt_level  Irql;
348  z85c30_context        *pz85c30Context;
349  setRegister_f          setReg;
350
351  setReg = Console_Port_Tbl[minor].setRegister;
352
353  pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
354 
355  /*
356   * Assert RTS
357   */
358
359  rtems_interrupt_disable(Irql);
360    pz85c30Context->ucModemCtrl|=SCC_WR5_RTS;
361    (*setReg)(
362      Console_Port_Tbl[minor].ulCtrlPort1,
363      SCC_WR0_SEL_WR5,
364      pz85c30Context->ucModemCtrl
365    );
366  rtems_interrupt_enable(Irql);
367  return 0;
368}
369
370/*
371 *  z85c30_negate_RTS
372 */
373
374Z85C30_STATIC int z85c30_negate_RTS(int minor)
375{
376  rtems_interrupt_level  Irql;
377  z85c30_context        *pz85c30Context;
378  setRegister_f          setReg;
379
380  setReg = Console_Port_Tbl[minor].setRegister;
381
382  pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
383 
384  /*
385   * Negate RTS
386   */
387
388  rtems_interrupt_disable(Irql);
389    pz85c30Context->ucModemCtrl&=~SCC_WR5_RTS;
390    (*setReg)(
391      Console_Port_Tbl[minor].ulCtrlPort1,
392      SCC_WR0_SEL_WR5,
393      pz85c30Context->ucModemCtrl
394    );
395  rtems_interrupt_enable(Irql);
396  return 0;
397}
398
399/*
400 * These flow control routines utilise a connection from the local DTR
401 * line to the remote CTS line
402 */
403
404/*
405 *  z85c30_assert_DTR
406 */
407
408Z85C30_STATIC int z85c30_assert_DTR(int minor)
409{
410  rtems_interrupt_level  Irql;
411  z85c30_context        *pz85c30Context;
412  setRegister_f          setReg;
413
414  setReg = Console_Port_Tbl[minor].setRegister;
415
416  pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
417 
418  /*
419   * Assert DTR
420   */
421
422  rtems_interrupt_disable(Irql);
423    pz85c30Context->ucModemCtrl|=SCC_WR5_DTR;
424    (*setReg)(
425      Console_Port_Tbl[minor].ulCtrlPort1,
426      SCC_WR0_SEL_WR5,
427      pz85c30Context->ucModemCtrl
428  );
429  rtems_interrupt_enable(Irql);
430  return 0;
431}
432
433/*
434 *  z85c30_negate_DTR
435 */
436
437Z85C30_STATIC int z85c30_negate_DTR(int minor)
438{
439  rtems_interrupt_level  Irql;
440  z85c30_context        *pz85c30Context;
441  setRegister_f          setReg;
442
443  setReg = Console_Port_Tbl[minor].setRegister;
444
445  pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
446 
447  /*
448   * Negate DTR
449   */
450
451  rtems_interrupt_disable(Irql);
452    pz85c30Context->ucModemCtrl&=~SCC_WR5_DTR;
453    (*setReg)(
454      Console_Port_Tbl[minor].ulCtrlPort1,
455      SCC_WR0_SEL_WR5,
456      pz85c30Context->ucModemCtrl
457  );
458  rtems_interrupt_enable(Irql);
459  return 0;
460}
461
462/*
463 *  z85c30_set_attributes
464 *
465 *  This function sets the SCC channel to reflect the requested termios
466 *  port settings.
467 */
468
469Z85C30_STATIC int z85c30_set_attributes(
470  int                   minor,
471  const struct termios *t
472)
473{
474  unsigned32             ulCtrlPort;
475  unsigned32             ulBaudDivisor;
476  unsigned32             wr3;
477  unsigned32             wr4;
478  unsigned32             wr5;
479  int                    baud_requested;
480  setRegister_f          setReg;
481  rtems_interrupt_level  Irql;
482
483  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
484  setReg     = Console_Port_Tbl[minor].setRegister;
485
486  /*
487   *  Calculate the baud rate divisor
488   */
489
490  baud_requested = t->c_cflag & CBAUD;
491  if (!baud_requested)
492    baud_requested = B9600;              /* default to 9600 baud */
493
494  ulBaudDivisor = Z85C30_Baud(
495    (unsigned32) Console_Port_Tbl[minor].ulClock,
496    (unsigned32) termios_baud_to_number( baud_requested )
497  );
498
499  wr3 = SCC_WR3_RX_EN;
500  wr4 = SCC_WR4_16_CLOCK;
501  wr5 = SCC_WR5_TX_EN;
502
503  /*
504   *  Parity
505   */
506
507  if (t->c_cflag & PARENB) {
508    wr4 |= SCC_WR4_PAR_EN;
509    if (!(t->c_cflag & PARODD))
510      wr4 |= SCC_WR4_PAR_EVEN;
511  }
512
513  /*
514   *  Character Size
515   */
516
517  if (t->c_cflag & CSIZE) {
518    switch (t->c_cflag & CSIZE) {
519      case CS5:   break;
520      case CS6:  wr3 |= SCC_WR3_RX_6_BITS;  wr5 |= SCC_WR5_TX_6_BITS;  break;
521      case CS7:  wr3 |= SCC_WR3_RX_7_BITS;  wr5 |= SCC_WR5_TX_7_BITS;  break;
522      case CS8:  wr3 |= SCC_WR3_RX_8_BITS;  wr5 |= SCC_WR5_TX_8_BITS;  break;
523    }
524  } else {
525    wr3 |= SCC_WR3_RX_8_BITS;       /* default to 9600,8,N,1 */
526    wr5 |= SCC_WR5_TX_8_BITS;       /* default to 9600,8,N,1 */
527  }
528
529  /*
530   *  Stop Bits
531   */
532
533  if (t->c_cflag & CSTOPB) {
534    wr4 |= SCC_WR4_2_STOP;                      /* 2 stop bits */
535  } else {
536    wr4 |= SCC_WR4_1_STOP;                      /* 1 stop bits */
537  }
538
539  rtems_interrupt_disable(Irql);
540    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, wr4 );
541    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, wr3 );
542    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, wr5 );
543
544    /*
545     * Setup the lower 8 bits time constants=1E.
546     * If the time constans=1E, then the desire
547     * baud rate will be equilvalent to 9600, via register 12.
548     */
549
550    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
551
552    /*
553     * using register 13
554     * Setup the upper 8 bits time constant
555     */
556
557    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );
558
559  rtems_interrupt_enable(Irql);
560
561  return 0;
562}
563
564/*
565 *  z85c30_isr
566 *
567 *  This routine is the console interrupt handler for COM3 and COM4
568 *
569 *  Input parameters:
570 *    vector - vector number
571 *
572 *  Output parameters: NONE
573 *
574 *  Return values:     NONE
575 */
576
577Z85C30_STATIC void z85c30_process(
578  int        minor,
579  unsigned8  ucIntPend
580)
581{
582  unsigned32          ulCtrlPort;
583  unsigned32          ulDataPort;
584  volatile unsigned8  z85c30_status;
585  char                cChar;
586  setRegister_f       setReg;
587  getRegister_f       getReg;
588  getData_f           getData;
589  setData_f           setData;
590
591  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
592  ulDataPort = Console_Port_Tbl[minor].ulDataPort;
593  setReg     = Console_Port_Tbl[minor].setRegister;
594  getReg     = Console_Port_Tbl[minor].getRegister;
595  getData    = Console_Port_Tbl[minor].getData;
596  setData    = Console_Port_Tbl[minor].setData;
597
598  /*
599   * Deal with any received characters
600   */
601  while (ucIntPend&SCC_RR3_B_RX_IP)
602  {
603    z85c30_status=(*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
604    if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
605      break;
606    }
607
608    /*
609     * Return the character read.
610     */
611
612    cChar = (*getData)(ulDataPort);
613
614    rtems_termios_enqueue_raw_characters(
615      Console_Port_Data[minor].termios_data,
616      &cChar,
617      1
618    );
619  }
620
621  while (TRUE)
622  {
623    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
624    if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
625      /*
626       * We'll get another interrupt when
627       * the transmitter holding reg. becomes
628       * free again and we are clear to send
629       */
630      break;
631    }
632 
633    if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {
634      /*
635       * We can't transmit yet
636       */
637      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
638      /*
639       * The next state change of CTS will wake us up
640       */
641      break;
642    }
643 
644    if (Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
645      Console_Port_Data[minor].bActive=FALSE;
646      if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
647        z85c30_negate_RTS(minor);
648      }
649      /*
650       * There is no data to transmit
651       */
652      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
653      break;
654    }
655
656    Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar);
657
658    /*
659     * transmit character
660     */
661    (*setData)(ulDataPort, cChar);
662
663    /*
664     * Interrupt once FIFO has room
665      */
666    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
667    break;
668  }
669
670  if (ucIntPend&SCC_RR3_B_EXT_IP) {
671    /*
672     * Clear the external status interrupt
673     */
674    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
675    z85c30_status=(*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
676  }
677
678  /*
679   * Reset interrupts
680   */
681  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS);
682}
683
684Z85C30_STATIC rtems_isr z85c30_isr(
685  rtems_vector_number vector
686)
687{
688  int                 minor;
689  unsigned32          ulCtrlPort;
690  volatile unsigned8  ucIntPend;
691  volatile unsigned8  ucIntPendPort;
692  getRegister_f    getReg;
693
694  for (minor=0;minor<Console_Port_Count;minor++) {
695    if(Console_Port_Tbl[minor].ulIntVector == vector &&
696       Console_Port_Tbl[minor].deviceType == SERIAL_Z85C30 ) {
697      ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort2;
698      getReg     = Console_Port_Tbl[minor].getRegister;
699      do {
700        ucIntPend=(*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3);
701
702          /*
703           * If this is channel A select channel A status
704           */
705
706          if (ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort1) {
707            ucIntPendPort = ucIntPend>>3;
708            ucIntPendPort = ucIntPendPort&=7;
709          } else {
710            ucIntPendPort = ucIntPend &= 7;
711          }
712
713          if (ucIntPendPort) {
714            z85c30_process(minor, ucIntPendPort);
715          }
716      } while (ucIntPendPort);
717    }
718  }
719}
720
721/*
722 *  z85c30_flush
723 */
724
725Z85C30_STATIC int z85c30_flush(
726  int major,
727  int minor,
728  void *arg
729)
730{
731  while (!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
732    /*
733     * Yield while we wait
734     */
735    if (_System_state_Is_up(_System_state_Get())) {
736      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
737    }
738  }
739
740  z85c30_close(major, minor, arg);
741
742  return(RTEMS_SUCCESSFUL);
743}
744
745/*
746 *  z85c30_initialize_interrupts
747 *
748 *  This routine initializes the console's receive and transmit
749 *  ring buffers and loads the appropriate vectors to handle the interrupts.
750 *
751 *  Input parameters:  NONE
752 *
753 *  Output parameters: NONE
754 *
755 *  Return values:     NONE
756 */
757
758Z85C30_STATIC void z85c30_enable_interrupts(
759  int minor
760)
761{
762  unsigned32     ulCtrlPort;
763  setRegister_f  setReg;
764
765  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
766  setReg     = Console_Port_Tbl[minor].setRegister;
767
768  /*
769   * Enable interrupts
770   */
771  (*setReg)(
772    ulCtrlPort,
773    SCC_WR0_SEL_WR1,
774    SCC_WR1_EXT_INT_EN | SCC_WR1_TX_INT_EN | SCC_WR1_INT_ALL_RX
775  );
776  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR2, 0);
777  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
778
779  /*
780   * Reset interrupts
781   */
782  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
783}
784
785Z85C30_STATIC void z85c30_initialize_interrupts(
786  int minor
787)
788{
789  z85c30_init(minor);
790
791  Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
792
793  Console_Port_Data[minor].bActive=FALSE;
794  if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
795    z85c30_negate_RTS(minor);
796  }
797
798  if (Console_Port_Tbl[minor].ulCtrlPort1== Console_Port_Tbl[minor].ulCtrlPort2) {
799    /*
800     * Only do this for Channel A
801     */
802
803    set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
804  }
805
806  z85c30_enable_interrupts(minor);
807}
808
809/*
810 *  z85c30_write_support_int
811 *
812 *  Console Termios output entry point.
813 *
814 */
815
816Z85C30_STATIC int z85c30_write_support_int(
817  int   minor,
818  const char *buf,
819  int   len)
820{
821  int i;
822  unsigned32 Irql;
823
824  for (i=0; i<len;) {
825    if (Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
826      if (!Console_Port_Data[minor].bActive) {
827        /*
828         * Wake up the device
829         */
830        if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
831          z85c30_assert_RTS(minor);
832        }
833        rtems_interrupt_disable(Irql);
834        Console_Port_Data[minor].bActive=TRUE;
835        z85c30_process(minor, SCC_RR3_B_TX_IP);
836        rtems_interrupt_enable(Irql);
837      } else {
838        /*
839         * Yield while we await an interrupt
840         */
841        rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
842      }
843
844      /*
845       * Wait for ring buffer to empty
846       */
847      continue;
848    } else {
849      Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
850      i++;
851    }
852  }
853
854  /*
855   * Ensure that characters are on the way
856   */
857  if (!Console_Port_Data[minor].bActive) {
858    /*
859     * Wake up the device
860     */
861    if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
862            z85c30_assert_RTS(minor);
863    }
864    rtems_interrupt_disable(Irql);
865    Console_Port_Data[minor].bActive=TRUE;
866    z85c30_process(minor, SCC_RR3_B_TX_IP);
867    rtems_interrupt_enable(Irql);
868  }
869
870  return (len);
871}
872
873/*
874 *  z85c30_inbyte_nonblocking_polled
875 *
876 *  This routine polls for a character.
877 */
878
879Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(
880  int  minor
881)
882{
883  volatile unsigned8  z85c30_status;
884  unsigned32          ulCtrlPort;
885  getRegister_f       getReg;
886  getData_f           getData;
887
888  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
889  getData    = Console_Port_Tbl[minor].getData;
890  getReg     = Console_Port_Tbl[minor].getRegister;
891
892  /*
893   * return -1 if a character is not available.
894   */
895  z85c30_status=(*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
896  if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
897    return -1;
898  }
899
900  /*
901   * Return the character read.
902   */
903  return (*getData)(Console_Port_Tbl[minor].ulDataPort);
904}
905
906/*
907 *  z85c30_write_support_polled
908 *
909 *  Console Termios output entry point.
910 *
911 */
912
913Z85C30_STATIC int z85c30_write_support_polled(
914  int   minor,
915  const char *buf,
916  int   len)
917{
918  int nwrite=0;
919
920  /*
921   * poll each byte in the string out of the port.
922   */
923  while (nwrite < len) {
924    z85c30_write_polled(minor, *buf++);
925    nwrite++;
926  }
927
928  /*
929   * return the number of bytes written.
930   */
931  return nwrite;
932}
Note: See TracBrowser for help on using the repository browser.