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 490

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

powered by: WebSVN 2.1.0

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