source: rtems/c/src/lib/libchip/serial/z85c30.c @ e283140c

4.104.114.84.9
Last change on this file since e283140c was e283140c, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 15, 1998 at 1:53:58 PM

Switched to "deviceOutput = TRUE" which made device output use interrupts.

  • 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 (vector==Console_Port_Tbl[minor].ulIntVector) {
696      ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort2;
697      getReg     = Console_Port_Tbl[minor].getRegister;
698      do {
699        ucIntPend=(*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3);
700
701          /*
702           * If this is channel A select channel A status
703           */
704
705          if (ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort1) {
706            ucIntPendPort = ucIntPend>>3;
707            ucIntPendPort = ucIntPendPort&=7;
708          } else {
709            ucIntPendPort = ucIntPend &= 7;
710          }
711
712          if (ucIntPendPort) {
713            z85c30_process(minor, ucIntPendPort);
714          }
715      } while (ucIntPendPort);
716    }
717  }
718}
719
720/*
721 *  z85c30_flush
722 */
723
724Z85C30_STATIC int z85c30_flush(
725  int major,
726  int minor,
727  void *arg
728)
729{
730  while (!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
731    /*
732     * Yield while we wait
733     */
734    if (_System_state_Is_up(_System_state_Get())) {
735      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
736    }
737  }
738
739  z85c30_close(major, minor, arg);
740
741  return(RTEMS_SUCCESSFUL);
742}
743
744/*
745 *  z85c30_initialize_interrupts
746 *
747 *  This routine initializes the console's receive and transmit
748 *  ring buffers and loads the appropriate vectors to handle the interrupts.
749 *
750 *  Input parameters:  NONE
751 *
752 *  Output parameters: NONE
753 *
754 *  Return values:     NONE
755 */
756
757Z85C30_STATIC void z85c30_enable_interrupts(
758  int minor
759)
760{
761  unsigned32     ulCtrlPort;
762  setRegister_f  setReg;
763
764  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
765  setReg     = Console_Port_Tbl[minor].setRegister;
766
767  /*
768   * Enable interrupts
769   */
770  (*setReg)(
771    ulCtrlPort,
772    SCC_WR0_SEL_WR1,
773    SCC_WR1_EXT_INT_EN | SCC_WR1_TX_INT_EN | SCC_WR1_INT_ALL_RX
774  );
775  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR2, 0);
776  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
777
778  /*
779   * Reset interrupts
780   */
781  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
782}
783
784Z85C30_STATIC void z85c30_initialize_interrupts(
785  int minor
786)
787{
788  z85c30_init(minor);
789
790  Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
791
792  Console_Port_Data[minor].bActive=FALSE;
793  if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
794    z85c30_negate_RTS(minor);
795  }
796
797  if (Console_Port_Tbl[minor].ulCtrlPort1== Console_Port_Tbl[minor].ulCtrlPort2) {
798    /*
799     * Only do this for Channel A
800     */
801
802    set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
803  }
804
805  z85c30_enable_interrupts(minor);
806}
807
808/*
809 *  z85c30_write_support_int
810 *
811 *  Console Termios output entry point.
812 *
813 */
814
815Z85C30_STATIC int z85c30_write_support_int(
816  int   minor, 
817  const char *buf, 
818  int   len)
819{
820  int i;
821  unsigned32 Irql;
822
823  for (i=0; i<len;) {
824    if (Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
825      if (!Console_Port_Data[minor].bActive) {
826        /*
827         * Wake up the device
828         */
829        if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
830          z85c30_assert_RTS(minor);
831        }
832        rtems_interrupt_disable(Irql);
833        Console_Port_Data[minor].bActive=TRUE;
834        z85c30_process(minor, SCC_RR3_B_TX_IP);
835        rtems_interrupt_enable(Irql);
836      } else {
837        /*
838         * Yield while we await an interrupt
839         */
840        rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
841      }
842
843      /*
844       * Wait for ring buffer to empty
845       */
846      continue;
847    } else {
848      Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
849      i++;
850    }
851  }
852
853  /*
854   * Ensure that characters are on the way
855   */
856  if (!Console_Port_Data[minor].bActive) {
857    /*
858     * Wake up the device
859     */
860    if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
861            z85c30_assert_RTS(minor);
862    }
863    rtems_interrupt_disable(Irql);
864    Console_Port_Data[minor].bActive=TRUE;
865    z85c30_process(minor, SCC_RR3_B_TX_IP);
866    rtems_interrupt_enable(Irql);
867  }
868
869  return (len);
870}
871
872/*
873 *  z85c30_inbyte_nonblocking_polled
874 *
875 *  This routine polls for a character.
876 */
877
878Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(
879  int  minor
880)
881{
882  volatile unsigned8  z85c30_status;
883  unsigned32          ulCtrlPort;
884  getRegister_f       getReg;
885  getData_f           getData;
886
887  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
888  getData    = Console_Port_Tbl[minor].getData;
889  getReg     = Console_Port_Tbl[minor].getRegister;
890
891  /*
892   * return -1 if a character is not available.
893   */
894  z85c30_status=(*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
895  if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
896    return -1;
897  }
898
899  /*
900   * Return the character read.
901   */
902  return (*getData)(Console_Port_Tbl[minor].ulDataPort);
903}
904
905/*
906 *  z85c30_write_support_polled
907 *
908 *  Console Termios output entry point.
909 *
910 */
911
912Z85C30_STATIC int z85c30_write_support_polled(
913  int   minor,
914  const char *buf,
915  int   len)
916{
917  int nwrite=0;
918
919  /*
920   * poll each byte in the string out of the port.
921   */
922  while (nwrite < len) {
923    z85c30_write_polled(minor, *buf++);
924    nwrite++;
925  }
926
927  /*
928   * return the number of bytes written.
929   */
930  return nwrite;
931}
Note: See TracBrowser for help on using the repository browser.