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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_1_0/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 1780

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

powered by: WebSVN 2.1.0

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