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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_47/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 1145

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 1073 rprescott
#include "channel.h"
41 31 lampret
 
42 409 markom
#define MIN(a,b) ((a) < (b) ? (a) : (b))
43
 
44 1073 rprescott
static struct dev_16450 uarts[MAX_UARTS];                       /* simulation info */
45
static struct channel * channels[MAX_UARTS] = { NULL, };        /* emulation info */
46 31 lampret
 
47
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
48
   before a single character is transmitted or received. */
49 355 markom
static unsigned long char_clks(int dll, int dlh, int lcr)
50 31 lampret
{
51 409 markom
  float bauds_per_char = 1.;
52 806 markom
  unsigned long char_clks = ((dlh << 8) + dll);
53 355 markom
 
54
  if (lcr & UART_LCR_PARITY)
55
    bauds_per_char = bauds_per_char + 1.;
56 31 lampret
 
57 355 markom
  /* stop bits 1 or two */
58
  if (lcr & UART_LCR_STOP)
59
    bauds_per_char = bauds_per_char + 2.;
60
  else
61
    if ((lcr & 0x3) != 0)
62
      bauds_per_char = bauds_per_char + 1.;
63
    else
64
      bauds_per_char = bauds_per_char + 1.5;
65
 
66
  bauds_per_char = bauds_per_char + (5. + (lcr & 0x3));
67
 
68
  return char_clks * bauds_per_char;
69 31 lampret
}
70
 
71
/* Set a specific UART register with value. */
72 238 erez
void uart_write_byte(unsigned long addr, unsigned long value)
73 31 lampret
{
74 355 markom
  int chipsel;
75
 
76
  debug(4, "uart_write_byte(%x,%02x)\n", addr, (unsigned)value);
77 341 markom
 
78 424 markom
  for(chipsel = 0; chipsel < MAX_UARTS; chipsel++)
79 355 markom
    if ((addr & ~(UART_ADDR_SPACE-1)) == config.uarts[chipsel].baseaddr)
80
      break;
81 424 markom
  if (chipsel >= MAX_UARTS) return;
82 31 lampret
 
83 355 markom
  if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
84
    switch (addr % UART_ADDR_SPACE) {
85
      case UART_DLL:
86
        uarts[chipsel].regs.dll = value;
87
        uarts[chipsel].char_clks = char_clks(uarts[chipsel].regs.dll, uarts[chipsel].regs.dlh, uarts[chipsel].regs.lcr);
88
        return;
89
      case UART_DLH:
90
        uarts[chipsel].regs.dlh = value;
91
        return;
92
    }
93
  }
94
 
95
  switch (addr % UART_ADDR_SPACE) {
96
    case UART_TXBUF:
97
      if (uarts[chipsel].istat.txbuf_full < uarts[chipsel].fifo_len) {
98
        uarts[chipsel].istat.txbuf_full++;
99
        uarts[chipsel].regs.txbuf[uarts[chipsel].istat.txbuf_head] = value;
100
        uarts[chipsel].istat.txbuf_head = (uarts[chipsel].istat.txbuf_head + 1) % uarts[chipsel].fifo_len;
101
      } else
102
        uarts[chipsel].regs.txbuf[uarts[chipsel].istat.txbuf_head] = value;
103 341 markom
 
104 411 markom
      uarts[chipsel].regs.lsr &= ~(UART_LSR_TXSERE | UART_LSR_TXBUFE);
105 355 markom
      uarts[chipsel].istat.thre_int = 0;
106
      break;
107 409 markom
    case UART_FCR:
108
      uarts[chipsel].regs.fcr = value & UART_VALID_FCR;
109
      if (uarts[chipsel].fifo_len == 1 && (value & UART_FCR_FIE)
110
       || uarts[chipsel].fifo_len != 1 && !(value & UART_FCR_FIE))
111
        value |= UART_FCR_RRXFI | UART_FCR_RTXFI;
112
      uarts[chipsel].fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
113
      if (value & UART_FCR_RTXFI) {
114
        uarts[chipsel].istat.txbuf_head = uarts[chipsel].istat.txbuf_tail = 0;
115
        uarts[chipsel].istat.txbuf_full = 0;
116 1145 sfurman
        uarts[chipsel].regs.lsr |= UART_LSR_TXBUFE;
117
 
118
        // For FIFO-mode only, THRE interrupt is set when THR and FIFO are empty
119
        uarts[chipsel].istat.thre_int = (uarts[chipsel].fifo_len == 16);
120 409 markom
      }
121
      if (value & UART_FCR_RRXFI) {
122
        uarts[chipsel].istat.rxbuf_head = uarts[chipsel].istat.rxbuf_tail = 0;
123
        uarts[chipsel].istat.rxbuf_full = 0;
124 411 markom
        uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY;
125 409 markom
      }
126
      break;
127 355 markom
    case UART_IER:
128
      uarts[chipsel].regs.ier = value & UART_VALID_IER;
129
      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 997 markom
  PRINTF ("'%c'\n", uarts[uart].iregs.txser);
247 409 markom
  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 997 markom
      PRINTF ("vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
308 409 markom
      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 1073 rprescott
      char buffer[1] = { uarts[uart].iregs.txser & 0xFF };
312
      channel_write(channels[uart], buffer, 1);
313 409 markom
    }
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 806 markom
/* Simulation hook. Must be called every clock cycle to simulate all UART
336
   devices. It does internal functional UART simulation. */
337 821 markom
void uart_clock16 (int i)
338 806 markom
{
339
  int retval;
340 1073 rprescott
 
341 821 markom
  /* Schedule for later */
342 884 markom
  SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
343 821 markom
 
344 806 markom
  /* If VAPI is not selected, UART communicates with two file streams;
345
     if VAPI is selected, we use VAPI streams.  */
346
  /* if txfs is corrupted, skip this uart. */
347 1073 rprescott
  if (!config.uarts[i].vapi_id && !channel_ok(channels[i])) return;
348 806 markom
 
349
  if (uarts[i].vapi.next_break_cnt >= 0)
350
    if (--uarts[i].vapi.next_break_cnt < 0) {
351
      if (!(uarts[i].vapi.cur_break = uarts[i].vapi.next_break))
352
        uarts[i].istat.break_set = 0;
353
    }
354 821 markom
 
355 806 markom
  /***************** Transmit *****************/
356
  if (!uarts[i].istat.txser_full) {
357
//      uarts[i].regs.lsr |= UART_LSR_TXBUFE;
358
    if (uarts[i].istat.txbuf_full) {
359
      uarts[i].iregs.txser = uarts[i].regs.txbuf[uarts[i].istat.txbuf_tail];
360
      uarts[i].istat.txbuf_tail = (uarts[i].istat.txbuf_tail + 1) % uarts[i].fifo_len;
361
      uarts[i].istat.txser_full = 1;
362
      uarts[i].istat.txbuf_full--;
363
      uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
364 1143 sfurman
 
365
      // When UART is in either character mode, i.e. 16450 emulation mode, or FIFO mode,
366
      // the THRE interrupt is raised when THR transitions from full to empty.
367
      if (!uarts[i].istat.txbuf_full) {
368
        uarts[i].istat.thre_int = 1;
369
        uarts[i].regs.lsr |= UART_LSR_TXBUFE;
370
      }
371 806 markom
    } else {
372
      uarts[i].regs.lsr |= UART_LSR_TXSERE;
373
    }
374
  } else if (uarts[i].char_clks <= uarts[i].istat.txser_clks++) {
375
    send_char(i, (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
376
  } else {
377
    /* We are still sending char here*/
378
 
379
    /* Check if we set the break bit */
380
    if (uarts[i].regs.lcr & UART_LCR_SBC) {
381
      if (!uarts[i].vapi.break_sent) {
382
#if 0
383
        /* Send broken frame */
384
        int nbits_sent = ((uarts[i].regs.lcr & UART_LCR_WLEN8) + 5) * (uarts[i].istat.txser_clks - 1) / uarts[i].char_clks;
385
        send_char(i, nbits_sent);
386
#endif
387
        /* Send one break signal */
388
        vapi_send (config.uarts[i].vapi_id, UART_LCR_SBC << 8);
389
        uarts[i].vapi.break_sent = 1;
390
      }
391
      /* mark as character was sent */
392
      uarts[i].istat.txser_full = 0;
393
      uarts[i].istat.txser_clks = 0;
394
    } else
395
      uarts[i].vapi.break_sent = 0;
396 1143 sfurman
 
397 806 markom
  }
398 1143 sfurman
 
399 806 markom
  /***************** Receive *****************/
400
 
401
  /* Is there a break? */
402
  if (uarts[i].vapi.cur_break) {
403
    uarts[i].vapi.cur_break_cnt++;
404
    if (uarts[i].vapi.cur_break_cnt > UART_BREAK_COUNT * uarts[i].vapi.char_clks) {
405
      if (!uarts[i].istat.break_set) {
406
        unsigned lsr;
407
        uarts[i].istat.break_set = 1;
408
        lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
409 997 markom
        PRINTF ("[%x]\n", uarts[i].regs.lsr);
410 806 markom
        uarts[i].istat.rxser_full = 0;
411
        uarts[i].istat.rxser_clks = 0;
412
        uart_add_char (i, lsr << 8);
413
      } else
414
        uarts[i].vapi.cur_break_cnt = 0;
415
    }
416
    if (uarts[i].istat.rxser_full) {
417
      uarts[i].istat.rxser_full = 0;
418
      uarts[i].istat.rxser_clks = 0;
419
    }
420
  } else {
421
    if (uarts[i].istat.rxser_full) {
422
      if (uarts[i].char_clks <= uarts[i].istat.rxser_clks++) {
423
        /* Set unused character bits to zero and allow lsr register in fifo */
424
        uarts[i].iregs.rxser &= ((1 << ((uarts[i].regs.lcr & 3) + 5)) - 1) | 0xff00;
425
        debug(4, "Receiving 0x%02x'%c' via UART%d...\n", uarts[i].iregs.rxser, uarts[i].iregs.rxser, i);
426
        uarts[i].istat.rxser_full = 0;
427
        uarts[i].istat.rxser_clks = 0;
428
        uart_add_char (i, uarts[i].iregs.rxser);
429
      }
430
    }
431
  }
432
 
433
  /* Check if there is something waiting, and put it into rxser */
434
  if (uarts[i].regs.mcr & UART_MCR_LOOP) {
435
    uarts[i].iregs.rxser = uarts[i].iregs.loopback;
436
    uarts[i].istat.rxser_full = 1;
437
  } else {
438
    if (!config.uarts[i].vapi_id) {
439
      if(uarts[i].istat.rxser_full == 0) {
440
        if (uarts[i].slowdown)
441
          uarts[i].slowdown--;
442 1073 rprescott
        else {
443
          char buffer[1];
444
          retval = channel_read(channels[i], buffer, 1);
445
          if(retval < 0)
446
                  perror(config.uarts[i].channel);
447
          else if(retval > 0) {
448 1116 sfurman
            uarts[i].iregs.rxser = (unsigned char)buffer[0];
449 1073 rprescott
            uarts[i].istat.rxser_full = 1;
450
          } else
451
            uarts[i].slowdown = UART_FGETC_SLOWDOWN;
452
        }
453 806 markom
      }
454
    } else { /* VAPI */
455
      int received = 0;
456
      /* do not handle commands while receiving */
457
      if (uarts[i].istat.rxser_full) return;
458
      while (!received) {
459
        if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
460
          unsigned long data = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
461
          debug(4, "Handling: %08x (%i,%i)\n", data, uarts[i].vapi_buf_head_ptr, uarts[i].vapi_buf_tail_ptr);
462
          uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
463
          switch (data >> 24) {
464
            case 0x00:
465
              uarts[i].vapi.lcr = (data >> 8) & 0xff;
466
              /* Put data into rx fifo */
467
              uarts[i].iregs.rxser = data & 0xff;
468
              uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr);
469
              if ((uarts[i].vapi.lcr & ~UART_LCR_SBC) != (uarts[i].regs.lcr & ~UART_LCR_SBC)
470
               || uarts[i].vapi.char_clks != uarts[i].char_clks
471
               || uarts[i].vapi.skew < -MAX_SKEW || uarts[i].vapi.skew > MAX_SKEW) {
472
                debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
473
                      uarts[i].vapi.lcr & ~UART_LCR_SBC, uarts[i].regs.lcr & ~UART_LCR_SBC);
474
                /* Set error bits */
475
                uarts[i].iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
476
                if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].iregs.rxser |= UART_LSR_PARITY << 8;
477
              }
478
              uarts[i].istat.rxser_full = 1;
479
              received = 1;
480
              break;
481
            case 0x01:
482
              uarts[i].vapi.dll = (data >> 0) & 0xff;
483
              uarts[i].vapi.dlh = (data >> 8) & 0xff;
484
              break;
485
            case 0x02:
486
              uarts[i].vapi.lcr = (data >> 8) & 0xff;
487
              break;
488
            case 0x03:
489
              uarts[i].vapi.skew = (signed short)(data & 0xffff);
490
              break;
491
            case 0x04:
492
              uarts[i].vapi.next_break_cnt = data & 0xffff;
493
              uarts[i].vapi.next_break = (data >> 16) & 1;
494
              break;
495
            default:
496
              debug (0, "WARNING: Invalid vapi command %02x\n", data >> 24);
497
              break;
498
          }
499
        } else break;
500
      }
501
    }
502
  }
503
 
504
  /***************** Loopback *****************/
505
  if (uarts[i].regs.mcr & UART_MCR_LOOP) {
506
    debug(5, "uart_clock: Loopback\n");
507
    if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
508
        ((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
509
      uarts[i].regs.msr |= UART_MSR_DDCD;
510
    if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
511
        ((uarts[i].regs.msr & UART_MSR_RI) >> 4))
512
      uarts[i].regs.msr |= UART_MSR_TERI;
513
    if ((uarts[i].regs.mcr & UART_MCR_RTS) !=
514
        ((uarts[i].regs.msr & UART_MSR_CTS) >> 3))
515
      uarts[i].regs.msr |= UART_MSR_DCTS;
516
    if ((uarts[i].regs.mcr & UART_MCR_DTR) !=
517
        ((uarts[i].regs.msr & UART_MSR_DSR) >> 5))
518
      uarts[i].regs.msr |= UART_MSR_DDSR;
519
    uarts[i].regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
520
              | UART_MSR_DSR | UART_MSR_CTS);
521
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX2) << 4);
522
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX1) << 4);
523
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_RTS) << 3);
524
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_DTR) << 5);
525
  }
526
 
527
  if (uarts[i].regs.lsr & UART_LSR_RDRDY)
528
    uarts[i].istat.timeout_count++;
529
 
530
  /* Update LSR error bits from the ones from rx FIFO */
531
  if (uarts[i].istat.rxbuf_full) {
532
    uarts[i].regs.lsr |= uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] >> 8;
533
    /* we must delete the lsr status, so that we can clear it from lsr */
534
    uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] &= 0xff;
535
  }
536
 
537
  /* Interrupt detection in proper priority order. */
538
  uarts[i].regs.iir = UART_IIR_NO_INT;
539
  if (uarts[i].regs.ier & UART_IER_RLSI &&                    /* Receiver LS */
540
      uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
541
        | UART_LSR_FRAME | UART_LSR_BREAK)) {
542
    uarts[i].regs.iir = UART_IIR_RLSI;
543
  } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* RD available */
544
      && (uarts[i].istat.rxbuf_full >= UART_FIFO_TRIGGER(uarts[i].regs.fcr >> 6))
545
      && (uarts[i].regs.lsr & UART_LSR_RDRDY)) {
546
    uarts[i].regs.iir = UART_IIR_RDI;
547
  } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* timeout */
548
      && (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)) {
549
    uarts[i].regs.iir = UART_IIR_CTI;
550
  } else if (uarts[i].regs.ier & UART_IER_THRI &&             /* Transm. empty */
551
      uarts[i].istat.thre_int == 1) {
552
    uarts[i].regs.iir = UART_IIR_THRI;
553
  } else if (uarts[i].regs.ier & UART_IER_MSI &&              /* Modem status */
554
      uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
555
        | UART_MSR_TERI | UART_MSR_DDCD)) {
556
    uarts[i].regs.iir = UART_IIR_MSI;
557
  }
558
  if (!(uarts[i].regs.iir & UART_IIR_NO_INT)) {
559
    debug (4, "uarts[i].regs.iir = %i\t", uarts[i].regs.iir);
560
    report_interrupt(config.uarts[i].irq);
561
  }
562
}
563
 
564 341 markom
/* Reset.  It initializes all registers of all UART devices to zero values,
565 31 lampret
   (re)opens all RX/TX file streams and places devices in memory address
566 341 markom
   space.  */
567 31 lampret
void uart_reset()
568
{
569 355 markom
  int i;
570 997 markom
  if (config.sim.verbose && config.nuarts) PRINTF("Resetting %u UART(s).\n", config.nuarts);
571 355 markom
  memset(uarts, 0, sizeof(uarts));
572 261 markom
 
573 355 markom
  for(i = 0; i < config.nuarts; i++) {
574 341 markom
    if (config.uarts[i].vapi_id) {
575
      if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
576
        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);
577
        config.uarts[i].vapi_id = 0;
578
      } else {
579 355 markom
        vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
580 970 simons
        register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
581 355 markom
      }
582 1073 rprescott
    } else if (config.uarts[i].channel[0]) { /* MM: Try to create stream.  */
583
      if(channels[i])
584
        channel_close(channels[i]);
585
      else
586
        channels[i] = channel_init(config.uarts[i].channel);
587
      if(channel_open(channels[i]) < 0) {
588
        debug (0, "WARNING: UART%d has problems with channel \"%s\".\n", i, config.uarts[i].channel);
589 355 markom
        continue;
590
      }
591 1073 rprescott
      if (config.sim.verbose)
592 997 markom
        PRINTF("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
593 970 simons
      register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
594 1073 rprescott
    } else {
595
        debug (0, "WARNING: UART%d has no vapi nor channel specified\n", i);
596
        continue;
597 341 markom
    }
598
 
599
    if (config.uarts[i].uart16550)
600
      uarts[i].fifo_len = 16;
601
    else
602
      uarts[i].fifo_len = 1;
603 344 markom
 
604 341 markom
    uarts[i].istat.rxbuf_head = uarts[i].istat.rxbuf_tail = 0;
605
    uarts[i].istat.txbuf_head = uarts[i].istat.txbuf_tail = 0;
606 344 markom
 
607 409 markom
    uarts[i].istat.break_set = 0;
608
    uarts[i].istat.timeout_count = 0;
609 1145 sfurman
 
610
    // For FIFO-mode only, THRE interrupt is set when both THR and FIFO are empty
611
    uarts[i].istat.thre_int = (uarts[i].fifo_len == 16);
612
 
613 713 markom
    uarts[i].slowdown = UART_FGETC_SLOWDOWN;
614 492 markom
 
615 344 markom
    uarts[i].regs.lcr = UART_LCR_RESET;
616 385 markom
    uarts[i].vapi.cur_break = uarts[i].vapi.cur_break_cnt = uarts[i].vapi.next_break = 0;
617
    uarts[i].vapi.next_break_cnt = -1;
618 997 markom
    PRINTF ("%i\n", i);
619 884 markom
    SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
620 336 markom
  }
621 31 lampret
}
622 261 markom
 
623 31 lampret
/* Print register values on stdout. */
624
void uart_status()
625
{
626 355 markom
  int i, j;
627
 
628
  for(i = 0; i < config.nuarts; i++) {
629
    if ( !config.uarts[i].baseaddr )
630
      continue;
631 997 markom
    PRINTF("\nUART%d visible registers at 0x%.8x:\n", i, config.uarts[i].baseaddr);
632 1145 sfurman
    PRINTF("RXBUF: ");
633 355 markom
    for (j = uarts[i].istat.rxbuf_head; j != uarts[i].istat.rxbuf_tail; j = (j + 1) % uarts[i].fifo_len)
634 997 markom
      PRINTF (" %.2x", uarts[i].regs.rxbuf[j]);
635 1145 sfurman
    PRINTF("TXBUF: ");
636
    for (j = uarts[i].istat.txbuf_head; j != uarts[i].istat.txbuf_tail; j = (j + 1) % uarts[i].fifo_len)
637
      PRINTF (" %.2x", uarts[i].regs.txbuf[j]);
638
    PRINTF("\n");
639 997 markom
    PRINTF("DLL  : %.2x  DLH  : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
640
    PRINTF("IER  : %.2x  IIR  : %.2x\n", uarts[i].regs.ier, uarts[i].regs.iir);
641
    PRINTF("LCR  : %.2x  MCR  : %.2x\n", uarts[i].regs.lcr, uarts[i].regs.mcr);
642
    PRINTF("LSR  : %.2x  MSR  : %.2x\n", uarts[i].regs.lsr, uarts[i].regs.msr);
643
    PRINTF("SCR  : %.2x\n", uarts[i].regs.scr);
644 31 lampret
 
645 997 markom
    PRINTF("\nInternal registers (sim debug):\n");
646
    PRINTF("RXSER: %.2x  TXSER: %.2x\n", uarts[i].iregs.rxser, uarts[i].iregs.txser);
647 31 lampret
 
648 997 markom
    PRINTF("\nInternal status (sim debug):\n");
649
    PRINTF("char_clks: %d\n", uarts[i].char_clks);
650
    PRINTF("rxser_clks: %d  txser_clks: %d\n", uarts[i].istat.rxser_clks, uarts[i].istat.txser_clks);
651
    PRINTF("rxser: %d  txser: %d\n", uarts[i].istat.rxser_full, uarts[i].istat.txser_full);
652 1145 sfurman
    PRINTF("rxbuf_full: %d  txbuf_full: %d\n", uarts[i].istat.rxbuf_full, uarts[i].istat.txbuf_full);
653 997 markom
    PRINTF("Using IRQ%i\n", config.uarts[i].irq);
654 336 markom
    if (config.uarts[i].vapi_id)
655 997 markom
      PRINTF ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
656 1073 rprescott
    /* TODO: replace by a channel_status
657 336 markom
    else
658 997 markom
      PRINTF("RX fs: %p  TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
659 1073 rprescott
    */
660 355 markom
  }
661 31 lampret
}

powered by: WebSVN 2.1.0

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