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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc2/] [or1ksim/] [peripheral/] [16450.c] - Blame information for rev 1753

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 1748 jeremybenn
 
3 31 lampret
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4 1748 jeremybenn
   Copyright (C) 2008 Embecosm Limited
5 31 lampret
 
6 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7 31 lampret
 
8 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9 31 lampret
 
10 1748 jeremybenn
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14 31 lampret
 
15 1748 jeremybenn
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19 31 lampret
 
20 1748 jeremybenn
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22 31 lampret
 
23 1748 jeremybenn
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
/* This is functional simulation of 8250/16450/16550 UARTs. Since we RX/TX
27
   data via file streams, we can't simulate modem control lines coming from
28
   the DCE and similar details of communication with the DCE.
29
 
30 31 lampret
   This simulated UART device is intended for basic UART device driver
31
   verification. From device driver perspective this device looks like a
32 1549 nogj
   regular UART but never reports any modem control lines changes (the
33 1748 jeremybenn
   only DCE responses are incoming characters from the file stream). */
34 31 lampret
 
35
 
36 1748 jeremybenn
/* Autoconf and/or portability configuration */
37 1350 nogj
#include "config.h"
38 1748 jeremybenn
#include "port.h"
39 1350 nogj
 
40 1748 jeremybenn
/* System includes */
41
#include <stdlib.h>
42 1350 nogj
 
43 1748 jeremybenn
/* Package includes */
44
#include "sim-config.h"
45 1350 nogj
#include "arch.h"
46 102 lampret
#include "pic.h"
47 1748 jeremybenn
#include "sched.h"
48 336 markom
#include "vapi.h"
49 1073 rprescott
#include "channel.h"
50 1748 jeremybenn
#include "abstract.h"
51
#include "toplevel-support.h"
52
#include "sim-cmd.h"
53 31 lampret
 
54 1392 nogj
 
55 409 markom
#define MIN(a,b) ((a) < (b) ? (a) : (b))
56 1748 jeremybenn
/* Definitions */
57
#define UART_ADDR_SPACE        8        /*!< UART addr space size in bytes */
58
#define UART_MAX_FIFO_LEN     16        /*!< rx FIFO for uart 16550 */
59
#define MAX_SKEW               1        /*!< max. clock skew in subclocks */
60
#define UART_VAPI_BUF_LEN    128        /*!< Size of VAPI command buffer */
61
#define UART_CLOCK_DIVIDER    16        /*!< UART clock divider */
62
#define UART_FGETC_SLOWDOWN  100        /*!< fgetc() slowdown factor */
63 409 markom
 
64 1748 jeremybenn
/*
65
 * Addresses of visible registers
66
 *
67
 */
68
#define UART_RXBUF  0           /* R: Rx buffer, DLAB=0 */
69
#define UART_TXBUF  0           /* W: Tx buffer, DLAB=0 */
70
#define UART_DLL  0             /* R/W: Divisor Latch Low, DLAB=1 */
71
#define UART_DLH  1             /* R/W: Divisor Latch High, DLAB=1 */
72
#define UART_IER  1             /* R/W: Interrupt Enable Register */
73
#define UART_IIR  2             /* R: Interrupt ID Register */
74
#define UART_FCR  2             /* W: FIFO Control Register */
75
#define UART_LCR  3             /* R/W: Line Control Register */
76
#define UART_MCR  4             /* W: Modem Control Register */
77
#define UART_LSR  5             /* R: Line Status Register */
78
#define UART_MSR  6             /* R: Modem Status Register */
79
#define UART_SCR  7             /* R/W: Scratch Register */
80 1499 nogj
 
81 1748 jeremybenn
/*
82
 * R/W masks for valid bits in 8250/16450 (mask out 16550 and later bits)
83
 *
84
 */
85
#define UART_VALID_LCR  0xff
86
#define UART_VALID_LSR  0xff
87
#define UART_VALID_IIR  0x0f
88
#define UART_VALID_FCR  0xc0
89
#define UART_VALID_IER  0x0f
90
#define UART_VALID_MCR  0x1f
91
#define UART_VALID_MSR  0xff
92
 
93
/*
94
 * Bit definitions for the Line Control Register
95
 *
96
 */
97
#define UART_LCR_DLAB 0x80      /* Divisor latch access bit */
98
#define UART_LCR_SBC  0x40      /* Set break control */
99
#define UART_LCR_SPAR 0x20      /* Stick parity (?) */
100
#define UART_LCR_EPAR 0x10      /* Even parity select */
101
#define UART_LCR_PARITY 0x08    /* Parity Enable */
102
#define UART_LCR_STOP 0x04      /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
103
#define UART_LCR_WLEN5  0x00    /* Wordlength: 5 bits */
104
#define UART_LCR_WLEN6  0x01    /* Wordlength: 6 bits */
105
#define UART_LCR_WLEN7  0x02    /* Wordlength: 7 bits */
106
#define UART_LCR_WLEN8  0x03    /* Wordlength: 8 bits */
107
#define UART_LCR_RESET  0x03
108
/*
109
 * Bit definitions for the Line Status Register
110
 */
111
#define UART_LSR_RXERR  0x80    /* Error in rx fifo */
112
#define UART_LSR_TXSERE 0x40    /* Transmitter serial register empty */
113
#define UART_LSR_TXBUFE 0x20    /* Transmitter buffer register empty */
114
#define UART_LSR_BREAK  0x10    /* Break interrupt indicator */
115
#define UART_LSR_FRAME  0x08    /* Frame error indicator */
116
#define UART_LSR_PARITY 0x04    /* Parity error indicator */
117
#define UART_LSR_OVRRUN 0x02    /* Overrun error indicator */
118
#define UART_LSR_RDRDY  0x01    /* Receiver data ready */
119
 
120
/*
121
 * Bit definitions for the Interrupt Identification Register
122
 */
123
#define UART_IIR_NO_INT 0x01    /* No interrupts pending */
124
#define UART_IIR_ID 0x06        /* Mask for the interrupt ID */
125
 
126
#define UART_IIR_MSI  0x00      /* Modem status interrupt (Low priority) */
127
#define UART_IIR_THRI 0x02      /* Transmitter holding register empty */
128
#define UART_IIR_RDI  0x04      /* Receiver data interrupt */
129
#define UART_IIR_RLSI 0x06      /* Receiver line status interrupt (High p.) */
130
#define UART_IIR_CTI  0x0c      /* Character timeout */
131
 
132
/*
133
 * Bit Definitions for the FIFO Control Register
134
 */
135
#define UART_FCR_FIE  0x01      /* FIFO enable */
136
#define UART_FCR_RRXFI 0x02     /* Reset rx FIFO */
137
#define UART_FCR_RTXFI 0x04     /* Reset tx FIFO */
138
#define UART_FIFO_TRIGGER(x) /* Trigger values for indexes 0..3 */\
139
  ((x) == 0 ? 1\
140
  :(x) == 1 ? 4\
141
  :(x) == 2 ? 8\
142
  :(x) == 3 ? 14 : 0)
143
 
144
/*
145
 * Bit definitions for the Interrupt Enable Register
146
 */
147
#define UART_IER_MSI  0x08      /* Enable Modem status interrupt */
148
#define UART_IER_RLSI 0x04      /* Enable receiver line status interrupt */
149
#define UART_IER_THRI 0x02      /* Enable Transmitter holding register int. */
150
#define UART_IER_RDI  0x01      /* Enable receiver data interrupt */
151
 
152
/*
153
 * Bit definitions for the Modem Control Register
154
 */
155
#define UART_MCR_LOOP 0x10      /* Enable loopback mode */
156
#define UART_MCR_AUX2 0x08      /* Auxilary 2  */
157
#define UART_MCR_AUX1 0x04      /* Auxilary 1 */
158
#define UART_MCR_RTS  0x02      /* Force RTS */
159
#define UART_MCR_DTR  0x01      /* Force DTR */
160
 
161
/*
162
 * Bit definitions for the Modem Status Register
163
 */
164
#define UART_MSR_DCD  0x80      /* Data Carrier Detect */
165
#define UART_MSR_RI   0x40      /* Ring Indicator */
166
#define UART_MSR_DSR  0x20      /* Data Set Ready */
167
#define UART_MSR_CTS  0x10      /* Clear to Send */
168
#define UART_MSR_DDCD 0x08      /* Delta DCD */
169
#define UART_MSR_TERI 0x04      /* Trailing edge ring indicator */
170
#define UART_MSR_DDSR 0x02      /* Delta DSR */
171
#define UART_MSR_DCTS 0x01      /* Delta CTS */
172
 
173
/*
174
 * Various definitions
175
 */
176
#define UART_BREAK_COUNT   1    /* # of chars to count when doing break */
177
#define UART_CHAR_TIMEOUT  4    /* # of chars to count when doing timeout int */
178
 
179
 
180
/* Registers */
181
 
182
struct dev_16450
183
{
184
  struct
185
  {
186
    uint8_t   txbuf[UART_MAX_FIFO_LEN];
187
    uint16_t  rxbuf[UART_MAX_FIFO_LEN]; /* Upper 8-bits is the LCR modifier */
188
    uint8_t   dll;
189
    uint8_t   dlh;
190
    uint8_t   ier;
191
    uint8_t   iir;
192
    uint8_t   fcr;
193
    uint8_t   lcr;
194
    uint8_t   mcr;
195
    uint8_t   lsr;
196
    uint8_t   msr;
197
    uint8_t   scr;
198
  } regs;                       /* Visible registers */
199
  struct
200
  {
201
    uint8_t   txser;            /* Character just sending */
202
    uint16_t  rxser;            /* Character just receiving */
203
    uint8_t   loopback;
204
  } iregs;                      /* Internal registers */
205
  struct
206
  {
207
    int           txbuf_head;
208
    int           txbuf_tail;
209
    int           rxbuf_head;
210
    int           rxbuf_tail;
211
    unsigned int  txbuf_full;
212
    unsigned int  rxbuf_full;
213
    int           receiveing;   /* Receiving a char */
214
    int           recv_break;   /* Receiving a break */
215
    int           ints;         /* Which interrupts are pending */
216
  } istat;                      /* Internal status */
217
 
218
  /* Clocks per char */
219
  unsigned long  char_clks;
220
 
221
  /* VAPI internal registers */
222
  struct
223
  {
224
    unsigned long  char_clks;
225
    uint8_t        dll;
226
    uint8_t        dlh;
227
    uint8_t        lcr;
228
    int            skew;
229
  } vapi;
230
 
231
  /* Required by VAPI - circular buffer to store incoming chars, since we
232
     cannothandle them so fast - we are serial. */
233
  unsigned long   vapi_buf[UART_VAPI_BUF_LEN];  /* Buffer */
234
  int             vapi_buf_head_ptr;            /* Where we write to */
235
  int             vapi_buf_tail_ptr;            /* Where we read from */
236
 
237
  /* Length of FIFO, 16 for 16550, 1 for 16450 */
238
  int             fifo_len;
239
 
240
  struct channel *channel;
241
 
242
  /* Configuration */
243
  int             enabled;
244
  int             jitter;
245
  oraddr_t        baseaddr;
246
  int             irq;
247
  unsigned long   vapi_id;
248
  int             uart16550;
249
  char           *channel_str;
250
};
251
 
252
/* Forward declarations of static functions */
253
static void uart_recv_break (void *dat);
254
static void uart_recv_char (void *dat);
255
static void uart_check_char (void *dat);
256
static void uart_sched_recv_check (struct dev_16450 *uart);
257
static void uart_vapi_cmd (void *dat);
258
static void uart_clear_int (struct dev_16450 *uart, int intr);
259
static void uart_tx_send (void *dat);
260
 
261
 
262 1503 nogj
/* Number of clock cycles (one clock cycle is when UART_CLOCK_DIVIDER simulator
263
 * cycles have elapsed) before a single character is transmitted or received. */
264 1748 jeremybenn
static unsigned long
265
char_clks (int dll, int dlh, int lcr)
266 31 lampret
{
267 1396 nogj
  unsigned int bauds_per_char = 2;
268 806 markom
  unsigned long char_clks = ((dlh << 8) + dll);
269 1748 jeremybenn
 
270 355 markom
  if (lcr & UART_LCR_PARITY)
271 1396 nogj
    bauds_per_char += 2;
272 31 lampret
 
273 355 markom
  /* stop bits 1 or two */
274
  if (lcr & UART_LCR_STOP)
275 1396 nogj
    bauds_per_char += 4;
276 1748 jeremybenn
  else if ((lcr & 0x3) != 0)
277
    bauds_per_char += 2;
278 355 markom
  else
279 1748 jeremybenn
    bauds_per_char += 3;
280
 
281 1396 nogj
  bauds_per_char += 10 + ((lcr & 0x3) << 1);
282 355 markom
 
283 1396 nogj
  return (char_clks * bauds_per_char) >> 1;
284 31 lampret
}
285
 
286 1502 nogj
/*---------------------------------------------------[ Interrupt handling ]---*/
287
/* Signals the specified interrupt.  If a higher priority interrupt is already
288
 * pending, do nothing */
289 1748 jeremybenn
static void
290
uart_int_msi (void *dat)
291 1502 nogj
{
292
  struct dev_16450 *uart = dat;
293
 
294
  uart->istat.ints |= 1 << UART_IIR_MSI;
295
 
296 1748 jeremybenn
  if (!(uart->regs.ier & UART_IER_MSI))
297 1502 nogj
    return;
298
 
299 1748 jeremybenn
  if ((uart->regs.iir & UART_IIR_NO_INT) || (uart->regs.iir == UART_IIR_MSI))
300
    {
301
      uart->regs.iir = UART_IIR_MSI;
302
      report_interrupt (uart->irq);
303
    }
304 1502 nogj
}
305
 
306 1748 jeremybenn
static void
307
uart_int_thri (void *dat)
308 1502 nogj
{
309
  struct dev_16450 *uart = dat;
310
 
311
  uart->istat.ints |= 1 << UART_IIR_THRI;
312
 
313 1748 jeremybenn
  if (!(uart->regs.ier & UART_IER_THRI))
314 1502 nogj
    return;
315
 
316 1748 jeremybenn
  if ((uart->regs.iir & UART_IIR_NO_INT) || (uart->regs.iir == UART_IIR_MSI)
317
      || (uart->regs.iir == UART_IIR_THRI))
318
    {
319
      uart->regs.iir = UART_IIR_THRI;
320
      report_interrupt (uart->irq);
321
    }
322 1502 nogj
}
323
 
324 1748 jeremybenn
static void
325
uart_int_cti (void *dat)
326 1502 nogj
{
327
  struct dev_16450 *uart = dat;
328
 
329
  uart->istat.ints |= 1 << UART_IIR_CTI;
330
 
331 1748 jeremybenn
  if (!(uart->regs.ier & UART_IER_RDI))
332 1502 nogj
    return;
333
 
334 1748 jeremybenn
  if ((uart->regs.iir != UART_IIR_RLSI) && (uart->regs.iir != UART_IIR_RDI))
335
    {
336
      uart->regs.iir = UART_IIR_CTI;
337
      report_interrupt (uart->irq);
338
    }
339 1502 nogj
}
340
 
341 1748 jeremybenn
static void
342
uart_int_rdi (void *dat)
343 1502 nogj
{
344
  struct dev_16450 *uart = dat;
345
 
346
  uart->istat.ints |= 1 << UART_IIR_RDI;
347
 
348 1748 jeremybenn
  if (!(uart->regs.ier & UART_IER_RDI))
349 1502 nogj
    return;
350
 
351 1748 jeremybenn
  if (uart->regs.iir != UART_IIR_RLSI)
352
    {
353
      uart->regs.iir = UART_IIR_RDI;
354
      report_interrupt (uart->irq);
355
    }
356 1502 nogj
}
357
 
358 1748 jeremybenn
static void
359
uart_int_rlsi (void *dat)
360 1502 nogj
{
361
  struct dev_16450 *uart = dat;
362
 
363
  uart->istat.ints |= 1 << UART_IIR_RLSI;
364
 
365 1748 jeremybenn
  if (!(uart->regs.ier & UART_IER_RLSI))
366 1502 nogj
    return;
367
 
368
  /* Highest priority interrupt */
369 1715 nogj
  uart->regs.iir = UART_IIR_RLSI;
370 1748 jeremybenn
  report_interrupt (uart->irq);
371 1502 nogj
}
372
 
373
/* Checks to see if an RLSI interrupt is due and schedules one if need be */
374 1748 jeremybenn
static void
375
uart_check_rlsi (void *dat)
376 1502 nogj
{
377
  struct dev_16450 *uart = dat;
378
 
379 1748 jeremybenn
  if (uart->regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY | UART_LSR_FRAME |
380
                        UART_LSR_BREAK))
381
    uart_int_rlsi (uart);
382 1502 nogj
}
383
 
384
/* Checks to see if an RDI interrupt is due and schedules one if need be */
385 1748 jeremybenn
static void
386
uart_check_rdi (void *dat)
387 1502 nogj
{
388
  struct dev_16450 *uart = dat;
389
 
390 1748 jeremybenn
  if (uart->istat.rxbuf_full >= UART_FIFO_TRIGGER (uart->regs.fcr >> 6))
391
    {
392
      uart_int_rdi (uart);
393
    }
394 1502 nogj
}
395
 
396
/* Raises the next highest priority interrupt */
397 1748 jeremybenn
static void
398
uart_next_int (struct dev_16450 *uart)
399 1502 nogj
{
400
  /* Interrupt detection in proper priority order. */
401 1748 jeremybenn
  if ((uart->istat.ints & (1 << UART_IIR_RLSI)) &&
402
      (uart->regs.ier & UART_IER_RLSI))
403
    uart_int_rlsi (uart);
404
  else if ((uart->istat.ints & (1 << UART_IIR_RDI)) &&
405
           (uart->regs.ier & UART_IER_RDI))
406
    uart_int_rdi (uart);
407
  else if ((uart->istat.ints & (1 << UART_IIR_CTI)) &&
408
           (uart->regs.ier & UART_IER_RDI))
409
    uart_int_cti (uart);
410
  else if ((uart->istat.ints & (1 << UART_IIR_THRI)) &&
411
           (uart->regs.ier & UART_IER_THRI))
412
    uart_int_thri (uart);
413
  else if ((uart->istat.ints & (1 << UART_IIR_MSI)) &&
414
           (uart->regs.ier & UART_IER_MSI))
415
    uart_int_msi (uart);
416
  else
417
    {
418
      clear_interrupt (uart->irq);
419
      uart->regs.iir = UART_IIR_NO_INT;
420
    }
421 1502 nogj
}
422
 
423
/* Clears potentially pending interrupts */
424 1748 jeremybenn
static void
425
uart_clear_int (struct dev_16450 *uart, int intr)
426 1502 nogj
{
427
  uart->istat.ints &= ~(1 << intr);
428
 
429 1715 nogj
  /* Some stuff schedule uart_int_cti, therefore remove it here */
430 1748 jeremybenn
  if (intr == UART_IIR_CTI)
431
    SCHED_FIND_REMOVE (uart_int_cti, uart);
432 1502 nogj
 
433 1748 jeremybenn
  if (intr != uart->regs.iir)
434 1502 nogj
    return;
435
 
436 1748 jeremybenn
  uart_next_int (uart);
437 1502 nogj
}
438
 
439 1503 nogj
/*----------------------------------------------------[ Loopback handling ]---*/
440 1748 jeremybenn
static void
441
uart_loopback (struct dev_16450 *uart)
442 1503 nogj
{
443 1748 jeremybenn
  if (!(uart->regs.mcr & UART_MCR_LOOP))
444 1503 nogj
    return;
445
 
446 1748 jeremybenn
  if ((uart->regs.mcr & UART_MCR_AUX2) !=
447
      ((uart->regs.msr & UART_MSR_DCD) >> 4))
448 1503 nogj
    uart->regs.msr |= UART_MSR_DDCD;
449
 
450 1748 jeremybenn
  if ((uart->regs.mcr & UART_MCR_AUX1) <
451
      ((uart->regs.msr & UART_MSR_RI) >> 4))
452 1503 nogj
    uart->regs.msr |= UART_MSR_TERI;
453
 
454 1748 jeremybenn
  if ((uart->regs.mcr & UART_MCR_RTS) !=
455
      ((uart->regs.msr & UART_MSR_CTS) >> 3))
456 1503 nogj
    uart->regs.msr |= UART_MSR_DCTS;
457
 
458 1748 jeremybenn
  if ((uart->regs.mcr & UART_MCR_DTR) !=
459
      ((uart->regs.msr & UART_MSR_DSR) >> 5))
460 1503 nogj
    uart->regs.msr |= UART_MSR_DDSR;
461
 
462 1748 jeremybenn
  uart->regs.msr &=
463
    ~(UART_MSR_DCD | UART_MSR_RI | UART_MSR_DSR | UART_MSR_CTS);
464 1503 nogj
  uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX2) << 4);
465
  uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX1) << 4);
466
  uart->regs.msr |= ((uart->regs.mcr & UART_MCR_RTS) << 3);
467
  uart->regs.msr |= ((uart->regs.mcr & UART_MCR_DTR) << 5);
468
 
469 1748 jeremybenn
  if (uart->regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR | UART_MSR_TERI |
470
                        UART_MSR_DDCD))
471
    uart_int_msi (uart);
472 1503 nogj
}
473
 
474 1499 nogj
/*----------------------------------------------------[ Transmitter logic ]---*/
475
/* Sends the data in the shift register to the outside world */
476 1748 jeremybenn
static void
477
send_char (struct dev_16450 *uart, int bits_send)
478 1499 nogj
{
479 1748 jeremybenn
  PRINTF ("%c", (char) uart->iregs.txser);
480 1499 nogj
  if (uart->regs.mcr & UART_MCR_LOOP)
481
    uart->iregs.loopback = uart->iregs.txser;
482 1748 jeremybenn
  else
483
    {
484
      /* Send to either VAPI or to file */
485
      if (uart->vapi_id)
486
        {
487
          int par, pe, fe, nbits;
488
          int j, data;
489
          unsigned long packet = 0;
490 1499 nogj
 
491 1748 jeremybenn
          nbits = MIN (bits_send, (uart->regs.lcr & UART_LCR_WLEN8) + 5);
492
          /* Encode a packet */
493
          packet = uart->iregs.txser & ((1 << nbits) - 1);
494 1499 nogj
 
495 1748 jeremybenn
          /* Calculate parity */
496
          for (j = 0, par = 0; j < nbits; j++)
497
            par ^= (packet >> j) & 1;
498 1499 nogj
 
499 1748 jeremybenn
          if (uart->regs.lcr & UART_LCR_PARITY)
500
            {
501
              if (uart->regs.lcr & UART_LCR_SPAR)
502
                {
503
                  packet |= 1 << nbits;
504
                }
505
              else
506
                {
507
                  if (uart->regs.lcr & UART_LCR_EPAR)
508
                    packet |= par << nbits;
509
                  else
510
                    packet |= (par ^ 1) << nbits;
511
                }
512
              nbits++;
513
            }
514
          packet |= 1 << (nbits++);
515
          if (uart->regs.lcr & UART_LCR_STOP)
516
            packet |= 1 << (nbits++);
517 1499 nogj
 
518 1748 jeremybenn
          /* Decode a packet */
519
          nbits = (uart->vapi.lcr & UART_LCR_WLEN8) + 5;
520
          data = packet & ((1 << nbits) - 1);
521
 
522
          /* Calculate parity, including parity bit */
523
          for (j = 0, par = 0; j < nbits + 1; j++)
524
            par ^= (packet >> j) & 1;
525
 
526
          if (uart->vapi.lcr & UART_LCR_PARITY)
527
            {
528
              if (uart->vapi.lcr & UART_LCR_SPAR)
529
                {
530
                  pe = !((packet >> nbits) & 1);
531
                }
532
              else
533
                {
534
                  if (uart->vapi.lcr & UART_LCR_EPAR)
535
                    pe = par != 0;
536
                  else
537
                    pe = par != 1;
538
                }
539
              nbits++;
540
            }
541
          else
542
            pe = 0;
543
 
544
          fe = ((packet >> (nbits++)) & 1) ^ 1;
545
          if (uart->vapi.lcr & UART_LCR_STOP)
546
            fe |= ((packet >> (nbits++)) & 1) ^ 1;
547
 
548
          data |=
549
            (uart->vapi.lcr << 8) | (pe << 16) | (fe << 17) | (uart->vapi.
550
                                                               lcr << 8);
551
          vapi_send (uart->vapi_id, data);
552
        }
553
      else
554
        {
555
          char buffer[1] = { uart->iregs.txser & 0xFF };
556
          channel_write (uart->channel, buffer, 1);
557
        }
558 1499 nogj
    }
559
}
560
 
561
/* Called when all the bits have been shifted out of the shift register */
562 1748 jeremybenn
void
563
uart_char_clock (void *dat)
564 1499 nogj
{
565
  struct dev_16450 *uart = dat;
566
 
567
  /* We've sent all bits */
568 1748 jeremybenn
  send_char (uart, (uart->regs.lcr & UART_LCR_WLEN8) + 5);
569 1499 nogj
 
570 1748 jeremybenn
  if (!uart->istat.txbuf_full)
571 1499 nogj
    uart->regs.lsr |= UART_LSR_TXSERE;
572
  else
573 1748 jeremybenn
    uart_tx_send (uart);
574 1499 nogj
}
575
 
576
/* Called when a break has been shifted out of the shift register */
577 1748 jeremybenn
void
578
uart_send_break (void *dat)
579 1499 nogj
{
580
  struct dev_16450 *uart = dat;
581
 
582
  /* Send one break signal */
583
  vapi_send (uart->vapi_id, UART_LCR_SBC << 8);
584
 
585
  /* Send the next char (if there is one) */
586 1748 jeremybenn
  if (!uart->istat.txbuf_full)
587 1499 nogj
    uart->regs.lsr |= UART_LSR_TXSERE;
588
  else
589 1748 jeremybenn
    uart_tx_send (uart);
590 1499 nogj
}
591
 
592
/* Scheduled whenever the TX buffer has characters in it and we aren't sending
593
 * a character. */
594 1748 jeremybenn
void
595
uart_tx_send (void *dat)
596 1499 nogj
{
597
  struct dev_16450 *uart = dat;
598
 
599
  uart->iregs.txser = uart->regs.txbuf[uart->istat.txbuf_tail];
600
  uart->istat.txbuf_tail = (uart->istat.txbuf_tail + 1) % uart->fifo_len;
601
  uart->istat.txbuf_full--;
602
  uart->regs.lsr &= ~UART_LSR_TXSERE;
603
 
604
  /* Schedules a char_clock to run in the correct amount of time */
605 1748 jeremybenn
  if (!(uart->regs.lcr & UART_LCR_SBC))
606
    {
607
      SCHED_ADD (uart_char_clock, uart, uart->char_clks * UART_CLOCK_DIVIDER);
608
    }
609
  else
610
    {
611
      SCHED_ADD (uart_send_break, uart, 0);
612
    }
613 1499 nogj
 
614
  /* When UART is in either character mode, i.e. 16450 emulation mode, or FIFO
615
   * mode, the THRE interrupt is raised when THR transitions from full to empty.
616
   */
617 1748 jeremybenn
  if (!uart->istat.txbuf_full)
618
    {
619
      uart->regs.lsr |= UART_LSR_TXBUFE;
620
      uart_int_thri (uart);
621
    }
622 1499 nogj
}
623
 
624 1501 nogj
/*-------------------------------------------------------[ Receiver logic ]---*/
625
/* Adds a character to the RX FIFO */
626 1748 jeremybenn
static void
627
uart_add_char (struct dev_16450 *uart, int ch)
628 1501 nogj
{
629
  uart->regs.lsr |= UART_LSR_RDRDY;
630 1748 jeremybenn
  uart_clear_int (uart, UART_IIR_CTI);
631
  SCHED_ADD (uart_int_cti, uart,
632
             uart->char_clks * UART_CHAR_TIMEOUT * UART_CLOCK_DIVIDER);
633 1501 nogj
 
634 1748 jeremybenn
  if (uart->istat.rxbuf_full + 1 > uart->fifo_len)
635
    {
636
      uart->regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR;
637
      uart_int_rlsi (uart);
638 1501 nogj
    }
639 1748 jeremybenn
  else
640
    {
641
      uart->regs.rxbuf[uart->istat.rxbuf_head] = ch;
642
      uart->istat.rxbuf_head = (uart->istat.rxbuf_head + 1) % uart->fifo_len;
643
      if (!uart->istat.rxbuf_full++)
644
        {
645
          uart->regs.lsr |= ch >> 8;
646
          uart_check_rlsi (uart);
647
        }
648
    }
649
  uart_check_rdi (uart);
650 1501 nogj
}
651
 
652
/* Called when a break sequence is about to start.  It stops receiveing
653
 * characters and schedules the uart_recv_break to send the break */
654 1748 jeremybenn
static void
655
uart_recv_break_start (void *dat)
656 1501 nogj
{
657
  struct dev_16450 *uart = dat;
658
 
659
  uart->istat.receiveing = 0;
660
  uart->istat.recv_break = 1;
661
 
662 1748 jeremybenn
  SCHED_FIND_REMOVE (uart_recv_char, uart);
663 1501 nogj
 
664 1748 jeremybenn
  if (uart->vapi_id && (uart->vapi_buf_head_ptr != uart->vapi_buf_tail_ptr))
665
    uart_vapi_cmd (uart);
666 1501 nogj
 
667 1748 jeremybenn
  SCHED_ADD (uart_recv_break, uart,
668
             UART_BREAK_COUNT * uart->vapi.char_clks * UART_CLOCK_DIVIDER);
669 1501 nogj
}
670
 
671
/* Stops sending breaks and starts receiveing characters */
672 1748 jeremybenn
static void
673
uart_recv_break_stop (void *dat)
674 1501 nogj
{
675
  struct dev_16450 *uart = dat;
676
 
677
  uart->istat.recv_break = 0;
678 1748 jeremybenn
  SCHED_FIND_REMOVE (uart_recv_break, dat);
679 1501 nogj
}
680
 
681
/* Receives a break */
682 1748 jeremybenn
static void
683
uart_recv_break (void *dat)
684 1501 nogj
{
685
  struct dev_16450 *uart = dat;
686
  unsigned lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
687
 
688 1748 jeremybenn
  uart_add_char (uart, lsr << 8);
689 1501 nogj
}
690
 
691
/* Moves a character from the serial register to the RX FIFO */
692 1748 jeremybenn
static void
693
uart_recv_char (void *dat)
694 1501 nogj
{
695
  struct dev_16450 *uart = dat;
696
  uint16_t char_to_add;
697
 
698
  /* Set unused character bits to zero and allow lsr register in fifo */
699 1748 jeremybenn
  char_to_add =
700
    uart->iregs.rxser & (((1 << ((uart->regs.lcr & 3) + 5)) - 1) | 0xff00);
701 1501 nogj
 
702 1748 jeremybenn
  PRINTF ("%c", (char) char_to_add);
703 1501 nogj
 
704 1748 jeremybenn
  if (uart->regs.mcr & UART_MCR_LOOP)
705
    {
706
      uart->iregs.rxser = uart->iregs.loopback;
707
      uart->istat.receiveing = 1;
708
      SCHED_ADD (uart_recv_char, uart, uart->char_clks * UART_CLOCK_DIVIDER);
709
    }
710
  else
711
    {
712
      uart->istat.receiveing = 0;
713
      uart_sched_recv_check (uart);
714
      if (uart->vapi_id
715
          && (uart->vapi_buf_head_ptr != uart->vapi_buf_tail_ptr))
716
        SCHED_ADD (uart_vapi_cmd, uart, 0);
717
    }
718 1501 nogj
 
719 1748 jeremybenn
  uart_add_char (uart, char_to_add);
720 1501 nogj
}
721
 
722
/* Checks if there is a character waiting to be received */
723 1748 jeremybenn
static void
724
uart_check_char (void *dat)
725 1501 nogj
{
726
  struct dev_16450 *uart = dat;
727 1517 nogj
  uint8_t buffer;
728 1501 nogj
  int retval;
729
 
730
  /* Check if there is something waiting, and put it into rxser */
731 1748 jeremybenn
  retval = channel_read (uart->channel, (char *) &buffer, 1);
732
  if (retval > 0)
733
    {
734
      uart->iregs.rxser = buffer;
735
      uart->istat.receiveing = 1;
736
      SCHED_ADD (uart_recv_char, uart, uart->char_clks * UART_CLOCK_DIVIDER);
737
      return;
738
    }
739 1501 nogj
 
740 1748 jeremybenn
  if (!retval)
741
    {
742
      SCHED_ADD (uart_check_char, uart,
743
                 UART_FGETC_SLOWDOWN * UART_CLOCK_DIVIDER);
744
      return;
745
    }
746 1501 nogj
 
747 1748 jeremybenn
  if (retval < 0)
748
    perror (uart->channel_str);
749 1501 nogj
}
750
 
751 1748 jeremybenn
static void
752
uart_sched_recv_check (struct dev_16450 *uart)
753 1501 nogj
{
754 1748 jeremybenn
  if (!uart->vapi_id)
755
    SCHED_ADD (uart_check_char, uart,
756
               UART_FGETC_SLOWDOWN * UART_CLOCK_DIVIDER);
757 1501 nogj
}
758
 
759 1505 nogj
/*----------------------------------------------------[ UART I/O handling ]---*/
760 31 lampret
/* Set a specific UART register with value. */
761 1748 jeremybenn
static void
762
uart_write_byte (oraddr_t addr, uint8_t value, void *dat)
763 31 lampret
{
764 1367 nogj
  struct dev_16450 *uart = dat;
765 1748 jeremybenn
 
766
  if (uart->regs.lcr & UART_LCR_DLAB)
767
    {
768
      switch (addr)
769
        {
770
        case UART_DLL:
771
          uart->regs.dll = value;
772
          uart->char_clks =
773
            char_clks (uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
774
          return;
775
        case UART_DLH:
776
          uart->regs.dlh = value;
777
          return;
778
        }
779 355 markom
    }
780 1748 jeremybenn
 
781
  switch (addr)
782
    {
783 355 markom
    case UART_TXBUF:
784 1499 nogj
      uart->regs.lsr &= ~UART_LSR_TXBUFE;
785 1748 jeremybenn
      if (uart->istat.txbuf_full < uart->fifo_len)
786
        {
787
          uart->regs.txbuf[uart->istat.txbuf_head] = value;
788
          uart->istat.txbuf_head =
789
            (uart->istat.txbuf_head + 1) % uart->fifo_len;
790
          if (!uart->istat.txbuf_full++ && (uart->regs.lsr & UART_LSR_TXSERE))
791
            SCHED_ADD (uart_tx_send, uart, 0);
792
        }
793
      else
794
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
795 341 markom
 
796 1748 jeremybenn
      uart_clear_int (uart, UART_IIR_THRI);
797 355 markom
      break;
798 409 markom
    case UART_FCR:
799 1367 nogj
      uart->regs.fcr = value & UART_VALID_FCR;
800
      if ((uart->fifo_len == 1 && (value & UART_FCR_FIE))
801 1748 jeremybenn
          || (uart->fifo_len != 1 && !(value & UART_FCR_FIE)))
802
        value |= UART_FCR_RRXFI | UART_FCR_RTXFI;
803 1367 nogj
      uart->fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
804 1748 jeremybenn
      if (value & UART_FCR_RTXFI)
805
        {
806
          uart->istat.txbuf_head = uart->istat.txbuf_tail = 0;
807
          uart->istat.txbuf_full = 0;
808
          uart->regs.lsr |= UART_LSR_TXBUFE;
809 1145 sfurman
 
810 1748 jeremybenn
          /* For FIFO-mode only, THRE interrupt is set when THR and FIFO are empty
811
           */
812
          if (uart->fifo_len == 16)
813
            uart_int_thri (uart);
814 1499 nogj
 
815 1748 jeremybenn
          SCHED_FIND_REMOVE (uart_tx_send, uart);
816
        }
817
      if (value & UART_FCR_RRXFI)
818
        {
819
          uart->istat.rxbuf_head = uart->istat.rxbuf_tail = 0;
820
          uart->istat.rxbuf_full = 0;
821
          uart->regs.lsr &= ~UART_LSR_RDRDY;
822
          uart_clear_int (uart, UART_IIR_RDI);
823
          uart_clear_int (uart, UART_IIR_CTI);
824
        }
825 409 markom
      break;
826 355 markom
    case UART_IER:
827 1367 nogj
      uart->regs.ier = value & UART_VALID_IER;
828 1748 jeremybenn
      uart_next_int (uart);
829 355 markom
      break;
830
    case UART_LCR:
831 1748 jeremybenn
      if ((uart->regs.lcr & UART_LCR_SBC) != (value & UART_LCR_SBC))
832
        {
833
          if ((value & UART_LCR_SBC) && !(uart->regs.lsr & UART_LSR_TXSERE))
834
            {
835
              /* Schedule a job to send the break char */
836
              SCHED_FIND_REMOVE (uart_char_clock, uart);
837
              SCHED_ADD (uart_send_break, uart, 0);
838
            }
839
          if (!(value & UART_LCR_SBC) && !(uart->regs.lsr & UART_LSR_TXSERE))
840
            {
841
              /* Schedule a job to start sending characters */
842
              SCHED_ADD (uart_tx_send, uart, 0);
843
              /* Remove the uart_send_break job just in case it has not run yet */
844
              SCHED_FIND_REMOVE (uart_char_clock, uart);
845
            }
846
        }
847 1367 nogj
      uart->regs.lcr = value & UART_VALID_LCR;
848 1748 jeremybenn
      uart->char_clks =
849
        char_clks (uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
850 355 markom
      break;
851
    case UART_MCR:
852 1367 nogj
      uart->regs.mcr = value & UART_VALID_MCR;
853 1748 jeremybenn
      uart_loopback (uart);
854 355 markom
      break;
855
    case UART_SCR:
856 1367 nogj
      uart->regs.scr = value;
857 355 markom
      break;
858 1748 jeremybenn
    }
859 31 lampret
}
860
 
861
/* Read a specific UART register. */
862 1748 jeremybenn
static uint8_t
863
uart_read_byte (oraddr_t addr, void *dat)
864 31 lampret
{
865 1367 nogj
  struct dev_16450 *uart = dat;
866 1350 nogj
  uint8_t value = 0;
867 1748 jeremybenn
 
868
  if (uart->regs.lcr & UART_LCR_DLAB)
869
    {
870
      switch (addr)
871
        {
872
        case UART_DLL:
873
          value = uart->regs.dll;
874
          return value;
875
        case UART_DLH:
876
          value = uart->regs.dlh;
877
          return value;
878
        }
879 355 markom
    }
880 1748 jeremybenn
 
881
  switch (addr)
882
    {
883 355 markom
    case UART_RXBUF:
884 1748 jeremybenn
      if (uart->istat.rxbuf_full)
885
        {
886
          value = uart->regs.rxbuf[uart->istat.rxbuf_tail];
887
          uart->istat.rxbuf_tail =
888
            (uart->istat.rxbuf_tail + 1) % uart->fifo_len;
889
          uart->istat.rxbuf_full--;
890
        }
891 1502 nogj
 
892 1748 jeremybenn
      uart_clear_int (uart, UART_IIR_RDI);
893
      uart_clear_int (uart, UART_IIR_CTI);
894 1502 nogj
 
895 1748 jeremybenn
      if (uart->istat.rxbuf_full)
896
        {
897
          uart->regs.lsr |=
898
            UART_LSR_RDRDY | uart->regs.rxbuf[uart->istat.rxbuf_tail] >> 8;
899
          SCHED_ADD (uart_int_cti, uart,
900
                     uart->char_clks * UART_CHAR_TIMEOUT *
901
                     UART_CLOCK_DIVIDER);
902
          uart_check_rlsi (uart);
903
          uart_check_rdi (uart);
904
        }
905
      else
906
        {
907
          uart->regs.lsr &= ~UART_LSR_RDRDY;
908
        }
909 355 markom
      break;
910
    case UART_IER:
911 1367 nogj
      value = uart->regs.ier & UART_VALID_IER;
912 355 markom
      break;
913
    case UART_IIR:
914 1367 nogj
      value = (uart->regs.iir & UART_VALID_IIR) | 0xc0;
915 1502 nogj
      /* Only clear the thri interrupt if it is the one we are repporting */
916 1748 jeremybenn
      if (uart->regs.iir == UART_IIR_THRI)
917
        uart_clear_int (uart, UART_IIR_THRI);
918 355 markom
      break;
919
    case UART_LCR:
920 1367 nogj
      value = uart->regs.lcr & UART_VALID_LCR;
921 355 markom
      break;
922
    case UART_MCR:
923
      value = 0;
924
      break;
925
    case UART_LSR:
926 1367 nogj
      value = uart->regs.lsr & UART_VALID_LSR;
927
      uart->regs.lsr &=
928 1748 jeremybenn
        ~(UART_LSR_OVRRUN | UART_LSR_BREAK | UART_LSR_PARITY
929
          | UART_LSR_FRAME | UART_LSR_RXERR);
930 1502 nogj
      /* Clear potentially pending RLSI interrupt */
931 1748 jeremybenn
      uart_clear_int (uart, UART_IIR_RLSI);
932 355 markom
      break;
933
    case UART_MSR:
934 1367 nogj
      value = uart->regs.msr & UART_VALID_MSR;
935
      uart->regs.msr = 0;
936 1748 jeremybenn
      uart_clear_int (uart, UART_IIR_MSI);
937
      uart_loopback (uart);
938 355 markom
      break;
939
    case UART_SCR:
940 1367 nogj
      value = uart->regs.scr;
941 355 markom
      break;
942 1748 jeremybenn
    }
943 355 markom
  return value;
944 31 lampret
}
945
 
946 1500 nogj
/*--------------------------------------------------------[ VAPI handling ]---*/
947
/* Decodes the read vapi command */
948 1748 jeremybenn
static void
949
uart_vapi_cmd (void *dat)
950 1500 nogj
{
951 1501 nogj
  struct dev_16450 *uart = dat;
952 1500 nogj
  int received = 0;
953
 
954 1748 jeremybenn
  while (!received)
955
    {
956
      if (uart->vapi_buf_head_ptr != uart->vapi_buf_tail_ptr)
957
        {
958
          unsigned long data = uart->vapi_buf[uart->vapi_buf_tail_ptr];
959
          uart->vapi_buf_tail_ptr =
960
            (uart->vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
961
          switch (data >> 24)
962
            {
963
            case 0x00:
964
              uart->vapi.lcr = (data >> 8) & 0xff;
965
              /* Put data into rx fifo */
966
              uart->iregs.rxser = data & 0xff;
967
              uart->vapi.char_clks =
968
                char_clks (uart->vapi.dll, uart->vapi.dlh, uart->vapi.lcr);
969
              if ((uart->vapi.lcr & ~UART_LCR_SBC) !=
970
                  (uart->regs.lcr & ~UART_LCR_SBC)
971
                  || uart->vapi.char_clks != uart->char_clks
972
                  || uart->vapi.skew < -MAX_SKEW
973
                  || uart->vapi.skew > MAX_SKEW)
974
                {
975
                  if ((uart->vapi.lcr & ~UART_LCR_SBC) !=
976
                      (uart->regs.lcr & ~UART_LCR_SBC))
977 1751 jeremybenn
                    fprintf (stderr, "Warning: Unmatched VAPI (%02" PRIx8
978
                             ") and uart (%02" PRIx8
979
                             ") modes.\n", uart->vapi.lcr & ~UART_LCR_SBC,
980
                             uart->regs.lcr & ~UART_LCR_SBC);
981 1748 jeremybenn
                  if (uart->vapi.char_clks != uart->char_clks)
982
                    {
983 1751 jeremybenn
                      fprintf (stderr, "Warning: Unmatched VAPI (%li) and "
984
                               "UART (%li) char clocks.\n",
985
                               uart->vapi.char_clks, uart->char_clks);
986
                      fprintf (stderr, "VAPI: lcr: %02" PRIx8 ", dll: %02"
987
                               PRIx8 ", dlh: %02" PRIx8 "\n", uart->vapi.lcr,
988
                               uart->vapi.dll, uart->vapi.dlh);
989
                      fprintf (stderr, "UART: lcr: %02" PRIx8 ", dll: %02"
990
                               PRIx8 ", dlh: %02" PRIx8 "\n", uart->regs.lcr,
991
                               uart->regs.dll, uart->vapi.dlh);
992 1748 jeremybenn
                    }
993
                  if (uart->vapi.skew < -MAX_SKEW
994
                      || uart->vapi.skew > MAX_SKEW)
995 1751 jeremybenn
                    {
996
                      fprintf(stderr, "VAPI skew is beyond max: %i\n",
997
                              uart->vapi.skew);
998
                    }
999 1748 jeremybenn
                  /* Set error bits */
1000
                  uart->iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
1001
                  if (uart->regs.lcr & UART_LCR_PARITY)
1002
                    uart->iregs.rxser |= UART_LSR_PARITY << 8;
1003
                }
1004
              if (!uart->istat.recv_break)
1005
                {
1006
                  uart->istat.receiveing = 1;
1007
                  SCHED_ADD (uart_recv_char, uart,
1008
                             uart->char_clks * UART_CLOCK_DIVIDER);
1009
                }
1010
              received = 1;
1011
              break;
1012
            case 0x01:
1013
              uart->vapi.dll = (data >> 0) & 0xff;
1014
              uart->vapi.dlh = (data >> 8) & 0xff;
1015
              break;
1016
            case 0x02:
1017
              uart->vapi.lcr = (data >> 8) & 0xff;
1018
              break;
1019
            case 0x03:
1020
              uart->vapi.skew = (signed short) (data & 0xffff);
1021
              break;
1022
            case 0x04:
1023
              if ((data >> 16) & 1)
1024
                {
1025
                  /* If data & 0xffff is 0 then set the break imediatly and handle the
1026
                   * following commands as appropriate */
1027
                  if (!(data & 0xffff))
1028
                    uart_recv_break_start (uart);
1029
                  else
1030
                    /* Schedule a job to start sending breaks */
1031
                    SCHED_ADD (uart_recv_break_start, uart,
1032
                               (data & 0xffff) * UART_CLOCK_DIVIDER);
1033
                }
1034
              else
1035
                {
1036
                  /* If data & 0xffff is 0 then release the break imediatly and handle
1037
                   * the following commands as appropriate */
1038
                  if (!(data & 0xffff))
1039
                    uart_recv_break_stop (uart);
1040
                  else
1041
                    /* Schedule a job to stop sending breaks */
1042
                    SCHED_ADD (uart_recv_break_stop, uart,
1043
                               (data & 0xffff) * UART_CLOCK_DIVIDER);
1044
                }
1045
              break;
1046
            default:
1047 1751 jeremybenn
              fprintf (stderr, "WARNING: Invalid vapi command %02lx\n",
1048
                       data >> 24);
1049 1748 jeremybenn
              break;
1050
            }
1051
        }
1052
      else
1053
        break;
1054
    }
1055 1500 nogj
}
1056
 
1057 336 markom
/* Function that handles incoming VAPI data.  */
1058 1748 jeremybenn
static void
1059
uart_vapi_read (unsigned long id, unsigned long data, void *dat)
1060 336 markom
{
1061 1367 nogj
  struct dev_16450 *uart = dat;
1062
  uart->vapi_buf[uart->vapi_buf_head_ptr] = data;
1063
  uart->vapi_buf_head_ptr = (uart->vapi_buf_head_ptr + 1) % UART_VAPI_BUF_LEN;
1064 1748 jeremybenn
  if (uart->vapi_buf_tail_ptr == uart->vapi_buf_head_ptr)
1065
    {
1066
      fprintf (stderr, "FATAL: uart VAPI buffer to small.\n");
1067
      exit (1);
1068
    }
1069
  if (!uart->istat.receiveing)
1070
    uart_vapi_cmd (uart);
1071 341 markom
}
1072 336 markom
 
1073 1505 nogj
/*--------------------------------------------------------[ Sim callbacks ]---*/
1074 341 markom
/* Reset.  It initializes all registers of all UART devices to zero values,
1075 1505 nogj
 * (re)opens all RX/TX file streams and places devices in memory address
1076
 * space.  */
1077 1748 jeremybenn
void
1078
uart_reset (void *dat)
1079 31 lampret
{
1080 1367 nogj
  struct dev_16450 *uart = dat;
1081 261 markom
 
1082 1748 jeremybenn
  if (uart->vapi_id)
1083
    {
1084
      vapi_install_handler (uart->vapi_id, uart_vapi_read, dat);
1085
    }
1086
  else if (uart->channel_str && uart->channel_str[0])
1087
    {                           /* Try to create stream. */
1088
      if (uart->channel)
1089
        channel_close (uart->channel);
1090
      else
1091
        uart->channel = channel_init (uart->channel_str);
1092
      if (channel_open (uart->channel) < 0)
1093
        {
1094 1751 jeremybenn
          fprintf (stderr, "Warning: problem with channel \"%s\" detected.\n",
1095
                   uart->channel_str);
1096 1748 jeremybenn
        }
1097
      else if (config.sim.verbose)
1098
        PRINTF ("UART at 0x%" PRIxADDR "\n", uart->baseaddr);
1099
    }
1100
  else
1101
    {
1102 1751 jeremybenn
      fprintf (stderr, "Warning: UART at %" PRIxADDR
1103
               " has no vapi nor channel specified\n", uart->baseaddr);
1104 1748 jeremybenn
    }
1105
 
1106 1367 nogj
  if (uart->uart16550)
1107
    uart->fifo_len = 16;
1108
  else
1109
    uart->fifo_len = 1;
1110 1145 sfurman
 
1111 1367 nogj
  uart->istat.rxbuf_head = uart->istat.rxbuf_tail = 0;
1112
  uart->istat.txbuf_head = uart->istat.txbuf_tail = 0;
1113 1748 jeremybenn
 
1114 1367 nogj
  uart->istat.txbuf_full = uart->istat.rxbuf_full = 0;
1115 1145 sfurman
 
1116 1367 nogj
  uart->char_clks = 0;
1117
 
1118
  uart->iregs.txser = 0;
1119
  uart->iregs.rxser = 0;
1120
  uart->iregs.loopback = 0;
1121 1501 nogj
  uart->istat.receiveing = 0;
1122
  uart->istat.recv_break = 0;
1123 1502 nogj
  uart->istat.ints = 0;
1124 1367 nogj
 
1125 1748 jeremybenn
  memset (uart->regs.txbuf, 0, sizeof (uart->regs.txbuf));
1126
  memset (uart->regs.rxbuf, 0, sizeof (uart->regs.rxbuf));
1127 1367 nogj
 
1128
  uart->regs.dll = 0;
1129
  uart->regs.dlh = 0;
1130
  uart->regs.ier = 0;
1131 1502 nogj
  uart->regs.iir = UART_IIR_NO_INT;
1132 1367 nogj
  uart->regs.fcr = 0;
1133
  uart->regs.lcr = UART_LCR_RESET;
1134
  uart->regs.mcr = 0;
1135 1499 nogj
  uart->regs.lsr = UART_LSR_TXBUFE | UART_LSR_TXSERE;
1136 1367 nogj
  uart->regs.msr = 0;
1137
  uart->regs.scr = 0;
1138
 
1139
  uart->vapi.skew = 0;
1140
  uart->vapi.lcr = 0;
1141
  uart->vapi.dll = 0;
1142
  uart->vapi.char_clks = 0;
1143
 
1144
  uart->vapi_buf_head_ptr = 0;
1145
  uart->vapi_buf_tail_ptr = 0;
1146 1748 jeremybenn
  memset (uart->vapi_buf, 0, sizeof (uart->vapi_buf));
1147 1367 nogj
 
1148 1748 jeremybenn
  uart_sched_recv_check (uart);
1149 31 lampret
}
1150 261 markom
 
1151 31 lampret
/* Print register values on stdout. */
1152 1748 jeremybenn
void
1153
uart_status (void *dat)
1154 31 lampret
{
1155 1367 nogj
  struct dev_16450 *uart = dat;
1156
  int i;
1157 1748 jeremybenn
 
1158
  PRINTF ("\nUART visible registers at 0x%" PRIxADDR ":\n", uart->baseaddr);
1159
  PRINTF ("RXBUF: ");
1160
  for (i = uart->istat.rxbuf_head; i != uart->istat.rxbuf_tail;
1161
       i = (i + 1) % uart->fifo_len)
1162 1367 nogj
    PRINTF (" %.2x", uart->regs.rxbuf[i]);
1163 1748 jeremybenn
  PRINTF ("TXBUF: ");
1164
  for (i = uart->istat.txbuf_head; i != uart->istat.txbuf_tail;
1165
       i = (i + 1) % uart->fifo_len)
1166 1367 nogj
    PRINTF (" %.2x", uart->regs.txbuf[i]);
1167 1748 jeremybenn
  PRINTF ("\n");
1168
  PRINTF ("DLL  : %.2x  DLH  : %.2x\n", uart->regs.dll, uart->regs.dlh);
1169
  PRINTF ("IER  : %.2x  IIR  : %.2x\n", uart->regs.ier, uart->regs.iir);
1170
  PRINTF ("LCR  : %.2x  MCR  : %.2x\n", uart->regs.lcr, uart->regs.mcr);
1171
  PRINTF ("LSR  : %.2x  MSR  : %.2x\n", uart->regs.lsr, uart->regs.msr);
1172
  PRINTF ("SCR  : %.2x\n", uart->regs.scr);
1173 31 lampret
 
1174 1748 jeremybenn
  PRINTF ("\nInternal registers (sim debug):\n");
1175
  PRINTF ("RXSER: %.2" PRIx16 "  TXSER: %.2" PRIx8 "\n", uart->iregs.rxser,
1176
          uart->iregs.txser);
1177 31 lampret
 
1178 1748 jeremybenn
  PRINTF ("\nInternal status (sim debug):\n");
1179
  PRINTF ("char_clks: %ld\n", uart->char_clks);
1180
  PRINTF ("rxbuf_full: %d  txbuf_full: %d\n", uart->istat.rxbuf_full,
1181
          uart->istat.txbuf_full);
1182
  PRINTF ("Using IRQ%i\n", uart->irq);
1183 1367 nogj
  if (uart->vapi_id)
1184
    PRINTF ("Connected to vapi ID=%lx\n\n", uart->vapi_id);
1185
  /* TODO: replace by a channel_status
1186 1748 jeremybenn
     else
1187
     PRINTF("RX fs: %p  TX fs: %p\n\n", uart->rxfs, uart->txfs);
1188
   */
1189 31 lampret
}
1190 1358 nogj
 
1191
/*---------------------------------------------------[ UART configuration ]---*/
1192 1748 jeremybenn
static void
1193
uart_baseaddr (union param_val val, void *dat)
1194 1358 nogj
{
1195 1367 nogj
  struct dev_16450 *uart = dat;
1196
  uart->baseaddr = val.addr_val;
1197 1358 nogj
}
1198
 
1199 1748 jeremybenn
static void
1200
uart_jitter (union param_val val, void *dat)
1201 1358 nogj
{
1202 1367 nogj
  struct dev_16450 *uart = dat;
1203
  uart->jitter = val.int_val;
1204 1358 nogj
}
1205
 
1206 1748 jeremybenn
static void
1207
uart_irq (union param_val val, void *dat)
1208 1358 nogj
{
1209 1367 nogj
  struct dev_16450 *uart = dat;
1210
  uart->irq = val.int_val;
1211 1358 nogj
}
1212
 
1213 1748 jeremybenn
static void
1214
uart_16550 (union param_val val, void *dat)
1215 1358 nogj
{
1216 1367 nogj
  struct dev_16450 *uart = dat;
1217
  uart->uart16550 = val.int_val;
1218 1358 nogj
}
1219
 
1220 1748 jeremybenn
/*---------------------------------------------------------------------------*/
1221
/*!Set the channel description
1222
 
1223
   Free any existing string.
1224
 
1225
   @param[in] val  The value to use
1226
   @param[in] dat  The config data structure                                 */
1227
/*---------------------------------------------------------------------------*/
1228
static void
1229
uart_channel (union param_val  val,
1230
              void            *dat)
1231 1358 nogj
{
1232 1367 nogj
  struct dev_16450 *uart = dat;
1233 1358 nogj
 
1234 1748 jeremybenn
  if (NULL != uart->channel_str)
1235
    {
1236
      free (uart->channel_str);
1237
      uart->channel_str = NULL;
1238
    }
1239
 
1240
  if (!(uart->channel_str = strdup (val.str_val)))
1241
    {
1242
      fprintf (stderr, "Peripheral 16450: Run out of memory\n");
1243
      exit (-1);
1244
    }
1245
 
1246
}       /* uart_channel() */
1247
 
1248
 
1249
static void
1250
uart_newway (union param_val val, void *dat)
1251 1358 nogj
{
1252 1751 jeremybenn
  fprintf (stderr, "Warning: txfile and rxfile now obsolete and ignored. "
1253
           "Use 'channel = \"file:rxfile,txfile\"'.");
1254 1358 nogj
}
1255
 
1256 1748 jeremybenn
static void
1257
uart_vapi_id (union param_val val, void *dat)
1258 1358 nogj
{
1259 1367 nogj
  struct dev_16450 *uart = dat;
1260
  uart->vapi_id = val.int_val;
1261 1358 nogj
}
1262
 
1263 1748 jeremybenn
static void
1264
uart_enabled (union param_val val, void *dat)
1265 1461 nogj
{
1266
  struct dev_16450 *uart = dat;
1267
  uart->enabled = val.int_val;
1268
}
1269
 
1270 1748 jeremybenn
 
1271
/*---------------------------------------------------------------------------*/
1272
/*!Initialize a new UART configuration
1273
 
1274
   ALL parameters are set explicitly to default values.                      */
1275
/*---------------------------------------------------------------------------*/
1276
static void *
1277
uart_sec_start ()
1278 1367 nogj
{
1279 1748 jeremybenn
  struct dev_16450 *new = malloc (sizeof (struct dev_16450));
1280 1367 nogj
 
1281 1748 jeremybenn
  if (!new)
1282
    {
1283
      fprintf (stderr, "Peripheral 16450: Run out of memory\n");
1284
      exit (-1);
1285
    }
1286 1367 nogj
 
1287 1461 nogj
  new->enabled = 1;
1288 1748 jeremybenn
  new->baseaddr = 0;
1289
  new->irq = 0;
1290
  new->uart16550 = 0;
1291
  new->jitter = 0;
1292
  new->channel_str = strdup ("xterm:");
1293 1367 nogj
  new->vapi_id = 0;
1294
 
1295 1748 jeremybenn
  new->channel = NULL;
1296
 
1297 1367 nogj
  return new;
1298
 
1299 1748 jeremybenn
}       /* uart_sec_start() */
1300
 
1301
 
1302
static void
1303
uart_sec_end (void *dat)
1304 1367 nogj
{
1305
  struct dev_16450 *uart = dat;
1306 1486 nogj
  struct mem_ops ops;
1307 1367 nogj
 
1308 1748 jeremybenn
  if (!uart->enabled)
1309
    {
1310
      free (dat);
1311
      return;
1312
    }
1313 1486 nogj
 
1314 1748 jeremybenn
  memset (&ops, 0, sizeof (struct mem_ops));
1315 1486 nogj
 
1316
  ops.readfunc8 = uart_read_byte;
1317
  ops.writefunc8 = uart_write_byte;
1318
  ops.read_dat8 = dat;
1319
  ops.write_dat8 = dat;
1320
 
1321
  /* FIXME: What should these be? */
1322
  ops.delayr = 2;
1323
  ops.delayw = 2;
1324
 
1325 1748 jeremybenn
  reg_mem_area (uart->baseaddr, UART_ADDR_SPACE, 0, &ops);
1326 1486 nogj
 
1327 1748 jeremybenn
  reg_sim_reset (uart_reset, dat);
1328
  reg_sim_stat (uart_status, dat);
1329 1367 nogj
}
1330
 
1331 1748 jeremybenn
void
1332
reg_uart_sec (void)
1333 1358 nogj
{
1334 1748 jeremybenn
  struct config_section *sec = reg_config_sec ("uart", uart_sec_start,
1335
                                               uart_sec_end);
1336 1358 nogj
 
1337 1748 jeremybenn
  reg_config_param (sec, "enabled", paramt_int, uart_enabled);
1338
  reg_config_param (sec, "baseaddr", paramt_addr, uart_baseaddr);
1339
  reg_config_param (sec, "irq", paramt_int, uart_irq);
1340
  reg_config_param (sec, "16550", paramt_int, uart_16550);
1341
  reg_config_param (sec, "jitter", paramt_int, uart_jitter);
1342
  reg_config_param (sec, "channel", paramt_str, uart_channel);
1343
  reg_config_param (sec, "txfile", paramt_str, uart_newway);
1344
  reg_config_param (sec, "rxfile", paramt_str, uart_newway);
1345
  reg_config_param (sec, "vapi_id", paramt_int, uart_vapi_id);
1346 1358 nogj
}

powered by: WebSVN 2.1.0

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