source: rtems/c/src/lib/libcpu/powerpc/mpc821/console-generic/console-generic.c @ 63b96b9

4.104.114.84.95
Last change on this file since 63b96b9 was 63b96b9, checked in by Joel Sherrill <joel.sherrill@…>, on 04/12/99 at 15:21:43

Addressed this bug report:

Date: Mon, 12 Apr 1999 00:38:04 +0000
From: Brendan Simon <brendan@…>
To: Jay Monkman <jmonkman@…>, "joel@…" <joel@…>
Subject: [Fwd: Goof in SMC initialize for mpc860]

Nick Simon reported this bug in the eth_comm BSP sources. I see that it is
still there in the latest snapshot that Joel sent me (thanks). I thought I
better forward this on to you guys.

Brendan.

Nick.SIMON@… wrote:

Sice I believe you're using the same base BSP as I am (you sent it to me) I
thought I'd mention..

In console-generic.c, in m860_smc_initialize, the receive buffer is malloced
and assigned to RxBd?[port+3]-> buffer - it should be [port-1].

TTFN

B

  • Property mode set to 100644
File size: 23.3 KB
Line 
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-1]->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.