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
};
|