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

Subversion Repositories or1k

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

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 1244 hpanther
  PRINTF ("%c", 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 1244 hpanther
                PRINTF ("%c", uarts[i].iregs.rxser);
428 806 markom
        uarts[i].istat.rxser_full = 0;
429
        uarts[i].istat.rxser_clks = 0;
430
        uart_add_char (i, uarts[i].iregs.rxser);
431
      }
432
    }
433
  }
434
 
435
  /* Check if there is something waiting, and put it into rxser */
436
  if (uarts[i].regs.mcr & UART_MCR_LOOP) {
437
    uarts[i].iregs.rxser = uarts[i].iregs.loopback;
438
    uarts[i].istat.rxser_full = 1;
439
  } else {
440
    if (!config.uarts[i].vapi_id) {
441
      if(uarts[i].istat.rxser_full == 0) {
442
        if (uarts[i].slowdown)
443
          uarts[i].slowdown--;
444 1073 rprescott
        else {
445
          char buffer[1];
446
          retval = channel_read(channels[i], buffer, 1);
447
          if(retval < 0)
448
                  perror(config.uarts[i].channel);
449
          else if(retval > 0) {
450 1116 sfurman
            uarts[i].iregs.rxser = (unsigned char)buffer[0];
451 1073 rprescott
            uarts[i].istat.rxser_full = 1;
452
          } else
453
            uarts[i].slowdown = UART_FGETC_SLOWDOWN;
454
        }
455 806 markom
      }
456
    } else { /* VAPI */
457
      int received = 0;
458
      /* do not handle commands while receiving */
459
      if (uarts[i].istat.rxser_full) return;
460
      while (!received) {
461
        if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
462
          unsigned long data = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
463
          debug(4, "Handling: %08x (%i,%i)\n", data, uarts[i].vapi_buf_head_ptr, uarts[i].vapi_buf_tail_ptr);
464
          uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
465
          switch (data >> 24) {
466
            case 0x00:
467
              uarts[i].vapi.lcr = (data >> 8) & 0xff;
468
              /* Put data into rx fifo */
469
              uarts[i].iregs.rxser = data & 0xff;
470
              uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr);
471
              if ((uarts[i].vapi.lcr & ~UART_LCR_SBC) != (uarts[i].regs.lcr & ~UART_LCR_SBC)
472
               || uarts[i].vapi.char_clks != uarts[i].char_clks
473
               || uarts[i].vapi.skew < -MAX_SKEW || uarts[i].vapi.skew > MAX_SKEW) {
474
                debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
475
                      uarts[i].vapi.lcr & ~UART_LCR_SBC, uarts[i].regs.lcr & ~UART_LCR_SBC);
476
                /* Set error bits */
477
                uarts[i].iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
478
                if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].iregs.rxser |= UART_LSR_PARITY << 8;
479
              }
480
              uarts[i].istat.rxser_full = 1;
481
              received = 1;
482
              break;
483
            case 0x01:
484
              uarts[i].vapi.dll = (data >> 0) & 0xff;
485
              uarts[i].vapi.dlh = (data >> 8) & 0xff;
486
              break;
487
            case 0x02:
488
              uarts[i].vapi.lcr = (data >> 8) & 0xff;
489
              break;
490
            case 0x03:
491
              uarts[i].vapi.skew = (signed short)(data & 0xffff);
492
              break;
493
            case 0x04:
494
              uarts[i].vapi.next_break_cnt = data & 0xffff;
495
              uarts[i].vapi.next_break = (data >> 16) & 1;
496
              break;
497
            default:
498
              debug (0, "WARNING: Invalid vapi command %02x\n", data >> 24);
499
              break;
500
          }
501
        } else break;
502
      }
503
    }
504
  }
505
 
506
  /***************** Loopback *****************/
507
  if (uarts[i].regs.mcr & UART_MCR_LOOP) {
508
    debug(5, "uart_clock: Loopback\n");
509
    if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
510
        ((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
511
      uarts[i].regs.msr |= UART_MSR_DDCD;
512
    if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
513
        ((uarts[i].regs.msr & UART_MSR_RI) >> 4))
514
      uarts[i].regs.msr |= UART_MSR_TERI;
515
    if ((uarts[i].regs.mcr & UART_MCR_RTS) !=
516
        ((uarts[i].regs.msr & UART_MSR_CTS) >> 3))
517
      uarts[i].regs.msr |= UART_MSR_DCTS;
518
    if ((uarts[i].regs.mcr & UART_MCR_DTR) !=
519
        ((uarts[i].regs.msr & UART_MSR_DSR) >> 5))
520
      uarts[i].regs.msr |= UART_MSR_DDSR;
521
    uarts[i].regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
522
              | UART_MSR_DSR | UART_MSR_CTS);
523
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX2) << 4);
524
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX1) << 4);
525
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_RTS) << 3);
526
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_DTR) << 5);
527
  }
528
 
529
  if (uarts[i].regs.lsr & UART_LSR_RDRDY)
530
    uarts[i].istat.timeout_count++;
531
 
532
  /* Update LSR error bits from the ones from rx FIFO */
533
  if (uarts[i].istat.rxbuf_full) {
534
    uarts[i].regs.lsr |= uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] >> 8;
535
    /* we must delete the lsr status, so that we can clear it from lsr */
536
    uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] &= 0xff;
537
  }
538
 
539
  /* Interrupt detection in proper priority order. */
540
  uarts[i].regs.iir = UART_IIR_NO_INT;
541
  if (uarts[i].regs.ier & UART_IER_RLSI &&                    /* Receiver LS */
542
      uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
543
        | UART_LSR_FRAME | UART_LSR_BREAK)) {
544
    uarts[i].regs.iir = UART_IIR_RLSI;
545
  } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* RD available */
546
      && (uarts[i].istat.rxbuf_full >= UART_FIFO_TRIGGER(uarts[i].regs.fcr >> 6))
547
      && (uarts[i].regs.lsr & UART_LSR_RDRDY)) {
548
    uarts[i].regs.iir = UART_IIR_RDI;
549
  } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* timeout */
550 1165 markom
      && (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)
551
      && (uarts[i].istat.rxbuf_head != uarts[i].istat.rxbuf_tail)) {
552 806 markom
    uarts[i].regs.iir = UART_IIR_CTI;
553
  } else if (uarts[i].regs.ier & UART_IER_THRI &&             /* Transm. empty */
554
      uarts[i].istat.thre_int == 1) {
555
    uarts[i].regs.iir = UART_IIR_THRI;
556
  } else if (uarts[i].regs.ier & UART_IER_MSI &&              /* Modem status */
557
      uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
558
        | UART_MSR_TERI | UART_MSR_DDCD)) {
559
    uarts[i].regs.iir = UART_IIR_MSI;
560
  }
561
  if (!(uarts[i].regs.iir & UART_IIR_NO_INT)) {
562
    debug (4, "uarts[i].regs.iir = %i\t", uarts[i].regs.iir);
563
    report_interrupt(config.uarts[i].irq);
564
  }
565
}
566
 
567 341 markom
/* Reset.  It initializes all registers of all UART devices to zero values,
568 31 lampret
   (re)opens all RX/TX file streams and places devices in memory address
569 341 markom
   space.  */
570 31 lampret
void uart_reset()
571
{
572 355 markom
  int i;
573 997 markom
  if (config.sim.verbose && config.nuarts) PRINTF("Resetting %u UART(s).\n", config.nuarts);
574 355 markom
  memset(uarts, 0, sizeof(uarts));
575 261 markom
 
576 355 markom
  for(i = 0; i < config.nuarts; i++) {
577 341 markom
    if (config.uarts[i].vapi_id) {
578
      if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
579
        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);
580
        config.uarts[i].vapi_id = 0;
581
      } else {
582 355 markom
        vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
583 970 simons
        register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
584 355 markom
      }
585 1073 rprescott
    } else if (config.uarts[i].channel[0]) { /* MM: Try to create stream.  */
586
      if(channels[i])
587
        channel_close(channels[i]);
588
      else
589
        channels[i] = channel_init(config.uarts[i].channel);
590
      if(channel_open(channels[i]) < 0) {
591
        debug (0, "WARNING: UART%d has problems with channel \"%s\".\n", i, config.uarts[i].channel);
592 355 markom
        continue;
593
      }
594 1073 rprescott
      if (config.sim.verbose)
595 997 markom
        PRINTF("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
596 970 simons
      register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
597 1073 rprescott
    } else {
598
        debug (0, "WARNING: UART%d has no vapi nor channel specified\n", i);
599
        continue;
600 341 markom
    }
601
 
602
    if (config.uarts[i].uart16550)
603
      uarts[i].fifo_len = 16;
604
    else
605
      uarts[i].fifo_len = 1;
606 344 markom
 
607 341 markom
    uarts[i].istat.rxbuf_head = uarts[i].istat.rxbuf_tail = 0;
608
    uarts[i].istat.txbuf_head = uarts[i].istat.txbuf_tail = 0;
609 344 markom
 
610 409 markom
    uarts[i].istat.break_set = 0;
611
    uarts[i].istat.timeout_count = 0;
612 1145 sfurman
 
613
    // For FIFO-mode only, THRE interrupt is set when both THR and FIFO are empty
614
    uarts[i].istat.thre_int = (uarts[i].fifo_len == 16);
615
 
616 713 markom
    uarts[i].slowdown = UART_FGETC_SLOWDOWN;
617 492 markom
 
618 344 markom
    uarts[i].regs.lcr = UART_LCR_RESET;
619 385 markom
    uarts[i].vapi.cur_break = uarts[i].vapi.cur_break_cnt = uarts[i].vapi.next_break = 0;
620
    uarts[i].vapi.next_break_cnt = -1;
621 997 markom
    PRINTF ("%i\n", i);
622 884 markom
    SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
623 336 markom
  }
624 31 lampret
}
625 261 markom
 
626 31 lampret
/* Print register values on stdout. */
627
void uart_status()
628
{
629 355 markom
  int i, j;
630
 
631
  for(i = 0; i < config.nuarts; i++) {
632
    if ( !config.uarts[i].baseaddr )
633
      continue;
634 997 markom
    PRINTF("\nUART%d visible registers at 0x%.8x:\n", i, config.uarts[i].baseaddr);
635 1145 sfurman
    PRINTF("RXBUF: ");
636 355 markom
    for (j = uarts[i].istat.rxbuf_head; j != uarts[i].istat.rxbuf_tail; j = (j + 1) % uarts[i].fifo_len)
637 997 markom
      PRINTF (" %.2x", uarts[i].regs.rxbuf[j]);
638 1145 sfurman
    PRINTF("TXBUF: ");
639
    for (j = uarts[i].istat.txbuf_head; j != uarts[i].istat.txbuf_tail; j = (j + 1) % uarts[i].fifo_len)
640
      PRINTF (" %.2x", uarts[i].regs.txbuf[j]);
641
    PRINTF("\n");
642 997 markom
    PRINTF("DLL  : %.2x  DLH  : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
643
    PRINTF("IER  : %.2x  IIR  : %.2x\n", uarts[i].regs.ier, uarts[i].regs.iir);
644
    PRINTF("LCR  : %.2x  MCR  : %.2x\n", uarts[i].regs.lcr, uarts[i].regs.mcr);
645
    PRINTF("LSR  : %.2x  MSR  : %.2x\n", uarts[i].regs.lsr, uarts[i].regs.msr);
646
    PRINTF("SCR  : %.2x\n", uarts[i].regs.scr);
647 31 lampret
 
648 997 markom
    PRINTF("\nInternal registers (sim debug):\n");
649
    PRINTF("RXSER: %.2x  TXSER: %.2x\n", uarts[i].iregs.rxser, uarts[i].iregs.txser);
650 31 lampret
 
651 997 markom
    PRINTF("\nInternal status (sim debug):\n");
652
    PRINTF("char_clks: %d\n", uarts[i].char_clks);
653
    PRINTF("rxser_clks: %d  txser_clks: %d\n", uarts[i].istat.rxser_clks, uarts[i].istat.txser_clks);
654
    PRINTF("rxser: %d  txser: %d\n", uarts[i].istat.rxser_full, uarts[i].istat.txser_full);
655 1145 sfurman
    PRINTF("rxbuf_full: %d  txbuf_full: %d\n", uarts[i].istat.rxbuf_full, uarts[i].istat.txbuf_full);
656 997 markom
    PRINTF("Using IRQ%i\n", config.uarts[i].irq);
657 336 markom
    if (config.uarts[i].vapi_id)
658 997 markom
      PRINTF ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
659 1073 rprescott
    /* TODO: replace by a channel_status
660 336 markom
    else
661 997 markom
      PRINTF("RX fs: %p  TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
662 1073 rprescott
    */
663 355 markom
  }
664 31 lampret
}

powered by: WebSVN 2.1.0

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