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 1073

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 221 markom
static int thre_int;
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 355 markom
      uarts[chipsel].istat.thre_int = 0;
107
      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 411 markom
        uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE;
118 409 markom
      }
119
      if (value & UART_FCR_RRXFI) {
120
        uarts[chipsel].istat.rxbuf_head = uarts[chipsel].istat.rxbuf_tail = 0;
121
        uarts[chipsel].istat.rxbuf_full = 0;
122 411 markom
        uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY;
123 409 markom
      }
124
      break;
125 355 markom
    case UART_IER:
126
      uarts[chipsel].regs.ier = value & UART_VALID_IER;
127 423 markom
#if 0
128 492 markom
      if (uarts[chipsel].regs.ier & UART_IER_THRI)
129
        uarts[chipsel].istat.thre_int = 1;
130 423 markom
#endif
131 355 markom
      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 492 markom
      if (uarts[chipsel].regs.ier & UART_IER_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 997 markom
  PRINTF ("'%c'\n", 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 997 markom
      PRINTF ("vapi_send (%08x, %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
      uarts[i].istat.thre_int = 1;
367
    } else {
368
      uarts[i].regs.lsr |= UART_LSR_TXSERE;
369
      uarts[i].regs.lsr |= UART_LSR_TXBUFE;
370
    }
371
  } else if (uarts[i].char_clks <= uarts[i].istat.txser_clks++) {
372
    send_char(i, (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
373
  } else {
374
    /* We are still sending char here*/
375
 
376
    /* Check if we set the break bit */
377
    if (uarts[i].regs.lcr & UART_LCR_SBC) {
378
      if (!uarts[i].vapi.break_sent) {
379
#if 0
380
        /* Send broken frame */
381
        int nbits_sent = ((uarts[i].regs.lcr & UART_LCR_WLEN8) + 5) * (uarts[i].istat.txser_clks - 1) / uarts[i].char_clks;
382
        send_char(i, nbits_sent);
383
#endif
384
        /* Send one break signal */
385
        vapi_send (config.uarts[i].vapi_id, UART_LCR_SBC << 8);
386
        uarts[i].vapi.break_sent = 1;
387
      }
388
      /* mark as character was sent */
389
      uarts[i].istat.txser_full = 0;
390
      uarts[i].istat.txser_clks = 0;
391
    } else
392
      uarts[i].vapi.break_sent = 0;
393
  }
394
 
395
  /***************** Receive *****************/
396
 
397
  /* Is there a break? */
398
  if (uarts[i].vapi.cur_break) {
399
    uarts[i].vapi.cur_break_cnt++;
400
    if (uarts[i].vapi.cur_break_cnt > UART_BREAK_COUNT * uarts[i].vapi.char_clks) {
401
      if (!uarts[i].istat.break_set) {
402
        unsigned lsr;
403
        uarts[i].istat.break_set = 1;
404
        lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
405 997 markom
        PRINTF ("[%x]\n", uarts[i].regs.lsr);
406 806 markom
        uarts[i].istat.rxser_full = 0;
407
        uarts[i].istat.rxser_clks = 0;
408
        uart_add_char (i, lsr << 8);
409
      } else
410
        uarts[i].vapi.cur_break_cnt = 0;
411
    }
412
    if (uarts[i].istat.rxser_full) {
413
      uarts[i].istat.rxser_full = 0;
414
      uarts[i].istat.rxser_clks = 0;
415
    }
416
  } else {
417
    if (uarts[i].istat.rxser_full) {
418
      if (uarts[i].char_clks <= uarts[i].istat.rxser_clks++) {
419
        /* Set unused character bits to zero and allow lsr register in fifo */
420
        uarts[i].iregs.rxser &= ((1 << ((uarts[i].regs.lcr & 3) + 5)) - 1) | 0xff00;
421
        debug(4, "Receiving 0x%02x'%c' via UART%d...\n", uarts[i].iregs.rxser, uarts[i].iregs.rxser, i);
422
        uarts[i].istat.rxser_full = 0;
423
        uarts[i].istat.rxser_clks = 0;
424
        uart_add_char (i, uarts[i].iregs.rxser);
425
      }
426
    }
427
  }
428
 
429
  /* Check if there is something waiting, and put it into rxser */
430
  if (uarts[i].regs.mcr & UART_MCR_LOOP) {
431
    uarts[i].iregs.rxser = uarts[i].iregs.loopback;
432
    uarts[i].istat.rxser_full = 1;
433
  } else {
434
    if (!config.uarts[i].vapi_id) {
435
      if(uarts[i].istat.rxser_full == 0) {
436
        if (uarts[i].slowdown)
437
          uarts[i].slowdown--;
438 1073 rprescott
        else {
439
          char buffer[1];
440
          retval = channel_read(channels[i], buffer, 1);
441
          if(retval < 0)
442
                  perror(config.uarts[i].channel);
443
          else if(retval > 0) {
444
            uarts[i].iregs.rxser = buffer[0];
445
            uarts[i].istat.rxser_full = 1;
446
          } else
447
            uarts[i].slowdown = UART_FGETC_SLOWDOWN;
448
        }
449 806 markom
      }
450
    } else { /* VAPI */
451
      int received = 0;
452
      /* do not handle commands while receiving */
453
      if (uarts[i].istat.rxser_full) return;
454
      while (!received) {
455
        if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
456
          unsigned long data = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
457
          debug(4, "Handling: %08x (%i,%i)\n", data, uarts[i].vapi_buf_head_ptr, uarts[i].vapi_buf_tail_ptr);
458
          uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
459
          switch (data >> 24) {
460
            case 0x00:
461
              uarts[i].vapi.lcr = (data >> 8) & 0xff;
462
              /* Put data into rx fifo */
463
              uarts[i].iregs.rxser = data & 0xff;
464
              uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr);
465
              if ((uarts[i].vapi.lcr & ~UART_LCR_SBC) != (uarts[i].regs.lcr & ~UART_LCR_SBC)
466
               || uarts[i].vapi.char_clks != uarts[i].char_clks
467
               || uarts[i].vapi.skew < -MAX_SKEW || uarts[i].vapi.skew > MAX_SKEW) {
468
                debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
469
                      uarts[i].vapi.lcr & ~UART_LCR_SBC, uarts[i].regs.lcr & ~UART_LCR_SBC);
470
                /* Set error bits */
471
                uarts[i].iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
472
                if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].iregs.rxser |= UART_LSR_PARITY << 8;
473
              }
474
              uarts[i].istat.rxser_full = 1;
475
              received = 1;
476
              break;
477
            case 0x01:
478
              uarts[i].vapi.dll = (data >> 0) & 0xff;
479
              uarts[i].vapi.dlh = (data >> 8) & 0xff;
480
              break;
481
            case 0x02:
482
              uarts[i].vapi.lcr = (data >> 8) & 0xff;
483
              break;
484
            case 0x03:
485
              uarts[i].vapi.skew = (signed short)(data & 0xffff);
486
              break;
487
            case 0x04:
488
              uarts[i].vapi.next_break_cnt = data & 0xffff;
489
              uarts[i].vapi.next_break = (data >> 16) & 1;
490
              break;
491
            default:
492
              debug (0, "WARNING: Invalid vapi command %02x\n", data >> 24);
493
              break;
494
          }
495
        } else break;
496
      }
497
    }
498
  }
499
 
500
  /***************** Loopback *****************/
501
  if (uarts[i].regs.mcr & UART_MCR_LOOP) {
502
    debug(5, "uart_clock: Loopback\n");
503
    if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
504
        ((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
505
      uarts[i].regs.msr |= UART_MSR_DDCD;
506
    if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
507
        ((uarts[i].regs.msr & UART_MSR_RI) >> 4))
508
      uarts[i].regs.msr |= UART_MSR_TERI;
509
    if ((uarts[i].regs.mcr & UART_MCR_RTS) !=
510
        ((uarts[i].regs.msr & UART_MSR_CTS) >> 3))
511
      uarts[i].regs.msr |= UART_MSR_DCTS;
512
    if ((uarts[i].regs.mcr & UART_MCR_DTR) !=
513
        ((uarts[i].regs.msr & UART_MSR_DSR) >> 5))
514
      uarts[i].regs.msr |= UART_MSR_DDSR;
515
    uarts[i].regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
516
              | UART_MSR_DSR | UART_MSR_CTS);
517
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX2) << 4);
518
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX1) << 4);
519
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_RTS) << 3);
520
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_DTR) << 5);
521
  }
522
 
523
  if (uarts[i].regs.lsr & UART_LSR_RDRDY)
524
    uarts[i].istat.timeout_count++;
525
 
526
  /* Update LSR error bits from the ones from rx FIFO */
527
  if (uarts[i].istat.rxbuf_full) {
528
    uarts[i].regs.lsr |= uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] >> 8;
529
    /* we must delete the lsr status, so that we can clear it from lsr */
530
    uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] &= 0xff;
531
  }
532
 
533
  /* Interrupt detection in proper priority order. */
534
  uarts[i].regs.iir = UART_IIR_NO_INT;
535
  if (uarts[i].regs.ier & UART_IER_RLSI &&                    /* Receiver LS */
536
      uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
537
        | UART_LSR_FRAME | UART_LSR_BREAK)) {
538
    uarts[i].regs.iir = UART_IIR_RLSI;
539
  } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* RD available */
540
      && (uarts[i].istat.rxbuf_full >= UART_FIFO_TRIGGER(uarts[i].regs.fcr >> 6))
541
      && (uarts[i].regs.lsr & UART_LSR_RDRDY)) {
542
    uarts[i].regs.iir = UART_IIR_RDI;
543
  } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* timeout */
544
      && (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)) {
545
    uarts[i].regs.iir = UART_IIR_CTI;
546
  } else if (uarts[i].regs.ier & UART_IER_THRI &&             /* Transm. empty */
547
      uarts[i].regs.lsr & UART_LSR_TXBUFE &&
548
      uarts[i].istat.thre_int == 1) {
549
    uarts[i].regs.iir = UART_IIR_THRI;
550
  } else if (uarts[i].regs.ier & UART_IER_MSI &&              /* Modem status */
551
      uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
552
        | UART_MSR_TERI | UART_MSR_DDCD)) {
553
    uarts[i].regs.iir = UART_IIR_MSI;
554
  }
555
  if (!(uarts[i].regs.iir & UART_IIR_NO_INT)) {
556
    debug (4, "uarts[i].regs.iir = %i\t", uarts[i].regs.iir);
557
    report_interrupt(config.uarts[i].irq);
558
  }
559
}
560
 
561 341 markom
/* Reset.  It initializes all registers of all UART devices to zero values,
562 31 lampret
   (re)opens all RX/TX file streams and places devices in memory address
563 341 markom
   space.  */
564 31 lampret
void uart_reset()
565
{
566 355 markom
  int i;
567 997 markom
  if (config.sim.verbose && config.nuarts) PRINTF("Resetting %u UART(s).\n", config.nuarts);
568 355 markom
  memset(uarts, 0, sizeof(uarts));
569 261 markom
 
570 355 markom
  for(i = 0; i < config.nuarts; i++) {
571 341 markom
    if (config.uarts[i].vapi_id) {
572
      if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
573
        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);
574
        config.uarts[i].vapi_id = 0;
575
      } else {
576 355 markom
        vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
577 970 simons
        register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
578 355 markom
      }
579 1073 rprescott
    } else if (config.uarts[i].channel[0]) { /* MM: Try to create stream.  */
580
      if(channels[i])
581
        channel_close(channels[i]);
582
      else
583
        channels[i] = channel_init(config.uarts[i].channel);
584
      if(channel_open(channels[i]) < 0) {
585
        debug (0, "WARNING: UART%d has problems with channel \"%s\".\n", i, config.uarts[i].channel);
586 355 markom
        continue;
587
      }
588 1073 rprescott
      if (config.sim.verbose)
589 997 markom
        PRINTF("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
590 970 simons
      register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
591 1073 rprescott
    } else {
592
        debug (0, "WARNING: UART%d has no vapi nor channel specified\n", i);
593
        continue;
594 341 markom
    }
595
 
596
    if (config.uarts[i].uart16550)
597
      uarts[i].fifo_len = 16;
598
    else
599
      uarts[i].fifo_len = 1;
600 344 markom
 
601 341 markom
    uarts[i].istat.rxbuf_head = uarts[i].istat.rxbuf_tail = 0;
602
    uarts[i].istat.txbuf_head = uarts[i].istat.txbuf_tail = 0;
603 344 markom
 
604 409 markom
    uarts[i].istat.break_set = 0;
605
    uarts[i].istat.timeout_count = 0;
606 492 markom
    uarts[i].istat.thre_int = 1; /* FIFO is empty at start */
607 713 markom
    uarts[i].slowdown = UART_FGETC_SLOWDOWN;
608 492 markom
 
609 344 markom
    uarts[i].regs.lcr = UART_LCR_RESET;
610 385 markom
    uarts[i].vapi.cur_break = uarts[i].vapi.cur_break_cnt = uarts[i].vapi.next_break = 0;
611
    uarts[i].vapi.next_break_cnt = -1;
612 997 markom
    PRINTF ("%i\n", i);
613 884 markom
    SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
614 336 markom
  }
615 31 lampret
}
616 261 markom
 
617 31 lampret
/* Print register values on stdout. */
618
void uart_status()
619
{
620 355 markom
  int i, j;
621
 
622
  for(i = 0; i < config.nuarts; i++) {
623
    if ( !config.uarts[i].baseaddr )
624
      continue;
625 997 markom
    PRINTF("\nUART%d visible registers at 0x%.8x:\n", i, config.uarts[i].baseaddr);
626
    PRINTF("RXBUF:");
627 355 markom
    for (j = uarts[i].istat.rxbuf_head; j != uarts[i].istat.rxbuf_tail; j = (j + 1) % uarts[i].fifo_len)
628 997 markom
      PRINTF (" %.2x", uarts[i].regs.rxbuf[j]);
629
    PRINTF("  TXBUF: %.2x\n", uarts[i].regs.txbuf);
630
    PRINTF("DLL  : %.2x  DLH  : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
631
    PRINTF("IER  : %.2x  IIR  : %.2x\n", uarts[i].regs.ier, uarts[i].regs.iir);
632
    PRINTF("LCR  : %.2x  MCR  : %.2x\n", uarts[i].regs.lcr, uarts[i].regs.mcr);
633
    PRINTF("LSR  : %.2x  MSR  : %.2x\n", uarts[i].regs.lsr, uarts[i].regs.msr);
634
    PRINTF("SCR  : %.2x\n", uarts[i].regs.scr);
635 31 lampret
 
636 997 markom
    PRINTF("\nInternal registers (sim debug):\n");
637
    PRINTF("RXSER: %.2x  TXSER: %.2x\n", uarts[i].iregs.rxser, uarts[i].iregs.txser);
638 31 lampret
 
639 997 markom
    PRINTF("\nInternal status (sim debug):\n");
640
    PRINTF("char_clks: %d\n", uarts[i].char_clks);
641
    PRINTF("rxser_clks: %d  txser_clks: %d\n", uarts[i].istat.rxser_clks, uarts[i].istat.txser_clks);
642
    PRINTF("rxser: %d  txser: %d\n", uarts[i].istat.rxser_full, uarts[i].istat.txser_full);
643
    PRINTF("rxbuf: %d  txbuf: %d\n", uarts[i].istat.rxbuf_full, uarts[i].istat.txbuf_full);
644
    PRINTF("Using IRQ%i\n", config.uarts[i].irq);
645 336 markom
    if (config.uarts[i].vapi_id)
646 997 markom
      PRINTF ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
647 1073 rprescott
    /* TODO: replace by a channel_status
648 336 markom
    else
649 997 markom
      PRINTF("RX fs: %p  TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
650 1073 rprescott
    */
651 355 markom
  }
652 31 lampret
}

powered by: WebSVN 2.1.0

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