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

4.104.114.84.95
Last change on this file since df49c60 was df49c60, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 12, 2000 at 3:00:15 PM

Merged from 4.5.0-beta3a

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