OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libcpu/] [powerpc/] [mpc860/] [console-generic/] [console-generic.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
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: console-generic.c,v 1.2 2001-09-27 12:01:29 chris Exp $
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
 
56
static Buf_t *rxBufList[NIFACES];
57
static 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
 */
68
static volatile char txBuf[NIFACES];
69
 
70
static volatile m860BufferDescriptor_t *RxBd[NIFACES], *TxBd[NIFACES];
71
 
72
/*
73
 * Device-specific routines
74
 */
75
static int m860_get_brg_cd(int);
76
unsigned char m860_get_brg_clk(int);
77
unsigned char m860_get_brg_clk(int);
78
 
79
 
80
/*
81
 * Compute baud-rate-generator configuration register value
82
 */
83
static int
84
m860_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 */
102
unsigned 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
 */
153
int
154
m860_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
 
191
int
192
m860_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
 
230
void
231
m860_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
 
358
void
359
m860_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
 
473
int
474
m860_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
 
490
int
491
m860_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
 */
507
rtems_isr
508
m860_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
 
546
rtems_isr
547
m860_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
 
585
rtems_isr
586
m860_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
 
624
rtems_isr
625
m860_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
 
663
rtems_isr
664
m860_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
 
702
rtems_isr
703
m860_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
 
741
int
742
m860_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
 
756
int
757
m860_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
 
772
void 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
 
786
rtems_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
 
852
rtems_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
 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.