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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_71/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 713

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

powered by: WebSVN 2.1.0

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