aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ioemu/iodev/serial.h
blob: 00f01c976e324e170b8716f716942e7219447286 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/////////////////////////////////////////////////////////////////////////
// $Id: serial.h,v 1.15 2003/11/16 08:21:10 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA


// Peter Grehan (grehan@iprg.nokia.com) coded most of this
// serial emulation.

#if USE_RAW_SERIAL
#include "serial_raw.h"
#endif // USE_RAW_SERIAL

#if BX_USE_SER_SMF
#  define BX_SER_SMF  static
#  define BX_SER_THIS theSerialDevice->
#else
#  define BX_SER_SMF
#  define BX_SER_THIS this->
#endif

#define BX_SERIAL_MAXDEV   4

#define  BX_PC_CLOCK_XTL   1843200.0

#define  BX_SER_RXIDLE  0
#define  BX_SER_RXPOLL  1
#define  BX_SER_RXWAIT  2

enum {
  BX_SER_INT_IER,
  BX_SER_INT_RXDATA,
  BX_SER_INT_TXHOLD,
  BX_SER_INT_RXLSTAT,
  BX_SER_INT_MODSTAT,
  BX_SER_INT_FIFO
};

typedef struct {
  /*
   * UART internal state
   */
  bx_bool  ls_interrupt;
  bx_bool  ms_interrupt;
  bx_bool  rx_interrupt;
  bx_bool  tx_interrupt;
  bx_bool  fifo_interrupt;
  bx_bool  ls_ipending;
  bx_bool  ms_ipending;
  bx_bool  rx_ipending;
  bx_bool  fifo_ipending;

  Bit8u IRQ;

  Bit8u rx_fifo_end;
  Bit8u tx_fifo_end;

  int  baudrate;
  int  tx_timer_index;

  int  rx_pollstate;
  int  rx_timer_index;
  int  fifo_timer_index;

  /*
   * Register definitions
   */
  Bit8u     rxbuffer;     /* receiver buffer register (r/o) */
  Bit8u     thrbuffer;    /* transmit holding register (w/o) */
  /* Interrupt Enable Register */
  struct {
    bx_bool    rxdata_enable;      /* 1=enable receive data interrupts */
    bx_bool    txhold_enable;      /* 1=enable tx. holding reg. empty ints */
    bx_bool    rxlstat_enable;     /* 1=enable rx line status interrupts */
    bx_bool    modstat_enable;     /* 1=enable modem status interrupts */
  } int_enable;
  /* Interrupt Identification Register (r/o) */
  struct {
    bx_bool    ipending;           /* 0=interrupt pending */
    Bit8u      int_ID;             /* 3-bit interrupt ID */
  } int_ident;
  /* FIFO Control Register (w/o) */
  struct {
    bx_bool    enable;             /* 1=enable tx and rx FIFOs */
    Bit8u      rxtrigger;          /* 2-bit code for rx fifo trigger level */
  } fifo_cntl;
  /* Line Control Register (r/w) */
  struct {
    Bit8u      wordlen_sel;        /* 2-bit code for char length */
    bx_bool    stopbits;           /* select stop bit len */
    bx_bool    parity_enable;      /* ... */
    bx_bool    evenparity_sel;     /* ... */
    bx_bool    stick_parity;       /* ... */
    bx_bool    break_cntl;         /* 1=send break signal */
    bx_bool    dlab;               /* divisor latch access bit */
  } line_cntl;
  /* MODEM Control Register (r/w) */
  struct {
    bx_bool    dtr;                /* DTR output value */
    bx_bool    rts;                /* RTS output value */
    bx_bool    out1;               /* OUTPUT1 value */
    bx_bool    out2;               /* OUTPUT2 value */
    bx_bool    local_loopback;     /* 1=loopback mode */
  } modem_cntl;
  /* Line Status Register (r/w) */
  struct {
    bx_bool    rxdata_ready;       /* 1=receiver data ready */
    bx_bool    overrun_error;      /* 1=receive overrun detected */
    bx_bool    parity_error;       /* 1=rx char has a bad parity bit */
    bx_bool    framing_error;      /* 1=no stop bit detected for rx char */
    bx_bool    break_int;          /* 1=break signal detected */
    bx_bool    thr_empty;          /* 1=tx hold register (or fifo) is empty */
    bx_bool    tsr_empty;          /* 1=shift reg and hold reg empty */
    bx_bool    fifo_error;         /* 1=at least 1 err condition in fifo */
  } line_status;
  /* Modem Status Register (r/w) */
  struct {
    bx_bool    delta_cts;          /* 1=CTS changed since last read */
    bx_bool    delta_dsr;          /* 1=DSR changed since last read */
    bx_bool    ri_trailedge;       /* 1=RI moved from low->high */
    bx_bool    delta_dcd;          /* 1=CD changed since last read */
    bx_bool    cts;                /* CTS input value */
    bx_bool    dsr;                /* DSR input value */
    bx_bool    ri;                 /* RI input value */
    bx_bool    dcd;                /* DCD input value */
  } modem_status;

  Bit8u  scratch;       /* Scratch Register (r/w) */
  Bit8u  tsrbuffer;     /* transmit shift register (internal) */
  Bit8u  rx_fifo[16];   /* receive FIFO (internal) */
  Bit8u  tx_fifo[16];   /* transmit FIFO (internal) */
  Bit8u  divisor_lsb;   /* Divisor latch, least-sig. byte */
  Bit8u  divisor_msb;   /* Divisor latch, most-sig. byte */
} bx_serial_t;



class bx_serial_c : public bx_devmodel_c {
public:
  bx_serial_c(void);
  ~bx_serial_c(void);
  virtual void   init(void);
  virtual void   reset(unsigned type);
#if USE_RAW_SERIAL
  serial_raw* raw;
#endif // USE_RAW_SERIAL

private:
    bx_serial_t s[BX_SERIAL_MAXDEV];

  static void lower_interrupt(Bit8u port);
  static void raise_interrupt(Bit8u port, int type);

  static void rx_fifo_enq(Bit8u port, Bit8u data);

  static void tx_timer_handler(void *);
  BX_SER_SMF void tx_timer(void);

  static void rx_timer_handler(void *);
  BX_SER_SMF void rx_timer(void);

  static void fifo_timer_handler(void *);
  BX_SER_SMF void fifo_timer(void);

  static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
  static void   write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
#if !BX_USE_SER_SMF
  Bit32u read(Bit32u address, unsigned io_len);
  void   write(Bit32u address, Bit32u value, unsigned io_len);
#endif
  };