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 1153

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
      && (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)) {
550
    uarts[i].regs.iir = UART_IIR_CTI;
551
  } else if (uarts[i].regs.ier & UART_IER_THRI &&             /* Transm. empty */
552
      uarts[i].istat.thre_int == 1) {
553
    uarts[i].regs.iir = UART_IIR_THRI;
554
  } else if (uarts[i].regs.ier & UART_IER_MSI &&              /* Modem status */
555
      uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
556
        | UART_MSR_TERI | UART_MSR_DDCD)) {
557
    uarts[i].regs.iir = UART_IIR_MSI;
558
  }
559
  if (!(uarts[i].regs.iir & UART_IIR_NO_INT)) {
560
    debug (4, "uarts[i].regs.iir = %i\t", uarts[i].regs.iir);
561
    report_interrupt(config.uarts[i].irq);
562
  }
563
}
564
 
565 341 markom
/* Reset.  It initializes all registers of all UART devices to zero values,
566 31 lampret
   (re)opens all RX/TX file streams and places devices in memory address
567 341 markom
   space.  */
568 31 lampret
void uart_reset()
569
{
570 355 markom
  int i;
571 997 markom
  if (config.sim.verbose && config.nuarts) PRINTF("Resetting %u UART(s).\n", config.nuarts);
572 355 markom
  memset(uarts, 0, sizeof(uarts));
573 261 markom
 
574 355 markom
  for(i = 0; i < config.nuarts; i++) {
575 341 markom
    if (config.uarts[i].vapi_id) {
576
      if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
577
        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);
578
        config.uarts[i].vapi_id = 0;
579
      } else {
580 355 markom
        vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
581 970 simons
        register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
582 355 markom
      }
583 1073 rprescott
    } else if (config.uarts[i].channel[0]) { /* MM: Try to create stream.  */
584
      if(channels[i])
585
        channel_close(channels[i]);
586
      else
587
        channels[i] = channel_init(config.uarts[i].channel);
588
      if(channel_open(channels[i]) < 0) {
589
        debug (0, "WARNING: UART%d has problems with channel \"%s\".\n", i, config.uarts[i].channel);
590 355 markom
        continue;
591
      }
592 1073 rprescott
      if (config.sim.verbose)
593 997 markom
        PRINTF("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
594 970 simons
      register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
595 1073 rprescott
    } else {
596
        debug (0, "WARNING: UART%d has no vapi nor channel specified\n", i);
597
        continue;
598 341 markom
    }
599
 
600
    if (config.uarts[i].uart16550)
601
      uarts[i].fifo_len = 16;
602
    else
603
      uarts[i].fifo_len = 1;
604 344 markom
 
605 341 markom
    uarts[i].istat.rxbuf_head = uarts[i].istat.rxbuf_tail = 0;
606
    uarts[i].istat.txbuf_head = uarts[i].istat.txbuf_tail = 0;
607 344 markom
 
608 409 markom
    uarts[i].istat.break_set = 0;
609
    uarts[i].istat.timeout_count = 0;
610 1145 sfurman
 
611
    // For FIFO-mode only, THRE interrupt is set when both THR and FIFO are empty
612
    uarts[i].istat.thre_int = (uarts[i].fifo_len == 16);
613
 
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 1145 sfurman
    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 1145 sfurman
    PRINTF("TXBUF: ");
637
    for (j = uarts[i].istat.txbuf_head; j != uarts[i].istat.txbuf_tail; j = (j + 1) % uarts[i].fifo_len)
638
      PRINTF (" %.2x", uarts[i].regs.txbuf[j]);
639
    PRINTF("\n");
640 997 markom
    PRINTF("DLL  : %.2x  DLH  : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
641
    PRINTF("IER  : %.2x  IIR  : %.2x\n", uarts[i].regs.ier, uarts[i].regs.iir);
642
    PRINTF("LCR  : %.2x  MCR  : %.2x\n", uarts[i].regs.lcr, uarts[i].regs.mcr);
643
    PRINTF("LSR  : %.2x  MSR  : %.2x\n", uarts[i].regs.lsr, uarts[i].regs.msr);
644
    PRINTF("SCR  : %.2x\n", uarts[i].regs.scr);
645 31 lampret
 
646 997 markom
    PRINTF("\nInternal registers (sim debug):\n");
647
    PRINTF("RXSER: %.2x  TXSER: %.2x\n", uarts[i].iregs.rxser, uarts[i].iregs.txser);
648 31 lampret
 
649 997 markom
    PRINTF("\nInternal status (sim debug):\n");
650
    PRINTF("char_clks: %d\n", uarts[i].char_clks);
651
    PRINTF("rxser_clks: %d  txser_clks: %d\n", uarts[i].istat.rxser_clks, uarts[i].istat.txser_clks);
652
    PRINTF("rxser: %d  txser: %d\n", uarts[i].istat.rxser_full, uarts[i].istat.txser_full);
653 1145 sfurman
    PRINTF("rxbuf_full: %d  txbuf_full: %d\n", uarts[i].istat.rxbuf_full, uarts[i].istat.txbuf_full);
654 997 markom
    PRINTF("Using IRQ%i\n", config.uarts[i].irq);
655 336 markom
    if (config.uarts[i].vapi_id)
656 997 markom
      PRINTF ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
657 1073 rprescott
    /* TODO: replace by a channel_status
658 336 markom
    else
659 997 markom
      PRINTF("RX fs: %p  TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
660 1073 rprescott
    */
661 355 markom
  }
662 31 lampret
}

powered by: WebSVN 2.1.0

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