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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_1_0/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 411

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 31 lampret
/* 16450.c -- Simulation of 8250/16450 serial UART
2
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
/* This is functional simulation of 8250/16450 UARTs. Since we RX/TX data
21
   via file streams, we can't simulate modem control lines coming from the
22
   DCE and similar details of communication with the DCE.
23
 
24
   This simulated UART device is intended for basic UART device driver
25
   verification. From device driver perspective this device looks like a
26
   regular UART but never reports and modem control lines changes (the
27
   only DCE responses are incoming characters from the file stream).
28
*/
29
 
30
#include <stdlib.h>
31
#include <stdio.h>
32
#include <string.h>
33
 
34 235 erez
#include "abstract.h"
35 31 lampret
#include "16450.h"
36
#include "sim-config.h"
37 102 lampret
#include "pic.h"
38 336 markom
#include "vapi.h"
39 31 lampret
 
40 409 markom
#define MIN(a,b) ((a) < (b) ? (a) : (b))
41
 
42 31 lampret
static struct dev_16450 uarts[NR_UARTS];
43 221 markom
static int thre_int;
44 31 lampret
 
45
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
46
   before a single character is transmitted or received. */
47 355 markom
static unsigned long char_clks(int dll, int dlh, int lcr)
48 31 lampret
{
49 409 markom
  float bauds_per_char = 1.;
50
  unsigned long char_clks = ((dlh << 8) + dll) * UART_CLOCK_DIVIDER;
51 355 markom
 
52
  if (lcr & UART_LCR_PARITY)
53
    bauds_per_char = bauds_per_char + 1.;
54 31 lampret
 
55 355 markom
  /* stop bits 1 or two */
56
  if (lcr & UART_LCR_STOP)
57
    bauds_per_char = bauds_per_char + 2.;
58
  else
59
    if ((lcr & 0x3) != 0)
60
      bauds_per_char = bauds_per_char + 1.;
61
    else
62
      bauds_per_char = bauds_per_char + 1.5;
63
 
64
  bauds_per_char = bauds_per_char + (5. + (lcr & 0x3));
65
 
66
  return char_clks * bauds_per_char;
67 31 lampret
}
68
 
69
/* Set a specific UART register with value. */
70 238 erez
void uart_write_byte(unsigned long addr, unsigned long value)
71 31 lampret
{
72 355 markom
  int chipsel;
73
 
74
  debug(4, "uart_write_byte(%x,%02x)\n", addr, (unsigned)value);
75 341 markom
 
76 355 markom
  for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
77
    if ((addr & ~(UART_ADDR_SPACE-1)) == config.uarts[chipsel].baseaddr)
78
      break;
79
  if (chipsel >= NR_UARTS) return;
80 31 lampret
 
81 355 markom
  if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
82
    switch (addr % UART_ADDR_SPACE) {
83
      case UART_DLL:
84
        uarts[chipsel].regs.dll = value;
85
        uarts[chipsel].char_clks = char_clks(uarts[chipsel].regs.dll, uarts[chipsel].regs.dlh, uarts[chipsel].regs.lcr);
86
        return;
87
      case UART_DLH:
88
        uarts[chipsel].regs.dlh = value;
89
        return;
90
    }
91
  }
92
 
93
  switch (addr % UART_ADDR_SPACE) {
94
    case UART_TXBUF:
95
      if (uarts[chipsel].istat.txbuf_full < uarts[chipsel].fifo_len) {
96
        uarts[chipsel].istat.txbuf_full++;
97
        uarts[chipsel].regs.txbuf[uarts[chipsel].istat.txbuf_head] = value;
98
        uarts[chipsel].istat.txbuf_head = (uarts[chipsel].istat.txbuf_head + 1) % uarts[chipsel].fifo_len;
99
      } else
100
        uarts[chipsel].regs.txbuf[uarts[chipsel].istat.txbuf_head] = value;
101 341 markom
 
102 411 markom
      uarts[chipsel].regs.lsr &= ~(UART_LSR_TXSERE | UART_LSR_TXBUFE);
103 341 markom
 
104 355 markom
      uarts[chipsel].istat.thre_int = 0;
105
      break;
106 409 markom
    case UART_FCR:
107
      uarts[chipsel].regs.fcr = value & UART_VALID_FCR;
108
      if (uarts[chipsel].fifo_len == 1 && (value & UART_FCR_FIE)
109
       || uarts[chipsel].fifo_len != 1 && !(value & UART_FCR_FIE))
110
        value |= UART_FCR_RRXFI | UART_FCR_RTXFI;
111
      uarts[chipsel].fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
112
      if (value & UART_FCR_RTXFI) {
113
        uarts[chipsel].istat.txbuf_head = uarts[chipsel].istat.txbuf_tail = 0;
114
        uarts[chipsel].istat.txbuf_full = 0;
115 411 markom
        uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE;
116 409 markom
      }
117
      if (value & UART_FCR_RRXFI) {
118
        uarts[chipsel].istat.rxbuf_head = uarts[chipsel].istat.rxbuf_tail = 0;
119
        uarts[chipsel].istat.rxbuf_full = 0;
120 411 markom
        uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY;
121 409 markom
      }
122
      break;
123 355 markom
    case UART_IER:
124
      uarts[chipsel].regs.ier = value & UART_VALID_IER;
125 409 markom
      uarts[chipsel].istat.thre_int = 0;
126 355 markom
      break;
127
    case UART_LCR:
128
      uarts[chipsel].regs.lcr = value & UART_VALID_LCR;
129 409 markom
      uarts[chipsel].char_clks = char_clks(uarts[chipsel].regs.dll, uarts[chipsel].regs.dlh, uarts[chipsel].regs.lcr);
130 355 markom
      break;
131
    case UART_MCR:
132
      uarts[chipsel].regs.mcr = value & UART_VALID_MCR;
133
      break;
134
    case UART_SCR:
135
      uarts[chipsel].regs.scr = value;
136
      break;
137
    default:
138
      debug(1, "write out of range (addr %x)\n", addr);
139
  }
140 31 lampret
}
141
 
142
/* Read a specific UART register. */
143 238 erez
unsigned long uart_read_byte(unsigned long addr)
144 31 lampret
{
145 355 markom
  unsigned char value = 0;
146
  int chipsel;
147
 
148
  debug(4, "uart_read_byte(%x)", addr);
149
 
150
  for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
151
    if ((addr & ~(UART_ADDR_SPACE-1)) == config.uarts[chipsel].baseaddr)
152
      break;
153 31 lampret
 
154 355 markom
  if (chipsel >= NR_UARTS)
155
    return 0;
156 344 markom
 
157 355 markom
  if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
158
    switch (addr % UART_ADDR_SPACE) {
159
      case UART_DLL:
160
        value = uarts[chipsel].regs.dll;
161
        debug(4, "= %x\n", value);
162
        return value;
163
      case UART_DLH:
164
        value = uarts[chipsel].regs.dlh;
165
        debug(4, "= %x\n", value);
166
        return value;
167
    }
168
  }
169
 
170
  switch (addr % UART_ADDR_SPACE) {
171
    case UART_RXBUF:
172 409 markom
      { /* Print out FIFO for debugging */
173
        int i;
174
        debug(4, "(%i/%i,%i,%i:", uarts[chipsel].istat.rxbuf_full, uarts[chipsel].fifo_len,
175
                  uarts[chipsel].istat.rxbuf_head, uarts[chipsel].istat.rxbuf_tail);
176
        for (i = 0; i < uarts[chipsel].istat.rxbuf_full; i++)
177
          debug(4, "%02x ", uarts[chipsel].regs.rxbuf[(uarts[chipsel].istat.rxbuf_tail + i) % uarts[chipsel].fifo_len]);
178
        debug(4, ")");
179
      }
180 355 markom
      if (uarts[chipsel].istat.rxbuf_full) {
181
        value = uarts[chipsel].regs.rxbuf[uarts[chipsel].istat.rxbuf_tail];
182
        uarts[chipsel].istat.rxbuf_tail = (uarts[chipsel].istat.rxbuf_tail + 1) % uarts[chipsel].fifo_len;
183
        uarts[chipsel].istat.rxbuf_full--;
184
      }
185
 
186
      if (uarts[chipsel].istat.rxbuf_full)
187
        uarts[chipsel].regs.lsr |= UART_LSR_RDRDY;
188
      else
189
        uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY;
190 409 markom
 
191
      uarts[chipsel].istat.timeout_count = 0;
192 355 markom
      break;
193
    case UART_IER:
194
      value = uarts[chipsel].regs.ier & UART_VALID_IER;
195
      break;
196
    case UART_IIR:
197
      value = (uarts[chipsel].regs.iir & UART_VALID_IIR) | 0xc0;
198
      uarts[chipsel].istat.thre_int = 0;
199
      break;
200
    case UART_LCR:
201
      value = uarts[chipsel].regs.lcr & UART_VALID_LCR;
202
      break;
203
    case UART_MCR:
204
      value = 0;
205
      break;
206
    case UART_LSR:
207
      value = uarts[chipsel].regs.lsr & UART_VALID_LSR;
208
      uarts[chipsel].regs.lsr &=
209 409 markom
        ~(UART_LSR_OVRRUN | UART_LSR_BREAK | UART_LSR_PARITY
210
         | UART_LSR_FRAME | UART_LSR_RXERR);
211 355 markom
      break;
212
    case UART_MSR:
213
      value = uarts[chipsel].regs.msr & UART_VALID_MSR;
214
      uarts[chipsel].regs.msr = 0;
215
      break;
216
    case UART_SCR:
217
      value = uarts[chipsel].regs.scr;
218
      break;
219
    default:
220
      debug(1, "read out of range (addr %x)\n", addr);
221
  }
222
  debug(4, " = %x\n", value);
223
  return value;
224 31 lampret
}
225
 
226 336 markom
/* Function that handles incoming VAPI data.  */
227
void uart_vapi_read (unsigned long id, unsigned long data)
228
{
229 341 markom
  int uart;
230 344 markom
  debug(4, "UART: id %08x, data %08x\n", id, data);
231 341 markom
  uart = id & VAPI_DEVICE_ID;
232
  uarts[uart].vapi_buf[uarts[uart].vapi_buf_head_ptr] = data;
233 409 markom
  uarts[uart].vapi_buf_head_ptr = (uarts[uart].vapi_buf_head_ptr + 1) % UART_VAPI_BUF_LEN;
234 341 markom
  if (uarts[uart].vapi_buf_tail_ptr == uarts[uart].vapi_buf_head_ptr) {
235
    fprintf (stderr, "FATAL: uart VAPI buffer to small.\n");
236
    exit (1);
237
  }
238
}
239 336 markom
 
240 409 markom
static void send_char (int uart, int bits_send)
241
{
242
  printf ("'%c'\n", uarts[uart].iregs.txser);
243
  debug(4, "TX \'%c\' via UART%d...\n", uarts[uart].iregs.txser, uart);
244
  if (uarts[uart].regs.mcr & UART_MCR_LOOP)
245
    uarts[uart].iregs.loopback = uarts[uart].iregs.txser;
246
  else {
247
    /* Send to either VAPI or to file */
248
    if (config.uarts[uart].vapi_id) {
249
      int par, pe, fe, nbits;
250
      int j, data;
251
      unsigned long packet = 0;
252
 
253
      nbits = MIN (bits_send, (uarts[uart].regs.lcr & UART_LCR_WLEN8) + 5);
254
      /* Encode a packet */
255
      packet = uarts[uart].iregs.txser & ((1 << nbits) - 1);
256
 
257
      /* Calculate parity */
258
      for (j = 0, par = 0; j < nbits; j++)
259
        par ^= (packet >> j) & 1;
260
 
261
      if (uarts[uart].regs.lcr & UART_LCR_PARITY) {
262
        if (uarts[uart].regs.lcr & UART_LCR_SPAR) {
263
          packet |= 1 << nbits;
264
        } else {
265
          if (uarts[uart].regs.lcr & UART_LCR_EPAR)
266
            packet |= par << nbits;
267
          else
268
            packet |= (par ^ 1) << nbits;
269
        }
270
        nbits++;
271
      }
272
      packet |= 1 << (nbits++);
273
      if (uarts[uart].regs.lcr & UART_LCR_STOP)
274
        packet |= 1 << (nbits++);
275
 
276
      /* Decode a packet */
277
      nbits = (uarts[uart].vapi.lcr & UART_LCR_WLEN8) + 5;
278
      data = packet & ((1 << nbits) - 1);
279
 
280
      /* Calculate parity, including parity bit */
281
      for (j = 0, par = 0; j < nbits + 1; j++)
282
        par ^= (packet >> j) & 1;
283
 
284
      if (uarts[uart].vapi.lcr & UART_LCR_PARITY) {
285
        if (uarts[uart].vapi.lcr & UART_LCR_SPAR) {
286
          pe = !((packet >> nbits) & 1);
287
        } else {
288
          if (uarts[uart].vapi.lcr & UART_LCR_EPAR)
289
            pe = par != 0;
290
          else
291
            pe = par != 1;
292
        }
293
        nbits++;
294
      } else
295
        pe = 0;
296
 
297
      fe = ((packet >> (nbits++)) & 1) ^ 1;
298
      if (uarts[uart].vapi.lcr & UART_LCR_STOP)
299
        fe |= ((packet >> (nbits++)) & 1) ^ 1;
300
 
301
      debug (4, "lcr vapi %02x, uart %02x\n", uarts[uart].vapi.lcr, uarts[uart].regs.lcr);
302
      data |= (uarts[uart].vapi.lcr << 8) | (pe << 16) | (fe << 17) | (uarts[uart].vapi.lcr << 8);
303
      printf ("vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
304
      debug (4, "vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
305
      vapi_send (config.uarts[uart].vapi_id, data);
306
    } else {
307
      fputc((int)(uarts[uart].iregs.txser & 0xFF), uarts[uart].txfs);
308
      fflush(uarts[uart].txfs);
309
    }
310
  }
311
  uarts[uart].istat.txser_full = 0;
312
  uarts[uart].istat.txser_clks = 0;
313
}
314
 
315 411 markom
/* Adds a character to the FIFO */
316
 
317
void uart_add_char (int uart, int ch)
318
{
319
  if (uarts[uart].istat.rxbuf_full + 1 > uarts[uart].fifo_len)
320
    uarts[uart].regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR;
321
  else {
322
    debug(4, "add %02x\n", ch);
323
    uarts[uart].regs.rxbuf[uarts[uart].istat.rxbuf_head] = ch;
324
    uarts[uart].istat.rxbuf_head = (uarts[uart].istat.rxbuf_head + 1) % uarts[uart].fifo_len;
325
    uarts[uart].istat.rxbuf_full++;
326
  }
327
  uarts[uart].regs.lsr |= UART_LSR_RDRDY;
328
  uarts[uart].istat.timeout_count = 0;
329
}
330
 
331 341 markom
/* Reset.  It initializes all registers of all UART devices to zero values,
332 31 lampret
   (re)opens all RX/TX file streams and places devices in memory address
333 341 markom
   space.  */
334 31 lampret
void uart_reset()
335
{
336 355 markom
  int i;
337
 
338 261 markom
  if (!config.uarts_enabled)
339
    config.nuarts = 0;
340 341 markom
 
341
  if (config.sim.verbose && config.nuarts)
342
    printf("Resetting %u UART(s).\n", config.nuarts);
343
 
344 355 markom
  memset(uarts, 0, sizeof(uarts));
345 261 markom
 
346 355 markom
  for(i = 0; i < config.nuarts; i++) {
347 341 markom
    if (config.uarts[i].vapi_id) {
348
      if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
349
        fprintf (stderr, "ERROR: Wrong vapi_id (0x%x) for uart %i, last byte is required to be %02x; ignoring.\n", config.uarts[i].vapi_id, i, i);
350
        config.uarts[i].vapi_id = 0;
351
        uarts[i].txfs = 0;
352
      } else {
353 355 markom
        vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
354
        register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, uart_read_byte, uart_write_byte);
355
      }
356
    } else if (config.uarts[i].txfile) { /* MM: Try to create stream.  */
357
      if (!(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r"))
358
        && !(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r+"))) {
359 361 markom
        debug (0, "WARNING: UART%d has problems with RX file stream.\n", i);
360 355 markom
        continue;
361
      }
362
      uarts[i].txfs = fopen(config.uarts[i].txfile, "a");
363
      if (uarts[i].rxfs && uarts[i].txfs && config.sim.verbose) {
364
        printf("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
365
        printf("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
366
      } else
367 361 markom
        debug (1, "WARNING: UART%d has problems with TX file stream.\n", i);
368 355 markom
      register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, uart_read_byte, uart_write_byte);
369 341 markom
    }
370
 
371
    if (config.uarts[i].uart16550)
372
      uarts[i].fifo_len = 16;
373
    else
374
      uarts[i].fifo_len = 1;
375 344 markom
 
376 341 markom
    uarts[i].istat.rxbuf_head = uarts[i].istat.rxbuf_tail = 0;
377
    uarts[i].istat.txbuf_head = uarts[i].istat.txbuf_tail = 0;
378 344 markom
 
379 409 markom
    uarts[i].istat.break_set = 0;
380
    uarts[i].istat.timeout_count = 0;
381
 
382 344 markom
    uarts[i].regs.lcr = UART_LCR_RESET;
383 385 markom
    uarts[i].vapi.cur_break = uarts[i].vapi.cur_break_cnt = uarts[i].vapi.next_break = 0;
384
    uarts[i].vapi.next_break_cnt = -1;
385 336 markom
  }
386 31 lampret
}
387 261 markom
 
388 31 lampret
/* Simulation hook. Must be called every clock cycle to simulate all UART
389
   devices. It does internal functional UART simulation. */
390
void uart_clock()
391
{
392 355 markom
  int i, retval;
393 341 markom
 
394 355 markom
  for(i = 0; i < config.nuarts; i++) {
395 341 markom
    /* If VAPI is not selected, UART communicates with two file streams;
396
       if VAPI is selected, we use VAPI streams.  */
397
 
398
    /* if txfs is corrupted, skip this uart. */
399 355 markom
    if (!config.uarts[i].vapi_id && !uarts[i].txfs) continue;
400 385 markom
 
401
    if (uarts[i].vapi.next_break_cnt >= 0)
402 409 markom
      if (--uarts[i].vapi.next_break_cnt < 0) {
403
        if (!(uarts[i].vapi.cur_break = uarts[i].vapi.next_break))
404
          uarts[i].istat.break_set = 0;
405
      }
406 385 markom
 
407
    /***************** Transmit *****************/
408 355 markom
    if (!uarts[i].istat.txser_full) {
409
      uarts[i].regs.lsr |= UART_LSR_TXBUFE;
410
      if (uarts[i].istat.txbuf_full) {
411
        uarts[i].iregs.txser = uarts[i].regs.txbuf[uarts[i].istat.txbuf_tail];
412
        uarts[i].istat.txbuf_tail = (uarts[i].istat.txbuf_tail + 1) % uarts[i].fifo_len;
413
        uarts[i].istat.txser_full = 1;
414
        uarts[i].istat.txbuf_full--;
415
        uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
416
        uarts[i].istat.thre_int = 1;
417
      } else
418
        uarts[i].regs.lsr |= UART_LSR_TXSERE;
419 409 markom
    } else if (uarts[i].char_clks <= uarts[i].istat.txser_clks++) {
420
      send_char(i, (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
421
    } else {
422
      /* We are still sending char here*/
423
 
424
      /* Check if we set the break bit */
425
      if (uarts[i].regs.lcr & UART_LCR_SBC) {
426
        if (!uarts[i].vapi.break_sent) {
427
#if 0
428
          /* Send broken frame */
429
          int nbits_sent = ((uarts[i].regs.lcr & UART_LCR_WLEN8) + 5) * (uarts[i].istat.txser_clks - 1) / uarts[i].char_clks;
430
          send_char(i, nbits_sent);
431
#endif
432
          /* Send one break signal */
433
          vapi_send (config.uarts[i].vapi_id, UART_LCR_SBC << 8);
434
          uarts[i].vapi.break_sent = 1;
435 355 markom
        }
436 409 markom
        /* mark as character was sent */
437
        uarts[i].istat.txser_full = 0;
438
        uarts[i].istat.txser_clks = 0;
439
      } else
440
        uarts[i].vapi.break_sent = 0;
441 355 markom
    }
442 341 markom
 
443 385 markom
    /***************** Receive *****************/
444
 
445
    /* Is there a break? */
446 409 markom
    if (uarts[i].vapi.cur_break) {
447 385 markom
      uarts[i].vapi.cur_break_cnt++;
448 409 markom
      if (uarts[i].vapi.cur_break_cnt > UART_BREAK_COUNT * uarts[i].vapi.char_clks) {
449
        if (!uarts[i].istat.break_set) {
450 411 markom
          unsigned lsr;
451 409 markom
          uarts[i].istat.break_set = 1;
452 411 markom
          lsr = UART_LSR_BREAK | UART_LSR_FRAME | UART_LSR_RXERR | UART_LSR_RDRDY;
453
          if (uarts[i].regs.lcr & UART_LCR_PARITY) lsr |= UART_LSR_PARITY;
454 409 markom
          printf ("[%x]\n", uarts[i].regs.lsr);
455
          uarts[i].istat.rxser_full = 0;
456
          uarts[i].istat.rxser_clks = 0;
457 411 markom
          uart_add_char (i, lsr << 8);
458 409 markom
        } else
459
          uarts[i].vapi.cur_break_cnt = 0;
460
      }
461
      if (uarts[i].istat.rxser_full) {
462
        uarts[i].istat.rxser_full = 0;
463
        uarts[i].istat.rxser_clks = 0;
464
      }
465 385 markom
    } else {
466
      if (uarts[i].istat.rxser_full) {
467 409 markom
        if (uarts[i].char_clks <= uarts[i].istat.rxser_clks++) {
468 411 markom
          /* Set unused character bits to zero and allow lsr register in fifo */
469
          uarts[i].iregs.rxser &= ((1 << ((uarts[i].regs.lcr & 3) + 5)) - 1) | 0xff00;
470 409 markom
          debug(4, "Receiving 0x%02x'%c' via UART%d...\n", uarts[i].iregs.rxser, uarts[i].iregs.rxser, i);
471 385 markom
          uarts[i].istat.rxser_full = 0;
472
          uarts[i].istat.rxser_clks = 0;
473 411 markom
          uart_add_char (i, uarts[i].iregs.rxser);
474 355 markom
        }
475
      }
476
    }
477
 
478
    /* Check if there is something waiting, and put it into rxser */
479
    if (uarts[i].regs.mcr & UART_MCR_LOOP) {
480
      uarts[i].iregs.rxser = uarts[i].iregs.loopback;
481
      uarts[i].istat.rxser_full = 1;
482
    } else {
483
      if (!config.uarts[i].vapi_id) {
484
        if((retval = fgetc(uarts[i].rxfs)) != EOF)
485
          uarts[i].iregs.rxser = (char)retval;
486 385 markom
        uarts[i].istat.rxser_full = 1;
487 355 markom
      } else { /* VAPI */
488
        int received = 0;
489 361 markom
        /* do not handle commands while receiving */
490
        if (uarts[i].istat.rxser_full)
491
          break;
492 355 markom
        while (!received) {
493
          if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
494
            unsigned long data = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
495 409 markom
            debug(4, "Handling: %08x (%i,%i)\n", data, uarts[i].vapi_buf_head_ptr, uarts[i].vapi_buf_tail_ptr);
496
            uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
497 355 markom
            switch (data >> 24) {
498
              case 0x00:
499
                uarts[i].vapi.lcr = (data >> 8) & 0xff;
500
                /* Put data into rx fifo */
501 411 markom
                uarts[i].iregs.rxser = data & 0xff;
502 355 markom
                uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr);
503 409 markom
                if ((uarts[i].vapi.lcr & ~UART_LCR_SBC) != (uarts[i].regs.lcr & ~UART_LCR_SBC)
504
                 || uarts[i].vapi.char_clks != uarts[i].char_clks
505 355 markom
                 || uarts[i].vapi.skew < -MAX_SKEW || uarts[i].vapi.skew > MAX_SKEW) {
506 409 markom
                  debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
507
                        uarts[i].vapi.lcr & ~UART_LCR_SBC, uarts[i].regs.lcr & ~UART_LCR_SBC);
508 355 markom
                  /* Set error bits */
509 411 markom
                  uarts[i].iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
510
                  if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].iregs.rxser |= UART_LSR_PARITY << 8;
511 355 markom
                }
512 409 markom
                uarts[i].istat.rxser_full = 1;
513 355 markom
                received = 1;
514
                break;
515
              case 0x01:
516
                uarts[i].vapi.dll = (data >> 0) & 0xff;
517
                uarts[i].vapi.dlh = (data >> 8) & 0xff;
518
                break;
519
              case 0x02:
520 361 markom
                uarts[i].vapi.lcr = (data >> 8) & 0xff;
521 355 markom
                break;
522
              case 0x03:
523
                uarts[i].vapi.skew = (signed short)(data & 0xffff);
524
                break;
525 385 markom
              case 0x04:
526
                uarts[i].vapi.next_break_cnt = data & 0xffff;
527
                uarts[i].vapi.next_break = (data >> 16) & 1;
528
                break;
529 355 markom
              default:
530 361 markom
                debug (0, "WARNING: Invalid vapi command %02x\n", data >> 24);
531 355 markom
                break;
532
            }
533
          } else break;
534
        }
535
      }
536
    }
537 341 markom
 
538 385 markom
    /***************** Loopback *****************/
539 355 markom
    if (uarts[i].regs.mcr & UART_MCR_LOOP) {
540
      debug(5, "uart_clock: Loopback\n");
541
      if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
542
          ((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
543
        uarts[i].regs.msr |= UART_MSR_DDCD;
544
      if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
545
          ((uarts[i].regs.msr & UART_MSR_RI) >> 4))
546
        uarts[i].regs.msr |= UART_MSR_TERI;
547
      if ((uarts[i].regs.mcr & UART_MCR_RTS) !=
548
          ((uarts[i].regs.msr & UART_MSR_CTS) >> 3))
549
        uarts[i].regs.msr |= UART_MSR_DCTS;
550
      if ((uarts[i].regs.mcr & UART_MCR_DTR) !=
551
          ((uarts[i].regs.msr & UART_MSR_DSR) >> 5))
552
        uarts[i].regs.msr |= UART_MSR_DDSR;
553
      uarts[i].regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
554
                | UART_MSR_DSR | UART_MSR_CTS);
555
      uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX2) << 4);
556
      uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX1) << 4);
557
      uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_RTS) << 3);
558
      uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_DTR) << 5);
559
    }
560
 
561 409 markom
    if (uarts[i].regs.lsr & UART_LSR_RDRDY)
562
      uarts[i].istat.timeout_count++;
563 411 markom
 
564
    /* Update LSR error bits from the ones from rx FIFO */
565
    if (uarts[i].istat.rxbuf_full) {
566
      uarts[i].regs.lsr |= uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] >> 8;
567
      /* we must delete the lsr status, so that we can clear it from lsr */
568
      uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] &= 0xff;
569
    }
570 409 markom
 
571 355 markom
    /* Interrupt detection in proper priority order. */
572
    uarts[i].regs.iir = UART_IIR_NO_INT;
573 409 markom
    if (uarts[i].regs.ier & UART_IER_RLSI &&                    /* Receiver LS */
574 355 markom
        uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
575
          | UART_LSR_FRAME | UART_LSR_BREAK)) {
576
      uarts[i].regs.iir = UART_IIR_RLSI;
577 409 markom
    } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* RD available */
578
        && (uarts[i].istat.rxbuf_full >= UART_FIFO_TRIGGER(uarts[i].regs.fcr >> 6))
579
        && (uarts[i].regs.lsr & UART_LSR_RDRDY)) {
580 355 markom
      uarts[i].regs.iir = UART_IIR_RDI;
581 409 markom
    } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* timeout */
582
        && (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)) {
583
      uarts[i].regs.iir = UART_IIR_CTI;
584
    } else if (uarts[i].regs.ier & UART_IER_THRI &&             /* Transm. empty */
585 355 markom
        uarts[i].regs.lsr & UART_LSR_TXBUFE &&
586
        uarts[i].istat.thre_int == 1) {
587
      uarts[i].regs.iir = UART_IIR_THRI;
588 409 markom
    } else if (uarts[i].regs.ier & UART_IER_MSI &&              /* Modem status */
589 355 markom
        uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
590
          | UART_MSR_TERI | UART_MSR_DDCD)) {
591
      uarts[i].regs.iir = UART_IIR_MSI;
592
    }
593 409 markom
    if (!(uarts[i].regs.iir & UART_IIR_NO_INT)) {
594
      debug (4, "uarts[i].regs.iir = %i\t", uarts[i].regs.iir);
595 355 markom
      report_interrupt(config.uarts[i].irq);
596 409 markom
    }
597 355 markom
  }
598 31 lampret
}
599
 
600
/* Print register values on stdout. */
601
void uart_status()
602
{
603 355 markom
  int i, j;
604
 
605
  for(i = 0; i < config.nuarts; i++) {
606
    if ( !config.uarts[i].baseaddr )
607
      continue;
608
    printf("\nUART%d visible registers at 0x%.8x:\n", i, config.uarts[i].baseaddr);
609
    printf("RXBUF:");
610
    for (j = uarts[i].istat.rxbuf_head; j != uarts[i].istat.rxbuf_tail; j = (j + 1) % uarts[i].fifo_len)
611
      printf (" %.2x", uarts[i].regs.rxbuf[j]);
612
    printf("  TXBUF: %.2x\n", uarts[i].regs.txbuf);
613
    printf("DLL  : %.2x  DLH  : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
614
    printf("IER  : %.2x  IIR  : %.2x\n", uarts[i].regs.ier, uarts[i].regs.iir);
615
    printf("LCR  : %.2x  MCR  : %.2x\n", uarts[i].regs.lcr, uarts[i].regs.mcr);
616
    printf("LSR  : %.2x  MSR  : %.2x\n", uarts[i].regs.lsr, uarts[i].regs.msr);
617
    printf("SCR  : %.2x\n", uarts[i].regs.scr);
618 31 lampret
 
619 355 markom
    printf("\nInternal registers (sim debug):\n");
620
    printf("RXSER: %.2x  TXSER: %.2x\n", uarts[i].iregs.rxser, uarts[i].iregs.txser);
621 31 lampret
 
622 355 markom
    printf("\nInternal status (sim debug):\n");
623
    printf("char_clks: %d\n", uarts[i].char_clks);
624
    printf("rxser_clks: %d  txser_clks: %d\n", uarts[i].istat.rxser_clks, uarts[i].istat.txser_clks);
625
    printf("rxser: %d  txser: %d\n", uarts[i].istat.rxser_full, uarts[i].istat.txser_full);
626
    printf("rxbuf: %d  txbuf: %d\n", uarts[i].istat.rxbuf_full, uarts[i].istat.txbuf_full);
627 344 markom
    printf("Using IRQ%i\n", config.uarts[i].irq);
628 336 markom
    if (config.uarts[i].vapi_id)
629
      printf ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
630
    else
631 355 markom
      printf("RX fs: %p  TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
632
  }
633 31 lampret
}

powered by: WebSVN 2.1.0

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