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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_34/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 1390

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 1350 nogj
#include "config.h"
35
 
36
#ifdef HAVE_INTTYPES_H
37
#include <inttypes.h>
38
#endif
39
 
40
#include "port.h"
41
#include "arch.h"
42 235 erez
#include "abstract.h"
43 31 lampret
#include "16450.h"
44
#include "sim-config.h"
45 102 lampret
#include "pic.h"
46 336 markom
#include "vapi.h"
47 805 markom
#include "sched.h"
48 1073 rprescott
#include "channel.h"
49 1308 phoenix
#include "debug.h"
50 31 lampret
 
51 409 markom
#define MIN(a,b) ((a) < (b) ? (a) : (b))
52
 
53 31 lampret
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
54
   before a single character is transmitted or received. */
55 355 markom
static unsigned long char_clks(int dll, int dlh, int lcr)
56 31 lampret
{
57 409 markom
  float bauds_per_char = 1.;
58 806 markom
  unsigned long char_clks = ((dlh << 8) + dll);
59 355 markom
 
60
  if (lcr & UART_LCR_PARITY)
61
    bauds_per_char = bauds_per_char + 1.;
62 31 lampret
 
63 355 markom
  /* stop bits 1 or two */
64
  if (lcr & UART_LCR_STOP)
65
    bauds_per_char = bauds_per_char + 2.;
66
  else
67
    if ((lcr & 0x3) != 0)
68
      bauds_per_char = bauds_per_char + 1.;
69
    else
70
      bauds_per_char = bauds_per_char + 1.5;
71
 
72
  bauds_per_char = bauds_per_char + (5. + (lcr & 0x3));
73
 
74
  return char_clks * bauds_per_char;
75 31 lampret
}
76
 
77
/* Set a specific UART register with value. */
78 1359 nogj
void uart_write_byte(oraddr_t addr, uint32_t value, void *dat)
79 31 lampret
{
80 1367 nogj
  struct dev_16450 *uart = dat;
81 355 markom
 
82 1350 nogj
  debug(4, "uart_write_byte(%"PRIxADDR",%02"PRIx32")\n", addr, value);
83 341 markom
 
84 1367 nogj
  if (uart->regs.lcr & UART_LCR_DLAB) {
85 355 markom
    switch (addr % UART_ADDR_SPACE) {
86
      case UART_DLL:
87 1367 nogj
        uart->regs.dll = value;
88
        uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
89 355 markom
        return;
90
      case UART_DLH:
91 1367 nogj
        uart->regs.dlh = value;
92 355 markom
        return;
93
    }
94
  }
95
 
96
  switch (addr % UART_ADDR_SPACE) {
97
    case UART_TXBUF:
98 1367 nogj
      if (uart->istat.txbuf_full < uart->fifo_len) {
99
        uart->istat.txbuf_full++;
100
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
101
        uart->istat.txbuf_head = (uart->istat.txbuf_head + 1) % uart->fifo_len;
102 355 markom
      } else
103 1367 nogj
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
104 341 markom
 
105 1367 nogj
      uart->regs.lsr &= ~(UART_LSR_TXSERE | UART_LSR_TXBUFE);
106
      if (uart->regs.iir & UART_IIR_THRI)
107
        uart->istat.thre_int = 0;
108 355 markom
      break;
109 409 markom
    case UART_FCR:
110 1367 nogj
      uart->regs.fcr = value & UART_VALID_FCR;
111
      if ((uart->fifo_len == 1 && (value & UART_FCR_FIE))
112
       || (uart->fifo_len != 1 && !(value & UART_FCR_FIE)))
113 409 markom
        value |= UART_FCR_RRXFI | UART_FCR_RTXFI;
114 1367 nogj
      uart->fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
115 409 markom
      if (value & UART_FCR_RTXFI) {
116 1367 nogj
        uart->istat.txbuf_head = uart->istat.txbuf_tail = 0;
117
        uart->istat.txbuf_full = 0;
118
        uart->regs.lsr |= UART_LSR_TXBUFE;
119 1145 sfurman
 
120
        // For FIFO-mode only, THRE interrupt is set when THR and FIFO are empty
121 1367 nogj
        uart->istat.thre_int = (uart->fifo_len == 16);
122 409 markom
      }
123
      if (value & UART_FCR_RRXFI) {
124 1367 nogj
        uart->istat.rxbuf_head = uart->istat.rxbuf_tail = 0;
125
        uart->istat.rxbuf_full = 0;
126
        uart->regs.lsr &= ~UART_LSR_RDRDY;
127 409 markom
      }
128
      break;
129 355 markom
    case UART_IER:
130 1367 nogj
      uart->regs.ier = value & UART_VALID_IER;
131 355 markom
      break;
132
    case UART_LCR:
133 1367 nogj
      uart->regs.lcr = value & UART_VALID_LCR;
134
      uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
135 355 markom
      break;
136
    case UART_MCR:
137 1367 nogj
      uart->regs.mcr = value & UART_VALID_MCR;
138 355 markom
      break;
139
    case UART_SCR:
140 1367 nogj
      uart->regs.scr = value;
141 355 markom
      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 1359 nogj
uint32_t uart_read_byte(oraddr_t addr, void *dat)
149 31 lampret
{
150 1367 nogj
  struct dev_16450 *uart = dat;
151 1350 nogj
  uint8_t value = 0;
152 355 markom
 
153 1350 nogj
  debug(4, "uart_read_byte(%"PRIxADDR")", addr);
154 355 markom
 
155 1367 nogj
  if (uart->regs.lcr & UART_LCR_DLAB) {
156 355 markom
    switch (addr % UART_ADDR_SPACE) {
157
      case UART_DLL:
158 1367 nogj
        value = uart->regs.dll;
159 1350 nogj
        debug(4, "= %"PRIx8"\n", value);
160 355 markom
        return value;
161
      case UART_DLH:
162 1367 nogj
        value = uart->regs.dlh;
163 1350 nogj
        debug(4, "= %"PRIx8"\n", value);
164 355 markom
        return value;
165
    }
166
  }
167
 
168
  switch (addr % UART_ADDR_SPACE) {
169
    case UART_RXBUF:
170 409 markom
      { /* Print out FIFO for debugging */
171
        int i;
172 1367 nogj
        debug(4, "(%i/%i,%i,%i:", uart->istat.rxbuf_full, uart->fifo_len,
173
                  uart->istat.rxbuf_head, uart->istat.rxbuf_tail);
174
        for (i = 0; i < uart->istat.rxbuf_full; i++)
175
          debug(4, "%02x ", uart->regs.rxbuf[(uart->istat.rxbuf_tail + i) % uart->fifo_len]);
176 409 markom
        debug(4, ")");
177
      }
178 1367 nogj
      if (uart->istat.rxbuf_full) {
179
        value = uart->regs.rxbuf[uart->istat.rxbuf_tail];
180
        uart->istat.rxbuf_tail = (uart->istat.rxbuf_tail + 1) % uart->fifo_len;
181
        uart->istat.rxbuf_full--;
182 355 markom
      }
183
 
184 1367 nogj
      if (uart->istat.rxbuf_full)
185
        uart->regs.lsr |= UART_LSR_RDRDY;
186 355 markom
      else
187 1367 nogj
        uart->regs.lsr &= ~UART_LSR_RDRDY;
188 409 markom
 
189 1367 nogj
      uart->istat.timeout_count = 0;
190 355 markom
      break;
191
    case UART_IER:
192 1367 nogj
      value = uart->regs.ier & UART_VALID_IER;
193 355 markom
      break;
194
    case UART_IIR:
195 1367 nogj
      value = (uart->regs.iir & UART_VALID_IIR) | 0xc0;
196
      if (uart->regs.iir & UART_IIR_THRI)
197
        uart->istat.thre_int = 0;
198 355 markom
      break;
199
    case UART_LCR:
200 1367 nogj
      value = uart->regs.lcr & UART_VALID_LCR;
201 355 markom
      break;
202
    case UART_MCR:
203
      value = 0;
204
      break;
205
    case UART_LSR:
206 1367 nogj
      value = uart->regs.lsr & UART_VALID_LSR;
207
      uart->regs.lsr &=
208 409 markom
        ~(UART_LSR_OVRRUN | UART_LSR_BREAK | UART_LSR_PARITY
209
         | UART_LSR_FRAME | UART_LSR_RXERR);
210 355 markom
      break;
211
    case UART_MSR:
212 1367 nogj
      value = uart->regs.msr & UART_VALID_MSR;
213
      uart->regs.msr = 0;
214 355 markom
      break;
215
    case UART_SCR:
216 1367 nogj
      value = uart->regs.scr;
217 355 markom
      break;
218
    default:
219 1350 nogj
      debug(1, "read out of range (addr %"PRIxADDR")\n", addr);
220 355 markom
  }
221 1350 nogj
  debug(4, " = %"PRIx8"\n", value);
222 355 markom
  return value;
223 31 lampret
}
224
 
225 336 markom
/* Function that handles incoming VAPI data.  */
226 1366 nogj
void uart_vapi_read (unsigned long id, unsigned long data, void *dat)
227 336 markom
{
228 1367 nogj
  struct dev_16450 *uart = dat;
229 1350 nogj
  debug(4, "UART: id %08lx, data %08lx\n", id, data);
230 1367 nogj
  uart->vapi_buf[uart->vapi_buf_head_ptr] = data;
231
  uart->vapi_buf_head_ptr = (uart->vapi_buf_head_ptr + 1) % UART_VAPI_BUF_LEN;
232
  if (uart->vapi_buf_tail_ptr == uart->vapi_buf_head_ptr) {
233 341 markom
    fprintf (stderr, "FATAL: uart VAPI buffer to small.\n");
234
    exit (1);
235
  }
236
}
237 336 markom
 
238 1367 nogj
static void send_char (struct dev_16450 *uart, int bits_send)
239 409 markom
{
240 1367 nogj
  PRINTF ("%c", (char)uart->iregs.txser);
241
  debug(4, "TX \'%c\' via UART at %"PRIxADDR"...\n", (char)uart->iregs.txser,
242
        uart->baseaddr);
243
  if (uart->regs.mcr & UART_MCR_LOOP)
244
    uart->iregs.loopback = uart->iregs.txser;
245 409 markom
  else {
246
    /* Send to either VAPI or to file */
247 1367 nogj
    if (uart->vapi_id) {
248 409 markom
      int par, pe, fe, nbits;
249
      int j, data;
250
      unsigned long packet = 0;
251
 
252 1367 nogj
      nbits = MIN (bits_send, (uart->regs.lcr & UART_LCR_WLEN8) + 5);
253 409 markom
      /* Encode a packet */
254 1367 nogj
      packet = uart->iregs.txser & ((1 << nbits) - 1);
255 409 markom
 
256
      /* Calculate parity */
257
      for (j = 0, par = 0; j < nbits; j++)
258
        par ^= (packet >> j) & 1;
259
 
260 1367 nogj
      if (uart->regs.lcr & UART_LCR_PARITY) {
261
        if (uart->regs.lcr & UART_LCR_SPAR) {
262 409 markom
          packet |= 1 << nbits;
263
        } else {
264 1367 nogj
          if (uart->regs.lcr & UART_LCR_EPAR)
265 409 markom
            packet |= par << nbits;
266
          else
267
            packet |= (par ^ 1) << nbits;
268
        }
269
        nbits++;
270
      }
271
      packet |= 1 << (nbits++);
272 1367 nogj
      if (uart->regs.lcr & UART_LCR_STOP)
273 409 markom
        packet |= 1 << (nbits++);
274
 
275
      /* Decode a packet */
276 1367 nogj
      nbits = (uart->vapi.lcr & UART_LCR_WLEN8) + 5;
277 409 markom
      data = packet & ((1 << nbits) - 1);
278
 
279
      /* Calculate parity, including parity bit */
280
      for (j = 0, par = 0; j < nbits + 1; j++)
281
        par ^= (packet >> j) & 1;
282
 
283 1367 nogj
      if (uart->vapi.lcr & UART_LCR_PARITY) {
284
        if (uart->vapi.lcr & UART_LCR_SPAR) {
285 409 markom
          pe = !((packet >> nbits) & 1);
286
        } else {
287 1367 nogj
          if (uart->vapi.lcr & UART_LCR_EPAR)
288 409 markom
            pe = par != 0;
289
          else
290
            pe = par != 1;
291
        }
292
        nbits++;
293
      } else
294
        pe = 0;
295
 
296
      fe = ((packet >> (nbits++)) & 1) ^ 1;
297 1367 nogj
      if (uart->vapi.lcr & UART_LCR_STOP)
298 409 markom
        fe |= ((packet >> (nbits++)) & 1) ^ 1;
299
 
300 1367 nogj
      debug (4, "lcr vapi %02x, uart %02x\n", uart->vapi.lcr, uart->regs.lcr);
301
      data |= (uart->vapi.lcr << 8) | (pe << 16) | (fe << 17) | (uart->vapi.lcr << 8);
302
      PRINTF ("vapi_send (%08lx, %08x)\n", uart->vapi_id, data);
303
      debug (4, "vapi_send (%08lx, %08x)\n", uart->vapi_id, data);
304
      vapi_send (uart->vapi_id, data);
305 409 markom
    } else {
306 1367 nogj
      char buffer[1] = { uart->iregs.txser & 0xFF };
307
      channel_write(uart->channel, buffer, 1);
308 409 markom
    }
309
  }
310 1367 nogj
  uart->istat.txser_full = 0;
311
  uart->istat.txser_clks = 0;
312 409 markom
}
313
 
314 411 markom
/* Adds a character to the FIFO */
315
 
316 1367 nogj
void uart_add_char (struct dev_16450 *uart, int ch)
317 411 markom
{
318 1367 nogj
  if (uart->istat.rxbuf_full + 1 > uart->fifo_len)
319
    uart->regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR;
320 411 markom
  else {
321
    debug(4, "add %02x\n", ch);
322 1367 nogj
    uart->regs.rxbuf[uart->istat.rxbuf_head] = ch;
323
    uart->istat.rxbuf_head = (uart->istat.rxbuf_head + 1) % uart->fifo_len;
324
    uart->istat.rxbuf_full++;
325 411 markom
  }
326 1367 nogj
  uart->regs.lsr |= UART_LSR_RDRDY;
327
  uart->istat.timeout_count = 0;
328 411 markom
}
329
 
330 806 markom
/* Simulation hook. Must be called every clock cycle to simulate all UART
331
   devices. It does internal functional UART simulation. */
332 1367 nogj
void uart_clock16 (void *dat)
333 806 markom
{
334 1367 nogj
  struct dev_16450 *uart = dat;
335 806 markom
  int retval;
336 1073 rprescott
 
337 821 markom
  /* Schedule for later */
338 1390 nogj
  SCHED_ADD (uart_clock16, dat, UART_CLOCK_DIVIDER);
339 821 markom
 
340 806 markom
  /* If VAPI is not selected, UART communicates with two file streams;
341
     if VAPI is selected, we use VAPI streams.  */
342
  /* if txfs is corrupted, skip this uart. */
343 1367 nogj
  if (!uart->vapi_id && !channel_ok(uart->channel)) return;
344 806 markom
 
345 1367 nogj
  if (uart->vapi.next_break_cnt >= 0)
346
    if (--uart->vapi.next_break_cnt < 0) {
347
      if (!(uart->vapi.cur_break = uart->vapi.next_break))
348
        uart->istat.break_set = 0;
349 806 markom
    }
350 821 markom
 
351 806 markom
  /***************** Transmit *****************/
352 1367 nogj
  if (!uart->istat.txser_full) {
353
//      uart->regs.lsr |= UART_LSR_TXBUFE;
354
    if (uart->istat.txbuf_full) {
355
      uart->iregs.txser = uart->regs.txbuf[uart->istat.txbuf_tail];
356
      uart->istat.txbuf_tail = (uart->istat.txbuf_tail + 1) % uart->fifo_len;
357
      uart->istat.txser_full = 1;
358
      uart->istat.txbuf_full--;
359
      uart->regs.lsr &= ~UART_LSR_TXSERE;
360 1143 sfurman
 
361
      // When UART is in either character mode, i.e. 16450 emulation mode, or FIFO mode,
362
      // the THRE interrupt is raised when THR transitions from full to empty.
363 1367 nogj
      if (!uart->istat.txbuf_full) {
364
        uart->istat.thre_int = 1;
365
        uart->regs.lsr |= UART_LSR_TXBUFE;
366 1143 sfurman
      }
367 806 markom
    } else {
368 1367 nogj
      uart->regs.lsr |= UART_LSR_TXSERE;
369 806 markom
    }
370 1367 nogj
  } else if (uart->char_clks <= uart->istat.txser_clks++) {
371
    send_char(uart, (uart->regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
372 806 markom
  } else {
373
    /* We are still sending char here*/
374
 
375
    /* Check if we set the break bit */
376 1367 nogj
    if (uart->regs.lcr & UART_LCR_SBC) {
377
      if (!uart->vapi.break_sent) {
378 806 markom
#if 0
379
        /* Send broken frame */
380 1367 nogj
        int nbits_sent = ((uart->regs.lcr & UART_LCR_WLEN8) + 5) * (uart->istat.txser_clks - 1) / uart->char_clks;
381 806 markom
        send_char(i, nbits_sent);
382
#endif
383
        /* Send one break signal */
384 1367 nogj
        vapi_send (uart->vapi_id, UART_LCR_SBC << 8);
385
        uart->vapi.break_sent = 1;
386 806 markom
      }
387
      /* mark as character was sent */
388 1367 nogj
      uart->istat.txser_full = 0;
389
      uart->istat.txser_clks = 0;
390 806 markom
    } else
391 1367 nogj
      uart->vapi.break_sent = 0;
392 1143 sfurman
 
393 806 markom
  }
394 1143 sfurman
 
395 806 markom
  /***************** Receive *****************/
396
 
397
  /* Is there a break? */
398 1367 nogj
  if (uart->vapi.cur_break) {
399
    uart->vapi.cur_break_cnt++;
400
    if (uart->vapi.cur_break_cnt > UART_BREAK_COUNT * uart->vapi.char_clks) {
401
      if (!uart->istat.break_set) {
402 806 markom
        unsigned lsr;
403 1367 nogj
        uart->istat.break_set = 1;
404 806 markom
        lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
405 1367 nogj
        PRINTF ("[%x]\n", uart->regs.lsr);
406
        uart->istat.rxser_full = 0;
407
        uart->istat.rxser_clks = 0;
408
        uart_add_char (uart, lsr << 8);
409 806 markom
      } else
410 1367 nogj
        uart->vapi.cur_break_cnt = 0;
411 806 markom
    }
412 1367 nogj
    if (uart->istat.rxser_full) {
413
      uart->istat.rxser_full = 0;
414
      uart->istat.rxser_clks = 0;
415 806 markom
    }
416
  } else {
417 1367 nogj
    if (uart->istat.rxser_full) {
418
      if (uart->char_clks <= uart->istat.rxser_clks++) {
419 806 markom
        /* Set unused character bits to zero and allow lsr register in fifo */
420 1367 nogj
        uart->iregs.rxser &= ((1 << ((uart->regs.lcr & 3) + 5)) - 1) | 0xff00;
421
        debug(4, "Receiving 0x%02lx'%c' via UART (at %"PRIxADDR"...\n",
422
              uart->iregs.rxser, (char)uart->iregs.rxser, uart->baseaddr);
423
        PRINTF ("%c", (char)uart->iregs.rxser);
424
        uart->istat.rxser_full = 0;
425
        uart->istat.rxser_clks = 0;
426
        uart_add_char (uart, uart->iregs.rxser);
427 806 markom
      }
428
    }
429
  }
430
 
431
  /* Check if there is something waiting, and put it into rxser */
432 1367 nogj
  if (uart->regs.mcr & UART_MCR_LOOP) {
433
    uart->iregs.rxser = uart->iregs.loopback;
434
    uart->istat.rxser_full = 1;
435 806 markom
  } else {
436 1367 nogj
    if (!uart->vapi_id) {
437
      if(uart->istat.rxser_full == 0) {
438
        if (uart->slowdown)
439
          uart->slowdown--;
440 1073 rprescott
        else {
441
          char buffer[1];
442 1367 nogj
          retval = channel_read(uart->channel, buffer, 1);
443 1073 rprescott
          if(retval < 0)
444 1367 nogj
                  perror(uart->channel_str);
445 1073 rprescott
          else if(retval > 0) {
446 1367 nogj
            uart->iregs.rxser = (unsigned char)buffer[0];
447
            uart->istat.rxser_full = 1;
448 1073 rprescott
          } else
449 1367 nogj
            uart->slowdown = UART_FGETC_SLOWDOWN;
450 1073 rprescott
        }
451 806 markom
      }
452
    } else { /* VAPI */
453
      int received = 0;
454
      /* do not handle commands while receiving */
455 1367 nogj
      if (uart->istat.rxser_full) return;
456 806 markom
      while (!received) {
457 1367 nogj
        if (uart->vapi_buf_head_ptr != uart->vapi_buf_tail_ptr) {
458
          unsigned long data = uart->vapi_buf[uart->vapi_buf_tail_ptr];
459
          debug(4, "Handling: %08lx (%i,%i)\n", data, uart->vapi_buf_head_ptr,
460
                uart->vapi_buf_tail_ptr);
461
          uart->vapi_buf_tail_ptr = (uart->vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
462 806 markom
          switch (data >> 24) {
463
            case 0x00:
464 1367 nogj
              uart->vapi.lcr = (data >> 8) & 0xff;
465 806 markom
              /* Put data into rx fifo */
466 1367 nogj
              uart->iregs.rxser = data & 0xff;
467
              uart->vapi.char_clks = char_clks (uart->vapi.dll, uart->vapi.dlh, uart->vapi.lcr);
468
              if ((uart->vapi.lcr & ~UART_LCR_SBC) != (uart->regs.lcr & ~UART_LCR_SBC)
469
               || uart->vapi.char_clks != uart->char_clks
470
               || uart->vapi.skew < -MAX_SKEW || uart->vapi.skew > MAX_SKEW) {
471 806 markom
                debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
472 1367 nogj
                      uart->vapi.lcr & ~UART_LCR_SBC, uart->regs.lcr & ~UART_LCR_SBC);
473 806 markom
                /* Set error bits */
474 1367 nogj
                uart->iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
475
                if (uart->regs.lcr & UART_LCR_PARITY) uart->iregs.rxser |= UART_LSR_PARITY << 8;
476 806 markom
              }
477 1367 nogj
              uart->istat.rxser_full = 1;
478 806 markom
              received = 1;
479
              break;
480
            case 0x01:
481 1367 nogj
              uart->vapi.dll = (data >> 0) & 0xff;
482
              uart->vapi.dlh = (data >> 8) & 0xff;
483 806 markom
              break;
484
            case 0x02:
485 1367 nogj
              uart->vapi.lcr = (data >> 8) & 0xff;
486 806 markom
              break;
487
            case 0x03:
488 1367 nogj
              uart->vapi.skew = (signed short)(data & 0xffff);
489 806 markom
              break;
490
            case 0x04:
491 1367 nogj
              uart->vapi.next_break_cnt = data & 0xffff;
492
              uart->vapi.next_break = (data >> 16) & 1;
493 806 markom
              break;
494
            default:
495 1350 nogj
              debug (0, "WARNING: Invalid vapi command %02lx\n", data >> 24);
496 806 markom
              break;
497
          }
498
        } else break;
499
      }
500
    }
501
  }
502
 
503
  /***************** Loopback *****************/
504 1367 nogj
  if (uart->regs.mcr & UART_MCR_LOOP) {
505 806 markom
    debug(5, "uart_clock: Loopback\n");
506 1367 nogj
    if ((uart->regs.mcr & UART_MCR_AUX2) !=
507
        ((uart->regs.msr & UART_MSR_DCD) >> 4))
508
      uart->regs.msr |= UART_MSR_DDCD;
509
    if ((uart->regs.mcr & UART_MCR_AUX1) <
510
        ((uart->regs.msr & UART_MSR_RI) >> 4))
511
      uart->regs.msr |= UART_MSR_TERI;
512
    if ((uart->regs.mcr & UART_MCR_RTS) !=
513
        ((uart->regs.msr & UART_MSR_CTS) >> 3))
514
      uart->regs.msr |= UART_MSR_DCTS;
515
    if ((uart->regs.mcr & UART_MCR_DTR) !=
516
        ((uart->regs.msr & UART_MSR_DSR) >> 5))
517
      uart->regs.msr |= UART_MSR_DDSR;
518
    uart->regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
519 806 markom
              | UART_MSR_DSR | UART_MSR_CTS);
520 1367 nogj
    uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX2) << 4);
521
    uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX1) << 4);
522
    uart->regs.msr |= ((uart->regs.mcr & UART_MCR_RTS) << 3);
523
    uart->regs.msr |= ((uart->regs.mcr & UART_MCR_DTR) << 5);
524 806 markom
  }
525
 
526 1367 nogj
  if (uart->regs.lsr & UART_LSR_RDRDY)
527
    uart->istat.timeout_count++;
528 806 markom
 
529
  /* Update LSR error bits from the ones from rx FIFO */
530 1367 nogj
  if (uart->istat.rxbuf_full) {
531
    uart->regs.lsr |= uart->regs.rxbuf[uart->istat.rxbuf_tail] >> 8;
532 806 markom
    /* we must delete the lsr status, so that we can clear it from lsr */
533 1367 nogj
    uart->regs.rxbuf[uart->istat.rxbuf_tail] &= 0xff;
534 806 markom
  }
535
 
536
  /* Interrupt detection in proper priority order. */
537 1367 nogj
  uart->regs.iir = UART_IIR_NO_INT;
538
  if (uart->regs.ier & UART_IER_RLSI &&                    /* Receiver LS */
539
      uart->regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
540 806 markom
        | UART_LSR_FRAME | UART_LSR_BREAK)) {
541 1367 nogj
    uart->regs.iir = UART_IIR_RLSI;
542
  } else if ((uart->regs.ier & UART_IER_RDI)               /* RD available */
543
      && (uart->istat.rxbuf_full >= UART_FIFO_TRIGGER(uart->regs.fcr >> 6))
544
      && (uart->regs.lsr & UART_LSR_RDRDY)) {
545
    uart->regs.iir = UART_IIR_RDI;
546
  } else if ((uart->regs.ier & UART_IER_RDI)               /* timeout */
547
      && (uart->istat.timeout_count >= UART_CHAR_TIMEOUT * uart->char_clks)
548
      && (uart->istat.rxbuf_head != uart->istat.rxbuf_tail)) {
549
    uart->regs.iir = UART_IIR_CTI;
550
  } else if (uart->regs.ier & UART_IER_THRI &&             /* Transm. empty */
551
      uart->istat.thre_int == 1) {
552
    uart->regs.iir = UART_IIR_THRI;
553
  } else if (uart->regs.ier & UART_IER_MSI &&              /* Modem status */
554
      uart->regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
555 806 markom
        | UART_MSR_TERI | UART_MSR_DDCD)) {
556 1367 nogj
    uart->regs.iir = UART_IIR_MSI;
557 806 markom
  }
558 1367 nogj
  if (!(uart->regs.iir & UART_IIR_NO_INT)) {
559
    debug (4, "uart->regs.iir = %i\t", uart->regs.iir);
560
    report_interrupt(uart->irq);
561 806 markom
  }
562
}
563
 
564 341 markom
/* Reset.  It initializes all registers of all UART devices to zero values,
565 31 lampret
   (re)opens all RX/TX file streams and places devices in memory address
566 341 markom
   space.  */
567 1367 nogj
void uart_reset(void *dat)
568 31 lampret
{
569 1367 nogj
  struct dev_16450 *uart = dat;
570 261 markom
 
571 1367 nogj
  if (uart->channel_str && uart->channel_str[0]) { /* Try to create stream. */
572
    if(uart->channel)
573
      channel_close(uart->channel);
574 341 markom
    else
575 1367 nogj
      uart->channel = channel_init(uart->channel_str);
576
    if(channel_open(uart->channel) < 0) {
577
      debug (0, "WARNING: UART has problems with channel \"%s\".\n", uart->channel_str);
578
    } else if (config.sim.verbose)
579
      PRINTF("UART at 0x%"PRIxADDR" uses ", uart->baseaddr);
580
  } else {
581
    debug (0, "WARNING: UART at %"PRIxADDR" has no vapi nor channel specified\n", uart->baseaddr);
582
  }
583 344 markom
 
584 1367 nogj
  if (uart->uart16550)
585
    uart->fifo_len = 16;
586
  else
587
    uart->fifo_len = 1;
588 1145 sfurman
 
589 1367 nogj
  uart->istat.rxbuf_head = uart->istat.rxbuf_tail = 0;
590
  uart->istat.txbuf_head = uart->istat.txbuf_tail = 0;
591
 
592
  uart->istat.txser_full = uart->istat.rxser_full = 0;
593
  uart->istat.txbuf_full = uart->istat.rxbuf_full = 0;
594 1145 sfurman
 
595 1367 nogj
  uart->istat.txser_clks = uart->istat.rxser_clks = 0;
596 492 markom
 
597 1367 nogj
  uart->istat.thre_int = 0;
598
  uart->istat.break_set = 0;
599
  uart->istat.timeout_count = 0;
600
 
601
  // For FIFO-mode only, THRE interrupt is set when both THR and FIFO are empty
602
  uart->istat.thre_int = (uart->fifo_len == 16);
603
 
604
  uart->char_clks = 0;
605
  uart->slowdown = UART_FGETC_SLOWDOWN;
606
 
607
  uart->iregs.txser = 0;
608
  uart->iregs.rxser = 0;
609
  uart->iregs.loopback = 0;
610
 
611
  memset(uart->regs.txbuf, 0, sizeof(uart->regs.txbuf));
612
  memset(uart->regs.rxbuf, 0, sizeof(uart->regs.rxbuf));
613
 
614
  uart->regs.lcr = UART_LCR_RESET;
615
  uart->regs.dll = 0;
616
  uart->regs.dlh = 0;
617
  uart->regs.ier = 0;
618
  uart->regs.iir = 0;
619
  uart->regs.fcr = 0;
620
  uart->regs.lcr = UART_LCR_RESET;
621
  uart->regs.mcr = 0;
622
  uart->regs.lsr = 0;
623
  uart->regs.msr = 0;
624
  uart->regs.scr = 0;
625
 
626
  uart->vapi.cur_break = uart->vapi.cur_break_cnt = uart->vapi.next_break = 0;
627
  uart->vapi.next_break_cnt = -1;
628
  uart->vapi.break_sent = 0;
629
  uart->vapi.skew = 0;
630
  uart->vapi.lcr = 0;
631
  uart->vapi.dll = 0;
632
  uart->vapi.char_clks = 0;
633
 
634
  uart->vapi_buf_head_ptr = 0;
635
  uart->vapi_buf_tail_ptr = 0;
636
  memset(uart->vapi_buf, 0, sizeof(uart->vapi_buf));
637
 
638 1390 nogj
  SCHED_ADD (uart_clock16, dat, UART_CLOCK_DIVIDER);
639 31 lampret
}
640 261 markom
 
641 31 lampret
/* Print register values on stdout. */
642 1367 nogj
void uart_status(void *dat)
643 31 lampret
{
644 1367 nogj
  struct dev_16450 *uart = dat;
645
  int i;
646 355 markom
 
647 1367 nogj
  PRINTF("\nUART visible registers at 0x%"PRIxADDR":\n", uart->baseaddr);
648
  PRINTF("RXBUF: ");
649
  for (i = uart->istat.rxbuf_head; i != uart->istat.rxbuf_tail; i = (i + 1) % uart->fifo_len)
650
    PRINTF (" %.2x", uart->regs.rxbuf[i]);
651
  PRINTF("TXBUF: ");
652
  for (i = uart->istat.txbuf_head; i != uart->istat.txbuf_tail; i = (i + 1) % uart->fifo_len)
653
    PRINTF (" %.2x", uart->regs.txbuf[i]);
654
  PRINTF("\n");
655
  PRINTF("DLL  : %.2x  DLH  : %.2x\n", uart->regs.dll, uart->regs.dlh);
656
  PRINTF("IER  : %.2x  IIR  : %.2x\n", uart->regs.ier, uart->regs.iir);
657
  PRINTF("LCR  : %.2x  MCR  : %.2x\n", uart->regs.lcr, uart->regs.mcr);
658
  PRINTF("LSR  : %.2x  MSR  : %.2x\n", uart->regs.lsr, uart->regs.msr);
659
  PRINTF("SCR  : %.2x\n", uart->regs.scr);
660 31 lampret
 
661 1367 nogj
  PRINTF("\nInternal registers (sim debug):\n");
662
  PRINTF("RXSER: %.2lx  TXSER: %.2lx\n", uart->iregs.rxser, uart->iregs.txser);
663 31 lampret
 
664 1367 nogj
  PRINTF("\nInternal status (sim debug):\n");
665
  PRINTF("char_clks: %ld\n", uart->char_clks);
666
  PRINTF("rxser_clks: %ld  txser_clks: %ld\n", uart->istat.rxser_clks,
667
         uart->istat.txser_clks);
668
  PRINTF("rxser: %d  txser: %d\n", uart->istat.rxser_full, uart->istat.txser_full);
669
  PRINTF("rxbuf_full: %d  txbuf_full: %d\n", uart->istat.rxbuf_full, uart->istat.txbuf_full);
670
  PRINTF("Using IRQ%i\n", uart->irq);
671
  if (uart->vapi_id)
672
    PRINTF ("Connected to vapi ID=%lx\n\n", uart->vapi_id);
673
  /* TODO: replace by a channel_status
674
  else
675
    PRINTF("RX fs: %p  TX fs: %p\n\n", uart->rxfs, uart->txfs);
676
  */
677 31 lampret
}
678 1358 nogj
 
679
/*---------------------------------------------------[ UART configuration ]---*/
680
void uart_baseaddr(union param_val val, void *dat)
681
{
682 1367 nogj
  struct dev_16450 *uart = dat;
683
  uart->baseaddr = val.addr_val;
684 1358 nogj
}
685
 
686
void uart_jitter(union param_val val, void *dat)
687
{
688 1367 nogj
  struct dev_16450 *uart = dat;
689
  uart->jitter = val.int_val;
690 1358 nogj
}
691
 
692
void uart_irq(union param_val val, void *dat)
693
{
694 1367 nogj
  struct dev_16450 *uart = dat;
695
  uart->irq = val.int_val;
696 1358 nogj
}
697
 
698
void uart_16550(union param_val val, void *dat)
699
{
700 1367 nogj
  struct dev_16450 *uart = dat;
701
  uart->uart16550 = val.int_val;
702 1358 nogj
}
703
 
704
void uart_channel(union param_val val, void *dat)
705
{
706 1367 nogj
  struct dev_16450 *uart = dat;
707
  if(!(uart->channel_str = strdup(val.str_val))) {
708
    fprintf(stderr, "Peripheral 16450: Run out of memory\n");
709
    exit(-1);
710
  }
711 1358 nogj
}
712
 
713
void uart_newway(union param_val val, void *dat)
714
{
715
  CONFIG_ERROR(" txfile and rxfile and now obsolete.\n\tUse 'channel = \"file:rxfile,txfile\"' instead.");
716
  exit(1);
717
}
718
 
719
void uart_vapi_id(union param_val val, void *dat)
720
{
721 1367 nogj
  struct dev_16450 *uart = dat;
722
  uart->vapi_id = val.int_val;
723 1358 nogj
}
724
 
725 1367 nogj
void *uart_sec_start(void)
726
{
727
  struct dev_16450 *new = malloc(sizeof(struct dev_16450));
728
 
729
  if(!new) {
730
    fprintf(stderr, "Peripheral 16450: Run out of memory\n");
731
    exit(-1);
732
  }
733
 
734
  new->channel_str = NULL;
735
  new->channel = NULL;
736
  new->vapi_id = 0;
737
 
738
  return new;
739
}
740
 
741
void uart_sec_end(void *dat)
742
{
743
  struct dev_16450 *uart = dat;
744
 
745
  if(uart->vapi_id)
746
    vapi_install_handler(uart->vapi_id, uart_vapi_read, dat);
747
  register_memoryarea(uart->baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte,
748
                      uart_write_byte, dat);
749
  reg_sim_reset(uart_reset, dat);
750
  reg_sim_stat(uart_status, dat);
751
}
752
 
753 1358 nogj
void reg_uart_sec(void)
754
{
755 1367 nogj
  struct config_section *sec = reg_config_sec("uart", uart_sec_start,
756
                                              uart_sec_end);
757 1358 nogj
 
758
  reg_config_param(sec, "baseaddr", paramt_addr, uart_baseaddr);
759
  reg_config_param(sec, "irq", paramt_int, uart_irq);
760
  reg_config_param(sec, "16550", paramt_int, uart_16550);
761
  reg_config_param(sec, "jitter", paramt_int, uart_jitter);
762
  reg_config_param(sec, "channel", paramt_str, uart_channel);
763
  reg_config_param(sec, "txfile", paramt_str, uart_newway);
764
  reg_config_param(sec, "rxfile", paramt_str, uart_newway);
765
  reg_config_param(sec, "vapi_id", paramt_int, uart_vapi_id);
766
}

powered by: WebSVN 2.1.0

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