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

4.104.114.84.95
Last change on this file since 08311cc3 was 08311cc3, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 17, 1999 at 5:51:34 PM

Updated copyright notice.

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