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

4.104.114.84.95
Last change on this file since cb27f05 was cb27f05, checked in by Joel Sherrill <joel.sherrill@…>, on 07/25/98 at 16:52:00

Changed variable to hold received data to unsigned.

  • Property mode set to 100644
File size: 20.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  NULL,                          /* 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  z85c30_initialize_port(minor);
220
221  /*
222   * Assert DTR
223   */
224
225  if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_DTRCTS) {
226    z85c30_assert_DTR(minor);
227  }
228
229  return(RTEMS_SUCCESSFUL);
230}
231
232Z85C30_STATIC int z85c30_close(
233  int   major,
234  int   minor,
235  void *arg
236)
237{
238  /*
239   * Negate DTR
240   */
241
242  if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_DTRCTS) {
243    z85c30_negate_DTR(minor);
244  }
245
246  return(RTEMS_SUCCESSFUL);
247}
248
249/*
250 *  Console Device Driver Entry Points
251 */
252
253Z85C30_STATIC void z85c30_init(int minor)
254{
255  unsigned32       ulCtrlPort;
256  unsigned8        dummy;
257  z85c30_context  *pz85c30Context;
258  setRegister_f    setReg;
259  getRegister_f    getReg;
260
261  setReg = Console_Port_Tbl[minor].setRegister;
262  getReg   = Console_Port_Tbl[minor].getRegister;
263
264  pz85c30Context = (z85c30_context *)malloc(sizeof(z85c30_context));
265
266  Console_Port_Data[minor].pDeviceContext = (void *)pz85c30Context;
267
268  pz85c30Context->ucModemCtrl = SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN;
269
270  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
271  if ( ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort2 ) {
272    /*
273     * This is channel A
274     */
275    /*
276     * Ensure port state machine is reset
277     */
278    dummy = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
279
280    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_A_RST);
281
282  } else {
283    /*
284     * This is channel B
285     */
286    /*
287     * Ensure port state machine is reset
288     */
289    dummy = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
290
291    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_B_RST);
292  }
293}
294
295/*
296 * These routines provide control of the RTS and DTR lines
297 */
298
299/*
300 *  z85c30_assert_RTS
301 */
302
303Z85C30_STATIC int z85c30_assert_RTS(int minor)
304{
305  rtems_interrupt_level  Irql;
306  z85c30_context        *pz85c30Context;
307  setRegister_f          setReg;
308
309  setReg = Console_Port_Tbl[minor].setRegister;
310
311  pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
312 
313  /*
314   * Assert RTS
315   */
316
317  rtems_interrupt_disable(Irql);
318    pz85c30Context->ucModemCtrl|=SCC_WR5_RTS;
319    (*setReg)(
320      Console_Port_Tbl[minor].ulCtrlPort1,
321      SCC_WR0_SEL_WR5,
322      pz85c30Context->ucModemCtrl
323    );
324  rtems_interrupt_enable(Irql);
325  return 0;
326}
327
328/*
329 *  z85c30_negate_RTS
330 */
331
332Z85C30_STATIC int z85c30_negate_RTS(int minor)
333{
334  rtems_interrupt_level  Irql;
335  z85c30_context        *pz85c30Context;
336  setRegister_f          setReg;
337
338  setReg = Console_Port_Tbl[minor].setRegister;
339
340  pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
341 
342  /*
343   * Negate RTS
344   */
345
346  rtems_interrupt_disable(Irql);
347    pz85c30Context->ucModemCtrl&=~SCC_WR5_RTS;
348    (*setReg)(
349      Console_Port_Tbl[minor].ulCtrlPort1,
350      SCC_WR0_SEL_WR5,
351      pz85c30Context->ucModemCtrl
352    );
353  rtems_interrupt_enable(Irql);
354  return 0;
355}
356
357/*
358 * These flow control routines utilise a connection from the local DTR
359 * line to the remote CTS line
360 */
361
362/*
363 *  z85c30_assert_DTR
364 */
365
366Z85C30_STATIC int z85c30_assert_DTR(int minor)
367{
368  rtems_interrupt_level  Irql;
369  z85c30_context        *pz85c30Context;
370  setRegister_f          setReg;
371
372  setReg = Console_Port_Tbl[minor].setRegister;
373
374  pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
375 
376  /*
377   * Assert DTR
378   */
379
380  rtems_interrupt_disable(Irql);
381    pz85c30Context->ucModemCtrl|=SCC_WR5_DTR;
382    (*setReg)(
383      Console_Port_Tbl[minor].ulCtrlPort1,
384      SCC_WR0_SEL_WR5,
385      pz85c30Context->ucModemCtrl
386  );
387  rtems_interrupt_enable(Irql);
388  return 0;
389}
390
391/*
392 *  z85c30_negate_DTR
393 */
394
395Z85C30_STATIC int z85c30_negate_DTR(int minor)
396{
397  rtems_interrupt_level  Irql;
398  z85c30_context        *pz85c30Context;
399  setRegister_f          setReg;
400
401  setReg = Console_Port_Tbl[minor].setRegister;
402
403  pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
404 
405  /*
406   * Negate DTR
407   */
408
409  rtems_interrupt_disable(Irql);
410    pz85c30Context->ucModemCtrl&=~SCC_WR5_DTR;
411    (*setReg)(
412      Console_Port_Tbl[minor].ulCtrlPort1,
413      SCC_WR0_SEL_WR5,
414      pz85c30Context->ucModemCtrl
415  );
416  rtems_interrupt_enable(Irql);
417  return 0;
418}
419
420/*
421 *  z85c30_set_attributes
422 *
423 *  This function sets the SCC channel to reflect the requested termios
424 *  port settings.
425 */
426
427Z85C30_STATIC int z85c30_set_attributes(
428  int                   minor,
429  const struct termios *t
430)
431{
432  unsigned32             ulCtrlPort;
433  unsigned32             ulBaudDivisor;
434  unsigned32             wr3;
435  unsigned32             wr4;
436  unsigned32             wr5;
437  int                    baud_requested;
438  setRegister_f          setReg;
439  rtems_interrupt_level  Irql;
440
441  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
442  setReg     = Console_Port_Tbl[minor].setRegister;
443
444  /*
445   *  Calculate the baud rate divisor
446   */
447
448  baud_requested = t->c_cflag & CBAUD;
449  if (!baud_requested)
450    baud_requested = B9600;              /* default to 9600 baud */
451
452  ulBaudDivisor = Z85C30_Baud(
453    (unsigned32) Console_Port_Tbl[minor].ulClock,
454    (unsigned32) termios_baud_to_number( baud_requested )
455  );
456
457  wr3 = SCC_WR3_RX_EN;
458  wr4 = SCC_WR4_16_CLOCK;
459  wr5 = SCC_WR5_TX_EN;
460
461  /*
462   *  Parity
463   */
464
465  if (t->c_cflag & PARENB) {
466    wr4 |= SCC_WR4_PAR_EN;
467    if (!(t->c_cflag & PARODD))
468      wr4 |= SCC_WR4_PAR_EVEN;
469  }
470
471  /*
472   *  Character Size
473   */
474
475  if (t->c_cflag & CSIZE) {
476    switch (t->c_cflag & CSIZE) {
477      case CS5:   break;
478      case CS6:  wr3 |= SCC_WR3_RX_6_BITS;  wr5 |= SCC_WR5_TX_6_BITS;  break;
479      case CS7:  wr3 |= SCC_WR3_RX_7_BITS;  wr5 |= SCC_WR5_TX_7_BITS;  break;
480      case CS8:  wr3 |= SCC_WR3_RX_8_BITS;  wr5 |= SCC_WR5_TX_8_BITS;  break;
481    }
482  } else {
483    wr3 |= SCC_WR3_RX_8_BITS;       /* default to 9600,8,N,1 */
484    wr5 |= SCC_WR5_TX_8_BITS;       /* default to 9600,8,N,1 */
485  }
486
487  /*
488   *  Stop Bits
489   */
490
491  if (t->c_cflag & CSTOPB) {
492    wr4 |= SCC_WR4_2_STOP;                      /* 2 stop bits */
493  } else {
494    wr4 |= SCC_WR4_1_STOP;                      /* 1 stop bits */
495  }
496
497  rtems_interrupt_disable(Irql);
498    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, wr4 );
499    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, wr3 );
500    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, wr5 );
501
502    /*
503     * Setup the lower 8 bits time constants=1E.
504     * If the time constans=1E, then the desire
505     * baud rate will be equilvalent to 9600, via register 12.
506     */
507
508    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
509
510    /*
511     * using register 13
512     * Setup the upper 8 bits time constant
513     */
514
515    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );
516
517  rtems_interrupt_enable(Irql);
518
519  return 0;
520}
521
522/*
523 *  z85c30_isr
524 *
525 *  This routine is the console interrupt handler for COM3 and COM4
526 *
527 *  Input parameters:
528 *    vector - vector number
529 *
530 *  Output parameters: NONE
531 *
532 *  Return values:     NONE
533 */
534
535Z85C30_STATIC void z85c30_process(
536  int        minor,
537  unsigned8  ucIntPend
538)
539{
540  unsigned32          ulCtrlPort;
541  volatile unsigned8  z85c30_status;
542  unsigned char       cChar;
543  setRegister_f       setReg;
544  getRegister_f       getReg;
545
546  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
547  setReg     = Console_Port_Tbl[minor].setRegister;
548  getReg     = Console_Port_Tbl[minor].getRegister;
549
550  /*
551   * Deal with any received characters
552   */
553
554  while (ucIntPend&SCC_RR3_B_RX_IP)
555  {
556    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
557    if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
558      break;
559    }
560
561    /*
562     * Return the character read.
563     */
564
565    cChar = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);
566
567    rtems_termios_enqueue_raw_characters(
568      Console_Port_Data[minor].termios_data,
569      &cChar,
570      1
571    );
572  }
573
574  /*
575   *  There could be a race condition here if there is not yet a TX
576   *  interrupt pending but the buffer is empty.  This condition has
577   *  been seen before on other z8530 drivers but has not been seen
578   *  with this one.  The typical solution is to use "vector includes
579   *  status" or to only look at the interrupts actually pending
580   *  in RR3.
581   */
582
583  while (TRUE) {
584    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
585    if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
586      /*
587       * We'll get another interrupt when
588       * the transmitter holding reg. becomes
589       * free again and we are clear to send
590       */
591      break;
592    }
593 
594#if 0
595    if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {
596      /*
597       * We can't transmit yet
598       */
599      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
600      /*
601       * The next state change of CTS will wake us up
602       */
603      break;
604    }
605#endif
606 
607    if (!rtems_termios_dequeue_characters(
608                Console_Port_Data[minor].termios_data, 1)) {
609      if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
610        z85c30_negate_RTS(minor);
611      }
612      Console_Port_Data[minor].bActive = FALSE;
613      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
614      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
615      break;
616    }
617
618  }
619
620  if (ucIntPend & SCC_RR3_B_EXT_IP) {
621    /*
622     * Clear the external status interrupt
623     */
624    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
625    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
626  }
627
628  /*
629   * Reset interrupts
630   */
631  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS);
632}
633
634Z85C30_STATIC rtems_isr z85c30_isr(
635  rtems_vector_number vector
636)
637{
638  int                 minor;
639  unsigned32          ulCtrlPort;
640  volatile unsigned8  ucIntPend;
641  volatile unsigned8  ucIntPendPort;
642  getRegister_f    getReg;
643
644  for (minor=0;minor<Console_Port_Count;minor++) {
645    if(Console_Port_Tbl[minor].ulIntVector == vector &&
646       Console_Port_Tbl[minor].deviceType == SERIAL_Z85C30 ) {
647      ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort2;
648      getReg     = Console_Port_Tbl[minor].getRegister;
649      do {
650        ucIntPend = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3);
651
652          /*
653           * If this is channel A select channel A status
654           */
655
656          if (ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort1) {
657            ucIntPendPort = ucIntPend>>3;
658            ucIntPendPort = ucIntPendPort&=7;
659          } else {
660            ucIntPendPort = ucIntPend &= 7;
661          }
662
663          if (ucIntPendPort) {
664            z85c30_process(minor, ucIntPendPort);
665          }
666      } while (ucIntPendPort);
667    }
668  }
669}
670
671/*
672 *  z85c30_enable_interrupts
673 *
674 *  This routine enables the specified interrupts for this minor.
675 */
676
677Z85C30_STATIC void z85c30_enable_interrupts(
678  int minor,
679  int interrupt_mask
680)
681{
682  unsigned32     ulCtrlPort;
683  setRegister_f  setReg;
684
685  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
686  setReg     = Console_Port_Tbl[minor].setRegister;
687
688  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);
689}
690
691/*
692 *  z85c30_initialize_interrupts
693 *
694 *  This routine initializes the port to use interrupts.
695 */
696
697Z85C30_STATIC void z85c30_initialize_interrupts(
698  int minor
699)
700{
701  unsigned32     ulCtrlPort1;
702  unsigned32     ulCtrlPort2;
703  setRegister_f  setReg;
704
705  ulCtrlPort1 = Console_Port_Tbl[minor].ulCtrlPort1;
706  ulCtrlPort2 = Console_Port_Tbl[minor].ulCtrlPort2;
707  setReg      = Console_Port_Tbl[minor].setRegister;
708
709
710  z85c30_init(minor);
711
712  Console_Port_Data[minor].bActive=FALSE;
713
714  z85c30_initialize_port( minor );
715
716  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
717    z85c30_negate_RTS(minor);
718  }
719
720  set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
721
722  z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
723
724  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0);              /* XXX vector */
725  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
726
727  /*
728   * Reset interrupts
729   */
730
731  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
732}
733
734/*
735 *  z85c30_write_support_int
736 *
737 *  Console Termios output entry point.
738 *
739 */
740
741Z85C30_STATIC int z85c30_write_support_int(
742  int   minor,
743  const char *buf,
744  int   len)
745{
746  unsigned32     Irql;
747  unsigned32     ulCtrlPort;
748  setRegister_f  setReg;
749
750  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
751  setReg     = Console_Port_Tbl[minor].setRegister;
752
753  /*
754   *  We are using interrupt driven output and termios only sends us
755   *  one character at a time.
756   */
757
758  if ( !len )
759    return 0;
760
761  /*
762   *  Put the character out and enable interrupts if necessary.
763   */
764
765  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
766    z85c30_assert_RTS(minor);
767  }
768  rtems_interrupt_disable(Irql);
769    if ( Console_Port_Data[minor].bActive == FALSE) {
770      Console_Port_Data[minor].bActive = TRUE;
771      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR);
772    }
773    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf);
774  rtems_interrupt_enable(Irql);
775
776  return 1;
777}
778
779/*
780 *  z85c30_inbyte_nonblocking_polled
781 *
782 *  This routine polls for a character.
783 */
784
785Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(
786  int  minor
787)
788{
789  volatile unsigned8  z85c30_status;
790  unsigned32          ulCtrlPort;
791  getRegister_f       getReg;
792
793  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
794  getReg     = Console_Port_Tbl[minor].getRegister;
795
796  /*
797   * return -1 if a character is not available.
798   */
799  z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
800  if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
801    return -1;
802  }
803
804  /*
805   * Return the character read.
806   */
807
808  return (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);
809}
810
811/*
812 *  z85c30_write_support_polled
813 *
814 *  Console Termios output entry point.
815 *
816 */
817
818Z85C30_STATIC int z85c30_write_support_polled(
819  int   minor,
820  const char *buf,
821  int   len)
822{
823  int nwrite=0;
824
825  /*
826   * poll each byte in the string out of the port.
827   */
828  while (nwrite < len) {
829    z85c30_write_polled(minor, *buf++);
830    nwrite++;
831  }
832
833  /*
834   * return the number of bytes written.
835   */
836  return nwrite;
837}
838
839/*
840 *  z85c30_write_polled
841 *
842 *  This routine transmits a character using polling.
843 */
844
845Z85C30_STATIC void z85c30_write_polled(
846  int   minor,
847  char  cChar
848)
849{
850  volatile unsigned8 z85c30_status;
851  unsigned32         ulCtrlPort;
852  getRegister_f      getReg;
853  setRegister_f      setReg;
854
855  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
856  getReg     = Console_Port_Tbl[minor].getRegister;
857  setReg     = Console_Port_Tbl[minor].setRegister;
858
859  /*
860   * Wait for the Transmit buffer to indicate that it is empty.
861   */
862
863  z85c30_status = (*getReg)( ulCtrlPort, SCC_WR0_SEL_RD0 );
864
865  while (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
866    /*
867     * Yield while we wait
868     */
869    if (_System_state_Is_up(_System_state_Get())) {
870      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
871    }
872    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
873  }
874
875  /*
876   * Write the character.
877   */
878
879  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR8, cChar );
880}
881
Note: See TracBrowser for help on using the repository browser.