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

4.104.114.84.95
Last change on this file since 63b96b9 was 63b96b9, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 12, 1999 at 3:21:43 PM

Addressed this bug report:

Date: Mon, 12 Apr 1999 00:38:04 +0000
From: Brendan Simon <brendan@…>
To: Jay Monkman <jmonkman@…>, "joel@…" <joel@…>
Subject: [Fwd: Goof in SMC initialize for mpc860]

Nick Simon reported this bug in the eth_comm BSP sources. I see that it is
still there in the latest snapshot that Joel sent me (thanks). I thought I
better forward this on to you guys.

Brendan.

Nick.SIMON@… wrote:

Sice I believe you're using the same base BSP as I am (you sent it to me) I
thought I'd mention..

In console-generic.c, in m860_smc_initialize, the receive buffer is malloced
and assigned to RxBd?[port+3]-> buffer - it should be [port-1].

TTFN

B

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