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

4.115
Last change on this file since a399857 was a399857, checked in by Ralf Corsepius <ralf.corsepius@…>, on Oct 10, 2011 at 8:37:28 AM

2011-10-10 Ralf Corsépius <ralf.corsepius@…>

  • libchip/serial/z85c30.c: Eliminate unused var "dummy".
  • 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 *
26 *  The license and distribution terms for this file may be
27 *  found in the file LICENSE in this distribution or at
28 *  http://www.rtems.com/license/LICENSE.
29 *
30 *  $Id$
31 */
32
33#include <rtems.h>
34#include <rtems/libio.h>
35#include <stdlib.h>
36
37#include <libchip/serial.h>
38#include <libchip/sersupp.h>
39#include "z85c30_p.h"
40
41/*
42 * Flow control is only supported when using interrupts
43 */
44
45console_flow z85c30_flow_RTSCTS = {
46  z85c30_negate_RTS,    /* deviceStopRemoteTx */
47  z85c30_assert_RTS     /* deviceStartRemoteTx */
48};
49
50console_flow z85c30_flow_DTRCTS = {
51  z85c30_negate_DTR,    /* deviceStopRemoteTx */
52  z85c30_assert_DTR     /* deviceStartRemoteTx */
53};
54
55/*
56 * Exported driver function table
57 */
58
59console_fns z85c30_fns = {
60  libchip_serial_default_probe,  /* deviceProbe */
61  z85c30_open,                   /* deviceFirstOpen */
62  NULL,                          /* deviceLastClose */
63  NULL,                          /* deviceRead */
64  z85c30_write_support_int,      /* deviceWrite */
65  z85c30_initialize_interrupts,  /* deviceInitialize */
66  z85c30_write_polled,           /* deviceWritePolled */
67  NULL,                          /* deviceSetAttributes */
68  true                           /* deviceOutputUsesInterrupts */
69};
70
71console_fns z85c30_fns_polled = {
72  libchip_serial_default_probe,      /* deviceProbe */
73  z85c30_open,                       /* deviceFirstOpen */
74  z85c30_close,                      /* deviceLastClose */
75  z85c30_inbyte_nonblocking_polled,  /* deviceRead */
76  z85c30_write_support_polled,       /* deviceWrite */
77  z85c30_init,                       /* deviceInitialize */
78  z85c30_write_polled,               /* deviceWritePolled */
79  NULL,                              /* deviceSetAttributes */
80  false                              /* deviceOutputUsesInterrupts */
81};
82
83extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
84
85/*
86 *  z85c30_initialize_port
87 *
88 *  initialize a z85c30 Port
89 */
90
91Z85C30_STATIC void z85c30_initialize_port(
92  int minor
93)
94{
95  uintptr_t       ulCtrlPort;
96  uintptr_t       ulBaudDivisor;
97  setRegister_f   setReg;
98
99  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
100  setReg   = Console_Port_Tbl[minor].setRegister;
101
102  /*
103   * Using register 4
104   * Set up the clock rate is 16 times the data
105   * rate, 8 bit sync char, 1 stop bit, no parity
106   */
107
108  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, SCC_WR4_1_STOP | SCC_WR4_16_CLOCK );
109
110  /*
111   * Set up for 8 bits/character on receive with
112   * receiver disable via register 3
113   */
114  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS );
115
116  /*
117   * Set up for 8 bits/character on transmit
118   * with transmitter disable via register 5
119   */
120  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS );
121
122  /*
123   * Clear misc control bits
124   */
125  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR10, 0x00 );
126
127  /*
128   * Setup the source of the receive and xmit
129   * clock as BRG output and the transmit clock
130   * as the output source for TRxC pin via register 11
131   */
132  (*setReg)(
133    ulCtrlPort,
134    SCC_WR0_SEL_WR11,
135    SCC_WR11_OUT_BR_GEN | SCC_WR11_TRXC_OI |
136      SCC_WR11_TX_BR_GEN | SCC_WR11_RX_BR_GEN
137  );
138
139  ulBaudDivisor = Z85C30_Baud(
140    (uint32_t) Console_Port_Tbl[minor].ulClock,
141    (uint32_t) ((uintptr_t)Console_Port_Tbl[minor].pDeviceParams)
142  );
143
144  /*
145   * Setup the lower 8 bits time constants=1E.
146   * If the time constans=1E, then the desire
147   * baud rate will be equilvalent to 9600, via register 12.
148   */
149  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
150
151  /*
152   * using register 13
153   * Setup the upper 8 bits time constant
154   */
155  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );
156
157  /*
158   * Enable the baud rate generator enable with clock from the
159   * SCC's PCLK input via register 14.
160   */
161  (*setReg)(
162    ulCtrlPort,
163    SCC_WR0_SEL_WR14,
164    SCC_WR14_BR_EN | SCC_WR14_BR_SRC | SCC_WR14_NULL
165  );
166
167  /*
168   * We are only interested in CTS state changes
169   */
170  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR15, SCC_WR15_CTS_IE );
171
172  /*
173   * Reset errors
174   */
175  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT );
176
177  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_ERR_RST );
178
179  /*
180   * Enable the receiver via register 3
181   */
182  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS | SCC_WR3_RX_EN );
183
184  /*
185   * Enable the transmitter pins set via register 5.
186   */
187  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN );
188
189  /*
190   * Disable interrupts
191   */
192  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR1, 0 );
193
194  /*
195   * Reset TX CRC
196   */
197  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_CRC );
198
199  /*
200   * Reset interrupts
201   */
202  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT );
203}
204
205/*
206 *  z85c30_open
207 */
208
209Z85C30_STATIC int z85c30_open(
210  int   major,
211  int   minor,
212  void *arg
213)
214{
215
216  z85c30_initialize_port(minor);
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
229/*
230 *  z85c30_close
231 */
232
233Z85C30_STATIC int z85c30_close(
234  int   major,
235  int   minor,
236  void *arg
237)
238{
239  /*
240   * Negate DTR
241   */
242
243  if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_DTRCTS) {
244    z85c30_negate_DTR(minor);
245  }
246
247  return(RTEMS_SUCCESSFUL);
248}
249
250/*
251 *  z85c30_init
252 */
253
254Z85C30_STATIC void z85c30_init(int minor)
255{
256  uintptr_t        ulCtrlPort;
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    (*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    (*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  uintptr_t              ulCtrlPort;
433  uint32_t               ulBaudDivisor;
434  uint32_t               wr3;
435  uint32_t               wr4;
436  uint32_t               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    (uint32_t) Console_Port_Tbl[minor].ulClock,
454    (uint32_t) rtems_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  /*
498   *  Now actually set the chip
499   */
500
501  rtems_interrupt_disable(Irql);
502    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, wr4 );
503    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, wr3 );
504    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, wr5 );
505
506    /*
507     * Setup the lower 8 bits time constants=1E.
508     * If the time constans=1E, then the desire
509     * baud rate will be equilvalent to 9600, via register 12.
510     */
511
512    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
513
514    /*
515     * using register 13
516     * Setup the upper 8 bits time constant
517     */
518
519    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );
520
521  rtems_interrupt_enable(Irql);
522
523  return 0;
524}
525
526/*
527 *  z85c30_process
528 *
529 *  This is the per port ISR handler.
530 */
531
532Z85C30_STATIC void z85c30_process(
533  int        minor,
534  uint8_t    ucIntPend
535)
536{
537  uint32_t            ulCtrlPort;
538  volatile uint8_t    z85c30_status;
539  char                cChar;
540  setRegister_f       setReg;
541  getRegister_f       getReg;
542
543  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
544  setReg     = Console_Port_Tbl[minor].setRegister;
545  getReg     = Console_Port_Tbl[minor].getRegister;
546
547  /*
548   * Deal with any received characters
549   */
550
551  while (ucIntPend&SCC_RR3_B_RX_IP)
552  {
553    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
554    if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
555      break;
556    }
557
558    /*
559     * Return the character read.
560     */
561
562    cChar = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);
563
564    rtems_termios_enqueue_raw_characters(
565      Console_Port_Data[minor].termios_data,
566      &cChar,
567      1
568    );
569  }
570
571  /*
572   *  There could be a race condition here if there is not yet a TX
573   *  interrupt pending but the buffer is empty.  This condition has
574   *  been seen before on other z8530 drivers but has not been seen
575   *  with this one.  The typical solution is to use "vector includes
576   *  status" or to only look at the interrupts actually pending
577   *  in RR3.
578   */
579
580  while (true) {
581    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
582    if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
583      /*
584       * We'll get another interrupt when
585       * the transmitter holding reg. becomes
586       * free again and we are clear to send
587       */
588      break;
589    }
590
591#if 0
592    if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {
593      /*
594       * We can't transmit yet
595       */
596      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
597      /*
598       * The next state change of CTS will wake us up
599       */
600      break;
601    }
602#endif
603
604    rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
605    if (rtems_termios_dequeue_characters(
606         Console_Port_Data[minor].termios_data, 1)) {
607      if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
608        z85c30_negate_RTS(minor);
609      }
610      Console_Port_Data[minor].bActive = FALSE;
611      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
612      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
613      break;
614    }
615
616  }
617
618  if (ucIntPend & SCC_RR3_B_EXT_IP) {
619    /*
620     * Clear the external status interrupt
621     */
622    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
623    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
624  }
625
626  /*
627   * Reset interrupts
628   */
629  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS);
630}
631
632/*
633 *  z85c30_isr
634 *
635 *  This is the ISR handler for each Z8530.
636 */
637
638Z85C30_STATIC rtems_isr z85c30_isr(
639  rtems_vector_number vector
640)
641{
642  int                 minor;
643  uint32_t            ulCtrlPort;
644  volatile uint8_t    ucIntPend;
645  volatile uint8_t    ucIntPendPort;
646  getRegister_f       getReg;
647
648  for (minor=0;minor<Console_Port_Count;minor++) {
649    if(Console_Port_Tbl[minor].ulIntVector == vector &&
650       Console_Port_Tbl[minor].deviceType == SERIAL_Z85C30 ) {
651      ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort2;
652      getReg     = Console_Port_Tbl[minor].getRegister;
653      do {
654        ucIntPend = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3);
655
656          /*
657           * If this is channel A select channel A status
658           */
659
660          if (ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort1) {
661            ucIntPendPort = ucIntPend >> 3;
662            ucIntPendPort &= 7;
663          } else {
664            ucIntPendPort = ucIntPend &= 7;
665          }
666
667          if (ucIntPendPort) {
668            z85c30_process(minor, ucIntPendPort);
669          }
670      } while (ucIntPendPort);
671    }
672  }
673}
674
675/*
676 *  z85c30_enable_interrupts
677 *
678 *  This routine enables the specified interrupts for this minor.
679 */
680
681Z85C30_STATIC void z85c30_enable_interrupts(
682  int minor,
683  int interrupt_mask
684)
685{
686  uint32_t       ulCtrlPort;
687  setRegister_f  setReg;
688
689  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
690  setReg     = Console_Port_Tbl[minor].setRegister;
691
692  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);
693}
694
695/*
696 *  z85c30_initialize_interrupts
697 *
698 *  This routine initializes the port to use interrupts.
699 */
700
701Z85C30_STATIC void z85c30_initialize_interrupts(
702  int minor
703)
704{
705  uint32_t       ulCtrlPort1;
706  uint32_t       ulCtrlPort2;
707  setRegister_f  setReg;
708
709  ulCtrlPort1 = Console_Port_Tbl[minor].ulCtrlPort1;
710  ulCtrlPort2 = Console_Port_Tbl[minor].ulCtrlPort2;
711  setReg      = Console_Port_Tbl[minor].setRegister;
712
713
714  z85c30_init(minor);
715
716  Console_Port_Data[minor].bActive=FALSE;
717
718  z85c30_initialize_port( minor );
719
720  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
721    z85c30_negate_RTS(minor);
722  }
723
724  set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
725
726  z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
727
728  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0);              /* XXX vector */
729  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
730
731  /*
732   * Reset interrupts
733   */
734
735  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
736}
737
738/*
739 *  z85c30_write_support_int
740 *
741 *  Console Termios output entry point.
742 *
743 */
744
745Z85C30_STATIC ssize_t z85c30_write_support_int(
746  int   minor,
747  const char *buf,
748  size_t len)
749{
750  uint32_t       Irql;
751  uint32_t       ulCtrlPort;
752  setRegister_f  setReg;
753
754  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
755  setReg     = Console_Port_Tbl[minor].setRegister;
756
757  /*
758   *  We are using interrupt driven output and termios only sends us
759   *  one character at a time.
760   */
761
762  if ( !len )
763    return 0;
764
765  /*
766   *  Put the character out and enable interrupts if necessary.
767   */
768
769  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
770    z85c30_assert_RTS(minor);
771  }
772  rtems_interrupt_disable(Irql);
773    if ( Console_Port_Data[minor].bActive == FALSE) {
774      Console_Port_Data[minor].bActive = TRUE;
775      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR);
776    }
777    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf);
778  rtems_interrupt_enable(Irql);
779
780  return 0;
781}
782
783/*
784 *  z85c30_inbyte_nonblocking_polled
785 *
786 *  This routine polls for a character.
787 */
788
789Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(
790  int  minor
791)
792{
793  volatile uint8_t    z85c30_status;
794  uint32_t            ulCtrlPort;
795  getRegister_f       getReg;
796
797  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
798  getReg     = Console_Port_Tbl[minor].getRegister;
799
800  /*
801   * return -1 if a character is not available.
802   */
803  z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
804  if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
805    return -1;
806  }
807
808  /*
809   * Return the character read.
810   */
811
812  return (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);
813}
814
815/*
816 *  z85c30_write_support_polled
817 *
818 *  Console Termios output entry point.
819 *
820 */
821
822Z85C30_STATIC ssize_t z85c30_write_support_polled(
823  int   minor,
824  const char *buf,
825  size_t len)
826{
827  int nwrite=0;
828
829  /*
830   * poll each byte in the string out of the port.
831   */
832  while (nwrite < len) {
833    z85c30_write_polled(minor, *buf++);
834    nwrite++;
835  }
836
837  /*
838   * return the number of bytes written.
839   */
840  return nwrite;
841}
842
843/*
844 *  z85c30_write_polled
845 *
846 *  This routine transmits a character using polling.
847 */
848
849Z85C30_STATIC void z85c30_write_polled(
850  int   minor,
851  char  cChar
852)
853{
854  volatile uint8_t   z85c30_status;
855  uint32_t           ulCtrlPort;
856  getRegister_f      getReg;
857  setRegister_f      setReg;
858
859  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
860  getReg     = Console_Port_Tbl[minor].getRegister;
861  setReg     = Console_Port_Tbl[minor].setRegister;
862
863  /*
864   * Wait for the Transmit buffer to indicate that it is empty.
865   */
866
867  z85c30_status = (*getReg)( ulCtrlPort, SCC_WR0_SEL_RD0 );
868
869  while (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
870    /*
871     * Yield while we wait
872     */
873#if 0
874    if (_System_state_Is_up(_System_state_Get())) {
875      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
876    }
877#endif
878    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
879  }
880
881  /*
882   * Write the character.
883   */
884
885  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR8, cChar );
886}
Note: See TracBrowser for help on using the repository browser.