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

Subversion Repositories or1k

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

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

powered by: WebSVN 2.1.0

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