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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_66/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 423

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

powered by: WebSVN 2.1.0

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