Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
staging
speakup
serialio.c
Go to the documentation of this file.
1
#include <
linux/interrupt.h
>
2
#include <
linux/ioport.h
>
3
4
#include "
spk_types.h
"
5
#include "
speakup.h
"
6
#include "
spk_priv.h
"
7
#include "
serialio.h
"
8
9
static
void
start_serial_interrupt(
int
irq);
10
11
static
const
struct
old_serial_port
rs_table[] = {
12
SERIAL_PORT_DFNS
13
};
14
static
const
struct
old_serial_port
*serstate;
15
static
int
timeouts;
16
17
const
struct
old_serial_port
*
spk_serial_init
(
int
index
)
18
{
19
int
baud
= 9600, quot = 0;
20
unsigned
int
cval = 0;
21
int
cflag
=
CREAD
|
HUPCL
|
CLOCAL
|
B9600
|
CS8
;
22
const
struct
old_serial_port
*
ser
= rs_table +
index
;
23
int
err
;
24
25
/* Divisor, bytesize and parity */
26
quot = ser->
baud_base
/
baud
;
27
cval = cflag & (
CSIZE
|
CSTOPB
);
28
#if defined(__powerpc__) || defined(__alpha__)
29
cval >>= 8;
30
#else
/* !__powerpc__ && !__alpha__ */
31
cval >>= 4;
32
#endif
/* !__powerpc__ && !__alpha__ */
33
if
(cflag &
PARENB
)
34
cval |=
UART_LCR_PARITY
;
35
if
(!(cflag &
PARODD
))
36
cval |=
UART_LCR_EPAR
;
37
if
(
synth_request_region
(ser->
port
, 8)) {
38
/* try to take it back. */
39
printk
(
KERN_INFO
"Ports not available, trying to steal them\n"
);
40
__release_region
(&
ioport_resource
, ser->
port
, 8);
41
err =
synth_request_region
(ser->
port
, 8);
42
if
(err) {
43
pr_warn
(
"Unable to allocate port at %x, errno %i"
,
44
ser->
port
, err);
45
return
NULL
;
46
}
47
}
48
49
/* Disable UART interrupts, set DTR and RTS high
50
* and set speed. */
51
outb
(cval |
UART_LCR_DLAB
, ser->
port
+
UART_LCR
);
/* set DLAB */
52
outb
(quot & 0xff, ser->
port
+
UART_DLL
);
/* LS of divisor */
53
outb
(quot >> 8, ser->
port
+
UART_DLM
);
/* MS of divisor */
54
outb
(cval, ser->
port
+
UART_LCR
);
/* reset DLAB */
55
56
/* Turn off Interrupts */
57
outb
(0, ser->
port
+
UART_IER
);
58
outb
(
UART_MCR_DTR
|
UART_MCR_RTS
, ser->
port
+
UART_MCR
);
59
60
/* If we read 0xff from the LSR, there is no UART here. */
61
if
(
inb
(ser->
port
+
UART_LSR
) == 0xff) {
62
synth_release_region
(ser->
port
, 8);
63
serstate =
NULL
;
64
return
NULL
;
65
}
66
67
mdelay
(1);
68
speakup_info
.port_tts = ser->
port
;
69
serstate =
ser
;
70
71
start_serial_interrupt(ser->
irq
);
72
73
return
ser
;
74
}
75
76
static
irqreturn_t
synth_readbuf_handler(
int
irq
,
void
*
dev_id
)
77
{
78
unsigned
long
flags
;
79
/*printk(KERN_ERR "in irq\n"); */
80
/*pr_warn("in IRQ\n"); */
81
int
c
;
82
spk_lock
(flags);
83
while
(
inb_p
(
speakup_info
.port_tts +
UART_LSR
) &
UART_LSR_DR
) {
84
85
c =
inb_p
(
speakup_info
.port_tts+
UART_RX
);
86
synth
->read_buff_add((
u_char
) c);
87
/*printk(KERN_ERR "c = %d\n", c); */
88
/*pr_warn("C = %d\n", c); */
89
}
90
spk_unlock
(flags);
91
return
IRQ_HANDLED
;
92
}
93
94
static
void
start_serial_interrupt(
int
irq)
95
{
96
int
rv;
97
98
if
(
synth
->read_buff_add ==
NULL
)
99
return
;
100
101
rv =
request_irq
(irq, synth_readbuf_handler,
IRQF_SHARED
,
102
"serial"
, (
void
*) synth_readbuf_handler);
103
104
if
(rv)
105
printk
(
KERN_ERR
"Unable to request Speakup serial I R Q\n"
);
106
/* Set MCR */
107
outb
(
UART_MCR_DTR
|
UART_MCR_RTS
|
UART_MCR_OUT2
,
108
speakup_info
.port_tts +
UART_MCR
);
109
/* Turn on Interrupts */
110
outb
(
UART_IER_MSI
|
UART_IER_RLSI
|
UART_IER_RDI
,
111
speakup_info
.port_tts +
UART_IER
);
112
inb
(
speakup_info
.port_tts+
UART_LSR
);
113
inb
(
speakup_info
.port_tts+
UART_RX
);
114
inb
(
speakup_info
.port_tts+
UART_IIR
);
115
inb
(
speakup_info
.port_tts+
UART_MSR
);
116
outb
(1,
speakup_info
.port_tts +
UART_FCR
);
/* Turn FIFO On */
117
}
118
119
void
stop_serial_interrupt
(
void
)
120
{
121
if
(
speakup_info
.port_tts == 0)
122
return
;
123
124
if
(
synth
->read_buff_add ==
NULL
)
125
return
;
126
127
/* Turn off interrupts */
128
outb
(0,
speakup_info
.port_tts+
UART_IER
);
129
/* Free IRQ */
130
free_irq
(serstate->
irq
, (
void
*) synth_readbuf_handler);
131
}
132
133
int
wait_for_xmitr
(
void
)
134
{
135
int
tmout =
SPK_XMITR_TIMEOUT
;
136
if
((
synth
->alive) && (timeouts >=
NUM_DISABLE_TIMEOUTS
)) {
137
pr_warn
(
"%s: too many timeouts, deactivating speakup\n"
,
138
synth
->long_name);
139
synth
->alive = 0;
140
/* No synth any more, so nobody will restart TTYs, and we thus
141
* need to do it ourselves. Now that there is no synth we can
142
* let application flood anyway */
143
speakup_start_ttys
();
144
timeouts = 0;
145
return
0;
146
}
147
while
(
spk_serial_tx_busy
()) {
148
if
(--tmout == 0) {
149
pr_warn
(
"%s: timed out (tx busy)\n"
,
synth
->long_name);
150
timeouts++;
151
return
0;
152
}
153
udelay
(1);
154
}
155
tmout =
SPK_CTS_TIMEOUT
;
156
while
(!((
inb_p
(
speakup_info
.port_tts +
UART_MSR
)) &
UART_MSR_CTS
)) {
157
/* CTS */
158
if
(--tmout == 0) {
159
/* pr_warn("%s: timed out (cts)\n",
160
* synth->long_name); */
161
timeouts++;
162
return
0;
163
}
164
udelay
(1);
165
}
166
timeouts = 0;
167
return
1;
168
}
169
170
unsigned
char
spk_serial_in
(
void
)
171
{
172
int
tmout =
SPK_SERIAL_TIMEOUT
;
173
174
while
(!(
inb_p
(
speakup_info
.port_tts +
UART_LSR
) & UART_LSR_DR)) {
175
if
(--tmout == 0) {
176
pr_warn
(
"time out while waiting for input.\n"
);
177
return
0xff;
178
}
179
udelay
(1);
180
}
181
return
inb_p
(
speakup_info
.port_tts +
UART_RX
);
182
}
183
EXPORT_SYMBOL_GPL
(
spk_serial_in
);
184
185
unsigned
char
spk_serial_in_nowait
(
void
)
186
{
187
unsigned
char
lsr;
188
189
lsr =
inb_p
(
speakup_info
.port_tts +
UART_LSR
);
190
if
(!(lsr & UART_LSR_DR))
191
return
0;
192
return
inb_p
(
speakup_info
.port_tts +
UART_RX
);
193
}
194
EXPORT_SYMBOL_GPL
(
spk_serial_in_nowait
);
195
196
int
spk_serial_out
(
const
char
ch)
197
{
198
if
(
synth
->alive &&
wait_for_xmitr
()) {
199
outb_p
(ch,
speakup_info
.port_tts);
200
return
1;
201
}
202
return
0;
203
}
204
EXPORT_SYMBOL_GPL
(
spk_serial_out
);
205
206
void
spk_serial_release
(
void
)
207
{
208
if
(
speakup_info
.port_tts == 0)
209
return
;
210
synth_release_region
(
speakup_info
.port_tts, 8);
211
speakup_info
.port_tts = 0;
212
}
213
EXPORT_SYMBOL_GPL
(
spk_serial_release
);
214
Generated on Thu Jan 10 2013 14:31:42 for Linux Kernel by
1.8.2