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

4.104.114.84.95
Last change on this file since f817b02 was f817b02, checked in by Joel Sherrill <joel.sherrill@…>, on 11/04/99 at 18:05:09

The files in libcpu should not be directly dependent on any BSP. In
particular, using bsp.h, or getting information from the BSP which
should properly be obtained from RTEMS is forbidden. This is
necessary to strengthen the division between the BSP independent
parts of RTEMS and the BSPs themselves. This started after
comments and analysis by Ralf Corsepius <corsepiu@…>.
The changes primarily eliminated the need to include bsp.h and
peeking at BSP_Configuration. The use of Cpu_table in each
BSP needs to be eliminated.

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