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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_34/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 805

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

powered by: WebSVN 2.1.0

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