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 1143

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

powered by: WebSVN 2.1.0

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