source: rtems/c/src/lib/libcpu/powerpc/mpc821/console-generic/console-generic.c @ 05a34668

Last change on this file since 05a34668 was 05a34668, checked in by Joel Sherrill <joel.sherrill@…>, on 03/21/00 at 18:35:00

Patch from Gunter Magin <magin@…> where the type was
not large enough to support high baud rates.

brg_spd[] is an array which stores the baud rates, for which one of the 4
available BRG dividers has been set. The array is used for deciding if a
BRG devider may be reused.

  1. What baud_rate and divisor is causing this to fail?

divisor is dependent on the system clock (Cpu_table.clock_speed), and gets
calculated in m860_get_brg_cd.

m860_get_brg_clk fails for any baudrates > (216-1), as those baudrates are
truncated to 16 bit which is the size of a short. In fact, as it has been a
short and not an unsigned short, it will fail at any baudrate >(2
15-1). In
any case, it failed for my application, which required 250000 Baud.

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