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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_52/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 1308

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

powered by: WebSVN 2.1.0

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