source: rtems/c/src/lib/libcpu/powerpc/mpc860/console-generic/console-generic.c @ 458bd34

4.104.114.84.95
Last change on this file since 458bd34 was 458bd34, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 5, 1999 at 4:44:02 PM

This is another pass at making sure that nothing outside the BSP
unnecessarily uses any variables defined by the BSP. On this
sweep, use of BSP_Configuration and Cpu_table was eliminated.

A significant part of this modification was the addition of
macros to access fields in the RTEMS configuration structures.

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@…>.

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