source: rtems/c/src/lib/libcpu/powerpc/mpc821/console-generic/console-generic.c @ 3084de2

4.104.114.84.95
Last change on this file since 3084de2 was 3084de2, checked in by Joel Sherrill <joel.sherrill@…>, on 04/07/99 at 15:57:05

MPC821 support and PPC patches from Andrew Bray <andy@…>:

In c/src/exec/score/cpu/powerpc/rtems/score/ppc.h:

A lot of hardware interrupts were omitted. Patch enclosed.
I have also added the 821.

In c/src/exec/score/cpu/powerpc/rtems/score/cpu.h:

My patch adds the 821.

In c/src/exec/score/cpu/powerpc/cpu.c:

I have added the MPC821, and also fixed up for the missing hardware
interrupts. It is also inconsistent with
c/src/lib/libcpu/powerpc/mpc860/vectors/vectors.S. This has been fixed.

In c/src/lib/libcpu/powerpc/mpc860/vectors/vectors.S:

Fixed an inconsistency with cpu.c.

I also include some new files to go with the above patches. These are the
cpu library rtems-19990331/c/src/lib/libcpu/powerpc/mpc821/* and
c/src/exec/score/cpu/powerpc/mpc821.h which are minor modifications of
the 860 equivalents.

Other comments:

The various accesses to the DPRAM on the 860 are done with a linktime
symbol. This could be done dynamically at run time by reading the immr
register, and masking off the lower 16 bits. This takes the same amount
of time as loading an address constant, and the same number of
instructions as well (2).

In c/src/lib/libcpu/powerpc/mpc860/console-generic/console-generic.c:

This will silently fail if you attempt to use SCC1. This is only relevant
if you are not using SCC1 for ethernet.

This file also sets one of port B output pins for each port. This is NOT
generic, it should be in the BSP specific console driver.

  • Property mode set to 100644
File size: 23.3 KB
RevLine 
[3084de2]1/*
2 *  General Serial I/O functions.
3 *
4 * This file contains the functions for performing serial I/O.
5 * The actual system calls (console_*) should be in the BSP part
6 * of the source tree. That way different BSPs can use whichever
7 * SMCs and SCCs they want. Originally, all the stuff was in
8 * this file, and it caused problems with one BSP using SCC2
9 * as /dev/console, others using SMC1 for /dev/console, etc.
10 *
11 *  On-chip resources used:
12 *   resource   minor                note
13 *    SMC1       0
14 *    SMC2       1
15 *    SCC1       2                   (shared with ethernet driver)
16 *    SCC2       3
17 *    BRG1
18 *    BRG2
19 *    BRG3
20 *    BRG4
21 *  Author: Jay Monkman (jmonkman@frasca.com)
22 *  Copyright (C) 1998 by Frasca International, Inc.
23 *
24 *  Derived from c/src/lib/libbsp/m68k/gen360/console/console.c:
25 *
26 *  Author:
27 *    W. Eric Norum
28 *    Saskatchewan Accelerator Laboratory
29 *    University of Saskatchewan
30 *    Saskatoon, Saskatchewan, CANADA
31 *    eric@skatter.usask.ca
32 *
33 *  COPYRIGHT (c) 1989-1998.
34 *  On-Line Applications Research Corporation (OAR).
35 *  Copyright assigned to U.S. Government, 1994.
36 *
37 *  The license and distribution terms for this file may be
38 *  found in the file LICENSE in this distribution or at
39 *
40 *  http://www.OARcorp.com/rtems/license.html.
41 *
42 *  $Id$
43 */
44
45#include <bsp.h>
46#include <rtems/libio.h>
47#include <mpc821.h>
48#include <mpc821/console.h>
49#include <stdlib.h>
50#include <unistd.h>
51#include <termios.h>
52
53#define NIFACES 4        /* number of console devices (serial ports) */
54
55extern rtems_cpu_table           Cpu_table;             /* owned by BSP */
56
57static Buf_t *rxBufList[NIFACES];
58static Buf_t *rxBufListTail[NIFACES];
59
60/*
61 * Interrupt-driven input buffer
62 */
63#define RXBUFSIZE       16
64
65
66/*
67 * I/O buffers and pointers to buffer descriptors
68 */
69static volatile char txBuf[NIFACES];
70
71static volatile m821BufferDescriptor_t *RxBd[NIFACES], *TxBd[NIFACES];
72
73/*
74 * Device-specific routines
75 */
76static int m821_get_brg_cd(int);
77unsigned char m821_get_brg_clk(int);
78void m821_console_reserve_resources(rtems_configuration_table *);
79unsigned char m821_get_brg_clk(int);
80
81
82/*
83 * Compute baud-rate-generator configuration register value
84 */
85static int
86m821_get_brg_cd (int baud)
87{
88  int divisor;
89  int div16 = 0;
90 
91  divisor = ((Cpu_table.clock_speed / 16) + (baud / 2)) / baud;
92  if (divisor > 4096) {
93    div16 = 1;
94    divisor = (divisor + 8) / 16;
95  }
96  return M821_BRG_EN | M821_BRG_EXTC_BRGCLK |
97    ((divisor - 1) << 1) | div16;
98}
99
100
101/* this function will fail if more that 4 baud rates have been selected */
102/*  at any time since the OS started. It needs to be fixed. FIXME */
103unsigned char m821_get_brg_clk(int baud)
104{
105  static short brg_spd[4];
106  static char  brg_used[4];
107  int i;
108
109  /* first try to find a BRG that is already at the right speed */
110  for (i=0; i<4; i++) {
111    if (brg_spd[i] == baud) {
112      break;
113    }
114  }
115
116  if (i==4) { /* I guess we didn't find one */
117    for (i=0; i<4; i++) {
118      if (brg_used[i] == 0) {
119        break;
120      }
121    }
122  }
123  if (i != 4) {
124    brg_used[i]++;
125    brg_spd[i]=baud;
126    switch (i) {
127    case 0:
128      m821.brgc1 = M821_BRG_RST;
129      m821.brgc1 = m821_get_brg_cd(baud);
130      break;
131    case 1:
132      m821.brgc2 = M821_BRG_RST;
133      m821.brgc2 = m821_get_brg_cd(baud);
134      break;
135    case 2:
136      m821.brgc3 = M821_BRG_RST;
137      m821.brgc3 = m821_get_brg_cd(baud);
138      break;
139    case 3:
140      m821.brgc4 = M821_BRG_RST;
141      m821.brgc4 = m821_get_brg_cd(baud);
142      break;
143    }
144    return i;
145  }
146
147  else
148    return 0xff;
149}
150
151/*
152 * Hardware-dependent portion of tcsetattr().
153 */
154int
155m821_smc_set_attributes (int minor, const struct termios *t)
156{
157  /*
158   * minor must be 0 or 1
159   */
160  int baud;
161  int brg;
162  switch (t->c_cflag & CBAUD) {
163  default:      baud = -1;      break;
164  case B50:     baud = 50;      break;
165  case B75:     baud = 75;      break;
166  case B110:    baud = 110;     break;
167  case B134:    baud = 134;     break;
168  case B150:    baud = 150;     break;
169  case B200:    baud = 200;     break;
170  case B300:    baud = 300;     break;
171  case B600:    baud = 600;     break;
172  case B1200:   baud = 1200;    break;
173  case B1800:   baud = 1800;    break;
174  case B2400:   baud = 2400;    break;
175  case B4800:   baud = 4800;    break;
176  case B9600:   baud = 9600;    break;
177  case B19200:  baud = 19200;   break;
178  case B38400:  baud = 38400;   break;
179  case B57600:  baud = 57600;   break;
180  case B115200: baud = 115200;  break;
181  case B230400: baud = 230400;  break;
182  case B460800: baud = 460800;  break;
183  }
184  if (baud > 0) {
185    brg = m821_get_brg_clk(baud);     /* 4 BRGs, 4 serial ports - hopefully */
186                                      /*  at least 2 ports will be the same */
187    m821.simode |= brg << (12 + ((minor) * 16));
188  }
189  return 0;
190}
191
192int
193m821_scc_set_attributes (int minor, const struct termios *t)
194{
195  /*
196   * minor must be 2, or 3
197   */
198  int baud;
199  int brg;
200  switch (t->c_cflag & CBAUD) {
201  default:      baud = -1;      break;
202  case B50:     baud = 50;      break;
203  case B75:     baud = 75;      break;
204  case B110:    baud = 110;     break;
205  case B134:    baud = 134;     break;
206  case B150:    baud = 150;     break;
207  case B200:    baud = 200;     break;
208  case B300:    baud = 300;     break;
209  case B600:    baud = 600;     break;
210  case B1200:   baud = 1200;    break;
211  case B1800:   baud = 1800;    break;
212  case B2400:   baud = 2400;    break;
213  case B4800:   baud = 4800;    break;
214  case B9600:   baud = 9600;    break;
215  case B19200:  baud = 19200;   break;
216  case B38400:  baud = 38400;   break;
217  case B57600:  baud = 57600;   break;
218  case B115200: baud = 115200;  break;
219  case B230400: baud = 230400;  break;
220  case B460800: baud = 460800;  break;
221  }
222  if (baud > 0) {
223    brg = m821_get_brg_clk(baud);     /* 4 BRGs, 5 serial ports - hopefully */
224                                      /*  at least 2 ports will be the same */
225    m821.sicr |= (brg << (3 + ((minor-2) * 8))) |
226                 (brg << ((minor-2) * 8));
227  }
228  return 0;
229}
230
231void
232m821_scc_initialize (int port)  /* port is the SCC # (i.e. 1, 2, 3 or 4) */
233{
234  unsigned char                brg;
235  volatile m821SCCparms_t     *sccparms;
236  volatile m821SCCRegisters_t *sccregs;
237
238  /*
239   * Allocate buffer descriptors
240   */
241  RxBd[port+1] = M821AllocateBufferDescriptors(1);
242  TxBd[port+1] = M821AllocateBufferDescriptors(1);
243 
244  /*
245   * Configure ports A and B to enable TXDx and RXDx pins
246   */
247  m821.papar |=  (0xC << ((port-2) * 2));
248  m821.padir &= ~(0xC << ((port-2) * 2));
249  m821.pbdir |=  (0x04 << (port-2));
250  m821.paodr &= ~(0x8 << ((port-2) * 2));
251  m821.pbdat &= ~(0x04 << (port-2));
252 
253  /* SCC2 is the only one with handshaking lines */
254  /*
255    if (port == 2) {
256    m821.pcpar |= (0x02);
257    m821.pcpar &= ~(0xc0);
258    m821.pcdir &= ~(0xc2);
259    m821.pcso  |= (0xc0);
260    }
261  */
262 
263  brg = m821_get_brg_clk(9600);     /* 4 BRGs, 5 serial ports - hopefully */
264                                    /*  at least 2 ports will be the same */
265 
266  /*
267   * Set up SDMA
268   */
269  m821.sdcr = 0x01; /* as recommended p 16-80, sec 16.10.2.1 MPC821UM/AD */
270 
271
272  m821.sicr &= ~(0xff << ((port-1) * 8));
273  m821.sicr |= (brg << (3 + ((port-1) * 8))) | (brg << ((port-1) * 8));
274 
275  /*
276   * Set up SCC1 parameter RAM common to all protocols
277   */
278  if (port == 1) {
279    sccparms = (m821SCCparms_t*)&m821.scc1p;
280    sccregs = &m821.scc1;
281  }
282  else if (port == 2) {
283    sccparms = &m821.scc2p;
284    sccregs = &m821.scc2;
285  }
286 
287  sccparms->rbase = (char *)RxBd[port+1] - (char *)&m821;
288  sccparms->tbase = (char *)TxBd[port+1] - (char *)&m821;
289 
290  if (port == 1)
291    M821ExecuteRISC (M821_CR_OP_INIT_RX_TX | M821_CR_CHAN_SCC1);
292  else if (port == 2)
293    M821ExecuteRISC (M821_CR_OP_INIT_RX_TX | M821_CR_CHAN_SCC2);
294 
295  sccparms->rfcr = M821_RFCR_MOT | M821_RFCR_DMA_SPACE(0);
296  sccparms->tfcr = M821_TFCR_MOT | M821_TFCR_DMA_SPACE(0);
297  sccparms->mrblr = RXBUFSIZE;
298 
299  sccparms->un.uart.max_idl = 10;
300  sccparms->un.uart.brklen = 0;
301  sccparms->un.uart.brkec = 0;
302  sccparms->un.uart.brkcr = 1;
303 
304  sccparms->un.uart.parec = 0;
305  sccparms->un.uart.frmec = 0;
306  sccparms->un.uart.nosec = 0;
307 
308  sccparms->un.uart.uaddr[0] = 0;
309  sccparms->un.uart.uaddr[1] = 0;
310  sccparms->un.uart.toseq  = 0;
311 
312  sccparms->un.uart.character[0] = 0x8000;
313  sccparms->un.uart.character[1] = 0x8000;
314  sccparms->un.uart.character[2] = 0x8000;
315  sccparms->un.uart.character[3] = 0x8000;
316  sccparms->un.uart.character[4] = 0x8000;
317  sccparms->un.uart.character[5] = 0x8000;
318  sccparms->un.uart.character[6] = 0x8000;
319  sccparms->un.uart.character[7] = 0x8000;
320 
321  sccparms->un.uart.rccm = 0xc0ff;
322 
323  /*
324   * Set up the Receive Buffer Descriptor
325   */
326  RxBd[port+1]->status = M821_BD_EMPTY | M821_BD_WRAP |
327    M821_BD_INTERRUPT;
328  RxBd[port+1]->length = 0;
329  RxBd[port+1]->buffer = malloc(RXBUFSIZE);
330 
331  /*
332   * Setup the Transmit Buffer Descriptor
333   */
334  TxBd[port+1]->status = M821_BD_WRAP;
335 
336  /*
337   * Set up SCCx general and protocol-specific mode registers
338   */
339  sccregs->scce = 0xffff;
340  sccregs->sccm = 0x0000;
341  sccregs->gsmr_h = 0x00000020;
342  sccregs->gsmr_l = 0x00028004;
343  sccregs->psmr   = 0x3000;
344  sccregs->gsmr_l = 0x00028034;
345}
346
347void
348m821_smc_initialize (int port)  /* port is the SMC number (i.e. 1 or 2) */
349{
350  unsigned char brg;
351
352  /*
353   * Allocate buffer descriptors
354   */
355  RxBd[port-1] = M821AllocateBufferDescriptors (1);
356  TxBd[port-1] = M821AllocateBufferDescriptors (1);
357
358  /*
359   * Configure port B pins to enable SMTXDx and SMRXDx pins
360   */
361  m821.pbpar |=  (0xC0 << ((port-1) * 4));
362  m821.pbdir &= ~(0xC0 << ((port-1) * 4));
363  m821.pbdir |=  (0x01 << (port-1));
364  m821.pbodr &= ~(0xC0 << ((port-1) * 4));
365  m821.pbdat &= ~(0x01 << (port-1));
366 
367  /*
368   * Set up BRG1 (9,600 baud)
369   */
370  brg = m821_get_brg_clk(9600);     /* 4 BRGs, 5 serial ports - hopefully */
371                                    /*  at least 2 ports will be the same */
372
373  /*
374   * Put SMC in NMSI mode, connect SMC to BRG
375   */
376  m821.simode &= ~0x7000 << ((port-1) * 8);
377  m821.simode |= brg << (12 + ((port-1) * 8));
378
379  /*
380   * Set up SMC1 parameter RAM common to all protocols
381   */
382  if (port == 1) {
383    m821.smc1p.rbase = (char *)RxBd[port-1] - (char *)&m821;
384    m821.smc1p.tbase = (char *)TxBd[port-1] - (char *)&m821;
385    m821.smc1p.rfcr = M821_RFCR_MOT | M821_RFCR_DMA_SPACE(0);
386    m821.smc1p.tfcr = M821_TFCR_MOT | M821_TFCR_DMA_SPACE(0);
387    m821.smc1p.mrblr = RXBUFSIZE;
388   
389    /*
390     * Set up SMC1 parameter RAM UART-specific parameters
391     */
392    m821.smc1p.un.uart.max_idl = 10;
393    m821.smc1p.un.uart.brklen = 0;
394    m821.smc1p.un.uart.brkec = 0;
395    m821.smc1p.un.uart.brkcr = 0;
396   
397  }
398  else {
399    m821.smc2p.rbase = (char *)RxBd[port-1] - (char *)&m821;
400    m821.smc2p.tbase = (char *)TxBd[port-1] - (char *)&m821;
401    m821.smc2p.rfcr = M821_RFCR_MOT | M821_RFCR_DMA_SPACE(0);
402    m821.smc2p.tfcr = M821_TFCR_MOT | M821_TFCR_DMA_SPACE(0);
403    m821.smc2p.mrblr = RXBUFSIZE;
404   
405    /*
406     * Set up SMC2 parameter RAM UART-specific parameters
407     */
408    m821.smc2p.un.uart.max_idl = 10;
409    m821.smc2p.un.uart.brklen = 0;
410    m821.smc2p.un.uart.brkec = 0;
411    m821.smc2p.un.uart.brkcr = 0;
412  }     
413 
414  /*
415   * Set up the Receive Buffer Descriptor
416   */
417  RxBd[port-1]->status = M821_BD_EMPTY | M821_BD_WRAP |
418                                  M821_BD_INTERRUPT;
419  RxBd[port-1]->length = 0;
420  RxBd[port+3]->buffer = malloc(RXBUFSIZE);
421         
422  /*
423   * Setup the Transmit Buffer Descriptor
424   */
425  TxBd[port-1]->status = M821_BD_WRAP;
426 
427  /*
428   * Set up SMCx general and protocol-specific mode registers
429   */
430  if (port == 1) {
431    m821.smc1.smce = ~0;        /* Clear any pending events */
432    m821.smc1.smcm = 0; /* Mask all interrupt/event sources */
433    m821.smc1.smcmr = M821_SMCMR_CLEN(9) | M821_SMCMR_SM_UART;
434   
435    /*
436     * Send "Init parameters" command
437     */
438    M821ExecuteRISC (M821_CR_OP_INIT_RX_TX | M821_CR_CHAN_SMC1);
439   
440    /*
441     * Enable receiver and transmitter
442     */
443    m821.smc1.smcmr |= M821_SMCMR_TEN | M821_SMCMR_REN;
444  }
445  else {
446    m821.smc2.smce = ~0;        /* Clear any pending events */
447    m821.smc2.smcm = 0; /* Mask all interrupt/event sources */
448    m821.smc2.smcmr = M821_SMCMR_CLEN(9) | M821_SMCMR_SM_UART;
449   
450    /*
451     * Send "Init parameters" command
452     */
453    M821ExecuteRISC (M821_CR_OP_INIT_RX_TX | M821_CR_CHAN_SMC2);
454   
455    /*
456     * Enable receiver and transmitter
457     */
458    m821.smc2.smcmr |= M821_SMCMR_TEN | M821_SMCMR_REN;
459  }
460}
461
462int
463m821_char_poll_read (int minor)
464{
465  unsigned char c;
466  rtems_unsigned32 level;
467
468  _CPU_ISR_Disable(level); 
469  if (RxBd[minor]->status & M821_BD_EMPTY) {
470    _CPU_ISR_Enable(level);
471    return -1;
472  }
473  c = ((char *)RxBd[minor]->buffer)[0];
474  RxBd[minor]->status = M821_BD_EMPTY | M821_BD_WRAP;
475  _CPU_ISR_Enable(level);
476  return c;
477}
478
479int
480m821_char_poll_write (int minor, const char *buf, int len)
481{
482  while (len--) {
483    while (TxBd[minor]->status & M821_BD_READY)
484      continue;
485    txBuf[minor] = *buf++;
486    TxBd[minor]->buffer = &txBuf[minor];
487    TxBd[minor]->length = 1;
488    TxBd[minor]->status = M821_BD_READY | M821_BD_WRAP;
489  }
490  return 0;
491}
492
493/*
494 * Interrupt handler
495 */
496rtems_isr
497m821_scc1_console_interrupt_handler (rtems_vector_number v)
498{
499  /*
500   * Buffer received?
501   */
502  if ((m821.scc1.sccm & 0x1) && (m821.scc1.scce & 0x1)) {
503    m821.scc1.scce = 0x1;
504    /*    m821.scc1.sccm &= ~0x1;*/
505   
506    while ((RxBd[SCC1_MINOR]->status & M821_BD_EMPTY) == 0) {
507      rxBufListTail[SCC1_MINOR]->next = malloc(sizeof(Buf_t));
508      if (rxBufListTail[SCC1_MINOR]->next) {
509        rxBufListTail[SCC1_MINOR] = rxBufListTail[SCC1_MINOR]->next;
510        rxBufListTail[SCC1_MINOR]->buf = RxBd[SCC1_MINOR]->buffer;
511        rxBufListTail[SCC1_MINOR]->len = RxBd[SCC1_MINOR]->length;
512        rxBufListTail[SCC1_MINOR]->pos = 0;
513        rxBufListTail[SCC1_MINOR]->next = 0;
514
515        RxBd[SCC1_MINOR]->buffer = malloc(RXBUFSIZE);
516      }
517      RxBd[SCC1_MINOR]->status = M821_BD_EMPTY | M821_BD_WRAP |
518                                 M821_BD_INTERRUPT;
519    }
520  }
521 
522  /*
523   * Buffer transmitted?
524   */
525#if 0
526  if (m821.smc1.smce & 0x2) {
527    m821.smc1.smce = 0x2;
528    if ((smcTxBd->status & M360_BD_READY) == 0)
529      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
530  }
531#endif
532  m821.cisr = 1UL << 30;  /* Clear SCC1 interrupt-in-service bit */
533}
534
535rtems_isr
536m821_scc2_console_interrupt_handler (rtems_vector_number v)
537{
538  /*
539   * Buffer received?
540   */
541  if ((m821.scc2.sccm & 0x1) && (m821.scc2.scce & 0x1)) {
542    m821.scc2.scce = 0x1;
543    /*    m821.scc2.sccm &= ~0x1;*/
544   
545    while ((RxBd[SCC2_MINOR]->status & M821_BD_EMPTY) == 0) {
546      rxBufListTail[SCC2_MINOR]->next = malloc(sizeof(Buf_t));
547      if (rxBufListTail[SCC2_MINOR]->next) {
548        rxBufListTail[SCC2_MINOR] = rxBufListTail[SCC2_MINOR]->next;
549        rxBufListTail[SCC2_MINOR]->buf = RxBd[SCC2_MINOR]->buffer;
550        rxBufListTail[SCC2_MINOR]->len = RxBd[SCC2_MINOR]->length;
551        rxBufListTail[SCC2_MINOR]->pos = 0;
552        rxBufListTail[SCC2_MINOR]->next = 0;
553
554        RxBd[SCC2_MINOR]->buffer = malloc(RXBUFSIZE);
555      }
556      RxBd[SCC2_MINOR]->status = M821_BD_EMPTY | M821_BD_WRAP |
557                                 M821_BD_INTERRUPT;
558    }
559  }
560 
561  /*
562   * Buffer transmitted?
563   */
564#if 0
565  if (m821.smc1.smce & 0x2) {
566    m821.smc1.smce = 0x2;
567    if ((smcTxBd->status & M360_BD_READY) == 0)
568      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
569  }
570#endif
571  m821.cisr = 1UL << 29;  /* Clear SCC2 interrupt-in-service bit */
572}
573
574rtems_isr
575m821_smc1_console_interrupt_handler (rtems_vector_number v)
576{
577  /*
578   * Buffer received?
579   */
580  if (m821.smc1.smce & 0x1) {
581    m821.smc1.smce = 0x1;
582    /*    m821.scc2.sccm &= ~0x1;*/
583   
584    while ((RxBd[SMC1_MINOR]->status & M821_BD_EMPTY) == 0) {
585      rxBufListTail[SMC1_MINOR]->next = malloc(sizeof(Buf_t));
586      if (rxBufListTail[SMC1_MINOR]->next) {
587        rxBufListTail[SMC1_MINOR] = rxBufListTail[SMC1_MINOR]->next;
588        rxBufListTail[SMC1_MINOR]->buf = RxBd[SMC1_MINOR]->buffer;
589        rxBufListTail[SMC1_MINOR]->len = RxBd[SMC1_MINOR]->length;
590        rxBufListTail[SMC1_MINOR]->pos = 0;
591        rxBufListTail[SMC1_MINOR]->next = 0;
592
593        RxBd[SMC1_MINOR]->buffer = malloc(RXBUFSIZE);
594      }
595      RxBd[SMC1_MINOR]->status = M821_BD_EMPTY | M821_BD_WRAP |
596                                 M821_BD_INTERRUPT;
597    }
598  }
599 
600  /*
601   * Buffer transmitted?
602   */
603#if 0
604  if (m821.smc1.smce & 0x2) {
605    m821.smc1.smce = 0x2;
606    if ((smcTxBd->status & M360_BD_READY) == 0)
607      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
608  }
609#endif
610  m821.cisr = 1UL << 4;  /* Clear SMC1 interrupt-in-service bit */
611}
612
613rtems_isr
614m821_smc2_console_interrupt_handler (rtems_vector_number v)
615{
616  /*
617   * Buffer received?
618   */
619  if (m821.smc2.smce & 0x1) {
620    m821.smc2.smce = 0x1;
621   
622    while ((RxBd[SMC2_MINOR]->status & M821_BD_EMPTY) == 0) {
623      rxBufListTail[SMC2_MINOR]->next = malloc(sizeof(Buf_t));
624      if (rxBufListTail[SMC2_MINOR]->next) {
625        rxBufListTail[SMC2_MINOR] = rxBufListTail[SMC2_MINOR]->next;
626        rxBufListTail[SMC2_MINOR]->buf = RxBd[SMC2_MINOR]->buffer;
627        rxBufListTail[SMC2_MINOR]->len = RxBd[SMC2_MINOR]->length;
628        rxBufListTail[SMC2_MINOR]->pos = 0;
629        rxBufListTail[SMC2_MINOR]->next = 0;
630
631        RxBd[SMC2_MINOR]->buffer = malloc(RXBUFSIZE);
632      }
633      RxBd[SMC2_MINOR]->status = M821_BD_EMPTY | M821_BD_WRAP |
634                                 M821_BD_INTERRUPT;
635    }
636  }
637 
638  /*
639   * Buffer transmitted?
640   */
641#if 0
642  if (m821.smc1.smce & 0x2) {
643    m821.smc1.smce = 0x2;
644    if ((smcTxBd->status & M360_BD_READY) == 0)
645      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
646  }
647#endif
648  m821.cisr = 1UL << 3;  /* Clear SMC2 interrupt-in-service bit */
649}
650
651
652int
653m821_buf_poll_read (int minor, char **buf)
654{
655  int len;
656
657  if (RxBd[minor]->status & M821_BD_EMPTY)
658    return -1;
659 
660  RxBd[minor]->buffer = malloc(RXBUFSIZE); /* I hope this succeeds ... */
661  len = RxBd[minor]->length;
662  RxBd[minor]->status = M821_BD_EMPTY | M821_BD_WRAP;
663 
664  return len;
665}
666
667int
668m821_buf_poll_write (int minor, char *buf, int len)
669{
670  static char *last_buf[6];
671
672  while (TxBd[minor]->status & M821_BD_READY)
673    continue;
674  if (last_buf[minor])
675    free(last_buf[minor]);
676  last_buf[minor] = buf;
677  TxBd[minor]->buffer = buf;
678  TxBd[minor]->length = len;
679  TxBd[minor]->status = M821_BD_READY | M821_BD_WRAP;
680  return 0;
681}
682
683/*
684 * This is needed in case we use TERMIOS
685 */
686void m821_console_reserve_resources(rtems_configuration_table *configuration)
687{
688  rtems_termios_reserve_resources (configuration, 1);
689}
690
691void m821_console_initialize(void)
692{
693  int i;
694
695  for (i=0; i < NIFACES; i++) {
696    rxBufList[i] = malloc(sizeof(Buf_t));
697    rxBufListTail[i] = rxBufList[i];
698    rxBufList[i]->buf  = 0;
699    rxBufList[i]->len  = 0;
700    rxBufList[i]->pos  = 0;
701    rxBufList[i]->next = 0;
702  }
703}
704
705rtems_device_driver m821_console_read(rtems_device_major_number major,
706                                      rtems_device_minor_number minor,
707                                      void *arg)
708{
709  rtems_libio_rw_args_t *rw_args;
710  char *buffer;
711  int maximum;
712  int count;
713  Buf_t *tmp_buf;
714  rtems_unsigned32 level;
715
716  /*
717   * Set up interrupts
718   * FIXME: DANGER: WARNING:
719   * CICR and SIMASK must be set in any module that uses
720   *   the CPM. Currently those are console-generic.c and
721   *   network.c. If the registers are not set the same
722   *   in both places, strange things may happen.
723   *   If they are only set in one place, then an application
724   *   that used the other module won't work correctly.
725   *   Put this comment in each module that sets these 2 registers
726   */
727  m821.cicr = 0x00e43e80;   /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
728                               SCdP=SCC4, IRL=1, HP=SCC1, IEN=1 */
729  m821.simask |= M821_SIMASK_LVM1;
730
731  rw_args = (rtems_libio_rw_args_t *) arg;
732  buffer = rw_args->buffer;
733  maximum = rw_args->count;
734  count = 0;
735
736  while (count == 0) {
737    if (rxBufList[minor]->len) {
738      while ((count < maximum) &&
739             (rxBufList[minor]->pos < rxBufList[minor]->len)) {
740        buffer[count++] = rxBufList[minor]->buf[rxBufList[minor]->pos++];
741      }
742      _CPU_ISR_Disable(level);
743      if (rxBufList[minor]->pos == rxBufList[minor]->len) {
744        if (rxBufList[minor]->next) {
745          tmp_buf=rxBufList[minor]->next;
746          free (rxBufList[minor]->buf);
747          free (rxBufList[minor]);
748          rxBufList[minor]=tmp_buf;
749        }
750        else {
751          free(rxBufList[minor]->buf);
752          rxBufList[minor]->buf=0;
753          rxBufList[minor]->len=0;
754          rxBufList[minor]->pos=0;
755        }
756      }
757      _CPU_ISR_Enable(level);
758    }
759    else
760      if(rxBufList[minor]->next && !rxBufList[minor]->len) {
761        tmp_buf = rxBufList[minor];
762        rxBufList[minor] = rxBufList[minor]->next;
763        free(tmp_buf);
764      }
765    /*      sleep(1);*/
766  }
767  rw_args->bytes_moved = count;
768  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
769}
770 
771rtems_device_driver m821_console_write(rtems_device_major_number major,
772                                       rtems_device_minor_number minor,
773                                       void *arg)
774{
775  int count;
776  int maximum;
777  rtems_libio_rw_args_t *rw_args;
778  char *in_buffer;
779  char *out_buffer;
780  int n;
781
782  /*
783   * Set up interrupts
784   * FIXME: DANGER: WARNING:
785   * CICR and SIMASK must be set in any module that uses
786   *   the CPM. Currently those are console-generic.c and
787   *   network.c. If the registers are not set the same
788   *   in both places, strange things may happen.
789   *   If they are only set in one place, then an application
790   *   that used the other module won't work correctly.
791   *   Put this comment in each module that sets these 2 registers
792   */
793/*  m821.cicr = 0x00e43e80;   /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
794                               SCdP=SCC4, IRL=1, HP=SCC1, IEN=1 */
795/*  m821.simask |= M821_SIMASK_LVM1;  */
796
797  rw_args = (rtems_libio_rw_args_t *) arg;
798
799  in_buffer = rw_args->buffer;
800  maximum = rw_args->count;
801
802  out_buffer = malloc(maximum*2);  /* This is wasteful, but it won't */
803                                   /*  be too small */
804
805  if (!out_buffer) {
806    rw_args->bytes_moved = 0;
807    return RTEMS_NO_MEMORY;
808  }
809  n=0;
810  for (count = 0; count < maximum; count++) {
811    if ( in_buffer[ count ] == '\n') {
812      out_buffer[count + n] = '\r';
813      n++;
814    }
815    out_buffer[count + n] = in_buffer[count];
816  }
817  m821_buf_poll_write(minor, out_buffer, maximum+n);
818  rw_args->bytes_moved = maximum;
819  return RTEMS_SUCCESSFUL;
820}
821
822
823/*
824 *  How to use the console.
825 *   In your BSP, have the following functions:
826 *
827 *  rtems_device_driver console_initialize(rtems_device_major_number  major,
828 *                                         rtems_device_minor_number  minor,
829 *                                         void *arg)
830 *  rtems_device_driver console_open(rtems_device_major_number major,
831 *                                   rtems_device_minor_number minor,
832 *                                   void *arg)
833 *  rtems_device_driver console_close(rtems_device_major_number major,
834 *                                    rtems_device_minor_number minor,
835 *                                    void *arg)
836 *  rtems_device_driver console_read(rtems_device_major_number major,
837 *                                   rtems_device_minor_number minor,
838 *                                   void *arg)
839 *  rtems_device_driver console_write(rtems_device_major_number major,
840 *                                    rtems_device_minor_number minor,
841 *                                    void *arg)
842 *  rtems_device_driver console_control(rtems_device_major_number major,
843 *                                      rtems_device_minor_number minor,
844 *                                      void *arg)
845 *
846 */
Note: See TracBrowser for help on using the repository browser.