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

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

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

  • Property mode set to 100644
File size: 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 <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
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.