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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_67/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 409

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

powered by: WebSVN 2.1.0

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