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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc1/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 1165

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

powered by: WebSVN 2.1.0

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