source: rtems/c/src/libchip/serial/z85c30.c @ 1c6926c1

Last change on this file since 1c6926c1 was 1c6926c1, checked in by Kevin Kirspel <kevin-kirspel@…>, on Mar 21, 2017 at 7:39:48 PM

termios: Synchronize with latest FreeBSD headers

Adding modified FreeBSD headers to synchronize RTEMS termios with
FreeBSD. Modify termios to support dedicated input and output baud for
termios structure. Updated BSPs to use dedicated input and output baud
in termios structure. Updated tools to use dedicated input and output
baud in termios structure. Updated termios testsuites to use dedicated
input and output baud in termios structure.

Close #2897.

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