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

Subversion Repositories openrisc_me

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

Go to most recent revision | 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
 *    BRG1
18
 *    BRG2
19
 *    BRG3
20
 *    BRG4
21
 *  Author: Jay Monkman (jmonkman@frasca.com)
22
 *  Copyright (C) 1998 by Frasca International, Inc.
23
 *
24
 *  Derived from c/src/lib/libbsp/m68k/gen360/console/console.c:
25
 *
26
 *  Author:
27
 *    W. Eric Norum
28
 *    Saskatchewan Accelerator Laboratory
29
 *    University of Saskatchewan
30
 *    Saskatoon, Saskatchewan, CANADA
31
 *    eric@skatter.usask.ca
32
 *
33
 *  COPYRIGHT (c) 1989-1999.
34
 *  On-Line Applications Research Corporation (OAR).
35
 *
36
 *  The license and distribution terms for this file may be
37
 *  found in the file LICENSE in this distribution or at
38
 *
39
 *  http://www.OARcorp.com/rtems/license.html.
40
 *
41
 *  $Id: console-generic.c,v 1.2 2001-09-27 12:01:26 chris Exp $
42
 */
43
 
44
#include <rtems/libio.h>
45
#include <mpc821.h>
46
#include <mpc821/console.h>
47
#include <stdlib.h>
48
#include <unistd.h>
49
#include <termios.h>
50
 
51
#define NIFACES 4        /* number of console devices (serial ports) */
52
 
53
static Buf_t *rxBufList[NIFACES];
54
static Buf_t *rxBufListTail[NIFACES];
55
 
56
/*
57
 * Interrupt-driven input buffer
58
 */
59
#define RXBUFSIZE       16
60
 
61
 
62
/*
63
 * I/O buffers and pointers to buffer descriptors
64
 */
65
static volatile char txBuf[NIFACES];
66
 
67
static volatile m821BufferDescriptor_t *RxBd[NIFACES], *TxBd[NIFACES];
68
 
69
/*
70
 * Device-specific routines
71
 */
72
static int m821_get_brg_cd(int);
73
unsigned char m821_get_brg_clk(int);
74
unsigned char m821_get_brg_clk(int);
75
 
76
 
77
/*
78
 * Compute baud-rate-generator configuration register value
79
 */
80
static int
81
m821_get_brg_cd (int baud)
82
{
83
  int divisor;
84
  int div16 = 0;
85
 
86
  divisor = ((rtems_cpu_configuration_get_clock_speed() / 16) +
87
              (baud / 2)) / baud;
88
  if (divisor > 4096) {
89
    div16 = 1;
90
    divisor = (divisor + 8) / 16;
91
  }
92
  return M821_BRG_EN | M821_BRG_EXTC_BRGCLK |
93
    ((divisor - 1) << 1) | div16;
94
}
95
 
96
 
97
/* this function will fail if more that 4 baud rates have been selected */
98
/*  at any time since the OS started. It needs to be fixed. FIXME */
99
unsigned char m821_get_brg_clk(int baud)
100
{
101
  static int   brg_spd[4];
102
  static char  brg_used[4];
103
  int i;
104
 
105
  /* first try to find a BRG that is already at the right speed */
106
  for (i=0; i<4; i++) {
107
    if (brg_spd[i] == baud) {
108
      break;
109
    }
110
  }
111
 
112
  if (i==4) { /* I guess we didn't find one */
113
    for (i=0; i<4; i++) {
114
      if (brg_used[i] == 0) {
115
        break;
116
      }
117
    }
118
  }
119
  if (i != 4) {
120
    brg_used[i]++;
121
    brg_spd[i]=baud;
122
    switch (i) {
123
    case 0:
124
      m821.brgc1 = M821_BRG_RST;
125
      m821.brgc1 = m821_get_brg_cd(baud);
126
      break;
127
    case 1:
128
      m821.brgc2 = M821_BRG_RST;
129
      m821.brgc2 = m821_get_brg_cd(baud);
130
      break;
131
    case 2:
132
      m821.brgc3 = M821_BRG_RST;
133
      m821.brgc3 = m821_get_brg_cd(baud);
134
      break;
135
    case 3:
136
      m821.brgc4 = M821_BRG_RST;
137
      m821.brgc4 = m821_get_brg_cd(baud);
138
      break;
139
    }
140
    return i;
141
  }
142
 
143
  else
144
    return 0xff;
145
}
146
 
147
/*
148
 * Hardware-dependent portion of tcsetattr().
149
 */
150
int
151
m821_smc_set_attributes (int minor, const struct termios *t)
152
{
153
  /*
154
   * minor must be 0 or 1
155
   */
156
  int baud;
157
  int brg;
158
  switch (t->c_cflag & CBAUD) {
159
  default:      baud = -1;      break;
160
  case B50:     baud = 50;      break;
161
  case B75:     baud = 75;      break;
162
  case B110:    baud = 110;     break;
163
  case B134:    baud = 134;     break;
164
  case B150:    baud = 150;     break;
165
  case B200:    baud = 200;     break;
166
  case B300:    baud = 300;     break;
167
  case B600:    baud = 600;     break;
168
  case B1200:   baud = 1200;    break;
169
  case B1800:   baud = 1800;    break;
170
  case B2400:   baud = 2400;    break;
171
  case B4800:   baud = 4800;    break;
172
  case B9600:   baud = 9600;    break;
173
  case B19200:  baud = 19200;   break;
174
  case B38400:  baud = 38400;   break;
175
  case B57600:  baud = 57600;   break;
176
  case B115200: baud = 115200;  break;
177
  case B230400: baud = 230400;  break;
178
  case B460800: baud = 460800;  break;
179
  }
180
  if (baud > 0) {
181
    brg = m821_get_brg_clk(baud);     /* 4 BRGs, 4 serial ports - hopefully */
182
                                      /*  at least 2 ports will be the same */
183
    m821.simode |= brg << (12 + ((minor) * 16));
184
  }
185
  return 0;
186
}
187
 
188
int
189
m821_scc_set_attributes (int minor, const struct termios *t)
190
{
191
  /*
192
   * minor must be 2, or 3
193
   */
194
  int baud;
195
  int brg;
196
  switch (t->c_cflag & CBAUD) {
197
  default:      baud = -1;      break;
198
  case B50:     baud = 50;      break;
199
  case B75:     baud = 75;      break;
200
  case B110:    baud = 110;     break;
201
  case B134:    baud = 134;     break;
202
  case B150:    baud = 150;     break;
203
  case B200:    baud = 200;     break;
204
  case B300:    baud = 300;     break;
205
  case B600:    baud = 600;     break;
206
  case B1200:   baud = 1200;    break;
207
  case B1800:   baud = 1800;    break;
208
  case B2400:   baud = 2400;    break;
209
  case B4800:   baud = 4800;    break;
210
  case B9600:   baud = 9600;    break;
211
  case B19200:  baud = 19200;   break;
212
  case B38400:  baud = 38400;   break;
213
  case B57600:  baud = 57600;   break;
214
  case B115200: baud = 115200;  break;
215
  case B230400: baud = 230400;  break;
216
  case B460800: baud = 460800;  break;
217
  }
218
  if (baud > 0) {
219
    brg = m821_get_brg_clk(baud);     /* 4 BRGs, 5 serial ports - hopefully */
220
                                      /*  at least 2 ports will be the same */
221
    m821.sicr |= (brg << (3 + ((minor-2) * 8))) |
222
                 (brg << ((minor-2) * 8));
223
  }
224
  return 0;
225
}
226
 
227
void
228
m821_scc_initialize (int port)  /* port is the SCC # (i.e. 1, 2, 3 or 4) */
229
{
230
  unsigned char                brg;
231
  volatile m821SCCparms_t     *sccparms;
232
  volatile m821SCCRegisters_t *sccregs;
233
 
234
  /*
235
   * Allocate buffer descriptors
236
   */
237
  RxBd[port+1] = M821AllocateBufferDescriptors(1);
238
  TxBd[port+1] = M821AllocateBufferDescriptors(1);
239
 
240
  /*
241
   * Configure ports A and B to enable TXDx and RXDx pins
242
   */
243
  m821.papar |=  (0xC << ((port-2) * 2));
244
  m821.padir &= ~(0xC << ((port-2) * 2));
245
  m821.pbdir |=  (0x04 << (port-2));
246
  m821.paodr &= ~(0x8 << ((port-2) * 2));
247
  m821.pbdat &= ~(0x04 << (port-2));
248
 
249
  /* SCC2 is the only one with handshaking lines */
250
  /*
251
    if (port == 2) {
252
    m821.pcpar |= (0x02);
253
    m821.pcpar &= ~(0xc0);
254
    m821.pcdir &= ~(0xc2);
255
    m821.pcso  |= (0xc0);
256
    }
257
  */
258
 
259
  brg = m821_get_brg_clk(9600);     /* 4 BRGs, 5 serial ports - hopefully */
260
                                    /*  at least 2 ports will be the same */
261
 
262
  /*
263
   * Set up SDMA
264
   */
265
  m821.sdcr = 0x01; /* as recommended p 16-80, sec 16.10.2.1 MPC821UM/AD */
266
 
267
 
268
  m821.sicr &= ~(0xff << ((port-1) * 8));
269
  m821.sicr |= (brg << (3 + ((port-1) * 8))) | (brg << ((port-1) * 8));
270
 
271
  /*
272
   * Set up SCC1 parameter RAM common to all protocols
273
   */
274
  if (port == 1) {
275
    sccparms = (m821SCCparms_t*)&m821.scc1p;
276
    sccregs = &m821.scc1;
277
  }
278
  else if (port == 2) {
279
    sccparms = &m821.scc2p;
280
    sccregs = &m821.scc2;
281
  }
282
 
283
  sccparms->rbase = (char *)RxBd[port+1] - (char *)&m821;
284
  sccparms->tbase = (char *)TxBd[port+1] - (char *)&m821;
285
 
286
  if (port == 1)
287
    M821ExecuteRISC (M821_CR_OP_INIT_RX_TX | M821_CR_CHAN_SCC1);
288
  else if (port == 2)
289
    M821ExecuteRISC (M821_CR_OP_INIT_RX_TX | M821_CR_CHAN_SCC2);
290
 
291
  sccparms->rfcr = M821_RFCR_MOT | M821_RFCR_DMA_SPACE(0);
292
  sccparms->tfcr = M821_TFCR_MOT | M821_TFCR_DMA_SPACE(0);
293
  sccparms->mrblr = RXBUFSIZE;
294
 
295
  sccparms->un.uart.max_idl = 10;
296
  sccparms->un.uart.brklen = 0;
297
  sccparms->un.uart.brkec = 0;
298
  sccparms->un.uart.brkcr = 1;
299
 
300
  sccparms->un.uart.parec = 0;
301
  sccparms->un.uart.frmec = 0;
302
  sccparms->un.uart.nosec = 0;
303
 
304
  sccparms->un.uart.uaddr[0] = 0;
305
  sccparms->un.uart.uaddr[1] = 0;
306
  sccparms->un.uart.toseq  = 0;
307
 
308
  sccparms->un.uart.character[0] = 0x8000;
309
  sccparms->un.uart.character[1] = 0x8000;
310
  sccparms->un.uart.character[2] = 0x8000;
311
  sccparms->un.uart.character[3] = 0x8000;
312
  sccparms->un.uart.character[4] = 0x8000;
313
  sccparms->un.uart.character[5] = 0x8000;
314
  sccparms->un.uart.character[6] = 0x8000;
315
  sccparms->un.uart.character[7] = 0x8000;
316
 
317
  sccparms->un.uart.rccm = 0xc0ff;
318
 
319
  /*
320
   * Set up the Receive Buffer Descriptor
321
   */
322
  RxBd[port+1]->status = M821_BD_EMPTY | M821_BD_WRAP |
323
    M821_BD_INTERRUPT;
324
  RxBd[port+1]->length = 0;
325
  RxBd[port+1]->buffer = malloc(RXBUFSIZE);
326
 
327
  /*
328
   * Setup the Transmit Buffer Descriptor
329
   */
330
  TxBd[port+1]->status = M821_BD_WRAP;
331
 
332
  /*
333
   * Set up SCCx general and protocol-specific mode registers
334
   */
335
  sccregs->scce = 0xffff;
336
  sccregs->sccm = 0x0000;
337
  sccregs->gsmr_h = 0x00000020;
338
  sccregs->gsmr_l = 0x00028004;
339
  sccregs->psmr   = 0x3000;
340
  sccregs->gsmr_l = 0x00028034;
341
}
342
 
343
void
344
m821_smc_initialize (int port)  /* port is the SMC number (i.e. 1 or 2) */
345
{
346
  unsigned char brg;
347
 
348
  /*
349
   * Allocate buffer descriptors
350
   */
351
  RxBd[port-1] = M821AllocateBufferDescriptors (1);
352
  TxBd[port-1] = M821AllocateBufferDescriptors (1);
353
 
354
  /*
355
   * Configure port B pins to enable SMTXDx and SMRXDx pins
356
   */
357
  m821.pbpar |=  (0xC0 << ((port-1) * 4));
358
  m821.pbdir &= ~(0xC0 << ((port-1) * 4));
359
  m821.pbdir |=  (0x01 << (port-1));
360
  m821.pbodr &= ~(0xC0 << ((port-1) * 4));
361
  m821.pbdat &= ~(0x01 << (port-1));
362
 
363
  /*
364
   * Set up BRG1 (9,600 baud)
365
   */
366
  brg = m821_get_brg_clk(9600);     /* 4 BRGs, 5 serial ports - hopefully */
367
                                    /*  at least 2 ports will be the same */
368
 
369
  /*
370
   * Put SMC in NMSI mode, connect SMC to BRG
371
   */
372
  m860.simode &= ~(0x7000 << ((port-1) * 16));
373
  m860.simode |= brg << (12 + ((port-1) * 16));
374
 
375
  /*
376
   * Set up SMC1 parameter RAM common to all protocols
377
   */
378
  if (port == 1) {
379
    m821.smc1p.rbase = (char *)RxBd[port-1] - (char *)&m821;
380
    m821.smc1p.tbase = (char *)TxBd[port-1] - (char *)&m821;
381
    m821.smc1p.rfcr = M821_RFCR_MOT | M821_RFCR_DMA_SPACE(0);
382
    m821.smc1p.tfcr = M821_TFCR_MOT | M821_TFCR_DMA_SPACE(0);
383
    m821.smc1p.mrblr = RXBUFSIZE;
384
 
385
    /*
386
     * Set up SMC1 parameter RAM UART-specific parameters
387
     */
388
    m821.smc1p.un.uart.max_idl = 10;
389
    m821.smc1p.un.uart.brklen = 0;
390
    m821.smc1p.un.uart.brkec = 0;
391
    m821.smc1p.un.uart.brkcr = 0;
392
 
393
  }
394
  else {
395
    m821.smc2p.rbase = (char *)RxBd[port-1] - (char *)&m821;
396
    m821.smc2p.tbase = (char *)TxBd[port-1] - (char *)&m821;
397
    m821.smc2p.rfcr = M821_RFCR_MOT | M821_RFCR_DMA_SPACE(0);
398
    m821.smc2p.tfcr = M821_TFCR_MOT | M821_TFCR_DMA_SPACE(0);
399
    m821.smc2p.mrblr = RXBUFSIZE;
400
 
401
    /*
402
     * Set up SMC2 parameter RAM UART-specific parameters
403
     */
404
    m821.smc2p.un.uart.max_idl = 10;
405
    m821.smc2p.un.uart.brklen = 0;
406
    m821.smc2p.un.uart.brkec = 0;
407
    m821.smc2p.un.uart.brkcr = 0;
408
  }
409
 
410
  /*
411
   * Set up the Receive Buffer Descriptor
412
   */
413
  RxBd[port-1]->status = M821_BD_EMPTY | M821_BD_WRAP |
414
                                  M821_BD_INTERRUPT;
415
  RxBd[port-1]->length = 0;
416
  RxBd[port-1]->buffer = malloc(RXBUFSIZE);
417
 
418
  /*
419
   * Setup the Transmit Buffer Descriptor
420
   */
421
  TxBd[port-1]->status = M821_BD_WRAP;
422
 
423
  /*
424
   * Set up SMCx general and protocol-specific mode registers
425
   */
426
  if (port == 1) {
427
    m821.smc1.smce = ~0;        /* Clear any pending events */
428
    m821.smc1.smcm = 0; /* Mask all interrupt/event sources */
429
    m821.smc1.smcmr = M821_SMCMR_CLEN(9) | M821_SMCMR_SM_UART;
430
 
431
    /*
432
     * Send "Init parameters" command
433
     */
434
    M821ExecuteRISC (M821_CR_OP_INIT_RX_TX | M821_CR_CHAN_SMC1);
435
 
436
    /*
437
     * Enable receiver and transmitter
438
     */
439
    m821.smc1.smcmr |= M821_SMCMR_TEN | M821_SMCMR_REN;
440
  }
441
  else {
442
    m821.smc2.smce = ~0;        /* Clear any pending events */
443
    m821.smc2.smcm = 0; /* Mask all interrupt/event sources */
444
    m821.smc2.smcmr = M821_SMCMR_CLEN(9) | M821_SMCMR_SM_UART;
445
 
446
    /*
447
     * Send "Init parameters" command
448
     */
449
    M821ExecuteRISC (M821_CR_OP_INIT_RX_TX | M821_CR_CHAN_SMC2);
450
 
451
    /*
452
     * Enable receiver and transmitter
453
     */
454
    m821.smc2.smcmr |= M821_SMCMR_TEN | M821_SMCMR_REN;
455
  }
456
}
457
 
458
int
459
m821_char_poll_read (int minor)
460
{
461
  unsigned char c;
462
  rtems_unsigned32 level;
463
 
464
  _CPU_ISR_Disable(level);
465
  if (RxBd[minor]->status & M821_BD_EMPTY) {
466
    _CPU_ISR_Enable(level);
467
    return -1;
468
  }
469
  c = ((char *)RxBd[minor]->buffer)[0];
470
  RxBd[minor]->status = M821_BD_EMPTY | M821_BD_WRAP;
471
  _CPU_ISR_Enable(level);
472
  return c;
473
}
474
 
475
int
476
m821_char_poll_write (int minor, const char *buf, int len)
477
{
478
  while (len--) {
479
    while (TxBd[minor]->status & M821_BD_READY)
480
      continue;
481
    txBuf[minor] = *buf++;
482
    TxBd[minor]->buffer = &txBuf[minor];
483
    TxBd[minor]->length = 1;
484
    TxBd[minor]->status = M821_BD_READY | M821_BD_WRAP;
485
  }
486
  return 0;
487
}
488
 
489
/*
490
 * Interrupt handler
491
 */
492
rtems_isr
493
m821_scc1_console_interrupt_handler (rtems_vector_number v)
494
{
495
  /*
496
   * Buffer received?
497
   */
498
  if ((m821.scc1.sccm & 0x1) && (m821.scc1.scce & 0x1)) {
499
    m821.scc1.scce = 0x1;
500
    /*    m821.scc1.sccm &= ~0x1;*/
501
 
502
    while ((RxBd[SCC1_MINOR]->status & M821_BD_EMPTY) == 0) {
503
      rxBufListTail[SCC1_MINOR]->next = malloc(sizeof(Buf_t));
504
      if (rxBufListTail[SCC1_MINOR]->next) {
505
        rxBufListTail[SCC1_MINOR] = rxBufListTail[SCC1_MINOR]->next;
506
        rxBufListTail[SCC1_MINOR]->buf = RxBd[SCC1_MINOR]->buffer;
507
        rxBufListTail[SCC1_MINOR]->len = RxBd[SCC1_MINOR]->length;
508
        rxBufListTail[SCC1_MINOR]->pos = 0;
509
        rxBufListTail[SCC1_MINOR]->next = 0;
510
 
511
        RxBd[SCC1_MINOR]->buffer = malloc(RXBUFSIZE);
512
      }
513
      RxBd[SCC1_MINOR]->status = M821_BD_EMPTY | M821_BD_WRAP |
514
                                 M821_BD_INTERRUPT;
515
    }
516
  }
517
 
518
  /*
519
   * Buffer transmitted?
520
   */
521
#if 0
522
  if (m821.smc1.smce & 0x2) {
523
    m821.smc1.smce = 0x2;
524
    if ((smcTxBd->status & M360_BD_READY) == 0)
525
      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
526
  }
527
#endif
528
  m821.cisr = 1UL << 30;  /* Clear SCC1 interrupt-in-service bit */
529
}
530
 
531
rtems_isr
532
m821_scc2_console_interrupt_handler (rtems_vector_number v)
533
{
534
  /*
535
   * Buffer received?
536
   */
537
  if ((m821.scc2.sccm & 0x1) && (m821.scc2.scce & 0x1)) {
538
    m821.scc2.scce = 0x1;
539
    /*    m821.scc2.sccm &= ~0x1;*/
540
 
541
    while ((RxBd[SCC2_MINOR]->status & M821_BD_EMPTY) == 0) {
542
      rxBufListTail[SCC2_MINOR]->next = malloc(sizeof(Buf_t));
543
      if (rxBufListTail[SCC2_MINOR]->next) {
544
        rxBufListTail[SCC2_MINOR] = rxBufListTail[SCC2_MINOR]->next;
545
        rxBufListTail[SCC2_MINOR]->buf = RxBd[SCC2_MINOR]->buffer;
546
        rxBufListTail[SCC2_MINOR]->len = RxBd[SCC2_MINOR]->length;
547
        rxBufListTail[SCC2_MINOR]->pos = 0;
548
        rxBufListTail[SCC2_MINOR]->next = 0;
549
 
550
        RxBd[SCC2_MINOR]->buffer = malloc(RXBUFSIZE);
551
      }
552
      RxBd[SCC2_MINOR]->status = M821_BD_EMPTY | M821_BD_WRAP |
553
                                 M821_BD_INTERRUPT;
554
    }
555
  }
556
 
557
  /*
558
   * Buffer transmitted?
559
   */
560
#if 0
561
  if (m821.smc1.smce & 0x2) {
562
    m821.smc1.smce = 0x2;
563
    if ((smcTxBd->status & M360_BD_READY) == 0)
564
      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
565
  }
566
#endif
567
  m821.cisr = 1UL << 29;  /* Clear SCC2 interrupt-in-service bit */
568
}
569
 
570
rtems_isr
571
m821_smc1_console_interrupt_handler (rtems_vector_number v)
572
{
573
  /*
574
   * Buffer received?
575
   */
576
  if (m821.smc1.smce & 0x1) {
577
    m821.smc1.smce = 0x1;
578
    /*    m821.scc2.sccm &= ~0x1;*/
579
 
580
    while ((RxBd[SMC1_MINOR]->status & M821_BD_EMPTY) == 0) {
581
      rxBufListTail[SMC1_MINOR]->next = malloc(sizeof(Buf_t));
582
      if (rxBufListTail[SMC1_MINOR]->next) {
583
        rxBufListTail[SMC1_MINOR] = rxBufListTail[SMC1_MINOR]->next;
584
        rxBufListTail[SMC1_MINOR]->buf = RxBd[SMC1_MINOR]->buffer;
585
        rxBufListTail[SMC1_MINOR]->len = RxBd[SMC1_MINOR]->length;
586
        rxBufListTail[SMC1_MINOR]->pos = 0;
587
        rxBufListTail[SMC1_MINOR]->next = 0;
588
 
589
        RxBd[SMC1_MINOR]->buffer = malloc(RXBUFSIZE);
590
      }
591
      RxBd[SMC1_MINOR]->status = M821_BD_EMPTY | M821_BD_WRAP |
592
                                 M821_BD_INTERRUPT;
593
    }
594
  }
595
 
596
  /*
597
   * Buffer transmitted?
598
   */
599
#if 0
600
  if (m821.smc1.smce & 0x2) {
601
    m821.smc1.smce = 0x2;
602
    if ((smcTxBd->status & M360_BD_READY) == 0)
603
      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
604
  }
605
#endif
606
  m821.cisr = 1UL << 4;  /* Clear SMC1 interrupt-in-service bit */
607
}
608
 
609
rtems_isr
610
m821_smc2_console_interrupt_handler (rtems_vector_number v)
611
{
612
  /*
613
   * Buffer received?
614
   */
615
  if (m821.smc2.smce & 0x1) {
616
    m821.smc2.smce = 0x1;
617
 
618
    while ((RxBd[SMC2_MINOR]->status & M821_BD_EMPTY) == 0) {
619
      rxBufListTail[SMC2_MINOR]->next = malloc(sizeof(Buf_t));
620
      if (rxBufListTail[SMC2_MINOR]->next) {
621
        rxBufListTail[SMC2_MINOR] = rxBufListTail[SMC2_MINOR]->next;
622
        rxBufListTail[SMC2_MINOR]->buf = RxBd[SMC2_MINOR]->buffer;
623
        rxBufListTail[SMC2_MINOR]->len = RxBd[SMC2_MINOR]->length;
624
        rxBufListTail[SMC2_MINOR]->pos = 0;
625
        rxBufListTail[SMC2_MINOR]->next = 0;
626
 
627
        RxBd[SMC2_MINOR]->buffer = malloc(RXBUFSIZE);
628
      }
629
      RxBd[SMC2_MINOR]->status = M821_BD_EMPTY | M821_BD_WRAP |
630
                                 M821_BD_INTERRUPT;
631
    }
632
  }
633
 
634
  /*
635
   * Buffer transmitted?
636
   */
637
#if 0
638
  if (m821.smc1.smce & 0x2) {
639
    m821.smc1.smce = 0x2;
640
    if ((smcTxBd->status & M360_BD_READY) == 0)
641
      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
642
  }
643
#endif
644
  m821.cisr = 1UL << 3;  /* Clear SMC2 interrupt-in-service bit */
645
}
646
 
647
 
648
int
649
m821_buf_poll_read (int minor, char **buf)
650
{
651
  int len;
652
 
653
  if (RxBd[minor]->status & M821_BD_EMPTY)
654
    return -1;
655
 
656
  RxBd[minor]->buffer = malloc(RXBUFSIZE); /* I hope this succeeds ... */
657
  len = RxBd[minor]->length;
658
  RxBd[minor]->status = M821_BD_EMPTY | M821_BD_WRAP;
659
 
660
  return len;
661
}
662
 
663
int
664
m821_buf_poll_write (int minor, char *buf, int len)
665
{
666
  static char *last_buf[6];
667
 
668
  while (TxBd[minor]->status & M821_BD_READY)
669
    continue;
670
  if (last_buf[minor])
671
    free(last_buf[minor]);
672
  last_buf[minor] = buf;
673
  TxBd[minor]->buffer = buf;
674
  TxBd[minor]->length = len;
675
  TxBd[minor]->status = M821_BD_READY | M821_BD_WRAP;
676
  return 0;
677
}
678
 
679
void m821_console_initialize(void)
680
{
681
  int i;
682
 
683
  for (i=0; i < NIFACES; i++) {
684
    rxBufList[i] = malloc(sizeof(Buf_t));
685
    rxBufListTail[i] = rxBufList[i];
686
    rxBufList[i]->buf  = 0;
687
    rxBufList[i]->len  = 0;
688
    rxBufList[i]->pos  = 0;
689
    rxBufList[i]->next = 0;
690
  }
691
}
692
 
693
rtems_device_driver m821_console_read(rtems_device_major_number major,
694
                                      rtems_device_minor_number minor,
695
                                      void *arg)
696
{
697
  rtems_libio_rw_args_t *rw_args;
698
  char *buffer;
699
  int maximum;
700
  int count;
701
  Buf_t *tmp_buf;
702
  rtems_unsigned32 level;
703
 
704
  /*
705
   * Set up interrupts
706
   * FIXME: DANGER: WARNING:
707
   * CICR and SIMASK must be set in any module that uses
708
   *   the CPM. Currently those are console-generic.c and
709
   *   network.c. If the registers are not set the same
710
   *   in both places, strange things may happen.
711
   *   If they are only set in one place, then an application
712
   *   that used the other module won't work correctly.
713
   *   Put this comment in each module that sets these 2 registers
714
   */
715
  m821.cicr = 0x00e43e80;   /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
716
                               SCdP=SCC4, IRL=1, HP=SCC1, IEN=1 */
717
  m821.simask |= M821_SIMASK_LVM1;
718
 
719
  rw_args = (rtems_libio_rw_args_t *) arg;
720
  buffer = rw_args->buffer;
721
  maximum = rw_args->count;
722
  count = 0;
723
 
724
  while (count == 0) {
725
    if (rxBufList[minor]->len) {
726
      while ((count < maximum) &&
727
             (rxBufList[minor]->pos < rxBufList[minor]->len)) {
728
        buffer[count++] = rxBufList[minor]->buf[rxBufList[minor]->pos++];
729
      }
730
      _CPU_ISR_Disable(level);
731
      if (rxBufList[minor]->pos == rxBufList[minor]->len) {
732
        if (rxBufList[minor]->next) {
733
          tmp_buf=rxBufList[minor]->next;
734
          free (rxBufList[minor]->buf);
735
          free (rxBufList[minor]);
736
          rxBufList[minor]=tmp_buf;
737
        }
738
        else {
739
          free(rxBufList[minor]->buf);
740
          rxBufList[minor]->buf=0;
741
          rxBufList[minor]->len=0;
742
          rxBufList[minor]->pos=0;
743
        }
744
      }
745
      _CPU_ISR_Enable(level);
746
    }
747
    else
748
      if(rxBufList[minor]->next && !rxBufList[minor]->len) {
749
        tmp_buf = rxBufList[minor];
750
        rxBufList[minor] = rxBufList[minor]->next;
751
        free(tmp_buf);
752
      }
753
    /*      sleep(1);*/
754
  }
755
  rw_args->bytes_moved = count;
756
  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
757
}
758
 
759
rtems_device_driver m821_console_write(rtems_device_major_number major,
760
                                       rtems_device_minor_number minor,
761
                                       void *arg)
762
{
763
  int count;
764
  int maximum;
765
  rtems_libio_rw_args_t *rw_args;
766
  char *in_buffer;
767
  char *out_buffer;
768
  int n;
769
 
770
  /*
771
   * Set up interrupts
772
   * FIXME: DANGER: WARNING:
773
   * CICR and SIMASK must be set in any module that uses
774
   *   the CPM. Currently those are console-generic.c and
775
   *   network.c. If the registers are not set the same
776
   *   in both places, strange things may happen.
777
   *   If they are only set in one place, then an application
778
   *   that used the other module won't work correctly.
779
   *   Put this comment in each module that sets these 2 registers
780
   */
781
/*  m821.cicr = 0x00e43e80;   /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
782
                               SCdP=SCC4, IRL=1, HP=SCC1, IEN=1 */
783
/*  m821.simask |= M821_SIMASK_LVM1;  */
784
 
785
  rw_args = (rtems_libio_rw_args_t *) arg;
786
 
787
  in_buffer = rw_args->buffer;
788
  maximum = rw_args->count;
789
 
790
  out_buffer = malloc(maximum*2);  /* This is wasteful, but it won't */
791
                                   /*  be too small */
792
 
793
  if (!out_buffer) {
794
    rw_args->bytes_moved = 0;
795
    return RTEMS_NO_MEMORY;
796
  }
797
  n=0;
798
  for (count = 0; count < maximum; count++) {
799
    if ( in_buffer[ count ] == '\n') {
800
      out_buffer[count + n] = '\r';
801
      n++;
802
    }
803
    out_buffer[count + n] = in_buffer[count];
804
  }
805
  m821_buf_poll_write(minor, out_buffer, maximum+n);
806
  rw_args->bytes_moved = maximum;
807
  return RTEMS_SUCCESSFUL;
808
}
809
 
810
 
811
/*
812
 *  How to use the console.
813
 *   In your BSP, have the following functions:
814
 *
815
 *  rtems_device_driver console_initialize(rtems_device_major_number  major,
816
 *                                         rtems_device_minor_number  minor,
817
 *                                         void *arg)
818
 *  rtems_device_driver console_open(rtems_device_major_number major,
819
 *                                   rtems_device_minor_number minor,
820
 *                                   void *arg)
821
 *  rtems_device_driver console_close(rtems_device_major_number major,
822
 *                                    rtems_device_minor_number minor,
823
 *                                    void *arg)
824
 *  rtems_device_driver console_read(rtems_device_major_number major,
825
 *                                   rtems_device_minor_number minor,
826
 *                                   void *arg)
827
 *  rtems_device_driver console_write(rtems_device_major_number major,
828
 *                                    rtems_device_minor_number minor,
829
 *                                    void *arg)
830
 *  rtems_device_driver console_control(rtems_device_major_number major,
831
 *                                      rtems_device_minor_number minor,
832
 *                                      void *arg)
833
 *
834
 */

powered by: WebSVN 2.1.0

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