diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-02-22 19:57:21 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-02-22 19:57:21 -0500 |
commit | 4a6514e6d096716fb7bedf238efaaca877e2a7e8 (patch) | |
tree | e3601ee168cca90307ac91e750a86d6ed04eab01 /drivers/char | |
parent | 282361a046edd9d58a134f358a3f65a7cb8655d9 (diff) |
tty: move obsolete and broken tty drivers to drivers/staging/tty/
As planned by Arnd Bergmann, this moves the following drivers to the
drivers/staging/tty/ directory where they will be removed after 2.6.41
if no one steps up to claim them.
epca
epca
ip2
istallion
riscom8
serial167
specialix
stallion
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char')
27 files changed, 0 insertions, 28968 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 1adfac6a7b0b..7b8cf0295f6c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -15,63 +15,6 @@ config DEVKMEM | |||
15 | kind of kernel debugging operations. | 15 | kind of kernel debugging operations. |
16 | When in doubt, say "N". | 16 | When in doubt, say "N". |
17 | 17 | ||
18 | config COMPUTONE | ||
19 | tristate "Computone IntelliPort Plus serial support" | ||
20 | depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) | ||
21 | ---help--- | ||
22 | This driver supports the entire family of Intelliport II/Plus | ||
23 | controllers with the exception of the MicroChannel controllers and | ||
24 | products previous to the Intelliport II. These are multiport cards, | ||
25 | which give you many serial ports. You would need something like this | ||
26 | to connect more than two modems to your Linux box, for instance in | ||
27 | order to become a dial-in server. If you have a card like that, say | ||
28 | Y here and read <file:Documentation/serial/computone.txt>. | ||
29 | |||
30 | To compile this driver as module, choose M here: the | ||
31 | module will be called ip2. | ||
32 | |||
33 | config DIGIEPCA | ||
34 | tristate "Digiboard Intelligent Async Support" | ||
35 | depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) | ||
36 | ---help--- | ||
37 | This is a driver for Digi International's Xx, Xeve, and Xem series | ||
38 | of cards which provide multiple serial ports. You would need | ||
39 | something like this to connect more than two modems to your Linux | ||
40 | box, for instance in order to become a dial-in server. This driver | ||
41 | supports the original PC (ISA) boards as well as PCI, and EISA. If | ||
42 | you have a card like this, say Y here and read the file | ||
43 | <file:Documentation/serial/digiepca.txt>. | ||
44 | |||
45 | To compile this driver as a module, choose M here: the | ||
46 | module will be called epca. | ||
47 | |||
48 | config RISCOM8 | ||
49 | tristate "SDL RISCom/8 card support" | ||
50 | depends on SERIAL_NONSTANDARD | ||
51 | help | ||
52 | This is a driver for the SDL Communications RISCom/8 multiport card, | ||
53 | which gives you many serial ports. You would need something like | ||
54 | this to connect more than two modems to your Linux box, for instance | ||
55 | in order to become a dial-in server. If you have a card like that, | ||
56 | say Y here and read the file <file:Documentation/serial/riscom8.txt>. | ||
57 | |||
58 | Also it's possible to say M here and compile this driver as kernel | ||
59 | loadable module; the module will be called riscom8. | ||
60 | |||
61 | config SPECIALIX | ||
62 | tristate "Specialix IO8+ card support" | ||
63 | depends on SERIAL_NONSTANDARD | ||
64 | help | ||
65 | This is a driver for the Specialix IO8+ multiport card (both the | ||
66 | ISA and the PCI version) which gives you many serial ports. You | ||
67 | would need something like this to connect more than two modems to | ||
68 | your Linux box, for instance in order to become a dial-in server. | ||
69 | |||
70 | If you have a card like that, say Y here and read the file | ||
71 | <file:Documentation/serial/specialix.txt>. Also it's possible to say | ||
72 | M here and compile this driver as kernel loadable module which will be | ||
73 | called specialix. | ||
74 | |||
75 | config SX | 18 | config SX |
76 | tristate "Specialix SX (and SI) card support" | 19 | tristate "Specialix SX (and SI) card support" |
77 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN | 20 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN |
@@ -112,28 +55,6 @@ config STALDRV | |||
112 | in this case. If you have never heard about all this, it's safe to | 55 | in this case. If you have never heard about all this, it's safe to |
113 | say N. | 56 | say N. |
114 | 57 | ||
115 | config STALLION | ||
116 | tristate "Stallion EasyIO or EC8/32 support" | ||
117 | depends on STALDRV && (ISA || EISA || PCI) | ||
118 | help | ||
119 | If you have an EasyIO or EasyConnection 8/32 multiport Stallion | ||
120 | card, then this is for you; say Y. Make sure to read | ||
121 | <file:Documentation/serial/stallion.txt>. | ||
122 | |||
123 | To compile this driver as a module, choose M here: the | ||
124 | module will be called stallion. | ||
125 | |||
126 | config ISTALLION | ||
127 | tristate "Stallion EC8/64, ONboard, Brumby support" | ||
128 | depends on STALDRV && (ISA || EISA || PCI) | ||
129 | help | ||
130 | If you have an EasyConnection 8/64, ONboard, Brumby or Stallion | ||
131 | serial multiport card, say Y here. Make sure to read | ||
132 | <file:Documentation/serial/stallion.txt>. | ||
133 | |||
134 | To compile this driver as a module, choose M here: the | ||
135 | module will be called istallion. | ||
136 | |||
137 | config A2232 | 58 | config A2232 |
138 | tristate "Commodore A2232 serial support (EXPERIMENTAL)" | 59 | tristate "Commodore A2232 serial support (EXPERIMENTAL)" |
139 | depends on EXPERIMENTAL && ZORRO && BROKEN | 60 | depends on EXPERIMENTAL && ZORRO && BROKEN |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index f5dc7c9bce6b..48bb8acbea49 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -8,15 +8,8 @@ obj-y += misc.o | |||
8 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o | 8 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o |
9 | obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o | 9 | obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o |
10 | obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o | 10 | obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o |
11 | obj-$(CONFIG_SERIAL167) += serial167.o | ||
12 | obj-$(CONFIG_STALLION) += stallion.o | ||
13 | obj-$(CONFIG_ISTALLION) += istallion.o | ||
14 | obj-$(CONFIG_DIGIEPCA) += epca.o | ||
15 | obj-$(CONFIG_SPECIALIX) += specialix.o | ||
16 | obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o | 11 | obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o |
17 | obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o | 12 | obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o |
18 | obj-$(CONFIG_COMPUTONE) += ip2/ | ||
19 | obj-$(CONFIG_RISCOM8) += riscom8.o | ||
20 | obj-$(CONFIG_SX) += sx.o generic_serial.o | 13 | obj-$(CONFIG_SX) += sx.o generic_serial.o |
21 | obj-$(CONFIG_RIO) += rio/ generic_serial.o | 14 | obj-$(CONFIG_RIO) += rio/ generic_serial.o |
22 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 15 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c deleted file mode 100644 index 7ad3638967ae..000000000000 --- a/drivers/char/epca.c +++ /dev/null | |||
@@ -1,2784 +0,0 @@ | |||
1 | /* | ||
2 | Copyright (C) 1996 Digi International. | ||
3 | |||
4 | For technical support please email digiLinux@dgii.com or | ||
5 | call Digi tech support at (612) 912-3456 | ||
6 | |||
7 | ** This driver is no longer supported by Digi ** | ||
8 | |||
9 | Much of this design and code came from epca.c which was | ||
10 | copyright (C) 1994, 1995 Troy De Jongh, and subsquently | ||
11 | modified by David Nugent, Christoph Lameter, Mike McLagan. | ||
12 | |||
13 | This program is free software; you can redistribute it and/or modify | ||
14 | it under the terms of the GNU General Public License as published by | ||
15 | the Free Software Foundation; either version 2 of the License, or | ||
16 | (at your option) any later version. | ||
17 | |||
18 | This program is distributed in the hope that it will be useful, | ||
19 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | GNU General Public License for more details. | ||
22 | |||
23 | You should have received a copy of the GNU General Public License | ||
24 | along with this program; if not, write to the Free Software | ||
25 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | /* See README.epca for change history --DAT*/ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/serial.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/ctype.h> | ||
37 | #include <linux/tty.h> | ||
38 | #include <linux/tty_flip.h> | ||
39 | #include <linux/slab.h> | ||
40 | #include <linux/ioport.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <linux/uaccess.h> | ||
43 | #include <linux/io.h> | ||
44 | #include <linux/spinlock.h> | ||
45 | #include <linux/pci.h> | ||
46 | #include "digiPCI.h" | ||
47 | |||
48 | |||
49 | #include "digi1.h" | ||
50 | #include "digiFep1.h" | ||
51 | #include "epca.h" | ||
52 | #include "epcaconfig.h" | ||
53 | |||
54 | #define VERSION "1.3.0.1-LK2.6" | ||
55 | |||
56 | /* This major needs to be submitted to Linux to join the majors list */ | ||
57 | #define DIGIINFOMAJOR 35 /* For Digi specific ioctl */ | ||
58 | |||
59 | |||
60 | #define MAXCARDS 7 | ||
61 | #define epcaassert(x, msg) if (!(x)) epca_error(__LINE__, msg) | ||
62 | |||
63 | #define PFX "epca: " | ||
64 | |||
65 | static int nbdevs, num_cards, liloconfig; | ||
66 | static int digi_poller_inhibited = 1 ; | ||
67 | |||
68 | static int setup_error_code; | ||
69 | static int invalid_lilo_config; | ||
70 | |||
71 | /* | ||
72 | * The ISA boards do window flipping into the same spaces so its only sane with | ||
73 | * a single lock. It's still pretty efficient. This lock guards the hardware | ||
74 | * and the tty_port lock guards the kernel side stuff like use counts. Take | ||
75 | * this lock inside the port lock if you must take both. | ||
76 | */ | ||
77 | static DEFINE_SPINLOCK(epca_lock); | ||
78 | |||
79 | /* MAXBOARDS is typically 12, but ISA and EISA cards are restricted | ||
80 | to 7 below. */ | ||
81 | static struct board_info boards[MAXBOARDS]; | ||
82 | |||
83 | static struct tty_driver *pc_driver; | ||
84 | static struct tty_driver *pc_info; | ||
85 | |||
86 | /* ------------------ Begin Digi specific structures -------------------- */ | ||
87 | |||
88 | /* | ||
89 | * digi_channels represents an array of structures that keep track of each | ||
90 | * channel of the Digi product. Information such as transmit and receive | ||
91 | * pointers, termio data, and signal definitions (DTR, CTS, etc ...) are stored | ||
92 | * here. This structure is NOT used to overlay the cards physical channel | ||
93 | * structure. | ||
94 | */ | ||
95 | static struct channel digi_channels[MAX_ALLOC]; | ||
96 | |||
97 | /* | ||
98 | * card_ptr is an array used to hold the address of the first channel structure | ||
99 | * of each card. This array will hold the addresses of various channels located | ||
100 | * in digi_channels. | ||
101 | */ | ||
102 | static struct channel *card_ptr[MAXCARDS]; | ||
103 | |||
104 | static struct timer_list epca_timer; | ||
105 | |||
106 | /* | ||
107 | * Begin generic memory functions. These functions will be alias (point at) | ||
108 | * more specific functions dependent on the board being configured. | ||
109 | */ | ||
110 | static void memwinon(struct board_info *b, unsigned int win); | ||
111 | static void memwinoff(struct board_info *b, unsigned int win); | ||
112 | static void globalwinon(struct channel *ch); | ||
113 | static void rxwinon(struct channel *ch); | ||
114 | static void txwinon(struct channel *ch); | ||
115 | static void memoff(struct channel *ch); | ||
116 | static void assertgwinon(struct channel *ch); | ||
117 | static void assertmemoff(struct channel *ch); | ||
118 | |||
119 | /* ---- Begin more 'specific' memory functions for cx_like products --- */ | ||
120 | |||
121 | static void pcxem_memwinon(struct board_info *b, unsigned int win); | ||
122 | static void pcxem_memwinoff(struct board_info *b, unsigned int win); | ||
123 | static void pcxem_globalwinon(struct channel *ch); | ||
124 | static void pcxem_rxwinon(struct channel *ch); | ||
125 | static void pcxem_txwinon(struct channel *ch); | ||
126 | static void pcxem_memoff(struct channel *ch); | ||
127 | |||
128 | /* ------ Begin more 'specific' memory functions for the pcxe ------- */ | ||
129 | |||
130 | static void pcxe_memwinon(struct board_info *b, unsigned int win); | ||
131 | static void pcxe_memwinoff(struct board_info *b, unsigned int win); | ||
132 | static void pcxe_globalwinon(struct channel *ch); | ||
133 | static void pcxe_rxwinon(struct channel *ch); | ||
134 | static void pcxe_txwinon(struct channel *ch); | ||
135 | static void pcxe_memoff(struct channel *ch); | ||
136 | |||
137 | /* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */ | ||
138 | /* Note : pc64xe and pcxi share the same windowing routines */ | ||
139 | |||
140 | static void pcxi_memwinon(struct board_info *b, unsigned int win); | ||
141 | static void pcxi_memwinoff(struct board_info *b, unsigned int win); | ||
142 | static void pcxi_globalwinon(struct channel *ch); | ||
143 | static void pcxi_rxwinon(struct channel *ch); | ||
144 | static void pcxi_txwinon(struct channel *ch); | ||
145 | static void pcxi_memoff(struct channel *ch); | ||
146 | |||
147 | /* - Begin 'specific' do nothing memory functions needed for some cards - */ | ||
148 | |||
149 | static void dummy_memwinon(struct board_info *b, unsigned int win); | ||
150 | static void dummy_memwinoff(struct board_info *b, unsigned int win); | ||
151 | static void dummy_globalwinon(struct channel *ch); | ||
152 | static void dummy_rxwinon(struct channel *ch); | ||
153 | static void dummy_txwinon(struct channel *ch); | ||
154 | static void dummy_memoff(struct channel *ch); | ||
155 | static void dummy_assertgwinon(struct channel *ch); | ||
156 | static void dummy_assertmemoff(struct channel *ch); | ||
157 | |||
158 | static struct channel *verifyChannel(struct tty_struct *); | ||
159 | static void pc_sched_event(struct channel *, int); | ||
160 | static void epca_error(int, char *); | ||
161 | static void pc_close(struct tty_struct *, struct file *); | ||
162 | static void shutdown(struct channel *, struct tty_struct *tty); | ||
163 | static void pc_hangup(struct tty_struct *); | ||
164 | static int pc_write_room(struct tty_struct *); | ||
165 | static int pc_chars_in_buffer(struct tty_struct *); | ||
166 | static void pc_flush_buffer(struct tty_struct *); | ||
167 | static void pc_flush_chars(struct tty_struct *); | ||
168 | static int pc_open(struct tty_struct *, struct file *); | ||
169 | static void post_fep_init(unsigned int crd); | ||
170 | static void epcapoll(unsigned long); | ||
171 | static void doevent(int); | ||
172 | static void fepcmd(struct channel *, int, int, int, int, int); | ||
173 | static unsigned termios2digi_h(struct channel *ch, unsigned); | ||
174 | static unsigned termios2digi_i(struct channel *ch, unsigned); | ||
175 | static unsigned termios2digi_c(struct channel *ch, unsigned); | ||
176 | static void epcaparam(struct tty_struct *, struct channel *); | ||
177 | static void receive_data(struct channel *, struct tty_struct *tty); | ||
178 | static int pc_ioctl(struct tty_struct *, | ||
179 | unsigned int, unsigned long); | ||
180 | static int info_ioctl(struct tty_struct *, | ||
181 | unsigned int, unsigned long); | ||
182 | static void pc_set_termios(struct tty_struct *, struct ktermios *); | ||
183 | static void do_softint(struct work_struct *work); | ||
184 | static void pc_stop(struct tty_struct *); | ||
185 | static void pc_start(struct tty_struct *); | ||
186 | static void pc_throttle(struct tty_struct *tty); | ||
187 | static void pc_unthrottle(struct tty_struct *tty); | ||
188 | static int pc_send_break(struct tty_struct *tty, int msec); | ||
189 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch); | ||
190 | |||
191 | static int pc_write(struct tty_struct *, const unsigned char *, int); | ||
192 | static int pc_init(void); | ||
193 | static int init_PCI(void); | ||
194 | |||
195 | /* | ||
196 | * Table of functions for each board to handle memory. Mantaining parallelism | ||
197 | * is a *very* good idea here. The idea is for the runtime code to blindly call | ||
198 | * these functions, not knowing/caring about the underlying hardware. This | ||
199 | * stuff should contain no conditionals; if more functionality is needed a | ||
200 | * different entry should be established. These calls are the interface calls | ||
201 | * and are the only functions that should be accessed. Anyone caught making | ||
202 | * direct calls deserves what they get. | ||
203 | */ | ||
204 | static void memwinon(struct board_info *b, unsigned int win) | ||
205 | { | ||
206 | b->memwinon(b, win); | ||
207 | } | ||
208 | |||
209 | static void memwinoff(struct board_info *b, unsigned int win) | ||
210 | { | ||
211 | b->memwinoff(b, win); | ||
212 | } | ||
213 | |||
214 | static void globalwinon(struct channel *ch) | ||
215 | { | ||
216 | ch->board->globalwinon(ch); | ||
217 | } | ||
218 | |||
219 | static void rxwinon(struct channel *ch) | ||
220 | { | ||
221 | ch->board->rxwinon(ch); | ||
222 | } | ||
223 | |||
224 | static void txwinon(struct channel *ch) | ||
225 | { | ||
226 | ch->board->txwinon(ch); | ||
227 | } | ||
228 | |||
229 | static void memoff(struct channel *ch) | ||
230 | { | ||
231 | ch->board->memoff(ch); | ||
232 | } | ||
233 | static void assertgwinon(struct channel *ch) | ||
234 | { | ||
235 | ch->board->assertgwinon(ch); | ||
236 | } | ||
237 | |||
238 | static void assertmemoff(struct channel *ch) | ||
239 | { | ||
240 | ch->board->assertmemoff(ch); | ||
241 | } | ||
242 | |||
243 | /* PCXEM windowing is the same as that used in the PCXR and CX series cards. */ | ||
244 | static void pcxem_memwinon(struct board_info *b, unsigned int win) | ||
245 | { | ||
246 | outb_p(FEPWIN | win, b->port + 1); | ||
247 | } | ||
248 | |||
249 | static void pcxem_memwinoff(struct board_info *b, unsigned int win) | ||
250 | { | ||
251 | outb_p(0, b->port + 1); | ||
252 | } | ||
253 | |||
254 | static void pcxem_globalwinon(struct channel *ch) | ||
255 | { | ||
256 | outb_p(FEPWIN, (int)ch->board->port + 1); | ||
257 | } | ||
258 | |||
259 | static void pcxem_rxwinon(struct channel *ch) | ||
260 | { | ||
261 | outb_p(ch->rxwin, (int)ch->board->port + 1); | ||
262 | } | ||
263 | |||
264 | static void pcxem_txwinon(struct channel *ch) | ||
265 | { | ||
266 | outb_p(ch->txwin, (int)ch->board->port + 1); | ||
267 | } | ||
268 | |||
269 | static void pcxem_memoff(struct channel *ch) | ||
270 | { | ||
271 | outb_p(0, (int)ch->board->port + 1); | ||
272 | } | ||
273 | |||
274 | /* ----------------- Begin pcxe memory window stuff ------------------ */ | ||
275 | static void pcxe_memwinon(struct board_info *b, unsigned int win) | ||
276 | { | ||
277 | outb_p(FEPWIN | win, b->port + 1); | ||
278 | } | ||
279 | |||
280 | static void pcxe_memwinoff(struct board_info *b, unsigned int win) | ||
281 | { | ||
282 | outb_p(inb(b->port) & ~FEPMEM, b->port + 1); | ||
283 | outb_p(0, b->port + 1); | ||
284 | } | ||
285 | |||
286 | static void pcxe_globalwinon(struct channel *ch) | ||
287 | { | ||
288 | outb_p(FEPWIN, (int)ch->board->port + 1); | ||
289 | } | ||
290 | |||
291 | static void pcxe_rxwinon(struct channel *ch) | ||
292 | { | ||
293 | outb_p(ch->rxwin, (int)ch->board->port + 1); | ||
294 | } | ||
295 | |||
296 | static void pcxe_txwinon(struct channel *ch) | ||
297 | { | ||
298 | outb_p(ch->txwin, (int)ch->board->port + 1); | ||
299 | } | ||
300 | |||
301 | static void pcxe_memoff(struct channel *ch) | ||
302 | { | ||
303 | outb_p(0, (int)ch->board->port); | ||
304 | outb_p(0, (int)ch->board->port + 1); | ||
305 | } | ||
306 | |||
307 | /* ------------- Begin pc64xe and pcxi memory window stuff -------------- */ | ||
308 | static void pcxi_memwinon(struct board_info *b, unsigned int win) | ||
309 | { | ||
310 | outb_p(inb(b->port) | FEPMEM, b->port); | ||
311 | } | ||
312 | |||
313 | static void pcxi_memwinoff(struct board_info *b, unsigned int win) | ||
314 | { | ||
315 | outb_p(inb(b->port) & ~FEPMEM, b->port); | ||
316 | } | ||
317 | |||
318 | static void pcxi_globalwinon(struct channel *ch) | ||
319 | { | ||
320 | outb_p(FEPMEM, ch->board->port); | ||
321 | } | ||
322 | |||
323 | static void pcxi_rxwinon(struct channel *ch) | ||
324 | { | ||
325 | outb_p(FEPMEM, ch->board->port); | ||
326 | } | ||
327 | |||
328 | static void pcxi_txwinon(struct channel *ch) | ||
329 | { | ||
330 | outb_p(FEPMEM, ch->board->port); | ||
331 | } | ||
332 | |||
333 | static void pcxi_memoff(struct channel *ch) | ||
334 | { | ||
335 | outb_p(0, ch->board->port); | ||
336 | } | ||
337 | |||
338 | static void pcxi_assertgwinon(struct channel *ch) | ||
339 | { | ||
340 | epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off"); | ||
341 | } | ||
342 | |||
343 | static void pcxi_assertmemoff(struct channel *ch) | ||
344 | { | ||
345 | epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on"); | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Not all of the cards need specific memory windowing routines. Some cards | ||
350 | * (Such as PCI) needs no windowing routines at all. We provide these do | ||
351 | * nothing routines so that the same code base can be used. The driver will | ||
352 | * ALWAYS call a windowing routine if it thinks it needs to; regardless of the | ||
353 | * card. However, dependent on the card the routine may or may not do anything. | ||
354 | */ | ||
355 | static void dummy_memwinon(struct board_info *b, unsigned int win) | ||
356 | { | ||
357 | } | ||
358 | |||
359 | static void dummy_memwinoff(struct board_info *b, unsigned int win) | ||
360 | { | ||
361 | } | ||
362 | |||
363 | static void dummy_globalwinon(struct channel *ch) | ||
364 | { | ||
365 | } | ||
366 | |||
367 | static void dummy_rxwinon(struct channel *ch) | ||
368 | { | ||
369 | } | ||
370 | |||
371 | static void dummy_txwinon(struct channel *ch) | ||
372 | { | ||
373 | } | ||
374 | |||
375 | static void dummy_memoff(struct channel *ch) | ||
376 | { | ||
377 | } | ||
378 | |||
379 | static void dummy_assertgwinon(struct channel *ch) | ||
380 | { | ||
381 | } | ||
382 | |||
383 | static void dummy_assertmemoff(struct channel *ch) | ||
384 | { | ||
385 | } | ||
386 | |||
387 | static struct channel *verifyChannel(struct tty_struct *tty) | ||
388 | { | ||
389 | /* | ||
390 | * This routine basically provides a sanity check. It insures that the | ||
391 | * channel returned is within the proper range of addresses as well as | ||
392 | * properly initialized. If some bogus info gets passed in | ||
393 | * through tty->driver_data this should catch it. | ||
394 | */ | ||
395 | if (tty) { | ||
396 | struct channel *ch = tty->driver_data; | ||
397 | if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) { | ||
398 | if (ch->magic == EPCA_MAGIC) | ||
399 | return ch; | ||
400 | } | ||
401 | } | ||
402 | return NULL; | ||
403 | } | ||
404 | |||
405 | static void pc_sched_event(struct channel *ch, int event) | ||
406 | { | ||
407 | /* | ||
408 | * We call this to schedule interrupt processing on some event. The | ||
409 | * kernel sees our request and calls the related routine in OUR driver. | ||
410 | */ | ||
411 | ch->event |= 1 << event; | ||
412 | schedule_work(&ch->tqueue); | ||
413 | } | ||
414 | |||
415 | static void epca_error(int line, char *msg) | ||
416 | { | ||
417 | printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg); | ||
418 | } | ||
419 | |||
420 | static void pc_close(struct tty_struct *tty, struct file *filp) | ||
421 | { | ||
422 | struct channel *ch; | ||
423 | struct tty_port *port; | ||
424 | /* | ||
425 | * verifyChannel returns the channel from the tty struct if it is | ||
426 | * valid. This serves as a sanity check. | ||
427 | */ | ||
428 | ch = verifyChannel(tty); | ||
429 | if (ch == NULL) | ||
430 | return; | ||
431 | port = &ch->port; | ||
432 | |||
433 | if (tty_port_close_start(port, tty, filp) == 0) | ||
434 | return; | ||
435 | |||
436 | pc_flush_buffer(tty); | ||
437 | shutdown(ch, tty); | ||
438 | |||
439 | tty_port_close_end(port, tty); | ||
440 | ch->event = 0; /* FIXME: review ch->event locking */ | ||
441 | tty_port_tty_set(port, NULL); | ||
442 | } | ||
443 | |||
444 | static void shutdown(struct channel *ch, struct tty_struct *tty) | ||
445 | { | ||
446 | unsigned long flags; | ||
447 | struct board_chan __iomem *bc; | ||
448 | struct tty_port *port = &ch->port; | ||
449 | |||
450 | if (!(port->flags & ASYNC_INITIALIZED)) | ||
451 | return; | ||
452 | |||
453 | spin_lock_irqsave(&epca_lock, flags); | ||
454 | |||
455 | globalwinon(ch); | ||
456 | bc = ch->brdchan; | ||
457 | |||
458 | /* | ||
459 | * In order for an event to be generated on the receipt of data the | ||
460 | * idata flag must be set. Since we are shutting down, this is not | ||
461 | * necessary clear this flag. | ||
462 | */ | ||
463 | if (bc) | ||
464 | writeb(0, &bc->idata); | ||
465 | |||
466 | /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */ | ||
467 | if (tty->termios->c_cflag & HUPCL) { | ||
468 | ch->omodem &= ~(ch->m_rts | ch->m_dtr); | ||
469 | fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1); | ||
470 | } | ||
471 | memoff(ch); | ||
472 | |||
473 | /* | ||
474 | * The channel has officialy been closed. The next time it is opened it | ||
475 | * will have to reinitialized. Set a flag to indicate this. | ||
476 | */ | ||
477 | /* Prevent future Digi programmed interrupts from coming active */ | ||
478 | port->flags &= ~ASYNC_INITIALIZED; | ||
479 | spin_unlock_irqrestore(&epca_lock, flags); | ||
480 | } | ||
481 | |||
482 | static void pc_hangup(struct tty_struct *tty) | ||
483 | { | ||
484 | struct channel *ch; | ||
485 | |||
486 | /* | ||
487 | * verifyChannel returns the channel from the tty struct if it is | ||
488 | * valid. This serves as a sanity check. | ||
489 | */ | ||
490 | ch = verifyChannel(tty); | ||
491 | if (ch != NULL) { | ||
492 | pc_flush_buffer(tty); | ||
493 | tty_ldisc_flush(tty); | ||
494 | shutdown(ch, tty); | ||
495 | |||
496 | ch->event = 0; /* FIXME: review locking of ch->event */ | ||
497 | tty_port_hangup(&ch->port); | ||
498 | } | ||
499 | } | ||
500 | |||
501 | static int pc_write(struct tty_struct *tty, | ||
502 | const unsigned char *buf, int bytesAvailable) | ||
503 | { | ||
504 | unsigned int head, tail; | ||
505 | int dataLen; | ||
506 | int size; | ||
507 | int amountCopied; | ||
508 | struct channel *ch; | ||
509 | unsigned long flags; | ||
510 | int remain; | ||
511 | struct board_chan __iomem *bc; | ||
512 | |||
513 | /* | ||
514 | * pc_write is primarily called directly by the kernel routine | ||
515 | * tty_write (Though it can also be called by put_char) found in | ||
516 | * tty_io.c. pc_write is passed a line discipline buffer where the data | ||
517 | * to be written out is stored. The line discipline implementation | ||
518 | * itself is done at the kernel level and is not brought into the | ||
519 | * driver. | ||
520 | */ | ||
521 | |||
522 | /* | ||
523 | * verifyChannel returns the channel from the tty struct if it is | ||
524 | * valid. This serves as a sanity check. | ||
525 | */ | ||
526 | ch = verifyChannel(tty); | ||
527 | if (ch == NULL) | ||
528 | return 0; | ||
529 | |||
530 | /* Make a pointer to the channel data structure found on the board. */ | ||
531 | bc = ch->brdchan; | ||
532 | size = ch->txbufsize; | ||
533 | amountCopied = 0; | ||
534 | |||
535 | spin_lock_irqsave(&epca_lock, flags); | ||
536 | globalwinon(ch); | ||
537 | |||
538 | head = readw(&bc->tin) & (size - 1); | ||
539 | tail = readw(&bc->tout); | ||
540 | |||
541 | if (tail != readw(&bc->tout)) | ||
542 | tail = readw(&bc->tout); | ||
543 | tail &= (size - 1); | ||
544 | |||
545 | if (head >= tail) { | ||
546 | /* head has not wrapped */ | ||
547 | /* | ||
548 | * remain (much like dataLen above) represents the total amount | ||
549 | * of space available on the card for data. Here dataLen | ||
550 | * represents the space existing between the head pointer and | ||
551 | * the end of buffer. This is important because a memcpy cannot | ||
552 | * be told to automatically wrap around when it hits the buffer | ||
553 | * end. | ||
554 | */ | ||
555 | dataLen = size - head; | ||
556 | remain = size - (head - tail) - 1; | ||
557 | } else { | ||
558 | /* head has wrapped around */ | ||
559 | remain = tail - head - 1; | ||
560 | dataLen = remain; | ||
561 | } | ||
562 | /* | ||
563 | * Check the space on the card. If we have more data than space; reduce | ||
564 | * the amount of data to fit the space. | ||
565 | */ | ||
566 | bytesAvailable = min(remain, bytesAvailable); | ||
567 | txwinon(ch); | ||
568 | while (bytesAvailable > 0) { | ||
569 | /* there is data to copy onto card */ | ||
570 | |||
571 | /* | ||
572 | * If head is not wrapped, the below will make sure the first | ||
573 | * data copy fills to the end of card buffer. | ||
574 | */ | ||
575 | dataLen = min(bytesAvailable, dataLen); | ||
576 | memcpy_toio(ch->txptr + head, buf, dataLen); | ||
577 | buf += dataLen; | ||
578 | head += dataLen; | ||
579 | amountCopied += dataLen; | ||
580 | bytesAvailable -= dataLen; | ||
581 | |||
582 | if (head >= size) { | ||
583 | head = 0; | ||
584 | dataLen = tail; | ||
585 | } | ||
586 | } | ||
587 | ch->statusflags |= TXBUSY; | ||
588 | globalwinon(ch); | ||
589 | writew(head, &bc->tin); | ||
590 | |||
591 | if ((ch->statusflags & LOWWAIT) == 0) { | ||
592 | ch->statusflags |= LOWWAIT; | ||
593 | writeb(1, &bc->ilow); | ||
594 | } | ||
595 | memoff(ch); | ||
596 | spin_unlock_irqrestore(&epca_lock, flags); | ||
597 | return amountCopied; | ||
598 | } | ||
599 | |||
600 | static int pc_write_room(struct tty_struct *tty) | ||
601 | { | ||
602 | int remain = 0; | ||
603 | struct channel *ch; | ||
604 | unsigned long flags; | ||
605 | unsigned int head, tail; | ||
606 | struct board_chan __iomem *bc; | ||
607 | /* | ||
608 | * verifyChannel returns the channel from the tty struct if it is | ||
609 | * valid. This serves as a sanity check. | ||
610 | */ | ||
611 | ch = verifyChannel(tty); | ||
612 | if (ch != NULL) { | ||
613 | spin_lock_irqsave(&epca_lock, flags); | ||
614 | globalwinon(ch); | ||
615 | |||
616 | bc = ch->brdchan; | ||
617 | head = readw(&bc->tin) & (ch->txbufsize - 1); | ||
618 | tail = readw(&bc->tout); | ||
619 | |||
620 | if (tail != readw(&bc->tout)) | ||
621 | tail = readw(&bc->tout); | ||
622 | /* Wrap tail if necessary */ | ||
623 | tail &= (ch->txbufsize - 1); | ||
624 | remain = tail - head - 1; | ||
625 | if (remain < 0) | ||
626 | remain += ch->txbufsize; | ||
627 | |||
628 | if (remain && (ch->statusflags & LOWWAIT) == 0) { | ||
629 | ch->statusflags |= LOWWAIT; | ||
630 | writeb(1, &bc->ilow); | ||
631 | } | ||
632 | memoff(ch); | ||
633 | spin_unlock_irqrestore(&epca_lock, flags); | ||
634 | } | ||
635 | /* Return how much room is left on card */ | ||
636 | return remain; | ||
637 | } | ||
638 | |||
639 | static int pc_chars_in_buffer(struct tty_struct *tty) | ||
640 | { | ||
641 | int chars; | ||
642 | unsigned int ctail, head, tail; | ||
643 | int remain; | ||
644 | unsigned long flags; | ||
645 | struct channel *ch; | ||
646 | struct board_chan __iomem *bc; | ||
647 | /* | ||
648 | * verifyChannel returns the channel from the tty struct if it is | ||
649 | * valid. This serves as a sanity check. | ||
650 | */ | ||
651 | ch = verifyChannel(tty); | ||
652 | if (ch == NULL) | ||
653 | return 0; | ||
654 | |||
655 | spin_lock_irqsave(&epca_lock, flags); | ||
656 | globalwinon(ch); | ||
657 | |||
658 | bc = ch->brdchan; | ||
659 | tail = readw(&bc->tout); | ||
660 | head = readw(&bc->tin); | ||
661 | ctail = readw(&ch->mailbox->cout); | ||
662 | |||
663 | if (tail == head && readw(&ch->mailbox->cin) == ctail && | ||
664 | readb(&bc->tbusy) == 0) | ||
665 | chars = 0; | ||
666 | else { /* Begin if some space on the card has been used */ | ||
667 | head = readw(&bc->tin) & (ch->txbufsize - 1); | ||
668 | tail &= (ch->txbufsize - 1); | ||
669 | /* | ||
670 | * The logic here is basically opposite of the above | ||
671 | * pc_write_room here we are finding the amount of bytes in the | ||
672 | * buffer filled. Not the amount of bytes empty. | ||
673 | */ | ||
674 | remain = tail - head - 1; | ||
675 | if (remain < 0) | ||
676 | remain += ch->txbufsize; | ||
677 | chars = (int)(ch->txbufsize - remain); | ||
678 | /* | ||
679 | * Make it possible to wakeup anything waiting for output in | ||
680 | * tty_ioctl.c, etc. | ||
681 | * | ||
682 | * If not already set. Setup an event to indicate when the | ||
683 | * transmit buffer empties. | ||
684 | */ | ||
685 | if (!(ch->statusflags & EMPTYWAIT)) | ||
686 | setup_empty_event(tty, ch); | ||
687 | } /* End if some space on the card has been used */ | ||
688 | memoff(ch); | ||
689 | spin_unlock_irqrestore(&epca_lock, flags); | ||
690 | /* Return number of characters residing on card. */ | ||
691 | return chars; | ||
692 | } | ||
693 | |||
694 | static void pc_flush_buffer(struct tty_struct *tty) | ||
695 | { | ||
696 | unsigned int tail; | ||
697 | unsigned long flags; | ||
698 | struct channel *ch; | ||
699 | struct board_chan __iomem *bc; | ||
700 | /* | ||
701 | * verifyChannel returns the channel from the tty struct if it is | ||
702 | * valid. This serves as a sanity check. | ||
703 | */ | ||
704 | ch = verifyChannel(tty); | ||
705 | if (ch == NULL) | ||
706 | return; | ||
707 | |||
708 | spin_lock_irqsave(&epca_lock, flags); | ||
709 | globalwinon(ch); | ||
710 | bc = ch->brdchan; | ||
711 | tail = readw(&bc->tout); | ||
712 | /* Have FEP move tout pointer; effectively flushing transmit buffer */ | ||
713 | fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); | ||
714 | memoff(ch); | ||
715 | spin_unlock_irqrestore(&epca_lock, flags); | ||
716 | tty_wakeup(tty); | ||
717 | } | ||
718 | |||
719 | static void pc_flush_chars(struct tty_struct *tty) | ||
720 | { | ||
721 | struct channel *ch; | ||
722 | /* | ||
723 | * verifyChannel returns the channel from the tty struct if it is | ||
724 | * valid. This serves as a sanity check. | ||
725 | */ | ||
726 | ch = verifyChannel(tty); | ||
727 | if (ch != NULL) { | ||
728 | unsigned long flags; | ||
729 | spin_lock_irqsave(&epca_lock, flags); | ||
730 | /* | ||
731 | * If not already set and the transmitter is busy setup an | ||
732 | * event to indicate when the transmit empties. | ||
733 | */ | ||
734 | if ((ch->statusflags & TXBUSY) && | ||
735 | !(ch->statusflags & EMPTYWAIT)) | ||
736 | setup_empty_event(tty, ch); | ||
737 | spin_unlock_irqrestore(&epca_lock, flags); | ||
738 | } | ||
739 | } | ||
740 | |||
741 | static int epca_carrier_raised(struct tty_port *port) | ||
742 | { | ||
743 | struct channel *ch = container_of(port, struct channel, port); | ||
744 | if (ch->imodem & ch->dcd) | ||
745 | return 1; | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static void epca_dtr_rts(struct tty_port *port, int onoff) | ||
750 | { | ||
751 | } | ||
752 | |||
753 | static int pc_open(struct tty_struct *tty, struct file *filp) | ||
754 | { | ||
755 | struct channel *ch; | ||
756 | struct tty_port *port; | ||
757 | unsigned long flags; | ||
758 | int line, retval, boardnum; | ||
759 | struct board_chan __iomem *bc; | ||
760 | unsigned int head; | ||
761 | |||
762 | line = tty->index; | ||
763 | if (line < 0 || line >= nbdevs) | ||
764 | return -ENODEV; | ||
765 | |||
766 | ch = &digi_channels[line]; | ||
767 | port = &ch->port; | ||
768 | boardnum = ch->boardnum; | ||
769 | |||
770 | /* Check status of board configured in system. */ | ||
771 | |||
772 | /* | ||
773 | * I check to see if the epca_setup routine detected a user error. It | ||
774 | * might be better to put this in pc_init, but for the moment it goes | ||
775 | * here. | ||
776 | */ | ||
777 | if (invalid_lilo_config) { | ||
778 | if (setup_error_code & INVALID_BOARD_TYPE) | ||
779 | printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n"); | ||
780 | if (setup_error_code & INVALID_NUM_PORTS) | ||
781 | printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n"); | ||
782 | if (setup_error_code & INVALID_MEM_BASE) | ||
783 | printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n"); | ||
784 | if (setup_error_code & INVALID_PORT_BASE) | ||
785 | printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n"); | ||
786 | if (setup_error_code & INVALID_BOARD_STATUS) | ||
787 | printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n"); | ||
788 | if (setup_error_code & INVALID_ALTPIN) | ||
789 | printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n"); | ||
790 | tty->driver_data = NULL; /* Mark this device as 'down' */ | ||
791 | return -ENODEV; | ||
792 | } | ||
793 | if (boardnum >= num_cards || boards[boardnum].status == DISABLED) { | ||
794 | tty->driver_data = NULL; /* Mark this device as 'down' */ | ||
795 | return(-ENODEV); | ||
796 | } | ||
797 | |||
798 | bc = ch->brdchan; | ||
799 | if (bc == NULL) { | ||
800 | tty->driver_data = NULL; | ||
801 | return -ENODEV; | ||
802 | } | ||
803 | |||
804 | spin_lock_irqsave(&port->lock, flags); | ||
805 | /* | ||
806 | * Every time a channel is opened, increment a counter. This is | ||
807 | * necessary because we do not wish to flush and shutdown the channel | ||
808 | * until the last app holding the channel open, closes it. | ||
809 | */ | ||
810 | port->count++; | ||
811 | /* | ||
812 | * Set a kernel structures pointer to our local channel structure. This | ||
813 | * way we can get to it when passed only a tty struct. | ||
814 | */ | ||
815 | tty->driver_data = ch; | ||
816 | port->tty = tty; | ||
817 | /* | ||
818 | * If this is the first time the channel has been opened, initialize | ||
819 | * the tty->termios struct otherwise let pc_close handle it. | ||
820 | */ | ||
821 | spin_lock(&epca_lock); | ||
822 | globalwinon(ch); | ||
823 | ch->statusflags = 0; | ||
824 | |||
825 | /* Save boards current modem status */ | ||
826 | ch->imodem = readb(&bc->mstat); | ||
827 | |||
828 | /* | ||
829 | * Set receive head and tail ptrs to each other. This indicates no data | ||
830 | * available to read. | ||
831 | */ | ||
832 | head = readw(&bc->rin); | ||
833 | writew(head, &bc->rout); | ||
834 | |||
835 | /* Set the channels associated tty structure */ | ||
836 | |||
837 | /* | ||
838 | * The below routine generally sets up parity, baud, flow control | ||
839 | * issues, etc.... It effect both control flags and input flags. | ||
840 | */ | ||
841 | epcaparam(tty, ch); | ||
842 | memoff(ch); | ||
843 | spin_unlock(&epca_lock); | ||
844 | port->flags |= ASYNC_INITIALIZED; | ||
845 | spin_unlock_irqrestore(&port->lock, flags); | ||
846 | |||
847 | retval = tty_port_block_til_ready(port, tty, filp); | ||
848 | if (retval) | ||
849 | return retval; | ||
850 | /* | ||
851 | * Set this again in case a hangup set it to zero while this open() was | ||
852 | * waiting for the line... | ||
853 | */ | ||
854 | spin_lock_irqsave(&port->lock, flags); | ||
855 | port->tty = tty; | ||
856 | spin_lock(&epca_lock); | ||
857 | globalwinon(ch); | ||
858 | /* Enable Digi Data events */ | ||
859 | writeb(1, &bc->idata); | ||
860 | memoff(ch); | ||
861 | spin_unlock(&epca_lock); | ||
862 | spin_unlock_irqrestore(&port->lock, flags); | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static int __init epca_module_init(void) | ||
867 | { | ||
868 | return pc_init(); | ||
869 | } | ||
870 | module_init(epca_module_init); | ||
871 | |||
872 | static struct pci_driver epca_driver; | ||
873 | |||
874 | static void __exit epca_module_exit(void) | ||
875 | { | ||
876 | int count, crd; | ||
877 | struct board_info *bd; | ||
878 | struct channel *ch; | ||
879 | |||
880 | del_timer_sync(&epca_timer); | ||
881 | |||
882 | if (tty_unregister_driver(pc_driver) || | ||
883 | tty_unregister_driver(pc_info)) { | ||
884 | printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n"); | ||
885 | return; | ||
886 | } | ||
887 | put_tty_driver(pc_driver); | ||
888 | put_tty_driver(pc_info); | ||
889 | |||
890 | for (crd = 0; crd < num_cards; crd++) { | ||
891 | bd = &boards[crd]; | ||
892 | if (!bd) { /* sanity check */ | ||
893 | printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n"); | ||
894 | return; | ||
895 | } | ||
896 | ch = card_ptr[crd]; | ||
897 | for (count = 0; count < bd->numports; count++, ch++) { | ||
898 | struct tty_struct *tty = tty_port_tty_get(&ch->port); | ||
899 | if (tty) { | ||
900 | tty_hangup(tty); | ||
901 | tty_kref_put(tty); | ||
902 | } | ||
903 | } | ||
904 | } | ||
905 | pci_unregister_driver(&epca_driver); | ||
906 | } | ||
907 | module_exit(epca_module_exit); | ||
908 | |||
909 | static const struct tty_operations pc_ops = { | ||
910 | .open = pc_open, | ||
911 | .close = pc_close, | ||
912 | .write = pc_write, | ||
913 | .write_room = pc_write_room, | ||
914 | .flush_buffer = pc_flush_buffer, | ||
915 | .chars_in_buffer = pc_chars_in_buffer, | ||
916 | .flush_chars = pc_flush_chars, | ||
917 | .ioctl = pc_ioctl, | ||
918 | .set_termios = pc_set_termios, | ||
919 | .stop = pc_stop, | ||
920 | .start = pc_start, | ||
921 | .throttle = pc_throttle, | ||
922 | .unthrottle = pc_unthrottle, | ||
923 | .hangup = pc_hangup, | ||
924 | .break_ctl = pc_send_break | ||
925 | }; | ||
926 | |||
927 | static const struct tty_port_operations epca_port_ops = { | ||
928 | .carrier_raised = epca_carrier_raised, | ||
929 | .dtr_rts = epca_dtr_rts, | ||
930 | }; | ||
931 | |||
932 | static int info_open(struct tty_struct *tty, struct file *filp) | ||
933 | { | ||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | static const struct tty_operations info_ops = { | ||
938 | .open = info_open, | ||
939 | .ioctl = info_ioctl, | ||
940 | }; | ||
941 | |||
942 | static int __init pc_init(void) | ||
943 | { | ||
944 | int crd; | ||
945 | struct board_info *bd; | ||
946 | unsigned char board_id = 0; | ||
947 | int err = -ENOMEM; | ||
948 | |||
949 | int pci_boards_found, pci_count; | ||
950 | |||
951 | pci_count = 0; | ||
952 | |||
953 | pc_driver = alloc_tty_driver(MAX_ALLOC); | ||
954 | if (!pc_driver) | ||
955 | goto out1; | ||
956 | |||
957 | pc_info = alloc_tty_driver(MAX_ALLOC); | ||
958 | if (!pc_info) | ||
959 | goto out2; | ||
960 | |||
961 | /* | ||
962 | * If epca_setup has not been ran by LILO set num_cards to defaults; | ||
963 | * copy board structure defined by digiConfig into drivers board | ||
964 | * structure. Note : If LILO has ran epca_setup then epca_setup will | ||
965 | * handle defining num_cards as well as copying the data into the board | ||
966 | * structure. | ||
967 | */ | ||
968 | if (!liloconfig) { | ||
969 | /* driver has been configured via. epcaconfig */ | ||
970 | nbdevs = NBDEVS; | ||
971 | num_cards = NUMCARDS; | ||
972 | memcpy(&boards, &static_boards, | ||
973 | sizeof(struct board_info) * NUMCARDS); | ||
974 | } | ||
975 | |||
976 | /* | ||
977 | * Note : If lilo was used to configure the driver and the ignore | ||
978 | * epcaconfig option was choosen (digiepca=2) then nbdevs and num_cards | ||
979 | * will equal 0 at this point. This is okay; PCI cards will still be | ||
980 | * picked up if detected. | ||
981 | */ | ||
982 | |||
983 | /* | ||
984 | * Set up interrupt, we will worry about memory allocation in | ||
985 | * post_fep_init. | ||
986 | */ | ||
987 | printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION); | ||
988 | |||
989 | /* | ||
990 | * NOTE : This code assumes that the number of ports found in the | ||
991 | * boards array is correct. This could be wrong if the card in question | ||
992 | * is PCI (And therefore has no ports entry in the boards structure.) | ||
993 | * The rest of the information will be valid for PCI because the | ||
994 | * beginning of pc_init scans for PCI and determines i/o and base | ||
995 | * memory addresses. I am not sure if it is possible to read the number | ||
996 | * of ports supported by the card prior to it being booted (Since that | ||
997 | * is the state it is in when pc_init is run). Because it is not | ||
998 | * possible to query the number of supported ports until after the card | ||
999 | * has booted; we are required to calculate the card_ptrs as the card | ||
1000 | * is initialized (Inside post_fep_init). The negative thing about this | ||
1001 | * approach is that digiDload's call to GET_INFO will have a bad port | ||
1002 | * value. (Since this is called prior to post_fep_init.) | ||
1003 | */ | ||
1004 | pci_boards_found = 0; | ||
1005 | if (num_cards < MAXBOARDS) | ||
1006 | pci_boards_found += init_PCI(); | ||
1007 | num_cards += pci_boards_found; | ||
1008 | |||
1009 | pc_driver->owner = THIS_MODULE; | ||
1010 | pc_driver->name = "ttyD"; | ||
1011 | pc_driver->major = DIGI_MAJOR; | ||
1012 | pc_driver->minor_start = 0; | ||
1013 | pc_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
1014 | pc_driver->subtype = SERIAL_TYPE_NORMAL; | ||
1015 | pc_driver->init_termios = tty_std_termios; | ||
1016 | pc_driver->init_termios.c_iflag = 0; | ||
1017 | pc_driver->init_termios.c_oflag = 0; | ||
1018 | pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; | ||
1019 | pc_driver->init_termios.c_lflag = 0; | ||
1020 | pc_driver->init_termios.c_ispeed = 9600; | ||
1021 | pc_driver->init_termios.c_ospeed = 9600; | ||
1022 | pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; | ||
1023 | tty_set_operations(pc_driver, &pc_ops); | ||
1024 | |||
1025 | pc_info->owner = THIS_MODULE; | ||
1026 | pc_info->name = "digi_ctl"; | ||
1027 | pc_info->major = DIGIINFOMAJOR; | ||
1028 | pc_info->minor_start = 0; | ||
1029 | pc_info->type = TTY_DRIVER_TYPE_SERIAL; | ||
1030 | pc_info->subtype = SERIAL_TYPE_INFO; | ||
1031 | pc_info->init_termios = tty_std_termios; | ||
1032 | pc_info->init_termios.c_iflag = 0; | ||
1033 | pc_info->init_termios.c_oflag = 0; | ||
1034 | pc_info->init_termios.c_lflag = 0; | ||
1035 | pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; | ||
1036 | pc_info->init_termios.c_ispeed = 9600; | ||
1037 | pc_info->init_termios.c_ospeed = 9600; | ||
1038 | pc_info->flags = TTY_DRIVER_REAL_RAW; | ||
1039 | tty_set_operations(pc_info, &info_ops); | ||
1040 | |||
1041 | |||
1042 | for (crd = 0; crd < num_cards; crd++) { | ||
1043 | /* | ||
1044 | * This is where the appropriate memory handlers for the | ||
1045 | * hardware is set. Everything at runtime blindly jumps through | ||
1046 | * these vectors. | ||
1047 | */ | ||
1048 | |||
1049 | /* defined in epcaconfig.h */ | ||
1050 | bd = &boards[crd]; | ||
1051 | |||
1052 | switch (bd->type) { | ||
1053 | case PCXEM: | ||
1054 | case EISAXEM: | ||
1055 | bd->memwinon = pcxem_memwinon; | ||
1056 | bd->memwinoff = pcxem_memwinoff; | ||
1057 | bd->globalwinon = pcxem_globalwinon; | ||
1058 | bd->txwinon = pcxem_txwinon; | ||
1059 | bd->rxwinon = pcxem_rxwinon; | ||
1060 | bd->memoff = pcxem_memoff; | ||
1061 | bd->assertgwinon = dummy_assertgwinon; | ||
1062 | bd->assertmemoff = dummy_assertmemoff; | ||
1063 | break; | ||
1064 | |||
1065 | case PCIXEM: | ||
1066 | case PCIXRJ: | ||
1067 | case PCIXR: | ||
1068 | bd->memwinon = dummy_memwinon; | ||
1069 | bd->memwinoff = dummy_memwinoff; | ||
1070 | bd->globalwinon = dummy_globalwinon; | ||
1071 | bd->txwinon = dummy_txwinon; | ||
1072 | bd->rxwinon = dummy_rxwinon; | ||
1073 | bd->memoff = dummy_memoff; | ||
1074 | bd->assertgwinon = dummy_assertgwinon; | ||
1075 | bd->assertmemoff = dummy_assertmemoff; | ||
1076 | break; | ||
1077 | |||
1078 | case PCXE: | ||
1079 | case PCXEVE: | ||
1080 | bd->memwinon = pcxe_memwinon; | ||
1081 | bd->memwinoff = pcxe_memwinoff; | ||
1082 | bd->globalwinon = pcxe_globalwinon; | ||
1083 | bd->txwinon = pcxe_txwinon; | ||
1084 | bd->rxwinon = pcxe_rxwinon; | ||
1085 | bd->memoff = pcxe_memoff; | ||
1086 | bd->assertgwinon = dummy_assertgwinon; | ||
1087 | bd->assertmemoff = dummy_assertmemoff; | ||
1088 | break; | ||
1089 | |||
1090 | case PCXI: | ||
1091 | case PC64XE: | ||
1092 | bd->memwinon = pcxi_memwinon; | ||
1093 | bd->memwinoff = pcxi_memwinoff; | ||
1094 | bd->globalwinon = pcxi_globalwinon; | ||
1095 | bd->txwinon = pcxi_txwinon; | ||
1096 | bd->rxwinon = pcxi_rxwinon; | ||
1097 | bd->memoff = pcxi_memoff; | ||
1098 | bd->assertgwinon = pcxi_assertgwinon; | ||
1099 | bd->assertmemoff = pcxi_assertmemoff; | ||
1100 | break; | ||
1101 | |||
1102 | default: | ||
1103 | break; | ||
1104 | } | ||
1105 | |||
1106 | /* | ||
1107 | * Some cards need a memory segment to be defined for use in | ||
1108 | * transmit and receive windowing operations. These boards are | ||
1109 | * listed in the below switch. In the case of the XI the amount | ||
1110 | * of memory on the board is variable so the memory_seg is also | ||
1111 | * variable. This code determines what they segment should be. | ||
1112 | */ | ||
1113 | switch (bd->type) { | ||
1114 | case PCXE: | ||
1115 | case PCXEVE: | ||
1116 | case PC64XE: | ||
1117 | bd->memory_seg = 0xf000; | ||
1118 | break; | ||
1119 | |||
1120 | case PCXI: | ||
1121 | board_id = inb((int)bd->port); | ||
1122 | if ((board_id & 0x1) == 0x1) { | ||
1123 | /* it's an XI card */ | ||
1124 | /* Is it a 64K board */ | ||
1125 | if ((board_id & 0x30) == 0) | ||
1126 | bd->memory_seg = 0xf000; | ||
1127 | |||
1128 | /* Is it a 128K board */ | ||
1129 | if ((board_id & 0x30) == 0x10) | ||
1130 | bd->memory_seg = 0xe000; | ||
1131 | |||
1132 | /* Is is a 256K board */ | ||
1133 | if ((board_id & 0x30) == 0x20) | ||
1134 | bd->memory_seg = 0xc000; | ||
1135 | |||
1136 | /* Is it a 512K board */ | ||
1137 | if ((board_id & 0x30) == 0x30) | ||
1138 | bd->memory_seg = 0x8000; | ||
1139 | } else | ||
1140 | printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port); | ||
1141 | break; | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | err = tty_register_driver(pc_driver); | ||
1146 | if (err) { | ||
1147 | printk(KERN_ERR "Couldn't register Digi PC/ driver"); | ||
1148 | goto out3; | ||
1149 | } | ||
1150 | |||
1151 | err = tty_register_driver(pc_info); | ||
1152 | if (err) { | ||
1153 | printk(KERN_ERR "Couldn't register Digi PC/ info "); | ||
1154 | goto out4; | ||
1155 | } | ||
1156 | |||
1157 | /* Start up the poller to check for events on all enabled boards */ | ||
1158 | init_timer(&epca_timer); | ||
1159 | epca_timer.function = epcapoll; | ||
1160 | mod_timer(&epca_timer, jiffies + HZ/25); | ||
1161 | return 0; | ||
1162 | |||
1163 | out4: | ||
1164 | tty_unregister_driver(pc_driver); | ||
1165 | out3: | ||
1166 | put_tty_driver(pc_info); | ||
1167 | out2: | ||
1168 | put_tty_driver(pc_driver); | ||
1169 | out1: | ||
1170 | return err; | ||
1171 | } | ||
1172 | |||
1173 | static void post_fep_init(unsigned int crd) | ||
1174 | { | ||
1175 | int i; | ||
1176 | void __iomem *memaddr; | ||
1177 | struct global_data __iomem *gd; | ||
1178 | struct board_info *bd; | ||
1179 | struct board_chan __iomem *bc; | ||
1180 | struct channel *ch; | ||
1181 | int shrinkmem = 0, lowwater; | ||
1182 | |||
1183 | /* | ||
1184 | * This call is made by the user via. the ioctl call DIGI_INIT. It is | ||
1185 | * responsible for setting up all the card specific stuff. | ||
1186 | */ | ||
1187 | bd = &boards[crd]; | ||
1188 | |||
1189 | /* | ||
1190 | * If this is a PCI board, get the port info. Remember PCI cards do not | ||
1191 | * have entries into the epcaconfig.h file, so we can't get the number | ||
1192 | * of ports from it. Unfortunetly, this means that anyone doing a | ||
1193 | * DIGI_GETINFO before the board has booted will get an invalid number | ||
1194 | * of ports returned (It should return 0). Calls to DIGI_GETINFO after | ||
1195 | * DIGI_INIT has been called will return the proper values. | ||
1196 | */ | ||
1197 | if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */ | ||
1198 | /* | ||
1199 | * Below we use XEMPORTS as a memory offset regardless of which | ||
1200 | * PCI card it is. This is because all of the supported PCI | ||
1201 | * cards have the same memory offset for the channel data. This | ||
1202 | * will have to be changed if we ever develop a PCI/XE card. | ||
1203 | * NOTE : The FEP manual states that the port offset is 0xC22 | ||
1204 | * as opposed to 0xC02. This is only true for PC/XE, and PC/XI | ||
1205 | * cards; not for the XEM, or CX series. On the PCI cards the | ||
1206 | * number of ports is determined by reading a ID PROM located | ||
1207 | * in the box attached to the card. The card can then determine | ||
1208 | * the index the id to determine the number of ports available. | ||
1209 | * (FYI - The id should be located at 0x1ac (And may use up to | ||
1210 | * 4 bytes if the box in question is a XEM or CX)). | ||
1211 | */ | ||
1212 | /* PCI cards are already remapped at this point ISA are not */ | ||
1213 | bd->numports = readw(bd->re_map_membase + XEMPORTS); | ||
1214 | epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports"); | ||
1215 | nbdevs += (bd->numports); | ||
1216 | } else { | ||
1217 | /* Fix up the mappings for ISA/EISA etc */ | ||
1218 | /* FIXME: 64K - can we be smarter ? */ | ||
1219 | bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000); | ||
1220 | } | ||
1221 | |||
1222 | if (crd != 0) | ||
1223 | card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports; | ||
1224 | else | ||
1225 | card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */ | ||
1226 | |||
1227 | ch = card_ptr[crd]; | ||
1228 | epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range"); | ||
1229 | |||
1230 | memaddr = bd->re_map_membase; | ||
1231 | |||
1232 | /* | ||
1233 | * The below assignment will set bc to point at the BEGINING of the | ||
1234 | * cards channel structures. For 1 card there will be between 8 and 64 | ||
1235 | * of these structures. | ||
1236 | */ | ||
1237 | bc = memaddr + CHANSTRUCT; | ||
1238 | |||
1239 | /* | ||
1240 | * The below assignment will set gd to point at the BEGINING of global | ||
1241 | * memory address 0xc00. The first data in that global memory actually | ||
1242 | * starts at address 0xc1a. The command in pointer begins at 0xd10. | ||
1243 | */ | ||
1244 | gd = memaddr + GLOBAL; | ||
1245 | |||
1246 | /* | ||
1247 | * XEPORTS (address 0xc22) points at the number of channels the card | ||
1248 | * supports. (For 64XE, XI, XEM, and XR use 0xc02) | ||
1249 | */ | ||
1250 | if ((bd->type == PCXEVE || bd->type == PCXE) && | ||
1251 | (readw(memaddr + XEPORTS) < 3)) | ||
1252 | shrinkmem = 1; | ||
1253 | if (bd->type < PCIXEM) | ||
1254 | if (!request_region((int)bd->port, 4, board_desc[bd->type])) | ||
1255 | return; | ||
1256 | memwinon(bd, 0); | ||
1257 | |||
1258 | /* | ||
1259 | * Remember ch is the main drivers channels structure, while bc is the | ||
1260 | * cards channel structure. | ||
1261 | */ | ||
1262 | for (i = 0; i < bd->numports; i++, ch++, bc++) { | ||
1263 | unsigned long flags; | ||
1264 | u16 tseg, rseg; | ||
1265 | |||
1266 | tty_port_init(&ch->port); | ||
1267 | ch->port.ops = &epca_port_ops; | ||
1268 | ch->brdchan = bc; | ||
1269 | ch->mailbox = gd; | ||
1270 | INIT_WORK(&ch->tqueue, do_softint); | ||
1271 | ch->board = &boards[crd]; | ||
1272 | |||
1273 | spin_lock_irqsave(&epca_lock, flags); | ||
1274 | switch (bd->type) { | ||
1275 | /* | ||
1276 | * Since some of the boards use different bitmaps for | ||
1277 | * their control signals we cannot hard code these | ||
1278 | * values and retain portability. We virtualize this | ||
1279 | * data here. | ||
1280 | */ | ||
1281 | case EISAXEM: | ||
1282 | case PCXEM: | ||
1283 | case PCIXEM: | ||
1284 | case PCIXRJ: | ||
1285 | case PCIXR: | ||
1286 | ch->m_rts = 0x02; | ||
1287 | ch->m_dcd = 0x80; | ||
1288 | ch->m_dsr = 0x20; | ||
1289 | ch->m_cts = 0x10; | ||
1290 | ch->m_ri = 0x40; | ||
1291 | ch->m_dtr = 0x01; | ||
1292 | break; | ||
1293 | |||
1294 | case PCXE: | ||
1295 | case PCXEVE: | ||
1296 | case PCXI: | ||
1297 | case PC64XE: | ||
1298 | ch->m_rts = 0x02; | ||
1299 | ch->m_dcd = 0x08; | ||
1300 | ch->m_dsr = 0x10; | ||
1301 | ch->m_cts = 0x20; | ||
1302 | ch->m_ri = 0x40; | ||
1303 | ch->m_dtr = 0x80; | ||
1304 | break; | ||
1305 | } | ||
1306 | |||
1307 | if (boards[crd].altpin) { | ||
1308 | ch->dsr = ch->m_dcd; | ||
1309 | ch->dcd = ch->m_dsr; | ||
1310 | ch->digiext.digi_flags |= DIGI_ALTPIN; | ||
1311 | } else { | ||
1312 | ch->dcd = ch->m_dcd; | ||
1313 | ch->dsr = ch->m_dsr; | ||
1314 | } | ||
1315 | |||
1316 | ch->boardnum = crd; | ||
1317 | ch->channelnum = i; | ||
1318 | ch->magic = EPCA_MAGIC; | ||
1319 | tty_port_tty_set(&ch->port, NULL); | ||
1320 | |||
1321 | if (shrinkmem) { | ||
1322 | fepcmd(ch, SETBUFFER, 32, 0, 0, 0); | ||
1323 | shrinkmem = 0; | ||
1324 | } | ||
1325 | |||
1326 | tseg = readw(&bc->tseg); | ||
1327 | rseg = readw(&bc->rseg); | ||
1328 | |||
1329 | switch (bd->type) { | ||
1330 | case PCIXEM: | ||
1331 | case PCIXRJ: | ||
1332 | case PCIXR: | ||
1333 | /* Cover all the 2MEG cards */ | ||
1334 | ch->txptr = memaddr + ((tseg << 4) & 0x1fffff); | ||
1335 | ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff); | ||
1336 | ch->txwin = FEPWIN | (tseg >> 11); | ||
1337 | ch->rxwin = FEPWIN | (rseg >> 11); | ||
1338 | break; | ||
1339 | |||
1340 | case PCXEM: | ||
1341 | case EISAXEM: | ||
1342 | /* Cover all the 32K windowed cards */ | ||
1343 | /* Mask equal to window size - 1 */ | ||
1344 | ch->txptr = memaddr + ((tseg << 4) & 0x7fff); | ||
1345 | ch->rxptr = memaddr + ((rseg << 4) & 0x7fff); | ||
1346 | ch->txwin = FEPWIN | (tseg >> 11); | ||
1347 | ch->rxwin = FEPWIN | (rseg >> 11); | ||
1348 | break; | ||
1349 | |||
1350 | case PCXEVE: | ||
1351 | case PCXE: | ||
1352 | ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) | ||
1353 | & 0x1fff); | ||
1354 | ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); | ||
1355 | ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) | ||
1356 | & 0x1fff); | ||
1357 | ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9); | ||
1358 | break; | ||
1359 | |||
1360 | case PCXI: | ||
1361 | case PC64XE: | ||
1362 | ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4); | ||
1363 | ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4); | ||
1364 | ch->txwin = ch->rxwin = 0; | ||
1365 | break; | ||
1366 | } | ||
1367 | |||
1368 | ch->txbufhead = 0; | ||
1369 | ch->txbufsize = readw(&bc->tmax) + 1; | ||
1370 | |||
1371 | ch->rxbufhead = 0; | ||
1372 | ch->rxbufsize = readw(&bc->rmax) + 1; | ||
1373 | |||
1374 | lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); | ||
1375 | |||
1376 | /* Set transmitter low water mark */ | ||
1377 | fepcmd(ch, STXLWATER, lowwater, 0, 10, 0); | ||
1378 | |||
1379 | /* Set receiver low water mark */ | ||
1380 | fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0); | ||
1381 | |||
1382 | /* Set receiver high water mark */ | ||
1383 | fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0); | ||
1384 | |||
1385 | writew(100, &bc->edelay); | ||
1386 | writeb(1, &bc->idata); | ||
1387 | |||
1388 | ch->startc = readb(&bc->startc); | ||
1389 | ch->stopc = readb(&bc->stopc); | ||
1390 | ch->startca = readb(&bc->startca); | ||
1391 | ch->stopca = readb(&bc->stopca); | ||
1392 | |||
1393 | ch->fepcflag = 0; | ||
1394 | ch->fepiflag = 0; | ||
1395 | ch->fepoflag = 0; | ||
1396 | ch->fepstartc = 0; | ||
1397 | ch->fepstopc = 0; | ||
1398 | ch->fepstartca = 0; | ||
1399 | ch->fepstopca = 0; | ||
1400 | |||
1401 | ch->port.close_delay = 50; | ||
1402 | |||
1403 | spin_unlock_irqrestore(&epca_lock, flags); | ||
1404 | } | ||
1405 | |||
1406 | printk(KERN_INFO | ||
1407 | "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", | ||
1408 | VERSION, board_desc[bd->type], (long)bd->port, | ||
1409 | (long)bd->membase, bd->numports); | ||
1410 | memwinoff(bd, 0); | ||
1411 | } | ||
1412 | |||
1413 | static void epcapoll(unsigned long ignored) | ||
1414 | { | ||
1415 | unsigned long flags; | ||
1416 | int crd; | ||
1417 | unsigned int head, tail; | ||
1418 | struct channel *ch; | ||
1419 | struct board_info *bd; | ||
1420 | |||
1421 | /* | ||
1422 | * This routine is called upon every timer interrupt. Even though the | ||
1423 | * Digi series cards are capable of generating interrupts this method | ||
1424 | * of non-looping polling is more efficient. This routine checks for | ||
1425 | * card generated events (Such as receive data, are transmit buffer | ||
1426 | * empty) and acts on those events. | ||
1427 | */ | ||
1428 | for (crd = 0; crd < num_cards; crd++) { | ||
1429 | bd = &boards[crd]; | ||
1430 | ch = card_ptr[crd]; | ||
1431 | |||
1432 | if ((bd->status == DISABLED) || digi_poller_inhibited) | ||
1433 | continue; | ||
1434 | |||
1435 | /* | ||
1436 | * assertmemoff is not needed here; indeed it is an empty | ||
1437 | * subroutine. It is being kept because future boards may need | ||
1438 | * this as well as some legacy boards. | ||
1439 | */ | ||
1440 | spin_lock_irqsave(&epca_lock, flags); | ||
1441 | |||
1442 | assertmemoff(ch); | ||
1443 | |||
1444 | globalwinon(ch); | ||
1445 | |||
1446 | /* | ||
1447 | * In this case head and tail actually refer to the event queue | ||
1448 | * not the transmit or receive queue. | ||
1449 | */ | ||
1450 | head = readw(&ch->mailbox->ein); | ||
1451 | tail = readw(&ch->mailbox->eout); | ||
1452 | |||
1453 | /* If head isn't equal to tail we have an event */ | ||
1454 | if (head != tail) | ||
1455 | doevent(crd); | ||
1456 | memoff(ch); | ||
1457 | |||
1458 | spin_unlock_irqrestore(&epca_lock, flags); | ||
1459 | } /* End for each card */ | ||
1460 | mod_timer(&epca_timer, jiffies + (HZ / 25)); | ||
1461 | } | ||
1462 | |||
1463 | static void doevent(int crd) | ||
1464 | { | ||
1465 | void __iomem *eventbuf; | ||
1466 | struct channel *ch, *chan0; | ||
1467 | static struct tty_struct *tty; | ||
1468 | struct board_info *bd; | ||
1469 | struct board_chan __iomem *bc; | ||
1470 | unsigned int tail, head; | ||
1471 | int event, channel; | ||
1472 | int mstat, lstat; | ||
1473 | |||
1474 | /* | ||
1475 | * This subroutine is called by epcapoll when an event is detected | ||
1476 | * in the event queue. This routine responds to those events. | ||
1477 | */ | ||
1478 | bd = &boards[crd]; | ||
1479 | |||
1480 | chan0 = card_ptr[crd]; | ||
1481 | epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); | ||
1482 | assertgwinon(chan0); | ||
1483 | while ((tail = readw(&chan0->mailbox->eout)) != | ||
1484 | (head = readw(&chan0->mailbox->ein))) { | ||
1485 | /* Begin while something in event queue */ | ||
1486 | assertgwinon(chan0); | ||
1487 | eventbuf = bd->re_map_membase + tail + ISTART; | ||
1488 | /* Get the channel the event occurred on */ | ||
1489 | channel = readb(eventbuf); | ||
1490 | /* Get the actual event code that occurred */ | ||
1491 | event = readb(eventbuf + 1); | ||
1492 | /* | ||
1493 | * The two assignments below get the current modem status | ||
1494 | * (mstat) and the previous modem status (lstat). These are | ||
1495 | * useful becuase an event could signal a change in modem | ||
1496 | * signals itself. | ||
1497 | */ | ||
1498 | mstat = readb(eventbuf + 2); | ||
1499 | lstat = readb(eventbuf + 3); | ||
1500 | |||
1501 | ch = chan0 + channel; | ||
1502 | if ((unsigned)channel >= bd->numports || !ch) { | ||
1503 | if (channel >= bd->numports) | ||
1504 | ch = chan0; | ||
1505 | bc = ch->brdchan; | ||
1506 | goto next; | ||
1507 | } | ||
1508 | |||
1509 | bc = ch->brdchan; | ||
1510 | if (bc == NULL) | ||
1511 | goto next; | ||
1512 | |||
1513 | tty = tty_port_tty_get(&ch->port); | ||
1514 | if (event & DATA_IND) { /* Begin DATA_IND */ | ||
1515 | receive_data(ch, tty); | ||
1516 | assertgwinon(ch); | ||
1517 | } /* End DATA_IND */ | ||
1518 | /* else *//* Fix for DCD transition missed bug */ | ||
1519 | if (event & MODEMCHG_IND) { | ||
1520 | /* A modem signal change has been indicated */ | ||
1521 | ch->imodem = mstat; | ||
1522 | if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) { | ||
1523 | /* We are now receiving dcd */ | ||
1524 | if (mstat & ch->dcd) | ||
1525 | wake_up_interruptible(&ch->port.open_wait); | ||
1526 | else /* No dcd; hangup */ | ||
1527 | pc_sched_event(ch, EPCA_EVENT_HANGUP); | ||
1528 | } | ||
1529 | } | ||
1530 | if (tty) { | ||
1531 | if (event & BREAK_IND) { | ||
1532 | /* A break has been indicated */ | ||
1533 | tty_insert_flip_char(tty, 0, TTY_BREAK); | ||
1534 | tty_schedule_flip(tty); | ||
1535 | } else if (event & LOWTX_IND) { | ||
1536 | if (ch->statusflags & LOWWAIT) { | ||
1537 | ch->statusflags &= ~LOWWAIT; | ||
1538 | tty_wakeup(tty); | ||
1539 | } | ||
1540 | } else if (event & EMPTYTX_IND) { | ||
1541 | /* This event is generated by | ||
1542 | setup_empty_event */ | ||
1543 | ch->statusflags &= ~TXBUSY; | ||
1544 | if (ch->statusflags & EMPTYWAIT) { | ||
1545 | ch->statusflags &= ~EMPTYWAIT; | ||
1546 | tty_wakeup(tty); | ||
1547 | } | ||
1548 | } | ||
1549 | tty_kref_put(tty); | ||
1550 | } | ||
1551 | next: | ||
1552 | globalwinon(ch); | ||
1553 | BUG_ON(!bc); | ||
1554 | writew(1, &bc->idata); | ||
1555 | writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout); | ||
1556 | globalwinon(chan0); | ||
1557 | } /* End while something in event queue */ | ||
1558 | } | ||
1559 | |||
1560 | static void fepcmd(struct channel *ch, int cmd, int word_or_byte, | ||
1561 | int byte2, int ncmds, int bytecmd) | ||
1562 | { | ||
1563 | unchar __iomem *memaddr; | ||
1564 | unsigned int head, cmdTail, cmdStart, cmdMax; | ||
1565 | long count; | ||
1566 | int n; | ||
1567 | |||
1568 | /* This is the routine in which commands may be passed to the card. */ | ||
1569 | |||
1570 | if (ch->board->status == DISABLED) | ||
1571 | return; | ||
1572 | assertgwinon(ch); | ||
1573 | /* Remember head (As well as max) is just an offset not a base addr */ | ||
1574 | head = readw(&ch->mailbox->cin); | ||
1575 | /* cmdStart is a base address */ | ||
1576 | cmdStart = readw(&ch->mailbox->cstart); | ||
1577 | /* | ||
1578 | * We do the addition below because we do not want a max pointer | ||
1579 | * relative to cmdStart. We want a max pointer that points at the | ||
1580 | * physical end of the command queue. | ||
1581 | */ | ||
1582 | cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax)); | ||
1583 | memaddr = ch->board->re_map_membase; | ||
1584 | |||
1585 | if (head >= (cmdMax - cmdStart) || (head & 03)) { | ||
1586 | printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", | ||
1587 | __LINE__, cmd, head); | ||
1588 | printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", | ||
1589 | __LINE__, cmdMax, cmdStart); | ||
1590 | return; | ||
1591 | } | ||
1592 | if (bytecmd) { | ||
1593 | writeb(cmd, memaddr + head + cmdStart + 0); | ||
1594 | writeb(ch->channelnum, memaddr + head + cmdStart + 1); | ||
1595 | /* Below word_or_byte is bits to set */ | ||
1596 | writeb(word_or_byte, memaddr + head + cmdStart + 2); | ||
1597 | /* Below byte2 is bits to reset */ | ||
1598 | writeb(byte2, memaddr + head + cmdStart + 3); | ||
1599 | } else { | ||
1600 | writeb(cmd, memaddr + head + cmdStart + 0); | ||
1601 | writeb(ch->channelnum, memaddr + head + cmdStart + 1); | ||
1602 | writeb(word_or_byte, memaddr + head + cmdStart + 2); | ||
1603 | } | ||
1604 | head = (head + 4) & (cmdMax - cmdStart - 4); | ||
1605 | writew(head, &ch->mailbox->cin); | ||
1606 | count = FEPTIMEOUT; | ||
1607 | |||
1608 | for (;;) { | ||
1609 | count--; | ||
1610 | if (count == 0) { | ||
1611 | printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n"); | ||
1612 | return; | ||
1613 | } | ||
1614 | head = readw(&ch->mailbox->cin); | ||
1615 | cmdTail = readw(&ch->mailbox->cout); | ||
1616 | n = (head - cmdTail) & (cmdMax - cmdStart - 4); | ||
1617 | /* | ||
1618 | * Basically this will break when the FEP acknowledges the | ||
1619 | * command by incrementing cmdTail (Making it equal to head). | ||
1620 | */ | ||
1621 | if (n <= ncmds * (sizeof(short) * 4)) | ||
1622 | break; | ||
1623 | } | ||
1624 | } | ||
1625 | |||
1626 | /* | ||
1627 | * Digi products use fields in their channels structures that are very similar | ||
1628 | * to the c_cflag and c_iflag fields typically found in UNIX termios | ||
1629 | * structures. The below three routines allow mappings between these hardware | ||
1630 | * "flags" and their respective Linux flags. | ||
1631 | */ | ||
1632 | static unsigned termios2digi_h(struct channel *ch, unsigned cflag) | ||
1633 | { | ||
1634 | unsigned res = 0; | ||
1635 | |||
1636 | if (cflag & CRTSCTS) { | ||
1637 | ch->digiext.digi_flags |= (RTSPACE | CTSPACE); | ||
1638 | res |= ((ch->m_cts) | (ch->m_rts)); | ||
1639 | } | ||
1640 | |||
1641 | if (ch->digiext.digi_flags & RTSPACE) | ||
1642 | res |= ch->m_rts; | ||
1643 | |||
1644 | if (ch->digiext.digi_flags & DTRPACE) | ||
1645 | res |= ch->m_dtr; | ||
1646 | |||
1647 | if (ch->digiext.digi_flags & CTSPACE) | ||
1648 | res |= ch->m_cts; | ||
1649 | |||
1650 | if (ch->digiext.digi_flags & DSRPACE) | ||
1651 | res |= ch->dsr; | ||
1652 | |||
1653 | if (ch->digiext.digi_flags & DCDPACE) | ||
1654 | res |= ch->dcd; | ||
1655 | |||
1656 | if (res & (ch->m_rts)) | ||
1657 | ch->digiext.digi_flags |= RTSPACE; | ||
1658 | |||
1659 | if (res & (ch->m_cts)) | ||
1660 | ch->digiext.digi_flags |= CTSPACE; | ||
1661 | |||
1662 | return res; | ||
1663 | } | ||
1664 | |||
1665 | static unsigned termios2digi_i(struct channel *ch, unsigned iflag) | ||
1666 | { | ||
1667 | unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | | ||
1668 | INPCK | ISTRIP | IXON | IXANY | IXOFF); | ||
1669 | if (ch->digiext.digi_flags & DIGI_AIXON) | ||
1670 | res |= IAIXON; | ||
1671 | return res; | ||
1672 | } | ||
1673 | |||
1674 | static unsigned termios2digi_c(struct channel *ch, unsigned cflag) | ||
1675 | { | ||
1676 | unsigned res = 0; | ||
1677 | if (cflag & CBAUDEX) { | ||
1678 | ch->digiext.digi_flags |= DIGI_FAST; | ||
1679 | /* | ||
1680 | * HUPCL bit is used by FEP to indicate fast baud table is to | ||
1681 | * be used. | ||
1682 | */ | ||
1683 | res |= FEP_HUPCL; | ||
1684 | } else | ||
1685 | ch->digiext.digi_flags &= ~DIGI_FAST; | ||
1686 | /* | ||
1687 | * CBAUD has bit position 0x1000 set these days to indicate Linux | ||
1688 | * baud rate remap. Digi hardware can't handle the bit assignment. | ||
1689 | * (We use a different bit assignment for high speed.). Clear this | ||
1690 | * bit out. | ||
1691 | */ | ||
1692 | res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE); | ||
1693 | /* | ||
1694 | * This gets a little confusing. The Digi cards have their own | ||
1695 | * representation of c_cflags controlling baud rate. For the most part | ||
1696 | * this is identical to the Linux implementation. However; Digi | ||
1697 | * supports one rate (76800) that Linux doesn't. This means that the | ||
1698 | * c_cflag entry that would normally mean 76800 for Digi actually means | ||
1699 | * 115200 under Linux. Without the below mapping, a stty 115200 would | ||
1700 | * only drive the board at 76800. Since the rate 230400 is also found | ||
1701 | * after 76800, the same problem afflicts us when we choose a rate of | ||
1702 | * 230400. Without the below modificiation stty 230400 would actually | ||
1703 | * give us 115200. | ||
1704 | * | ||
1705 | * There are two additional differences. The Linux value for CLOCAL | ||
1706 | * (0x800; 0004000) has no meaning to the Digi hardware. Also in later | ||
1707 | * releases of Linux; the CBAUD define has CBAUDEX (0x1000; 0010000) | ||
1708 | * ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX should be | ||
1709 | * checked for a screened out prior to termios2digi_c returning. Since | ||
1710 | * CLOCAL isn't used by the board this can be ignored as long as the | ||
1711 | * returned value is used only by Digi hardware. | ||
1712 | */ | ||
1713 | if (cflag & CBAUDEX) { | ||
1714 | /* | ||
1715 | * The below code is trying to guarantee that only baud rates | ||
1716 | * 115200 and 230400 are remapped. We use exclusive or because | ||
1717 | * the various baud rates share common bit positions and | ||
1718 | * therefore can't be tested for easily. | ||
1719 | */ | ||
1720 | if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) || | ||
1721 | (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX)))) | ||
1722 | res += 1; | ||
1723 | } | ||
1724 | return res; | ||
1725 | } | ||
1726 | |||
1727 | /* Caller must hold the locks */ | ||
1728 | static void epcaparam(struct tty_struct *tty, struct channel *ch) | ||
1729 | { | ||
1730 | unsigned int cmdHead; | ||
1731 | struct ktermios *ts; | ||
1732 | struct board_chan __iomem *bc; | ||
1733 | unsigned mval, hflow, cflag, iflag; | ||
1734 | |||
1735 | bc = ch->brdchan; | ||
1736 | epcaassert(bc != NULL, "bc out of range"); | ||
1737 | |||
1738 | assertgwinon(ch); | ||
1739 | ts = tty->termios; | ||
1740 | if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ | ||
1741 | cmdHead = readw(&bc->rin); | ||
1742 | writew(cmdHead, &bc->rout); | ||
1743 | cmdHead = readw(&bc->tin); | ||
1744 | /* Changing baud in mid-stream transmission can be wonderful */ | ||
1745 | /* | ||
1746 | * Flush current transmit buffer by setting cmdTail pointer | ||
1747 | * (tout) to cmdHead pointer (tin). Hopefully the transmit | ||
1748 | * buffer is empty. | ||
1749 | */ | ||
1750 | fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0); | ||
1751 | mval = 0; | ||
1752 | } else { /* Begin CBAUD not detected */ | ||
1753 | /* | ||
1754 | * c_cflags have changed but that change had nothing to do with | ||
1755 | * BAUD. Propagate the change to the card. | ||
1756 | */ | ||
1757 | cflag = termios2digi_c(ch, ts->c_cflag); | ||
1758 | if (cflag != ch->fepcflag) { | ||
1759 | ch->fepcflag = cflag; | ||
1760 | /* Set baud rate, char size, stop bits, parity */ | ||
1761 | fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0); | ||
1762 | } | ||
1763 | /* | ||
1764 | * If the user has not forced CLOCAL and if the device is not a | ||
1765 | * CALLOUT device (Which is always CLOCAL) we set flags such | ||
1766 | * that the driver will wait on carrier detect. | ||
1767 | */ | ||
1768 | if (ts->c_cflag & CLOCAL) | ||
1769 | clear_bit(ASYNCB_CHECK_CD, &ch->port.flags); | ||
1770 | else | ||
1771 | set_bit(ASYNCB_CHECK_CD, &ch->port.flags); | ||
1772 | mval = ch->m_dtr | ch->m_rts; | ||
1773 | } /* End CBAUD not detected */ | ||
1774 | iflag = termios2digi_i(ch, ts->c_iflag); | ||
1775 | /* Check input mode flags */ | ||
1776 | if (iflag != ch->fepiflag) { | ||
1777 | ch->fepiflag = iflag; | ||
1778 | /* | ||
1779 | * Command sets channels iflag structure on the board. Such | ||
1780 | * things as input soft flow control, handling of parity | ||
1781 | * errors, and break handling are all set here. | ||
1782 | * | ||
1783 | * break handling, parity handling, input stripping, | ||
1784 | * flow control chars | ||
1785 | */ | ||
1786 | fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); | ||
1787 | } | ||
1788 | /* | ||
1789 | * Set the board mint value for this channel. This will cause hardware | ||
1790 | * events to be generated each time the DCD signal (Described in mint) | ||
1791 | * changes. | ||
1792 | */ | ||
1793 | writeb(ch->dcd, &bc->mint); | ||
1794 | if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD)) | ||
1795 | if (ch->digiext.digi_flags & DIGI_FORCEDCD) | ||
1796 | writeb(0, &bc->mint); | ||
1797 | ch->imodem = readb(&bc->mstat); | ||
1798 | hflow = termios2digi_h(ch, ts->c_cflag); | ||
1799 | if (hflow != ch->hflow) { | ||
1800 | ch->hflow = hflow; | ||
1801 | /* | ||
1802 | * Hard flow control has been selected but the board is not | ||
1803 | * using it. Activate hard flow control now. | ||
1804 | */ | ||
1805 | fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1); | ||
1806 | } | ||
1807 | mval ^= ch->modemfake & (mval ^ ch->modem); | ||
1808 | |||
1809 | if (ch->omodem ^ mval) { | ||
1810 | ch->omodem = mval; | ||
1811 | /* | ||
1812 | * The below command sets the DTR and RTS mstat structure. If | ||
1813 | * hard flow control is NOT active these changes will drive the | ||
1814 | * output of the actual DTR and RTS lines. If hard flow control | ||
1815 | * is active, the changes will be saved in the mstat structure | ||
1816 | * and only asserted when hard flow control is turned off. | ||
1817 | */ | ||
1818 | |||
1819 | /* First reset DTR & RTS; then set them */ | ||
1820 | fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1); | ||
1821 | fepcmd(ch, SETMODEM, mval, 0, 0, 1); | ||
1822 | } | ||
1823 | if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) { | ||
1824 | ch->fepstartc = ch->startc; | ||
1825 | ch->fepstopc = ch->stopc; | ||
1826 | /* | ||
1827 | * The XON / XOFF characters have changed; propagate these | ||
1828 | * changes to the card. | ||
1829 | */ | ||
1830 | fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); | ||
1831 | } | ||
1832 | if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) { | ||
1833 | ch->fepstartca = ch->startca; | ||
1834 | ch->fepstopca = ch->stopca; | ||
1835 | /* | ||
1836 | * Similar to the above, this time the auxilarly XON / XOFF | ||
1837 | * characters have changed; propagate these changes to the card. | ||
1838 | */ | ||
1839 | fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); | ||
1840 | } | ||
1841 | } | ||
1842 | |||
1843 | /* Caller holds lock */ | ||
1844 | static void receive_data(struct channel *ch, struct tty_struct *tty) | ||
1845 | { | ||
1846 | unchar *rptr; | ||
1847 | struct ktermios *ts = NULL; | ||
1848 | struct board_chan __iomem *bc; | ||
1849 | int dataToRead, wrapgap, bytesAvailable; | ||
1850 | unsigned int tail, head; | ||
1851 | unsigned int wrapmask; | ||
1852 | |||
1853 | /* | ||
1854 | * This routine is called by doint when a receive data event has taken | ||
1855 | * place. | ||
1856 | */ | ||
1857 | globalwinon(ch); | ||
1858 | if (ch->statusflags & RXSTOPPED) | ||
1859 | return; | ||
1860 | if (tty) | ||
1861 | ts = tty->termios; | ||
1862 | bc = ch->brdchan; | ||
1863 | BUG_ON(!bc); | ||
1864 | wrapmask = ch->rxbufsize - 1; | ||
1865 | |||
1866 | /* | ||
1867 | * Get the head and tail pointers to the receiver queue. Wrap the head | ||
1868 | * pointer if it has reached the end of the buffer. | ||
1869 | */ | ||
1870 | head = readw(&bc->rin); | ||
1871 | head &= wrapmask; | ||
1872 | tail = readw(&bc->rout) & wrapmask; | ||
1873 | |||
1874 | bytesAvailable = (head - tail) & wrapmask; | ||
1875 | if (bytesAvailable == 0) | ||
1876 | return; | ||
1877 | |||
1878 | /* If CREAD bit is off or device not open, set TX tail to head */ | ||
1879 | if (!tty || !ts || !(ts->c_cflag & CREAD)) { | ||
1880 | writew(head, &bc->rout); | ||
1881 | return; | ||
1882 | } | ||
1883 | |||
1884 | if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0) | ||
1885 | return; | ||
1886 | |||
1887 | if (readb(&bc->orun)) { | ||
1888 | writeb(0, &bc->orun); | ||
1889 | printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n", | ||
1890 | tty->name); | ||
1891 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
1892 | } | ||
1893 | rxwinon(ch); | ||
1894 | while (bytesAvailable > 0) { | ||
1895 | /* Begin while there is data on the card */ | ||
1896 | wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; | ||
1897 | /* | ||
1898 | * Even if head has wrapped around only report the amount of | ||
1899 | * data to be equal to the size - tail. Remember memcpy can't | ||
1900 | * automaticly wrap around the receive buffer. | ||
1901 | */ | ||
1902 | dataToRead = (wrapgap < bytesAvailable) ? wrapgap | ||
1903 | : bytesAvailable; | ||
1904 | /* Make sure we don't overflow the buffer */ | ||
1905 | dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead); | ||
1906 | if (dataToRead == 0) | ||
1907 | break; | ||
1908 | /* | ||
1909 | * Move data read from our card into the line disciplines | ||
1910 | * buffer for translation if necessary. | ||
1911 | */ | ||
1912 | memcpy_fromio(rptr, ch->rxptr + tail, dataToRead); | ||
1913 | tail = (tail + dataToRead) & wrapmask; | ||
1914 | bytesAvailable -= dataToRead; | ||
1915 | } /* End while there is data on the card */ | ||
1916 | globalwinon(ch); | ||
1917 | writew(tail, &bc->rout); | ||
1918 | /* Must be called with global data */ | ||
1919 | tty_schedule_flip(tty); | ||
1920 | } | ||
1921 | |||
1922 | static int info_ioctl(struct tty_struct *tty, | ||
1923 | unsigned int cmd, unsigned long arg) | ||
1924 | { | ||
1925 | switch (cmd) { | ||
1926 | case DIGI_GETINFO: | ||
1927 | { | ||
1928 | struct digi_info di; | ||
1929 | int brd; | ||
1930 | |||
1931 | if (get_user(brd, (unsigned int __user *)arg)) | ||
1932 | return -EFAULT; | ||
1933 | if (brd < 0 || brd >= num_cards || num_cards == 0) | ||
1934 | return -ENODEV; | ||
1935 | |||
1936 | memset(&di, 0, sizeof(di)); | ||
1937 | |||
1938 | di.board = brd; | ||
1939 | di.status = boards[brd].status; | ||
1940 | di.type = boards[brd].type ; | ||
1941 | di.numports = boards[brd].numports ; | ||
1942 | /* Legacy fixups - just move along nothing to see */ | ||
1943 | di.port = (unsigned char *)boards[brd].port ; | ||
1944 | di.membase = (unsigned char *)boards[brd].membase ; | ||
1945 | |||
1946 | if (copy_to_user((void __user *)arg, &di, sizeof(di))) | ||
1947 | return -EFAULT; | ||
1948 | break; | ||
1949 | |||
1950 | } | ||
1951 | |||
1952 | case DIGI_POLLER: | ||
1953 | { | ||
1954 | int brd = arg & 0xff000000 >> 16; | ||
1955 | unsigned char state = arg & 0xff; | ||
1956 | |||
1957 | if (brd < 0 || brd >= num_cards) { | ||
1958 | printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n"); | ||
1959 | return -ENODEV; | ||
1960 | } | ||
1961 | digi_poller_inhibited = state; | ||
1962 | break; | ||
1963 | } | ||
1964 | |||
1965 | case DIGI_INIT: | ||
1966 | { | ||
1967 | /* | ||
1968 | * This call is made by the apps to complete the | ||
1969 | * initialization of the board(s). This routine is | ||
1970 | * responsible for setting the card to its initial | ||
1971 | * state and setting the drivers control fields to the | ||
1972 | * sutianle settings for the card in question. | ||
1973 | */ | ||
1974 | int crd; | ||
1975 | for (crd = 0; crd < num_cards; crd++) | ||
1976 | post_fep_init(crd); | ||
1977 | break; | ||
1978 | } | ||
1979 | default: | ||
1980 | return -ENOTTY; | ||
1981 | } | ||
1982 | return 0; | ||
1983 | } | ||
1984 | |||
1985 | static int pc_tiocmget(struct tty_struct *tty) | ||
1986 | { | ||
1987 | struct channel *ch = tty->driver_data; | ||
1988 | struct board_chan __iomem *bc; | ||
1989 | unsigned int mstat, mflag = 0; | ||
1990 | unsigned long flags; | ||
1991 | |||
1992 | if (ch) | ||
1993 | bc = ch->brdchan; | ||
1994 | else | ||
1995 | return -EINVAL; | ||
1996 | |||
1997 | spin_lock_irqsave(&epca_lock, flags); | ||
1998 | globalwinon(ch); | ||
1999 | mstat = readb(&bc->mstat); | ||
2000 | memoff(ch); | ||
2001 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2002 | |||
2003 | if (mstat & ch->m_dtr) | ||
2004 | mflag |= TIOCM_DTR; | ||
2005 | if (mstat & ch->m_rts) | ||
2006 | mflag |= TIOCM_RTS; | ||
2007 | if (mstat & ch->m_cts) | ||
2008 | mflag |= TIOCM_CTS; | ||
2009 | if (mstat & ch->dsr) | ||
2010 | mflag |= TIOCM_DSR; | ||
2011 | if (mstat & ch->m_ri) | ||
2012 | mflag |= TIOCM_RI; | ||
2013 | if (mstat & ch->dcd) | ||
2014 | mflag |= TIOCM_CD; | ||
2015 | return mflag; | ||
2016 | } | ||
2017 | |||
2018 | static int pc_tiocmset(struct tty_struct *tty, | ||
2019 | unsigned int set, unsigned int clear) | ||
2020 | { | ||
2021 | struct channel *ch = tty->driver_data; | ||
2022 | unsigned long flags; | ||
2023 | |||
2024 | if (!ch) | ||
2025 | return -EINVAL; | ||
2026 | |||
2027 | spin_lock_irqsave(&epca_lock, flags); | ||
2028 | /* | ||
2029 | * I think this modemfake stuff is broken. It doesn't correctly reflect | ||
2030 | * the behaviour desired by the TIOCM* ioctls. Therefore this is | ||
2031 | * probably broken. | ||
2032 | */ | ||
2033 | if (set & TIOCM_RTS) { | ||
2034 | ch->modemfake |= ch->m_rts; | ||
2035 | ch->modem |= ch->m_rts; | ||
2036 | } | ||
2037 | if (set & TIOCM_DTR) { | ||
2038 | ch->modemfake |= ch->m_dtr; | ||
2039 | ch->modem |= ch->m_dtr; | ||
2040 | } | ||
2041 | if (clear & TIOCM_RTS) { | ||
2042 | ch->modemfake |= ch->m_rts; | ||
2043 | ch->modem &= ~ch->m_rts; | ||
2044 | } | ||
2045 | if (clear & TIOCM_DTR) { | ||
2046 | ch->modemfake |= ch->m_dtr; | ||
2047 | ch->modem &= ~ch->m_dtr; | ||
2048 | } | ||
2049 | globalwinon(ch); | ||
2050 | /* | ||
2051 | * The below routine generally sets up parity, baud, flow control | ||
2052 | * issues, etc.... It effect both control flags and input flags. | ||
2053 | */ | ||
2054 | epcaparam(tty, ch); | ||
2055 | memoff(ch); | ||
2056 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2057 | return 0; | ||
2058 | } | ||
2059 | |||
2060 | static int pc_ioctl(struct tty_struct *tty, | ||
2061 | unsigned int cmd, unsigned long arg) | ||
2062 | { | ||
2063 | digiflow_t dflow; | ||
2064 | unsigned long flags; | ||
2065 | unsigned int mflag, mstat; | ||
2066 | unsigned char startc, stopc; | ||
2067 | struct board_chan __iomem *bc; | ||
2068 | struct channel *ch = tty->driver_data; | ||
2069 | void __user *argp = (void __user *)arg; | ||
2070 | |||
2071 | if (ch) | ||
2072 | bc = ch->brdchan; | ||
2073 | else | ||
2074 | return -EINVAL; | ||
2075 | switch (cmd) { | ||
2076 | case TIOCMODG: | ||
2077 | mflag = pc_tiocmget(tty); | ||
2078 | if (put_user(mflag, (unsigned long __user *)argp)) | ||
2079 | return -EFAULT; | ||
2080 | break; | ||
2081 | case TIOCMODS: | ||
2082 | if (get_user(mstat, (unsigned __user *)argp)) | ||
2083 | return -EFAULT; | ||
2084 | return pc_tiocmset(tty, mstat, ~mstat); | ||
2085 | case TIOCSDTR: | ||
2086 | spin_lock_irqsave(&epca_lock, flags); | ||
2087 | ch->omodem |= ch->m_dtr; | ||
2088 | globalwinon(ch); | ||
2089 | fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1); | ||
2090 | memoff(ch); | ||
2091 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2092 | break; | ||
2093 | |||
2094 | case TIOCCDTR: | ||
2095 | spin_lock_irqsave(&epca_lock, flags); | ||
2096 | ch->omodem &= ~ch->m_dtr; | ||
2097 | globalwinon(ch); | ||
2098 | fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1); | ||
2099 | memoff(ch); | ||
2100 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2101 | break; | ||
2102 | case DIGI_GETA: | ||
2103 | if (copy_to_user(argp, &ch->digiext, sizeof(digi_t))) | ||
2104 | return -EFAULT; | ||
2105 | break; | ||
2106 | case DIGI_SETAW: | ||
2107 | case DIGI_SETAF: | ||
2108 | if (cmd == DIGI_SETAW) { | ||
2109 | /* Setup an event to indicate when the transmit | ||
2110 | buffer empties */ | ||
2111 | spin_lock_irqsave(&epca_lock, flags); | ||
2112 | setup_empty_event(tty, ch); | ||
2113 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2114 | tty_wait_until_sent(tty, 0); | ||
2115 | } else { | ||
2116 | /* ldisc lock already held in ioctl */ | ||
2117 | if (tty->ldisc->ops->flush_buffer) | ||
2118 | tty->ldisc->ops->flush_buffer(tty); | ||
2119 | } | ||
2120 | /* Fall Thru */ | ||
2121 | case DIGI_SETA: | ||
2122 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) | ||
2123 | return -EFAULT; | ||
2124 | |||
2125 | if (ch->digiext.digi_flags & DIGI_ALTPIN) { | ||
2126 | ch->dcd = ch->m_dsr; | ||
2127 | ch->dsr = ch->m_dcd; | ||
2128 | } else { | ||
2129 | ch->dcd = ch->m_dcd; | ||
2130 | ch->dsr = ch->m_dsr; | ||
2131 | } | ||
2132 | |||
2133 | spin_lock_irqsave(&epca_lock, flags); | ||
2134 | globalwinon(ch); | ||
2135 | |||
2136 | /* | ||
2137 | * The below routine generally sets up parity, baud, flow | ||
2138 | * control issues, etc.... It effect both control flags and | ||
2139 | * input flags. | ||
2140 | */ | ||
2141 | epcaparam(tty, ch); | ||
2142 | memoff(ch); | ||
2143 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2144 | break; | ||
2145 | |||
2146 | case DIGI_GETFLOW: | ||
2147 | case DIGI_GETAFLOW: | ||
2148 | spin_lock_irqsave(&epca_lock, flags); | ||
2149 | globalwinon(ch); | ||
2150 | if (cmd == DIGI_GETFLOW) { | ||
2151 | dflow.startc = readb(&bc->startc); | ||
2152 | dflow.stopc = readb(&bc->stopc); | ||
2153 | } else { | ||
2154 | dflow.startc = readb(&bc->startca); | ||
2155 | dflow.stopc = readb(&bc->stopca); | ||
2156 | } | ||
2157 | memoff(ch); | ||
2158 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2159 | |||
2160 | if (copy_to_user(argp, &dflow, sizeof(dflow))) | ||
2161 | return -EFAULT; | ||
2162 | break; | ||
2163 | |||
2164 | case DIGI_SETAFLOW: | ||
2165 | case DIGI_SETFLOW: | ||
2166 | if (cmd == DIGI_SETFLOW) { | ||
2167 | startc = ch->startc; | ||
2168 | stopc = ch->stopc; | ||
2169 | } else { | ||
2170 | startc = ch->startca; | ||
2171 | stopc = ch->stopca; | ||
2172 | } | ||
2173 | |||
2174 | if (copy_from_user(&dflow, argp, sizeof(dflow))) | ||
2175 | return -EFAULT; | ||
2176 | |||
2177 | if (dflow.startc != startc || dflow.stopc != stopc) { | ||
2178 | /* Begin if setflow toggled */ | ||
2179 | spin_lock_irqsave(&epca_lock, flags); | ||
2180 | globalwinon(ch); | ||
2181 | |||
2182 | if (cmd == DIGI_SETFLOW) { | ||
2183 | ch->fepstartc = ch->startc = dflow.startc; | ||
2184 | ch->fepstopc = ch->stopc = dflow.stopc; | ||
2185 | fepcmd(ch, SONOFFC, ch->fepstartc, | ||
2186 | ch->fepstopc, 0, 1); | ||
2187 | } else { | ||
2188 | ch->fepstartca = ch->startca = dflow.startc; | ||
2189 | ch->fepstopca = ch->stopca = dflow.stopc; | ||
2190 | fepcmd(ch, SAUXONOFFC, ch->fepstartca, | ||
2191 | ch->fepstopca, 0, 1); | ||
2192 | } | ||
2193 | |||
2194 | if (ch->statusflags & TXSTOPPED) | ||
2195 | pc_start(tty); | ||
2196 | |||
2197 | memoff(ch); | ||
2198 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2199 | } /* End if setflow toggled */ | ||
2200 | break; | ||
2201 | default: | ||
2202 | return -ENOIOCTLCMD; | ||
2203 | } | ||
2204 | return 0; | ||
2205 | } | ||
2206 | |||
2207 | static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | ||
2208 | { | ||
2209 | struct channel *ch; | ||
2210 | unsigned long flags; | ||
2211 | /* | ||
2212 | * verifyChannel returns the channel from the tty struct if it is | ||
2213 | * valid. This serves as a sanity check. | ||
2214 | */ | ||
2215 | ch = verifyChannel(tty); | ||
2216 | |||
2217 | if (ch != NULL) { /* Begin if channel valid */ | ||
2218 | spin_lock_irqsave(&epca_lock, flags); | ||
2219 | globalwinon(ch); | ||
2220 | epcaparam(tty, ch); | ||
2221 | memoff(ch); | ||
2222 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2223 | |||
2224 | if ((old_termios->c_cflag & CRTSCTS) && | ||
2225 | ((tty->termios->c_cflag & CRTSCTS) == 0)) | ||
2226 | tty->hw_stopped = 0; | ||
2227 | |||
2228 | if (!(old_termios->c_cflag & CLOCAL) && | ||
2229 | (tty->termios->c_cflag & CLOCAL)) | ||
2230 | wake_up_interruptible(&ch->port.open_wait); | ||
2231 | |||
2232 | } /* End if channel valid */ | ||
2233 | } | ||
2234 | |||
2235 | static void do_softint(struct work_struct *work) | ||
2236 | { | ||
2237 | struct channel *ch = container_of(work, struct channel, tqueue); | ||
2238 | /* Called in response to a modem change event */ | ||
2239 | if (ch && ch->magic == EPCA_MAGIC) { | ||
2240 | struct tty_struct *tty = tty_port_tty_get(&ch->port); | ||
2241 | |||
2242 | if (tty && tty->driver_data) { | ||
2243 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { | ||
2244 | tty_hangup(tty); | ||
2245 | wake_up_interruptible(&ch->port.open_wait); | ||
2246 | clear_bit(ASYNCB_NORMAL_ACTIVE, | ||
2247 | &ch->port.flags); | ||
2248 | } | ||
2249 | } | ||
2250 | tty_kref_put(tty); | ||
2251 | } | ||
2252 | } | ||
2253 | |||
2254 | /* | ||
2255 | * pc_stop and pc_start provide software flow control to the routine and the | ||
2256 | * pc_ioctl routine. | ||
2257 | */ | ||
2258 | static void pc_stop(struct tty_struct *tty) | ||
2259 | { | ||
2260 | struct channel *ch; | ||
2261 | unsigned long flags; | ||
2262 | /* | ||
2263 | * verifyChannel returns the channel from the tty struct if it is | ||
2264 | * valid. This serves as a sanity check. | ||
2265 | */ | ||
2266 | ch = verifyChannel(tty); | ||
2267 | if (ch != NULL) { | ||
2268 | spin_lock_irqsave(&epca_lock, flags); | ||
2269 | if ((ch->statusflags & TXSTOPPED) == 0) { | ||
2270 | /* Begin if transmit stop requested */ | ||
2271 | globalwinon(ch); | ||
2272 | /* STOP transmitting now !! */ | ||
2273 | fepcmd(ch, PAUSETX, 0, 0, 0, 0); | ||
2274 | ch->statusflags |= TXSTOPPED; | ||
2275 | memoff(ch); | ||
2276 | } /* End if transmit stop requested */ | ||
2277 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2278 | } | ||
2279 | } | ||
2280 | |||
2281 | static void pc_start(struct tty_struct *tty) | ||
2282 | { | ||
2283 | struct channel *ch; | ||
2284 | /* | ||
2285 | * verifyChannel returns the channel from the tty struct if it is | ||
2286 | * valid. This serves as a sanity check. | ||
2287 | */ | ||
2288 | ch = verifyChannel(tty); | ||
2289 | if (ch != NULL) { | ||
2290 | unsigned long flags; | ||
2291 | spin_lock_irqsave(&epca_lock, flags); | ||
2292 | /* Just in case output was resumed because of a change | ||
2293 | in Digi-flow */ | ||
2294 | if (ch->statusflags & TXSTOPPED) { | ||
2295 | /* Begin transmit resume requested */ | ||
2296 | struct board_chan __iomem *bc; | ||
2297 | globalwinon(ch); | ||
2298 | bc = ch->brdchan; | ||
2299 | if (ch->statusflags & LOWWAIT) | ||
2300 | writeb(1, &bc->ilow); | ||
2301 | /* Okay, you can start transmitting again... */ | ||
2302 | fepcmd(ch, RESUMETX, 0, 0, 0, 0); | ||
2303 | ch->statusflags &= ~TXSTOPPED; | ||
2304 | memoff(ch); | ||
2305 | } /* End transmit resume requested */ | ||
2306 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2307 | } | ||
2308 | } | ||
2309 | |||
2310 | /* | ||
2311 | * The below routines pc_throttle and pc_unthrottle are used to slow (And | ||
2312 | * resume) the receipt of data into the kernels receive buffers. The exact | ||
2313 | * occurrence of this depends on the size of the kernels receive buffer and | ||
2314 | * what the 'watermarks' are set to for that buffer. See the n_ttys.c file for | ||
2315 | * more details. | ||
2316 | */ | ||
2317 | static void pc_throttle(struct tty_struct *tty) | ||
2318 | { | ||
2319 | struct channel *ch; | ||
2320 | unsigned long flags; | ||
2321 | /* | ||
2322 | * verifyChannel returns the channel from the tty struct if it is | ||
2323 | * valid. This serves as a sanity check. | ||
2324 | */ | ||
2325 | ch = verifyChannel(tty); | ||
2326 | if (ch != NULL) { | ||
2327 | spin_lock_irqsave(&epca_lock, flags); | ||
2328 | if ((ch->statusflags & RXSTOPPED) == 0) { | ||
2329 | globalwinon(ch); | ||
2330 | fepcmd(ch, PAUSERX, 0, 0, 0, 0); | ||
2331 | ch->statusflags |= RXSTOPPED; | ||
2332 | memoff(ch); | ||
2333 | } | ||
2334 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2335 | } | ||
2336 | } | ||
2337 | |||
2338 | static void pc_unthrottle(struct tty_struct *tty) | ||
2339 | { | ||
2340 | struct channel *ch; | ||
2341 | unsigned long flags; | ||
2342 | /* | ||
2343 | * verifyChannel returns the channel from the tty struct if it is | ||
2344 | * valid. This serves as a sanity check. | ||
2345 | */ | ||
2346 | ch = verifyChannel(tty); | ||
2347 | if (ch != NULL) { | ||
2348 | /* Just in case output was resumed because of a change | ||
2349 | in Digi-flow */ | ||
2350 | spin_lock_irqsave(&epca_lock, flags); | ||
2351 | if (ch->statusflags & RXSTOPPED) { | ||
2352 | globalwinon(ch); | ||
2353 | fepcmd(ch, RESUMERX, 0, 0, 0, 0); | ||
2354 | ch->statusflags &= ~RXSTOPPED; | ||
2355 | memoff(ch); | ||
2356 | } | ||
2357 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2358 | } | ||
2359 | } | ||
2360 | |||
2361 | static int pc_send_break(struct tty_struct *tty, int msec) | ||
2362 | { | ||
2363 | struct channel *ch = tty->driver_data; | ||
2364 | unsigned long flags; | ||
2365 | |||
2366 | if (msec == -1) | ||
2367 | msec = 0xFFFF; | ||
2368 | else if (msec > 0xFFFE) | ||
2369 | msec = 0xFFFE; | ||
2370 | else if (msec < 1) | ||
2371 | msec = 1; | ||
2372 | |||
2373 | spin_lock_irqsave(&epca_lock, flags); | ||
2374 | globalwinon(ch); | ||
2375 | /* | ||
2376 | * Maybe I should send an infinite break here, schedule() for msec | ||
2377 | * amount of time, and then stop the break. This way, the user can't | ||
2378 | * screw up the FEP by causing digi_send_break() to be called (i.e. via | ||
2379 | * an ioctl()) more than once in msec amount of time. | ||
2380 | * Try this for now... | ||
2381 | */ | ||
2382 | fepcmd(ch, SENDBREAK, msec, 0, 10, 0); | ||
2383 | memoff(ch); | ||
2384 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2385 | return 0; | ||
2386 | } | ||
2387 | |||
2388 | /* Caller MUST hold the lock */ | ||
2389 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch) | ||
2390 | { | ||
2391 | struct board_chan __iomem *bc = ch->brdchan; | ||
2392 | |||
2393 | globalwinon(ch); | ||
2394 | ch->statusflags |= EMPTYWAIT; | ||
2395 | /* | ||
2396 | * When set the iempty flag request a event to be generated when the | ||
2397 | * transmit buffer is empty (If there is no BREAK in progress). | ||
2398 | */ | ||
2399 | writeb(1, &bc->iempty); | ||
2400 | memoff(ch); | ||
2401 | } | ||
2402 | |||
2403 | #ifndef MODULE | ||
2404 | static void __init epca_setup(char *str, int *ints) | ||
2405 | { | ||
2406 | struct board_info board; | ||
2407 | int index, loop, last; | ||
2408 | char *temp, *t2; | ||
2409 | unsigned len; | ||
2410 | |||
2411 | /* | ||
2412 | * If this routine looks a little strange it is because it is only | ||
2413 | * called if a LILO append command is given to boot the kernel with | ||
2414 | * parameters. In this way, we can provide the user a method of | ||
2415 | * changing his board configuration without rebuilding the kernel. | ||
2416 | */ | ||
2417 | if (!liloconfig) | ||
2418 | liloconfig = 1; | ||
2419 | |||
2420 | memset(&board, 0, sizeof(board)); | ||
2421 | |||
2422 | /* Assume the data is int first, later we can change it */ | ||
2423 | /* I think that array position 0 of ints holds the number of args */ | ||
2424 | for (last = 0, index = 1; index <= ints[0]; index++) | ||
2425 | switch (index) { /* Begin parse switch */ | ||
2426 | case 1: | ||
2427 | board.status = ints[index]; | ||
2428 | /* | ||
2429 | * We check for 2 (As opposed to 1; because 2 is a flag | ||
2430 | * instructing the driver to ignore epcaconfig.) For | ||
2431 | * this reason we check for 2. | ||
2432 | */ | ||
2433 | if (board.status == 2) { | ||
2434 | /* Begin ignore epcaconfig as well as lilo cmd line */ | ||
2435 | nbdevs = 0; | ||
2436 | num_cards = 0; | ||
2437 | return; | ||
2438 | } /* End ignore epcaconfig as well as lilo cmd line */ | ||
2439 | |||
2440 | if (board.status > 2) { | ||
2441 | printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", | ||
2442 | board.status); | ||
2443 | invalid_lilo_config = 1; | ||
2444 | setup_error_code |= INVALID_BOARD_STATUS; | ||
2445 | return; | ||
2446 | } | ||
2447 | last = index; | ||
2448 | break; | ||
2449 | case 2: | ||
2450 | board.type = ints[index]; | ||
2451 | if (board.type >= PCIXEM) { | ||
2452 | printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type); | ||
2453 | invalid_lilo_config = 1; | ||
2454 | setup_error_code |= INVALID_BOARD_TYPE; | ||
2455 | return; | ||
2456 | } | ||
2457 | last = index; | ||
2458 | break; | ||
2459 | case 3: | ||
2460 | board.altpin = ints[index]; | ||
2461 | if (board.altpin > 1) { | ||
2462 | printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin); | ||
2463 | invalid_lilo_config = 1; | ||
2464 | setup_error_code |= INVALID_ALTPIN; | ||
2465 | return; | ||
2466 | } | ||
2467 | last = index; | ||
2468 | break; | ||
2469 | |||
2470 | case 4: | ||
2471 | board.numports = ints[index]; | ||
2472 | if (board.numports < 2 || board.numports > 256) { | ||
2473 | printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports); | ||
2474 | invalid_lilo_config = 1; | ||
2475 | setup_error_code |= INVALID_NUM_PORTS; | ||
2476 | return; | ||
2477 | } | ||
2478 | nbdevs += board.numports; | ||
2479 | last = index; | ||
2480 | break; | ||
2481 | |||
2482 | case 5: | ||
2483 | board.port = ints[index]; | ||
2484 | if (ints[index] <= 0) { | ||
2485 | printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port); | ||
2486 | invalid_lilo_config = 1; | ||
2487 | setup_error_code |= INVALID_PORT_BASE; | ||
2488 | return; | ||
2489 | } | ||
2490 | last = index; | ||
2491 | break; | ||
2492 | |||
2493 | case 6: | ||
2494 | board.membase = ints[index]; | ||
2495 | if (ints[index] <= 0) { | ||
2496 | printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n", | ||
2497 | (unsigned int)board.membase); | ||
2498 | invalid_lilo_config = 1; | ||
2499 | setup_error_code |= INVALID_MEM_BASE; | ||
2500 | return; | ||
2501 | } | ||
2502 | last = index; | ||
2503 | break; | ||
2504 | |||
2505 | default: | ||
2506 | printk(KERN_ERR "<Error> - epca_setup: Too many integer parms\n"); | ||
2507 | return; | ||
2508 | |||
2509 | } /* End parse switch */ | ||
2510 | |||
2511 | while (str && *str) { /* Begin while there is a string arg */ | ||
2512 | /* find the next comma or terminator */ | ||
2513 | temp = str; | ||
2514 | /* While string is not null, and a comma hasn't been found */ | ||
2515 | while (*temp && (*temp != ',')) | ||
2516 | temp++; | ||
2517 | if (!*temp) | ||
2518 | temp = NULL; | ||
2519 | else | ||
2520 | *temp++ = 0; | ||
2521 | /* Set index to the number of args + 1 */ | ||
2522 | index = last + 1; | ||
2523 | |||
2524 | switch (index) { | ||
2525 | case 1: | ||
2526 | len = strlen(str); | ||
2527 | if (strncmp("Disable", str, len) == 0) | ||
2528 | board.status = 0; | ||
2529 | else if (strncmp("Enable", str, len) == 0) | ||
2530 | board.status = 1; | ||
2531 | else { | ||
2532 | printk(KERN_ERR "epca_setup: Invalid status %s\n", str); | ||
2533 | invalid_lilo_config = 1; | ||
2534 | setup_error_code |= INVALID_BOARD_STATUS; | ||
2535 | return; | ||
2536 | } | ||
2537 | last = index; | ||
2538 | break; | ||
2539 | |||
2540 | case 2: | ||
2541 | for (loop = 0; loop < EPCA_NUM_TYPES; loop++) | ||
2542 | if (strcmp(board_desc[loop], str) == 0) | ||
2543 | break; | ||
2544 | /* | ||
2545 | * If the index incremented above refers to a | ||
2546 | * legitamate board type set it here. | ||
2547 | */ | ||
2548 | if (index < EPCA_NUM_TYPES) | ||
2549 | board.type = loop; | ||
2550 | else { | ||
2551 | printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str); | ||
2552 | invalid_lilo_config = 1; | ||
2553 | setup_error_code |= INVALID_BOARD_TYPE; | ||
2554 | return; | ||
2555 | } | ||
2556 | last = index; | ||
2557 | break; | ||
2558 | |||
2559 | case 3: | ||
2560 | len = strlen(str); | ||
2561 | if (strncmp("Disable", str, len) == 0) | ||
2562 | board.altpin = 0; | ||
2563 | else if (strncmp("Enable", str, len) == 0) | ||
2564 | board.altpin = 1; | ||
2565 | else { | ||
2566 | printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str); | ||
2567 | invalid_lilo_config = 1; | ||
2568 | setup_error_code |= INVALID_ALTPIN; | ||
2569 | return; | ||
2570 | } | ||
2571 | last = index; | ||
2572 | break; | ||
2573 | |||
2574 | case 4: | ||
2575 | t2 = str; | ||
2576 | while (isdigit(*t2)) | ||
2577 | t2++; | ||
2578 | |||
2579 | if (*t2) { | ||
2580 | printk(KERN_ERR "epca_setup: Invalid port count %s\n", str); | ||
2581 | invalid_lilo_config = 1; | ||
2582 | setup_error_code |= INVALID_NUM_PORTS; | ||
2583 | return; | ||
2584 | } | ||
2585 | |||
2586 | /* | ||
2587 | * There is not a man page for simple_strtoul but the | ||
2588 | * code can be found in vsprintf.c. The first argument | ||
2589 | * is the string to translate (To an unsigned long | ||
2590 | * obviously), the second argument can be the address | ||
2591 | * of any character variable or a NULL. If a variable | ||
2592 | * is given, the end pointer of the string will be | ||
2593 | * stored in that variable; if a NULL is given the end | ||
2594 | * pointer will not be returned. The last argument is | ||
2595 | * the base to use. If a 0 is indicated, the routine | ||
2596 | * will attempt to determine the proper base by looking | ||
2597 | * at the values prefix (A '0' for octal, a 'x' for | ||
2598 | * hex, etc ... If a value is given it will use that | ||
2599 | * value as the base. | ||
2600 | */ | ||
2601 | board.numports = simple_strtoul(str, NULL, 0); | ||
2602 | nbdevs += board.numports; | ||
2603 | last = index; | ||
2604 | break; | ||
2605 | |||
2606 | case 5: | ||
2607 | t2 = str; | ||
2608 | while (isxdigit(*t2)) | ||
2609 | t2++; | ||
2610 | |||
2611 | if (*t2) { | ||
2612 | printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str); | ||
2613 | invalid_lilo_config = 1; | ||
2614 | setup_error_code |= INVALID_PORT_BASE; | ||
2615 | return; | ||
2616 | } | ||
2617 | |||
2618 | board.port = simple_strtoul(str, NULL, 16); | ||
2619 | last = index; | ||
2620 | break; | ||
2621 | |||
2622 | case 6: | ||
2623 | t2 = str; | ||
2624 | while (isxdigit(*t2)) | ||
2625 | t2++; | ||
2626 | |||
2627 | if (*t2) { | ||
2628 | printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str); | ||
2629 | invalid_lilo_config = 1; | ||
2630 | setup_error_code |= INVALID_MEM_BASE; | ||
2631 | return; | ||
2632 | } | ||
2633 | board.membase = simple_strtoul(str, NULL, 16); | ||
2634 | last = index; | ||
2635 | break; | ||
2636 | default: | ||
2637 | printk(KERN_ERR "epca: Too many string parms\n"); | ||
2638 | return; | ||
2639 | } | ||
2640 | str = temp; | ||
2641 | } /* End while there is a string arg */ | ||
2642 | |||
2643 | if (last < 6) { | ||
2644 | printk(KERN_ERR "epca: Insufficient parms specified\n"); | ||
2645 | return; | ||
2646 | } | ||
2647 | |||
2648 | /* I should REALLY validate the stuff here */ | ||
2649 | /* Copies our local copy of board into boards */ | ||
2650 | memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board)); | ||
2651 | /* Does this get called once per lilo arg are what ? */ | ||
2652 | printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n", | ||
2653 | num_cards, board_desc[board.type], | ||
2654 | board.numports, (int)board.port, (unsigned int) board.membase); | ||
2655 | num_cards++; | ||
2656 | } | ||
2657 | |||
2658 | static int __init epca_real_setup(char *str) | ||
2659 | { | ||
2660 | int ints[11]; | ||
2661 | |||
2662 | epca_setup(get_options(str, 11, ints), ints); | ||
2663 | return 1; | ||
2664 | } | ||
2665 | |||
2666 | __setup("digiepca", epca_real_setup); | ||
2667 | #endif | ||
2668 | |||
2669 | enum epic_board_types { | ||
2670 | brd_xr = 0, | ||
2671 | brd_xem, | ||
2672 | brd_cx, | ||
2673 | brd_xrj, | ||
2674 | }; | ||
2675 | |||
2676 | /* indexed directly by epic_board_types enum */ | ||
2677 | static struct { | ||
2678 | unsigned char board_type; | ||
2679 | unsigned bar_idx; /* PCI base address region */ | ||
2680 | } epca_info_tbl[] = { | ||
2681 | { PCIXR, 0, }, | ||
2682 | { PCIXEM, 0, }, | ||
2683 | { PCICX, 0, }, | ||
2684 | { PCIXRJ, 2, }, | ||
2685 | }; | ||
2686 | |||
2687 | static int __devinit epca_init_one(struct pci_dev *pdev, | ||
2688 | const struct pci_device_id *ent) | ||
2689 | { | ||
2690 | static int board_num = -1; | ||
2691 | int board_idx, info_idx = ent->driver_data; | ||
2692 | unsigned long addr; | ||
2693 | |||
2694 | if (pci_enable_device(pdev)) | ||
2695 | return -EIO; | ||
2696 | |||
2697 | board_num++; | ||
2698 | board_idx = board_num + num_cards; | ||
2699 | if (board_idx >= MAXBOARDS) | ||
2700 | goto err_out; | ||
2701 | |||
2702 | addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx); | ||
2703 | if (!addr) { | ||
2704 | printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n", | ||
2705 | epca_info_tbl[info_idx].bar_idx); | ||
2706 | goto err_out; | ||
2707 | } | ||
2708 | |||
2709 | boards[board_idx].status = ENABLED; | ||
2710 | boards[board_idx].type = epca_info_tbl[info_idx].board_type; | ||
2711 | boards[board_idx].numports = 0x0; | ||
2712 | boards[board_idx].port = addr + PCI_IO_OFFSET; | ||
2713 | boards[board_idx].membase = addr; | ||
2714 | |||
2715 | if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) { | ||
2716 | printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", | ||
2717 | 0x200000, addr + PCI_IO_OFFSET); | ||
2718 | goto err_out; | ||
2719 | } | ||
2720 | |||
2721 | boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET, | ||
2722 | 0x200000); | ||
2723 | if (!boards[board_idx].re_map_port) { | ||
2724 | printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", | ||
2725 | 0x200000, addr + PCI_IO_OFFSET); | ||
2726 | goto err_out_free_pciio; | ||
2727 | } | ||
2728 | |||
2729 | if (!request_mem_region(addr, 0x200000, "epca")) { | ||
2730 | printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", | ||
2731 | 0x200000, addr); | ||
2732 | goto err_out_free_iounmap; | ||
2733 | } | ||
2734 | |||
2735 | boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000); | ||
2736 | if (!boards[board_idx].re_map_membase) { | ||
2737 | printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", | ||
2738 | 0x200000, addr + PCI_IO_OFFSET); | ||
2739 | goto err_out_free_memregion; | ||
2740 | } | ||
2741 | |||
2742 | /* | ||
2743 | * I don't know what the below does, but the hardware guys say its | ||
2744 | * required on everything except PLX (In this case XRJ). | ||
2745 | */ | ||
2746 | if (info_idx != brd_xrj) { | ||
2747 | pci_write_config_byte(pdev, 0x40, 0); | ||
2748 | pci_write_config_byte(pdev, 0x46, 0); | ||
2749 | } | ||
2750 | |||
2751 | return 0; | ||
2752 | |||
2753 | err_out_free_memregion: | ||
2754 | release_mem_region(addr, 0x200000); | ||
2755 | err_out_free_iounmap: | ||
2756 | iounmap(boards[board_idx].re_map_port); | ||
2757 | err_out_free_pciio: | ||
2758 | release_mem_region(addr + PCI_IO_OFFSET, 0x200000); | ||
2759 | err_out: | ||
2760 | return -ENODEV; | ||
2761 | } | ||
2762 | |||
2763 | |||
2764 | static struct pci_device_id epca_pci_tbl[] = { | ||
2765 | { PCI_VENDOR_DIGI, PCI_DEVICE_XR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xr }, | ||
2766 | { PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem }, | ||
2767 | { PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx }, | ||
2768 | { PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj }, | ||
2769 | { 0, } | ||
2770 | }; | ||
2771 | |||
2772 | MODULE_DEVICE_TABLE(pci, epca_pci_tbl); | ||
2773 | |||
2774 | static int __init init_PCI(void) | ||
2775 | { | ||
2776 | memset(&epca_driver, 0, sizeof(epca_driver)); | ||
2777 | epca_driver.name = "epca"; | ||
2778 | epca_driver.id_table = epca_pci_tbl; | ||
2779 | epca_driver.probe = epca_init_one; | ||
2780 | |||
2781 | return pci_register_driver(&epca_driver); | ||
2782 | } | ||
2783 | |||
2784 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/epca.h b/drivers/char/epca.h deleted file mode 100644 index d414bf2dbf7c..000000000000 --- a/drivers/char/epca.h +++ /dev/null | |||
@@ -1,158 +0,0 @@ | |||
1 | #define XEMPORTS 0xC02 | ||
2 | #define XEPORTS 0xC22 | ||
3 | |||
4 | #define MAX_ALLOC 0x100 | ||
5 | |||
6 | #define MAXBOARDS 12 | ||
7 | #define FEPCODESEG 0x0200L | ||
8 | #define FEPCODE 0x2000L | ||
9 | #define BIOSCODE 0xf800L | ||
10 | |||
11 | #define MISCGLOBAL 0x0C00L | ||
12 | #define NPORT 0x0C22L | ||
13 | #define MBOX 0x0C40L | ||
14 | #define PORTBASE 0x0C90L | ||
15 | |||
16 | /* Begin code defines used for epca_setup */ | ||
17 | |||
18 | #define INVALID_BOARD_TYPE 0x1 | ||
19 | #define INVALID_NUM_PORTS 0x2 | ||
20 | #define INVALID_MEM_BASE 0x4 | ||
21 | #define INVALID_PORT_BASE 0x8 | ||
22 | #define INVALID_BOARD_STATUS 0x10 | ||
23 | #define INVALID_ALTPIN 0x20 | ||
24 | |||
25 | /* End code defines used for epca_setup */ | ||
26 | |||
27 | |||
28 | #define FEPCLR 0x00 | ||
29 | #define FEPMEM 0x02 | ||
30 | #define FEPRST 0x04 | ||
31 | #define FEPINT 0x08 | ||
32 | #define FEPMASK 0x0e | ||
33 | #define FEPWIN 0x80 | ||
34 | |||
35 | #define PCXE 0 | ||
36 | #define PCXEVE 1 | ||
37 | #define PCXEM 2 | ||
38 | #define EISAXEM 3 | ||
39 | #define PC64XE 4 | ||
40 | #define PCXI 5 | ||
41 | #define PCIXEM 7 | ||
42 | #define PCICX 8 | ||
43 | #define PCIXR 9 | ||
44 | #define PCIXRJ 10 | ||
45 | #define EPCA_NUM_TYPES 6 | ||
46 | |||
47 | |||
48 | static char *board_desc[] = | ||
49 | { | ||
50 | "PC/Xe", | ||
51 | "PC/Xeve", | ||
52 | "PC/Xem", | ||
53 | "EISA/Xem", | ||
54 | "PC/64Xe", | ||
55 | "PC/Xi", | ||
56 | "unknown", | ||
57 | "PCI/Xem", | ||
58 | "PCI/CX", | ||
59 | "PCI/Xr", | ||
60 | "PCI/Xrj", | ||
61 | }; | ||
62 | |||
63 | #define STARTC 021 | ||
64 | #define STOPC 023 | ||
65 | #define IAIXON 0x2000 | ||
66 | |||
67 | |||
68 | #define TXSTOPPED 0x1 | ||
69 | #define LOWWAIT 0x2 | ||
70 | #define EMPTYWAIT 0x4 | ||
71 | #define RXSTOPPED 0x8 | ||
72 | #define TXBUSY 0x10 | ||
73 | |||
74 | #define DISABLED 0 | ||
75 | #define ENABLED 1 | ||
76 | #define OFF 0 | ||
77 | #define ON 1 | ||
78 | |||
79 | #define FEPTIMEOUT 200000 | ||
80 | #define SERIAL_TYPE_INFO 3 | ||
81 | #define EPCA_EVENT_HANGUP 1 | ||
82 | #define EPCA_MAGIC 0x5c6df104L | ||
83 | |||
84 | struct channel | ||
85 | { | ||
86 | long magic; | ||
87 | struct tty_port port; | ||
88 | unsigned char boardnum; | ||
89 | unsigned char channelnum; | ||
90 | unsigned char omodem; /* FEP output modem status */ | ||
91 | unsigned char imodem; /* FEP input modem status */ | ||
92 | unsigned char modemfake; /* Modem values to be forced */ | ||
93 | unsigned char modem; /* Force values */ | ||
94 | unsigned char hflow; | ||
95 | unsigned char dsr; | ||
96 | unsigned char dcd; | ||
97 | unsigned char m_rts ; /* The bits used in whatever FEP */ | ||
98 | unsigned char m_dcd ; /* is indiginous to this board to */ | ||
99 | unsigned char m_dsr ; /* represent each of the physical */ | ||
100 | unsigned char m_cts ; /* handshake lines */ | ||
101 | unsigned char m_ri ; | ||
102 | unsigned char m_dtr ; | ||
103 | unsigned char stopc; | ||
104 | unsigned char startc; | ||
105 | unsigned char stopca; | ||
106 | unsigned char startca; | ||
107 | unsigned char fepstopc; | ||
108 | unsigned char fepstartc; | ||
109 | unsigned char fepstopca; | ||
110 | unsigned char fepstartca; | ||
111 | unsigned char txwin; | ||
112 | unsigned char rxwin; | ||
113 | unsigned short fepiflag; | ||
114 | unsigned short fepcflag; | ||
115 | unsigned short fepoflag; | ||
116 | unsigned short txbufhead; | ||
117 | unsigned short txbufsize; | ||
118 | unsigned short rxbufhead; | ||
119 | unsigned short rxbufsize; | ||
120 | int close_delay; | ||
121 | unsigned long event; | ||
122 | uint dev; | ||
123 | unsigned long statusflags; | ||
124 | unsigned long c_iflag; | ||
125 | unsigned long c_cflag; | ||
126 | unsigned long c_lflag; | ||
127 | unsigned long c_oflag; | ||
128 | unsigned char __iomem *txptr; | ||
129 | unsigned char __iomem *rxptr; | ||
130 | struct board_info *board; | ||
131 | struct board_chan __iomem *brdchan; | ||
132 | struct digi_struct digiext; | ||
133 | struct work_struct tqueue; | ||
134 | struct global_data __iomem *mailbox; | ||
135 | }; | ||
136 | |||
137 | struct board_info | ||
138 | { | ||
139 | unsigned char status; | ||
140 | unsigned char type; | ||
141 | unsigned char altpin; | ||
142 | unsigned short numports; | ||
143 | unsigned long port; | ||
144 | unsigned long membase; | ||
145 | void __iomem *re_map_port; | ||
146 | void __iomem *re_map_membase; | ||
147 | unsigned long memory_seg; | ||
148 | void ( * memwinon ) (struct board_info *, unsigned int) ; | ||
149 | void ( * memwinoff ) (struct board_info *, unsigned int) ; | ||
150 | void ( * globalwinon ) (struct channel *) ; | ||
151 | void ( * txwinon ) (struct channel *) ; | ||
152 | void ( * rxwinon ) (struct channel *) ; | ||
153 | void ( * memoff ) (struct channel *) ; | ||
154 | void ( * assertgwinon ) (struct channel *) ; | ||
155 | void ( * assertmemoff ) (struct channel *) ; | ||
156 | unsigned char poller_inhibited ; | ||
157 | }; | ||
158 | |||
diff --git a/drivers/char/epcaconfig.h b/drivers/char/epcaconfig.h deleted file mode 100644 index 55dec067078e..000000000000 --- a/drivers/char/epcaconfig.h +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | #define NUMCARDS 0 | ||
2 | #define NBDEVS 0 | ||
3 | |||
4 | struct board_info static_boards[NUMCARDS]={ | ||
5 | }; | ||
6 | |||
7 | /* DO NOT HAND EDIT THIS FILE! */ | ||
diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile deleted file mode 100644 index 7b78e0dfc5b0..000000000000 --- a/drivers/char/ip2/Makefile +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the Computone IntelliPort Plus Driver | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_COMPUTONE) += ip2.o | ||
6 | |||
7 | ip2-y := ip2main.o | ||
8 | |||
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c deleted file mode 100644 index e7af647800b6..000000000000 --- a/drivers/char/ip2/i2cmd.c +++ /dev/null | |||
@@ -1,210 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Definition table for In-line and Bypass commands. Applicable | ||
12 | * only when the standard loadware is active. (This is included | ||
13 | * source code, not a separate compilation module.) | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | |||
17 | //------------------------------------------------------------------------------ | ||
18 | // | ||
19 | // Revision History: | ||
20 | // | ||
21 | // 10 October 1991 MAG First Draft | ||
22 | // 7 November 1991 MAG Reflects additional commands. | ||
23 | // 24 February 1992 MAG Additional commands for 1.4.x loadware | ||
24 | // 11 March 1992 MAG Additional commands | ||
25 | // 30 March 1992 MAG Additional command: CMD_DSS_NOW | ||
26 | // 18 May 1992 MAG Discovered commands 39 & 40 must be at the end of a | ||
27 | // packet: affects implementation. | ||
28 | //------------------------------------------------------------------------------ | ||
29 | |||
30 | //************ | ||
31 | //* Includes * | ||
32 | //************ | ||
33 | |||
34 | #include "i2cmd.h" /* To get some bit-defines */ | ||
35 | |||
36 | //------------------------------------------------------------------------------ | ||
37 | // Here is the table of global arrays which represent each type of command | ||
38 | // supported in the IntelliPort standard loadware. See also i2cmd.h | ||
39 | // for a more complete explanation of what is going on. | ||
40 | //------------------------------------------------------------------------------ | ||
41 | |||
42 | // Here are the various globals: note that the names are not used except through | ||
43 | // the macros defined in i2cmd.h. Also note that although they are character | ||
44 | // arrays here (for extendability) they are cast to structure pointers in the | ||
45 | // i2cmd.h macros. See i2cmd.h for flags definitions. | ||
46 | |||
47 | // Length Flags Command | ||
48 | static UCHAR ct02[] = { 1, BTH, 0x02 }; // DTR UP | ||
49 | static UCHAR ct03[] = { 1, BTH, 0x03 }; // DTR DN | ||
50 | static UCHAR ct04[] = { 1, BTH, 0x04 }; // RTS UP | ||
51 | static UCHAR ct05[] = { 1, BTH, 0x05 }; // RTS DN | ||
52 | static UCHAR ct06[] = { 1, BYP, 0x06 }; // START FL | ||
53 | static UCHAR ct07[] = { 2, BTH, 0x07,0 }; // BAUD | ||
54 | static UCHAR ct08[] = { 2, BTH, 0x08,0 }; // BITS | ||
55 | static UCHAR ct09[] = { 2, BTH, 0x09,0 }; // STOP | ||
56 | static UCHAR ct10[] = { 2, BTH, 0x0A,0 }; // PARITY | ||
57 | static UCHAR ct11[] = { 2, BTH, 0x0B,0 }; // XON | ||
58 | static UCHAR ct12[] = { 2, BTH, 0x0C,0 }; // XOFF | ||
59 | static UCHAR ct13[] = { 1, BTH, 0x0D }; // STOP FL | ||
60 | static UCHAR ct14[] = { 1, BYP|VIP, 0x0E }; // ACK HOTK | ||
61 | //static UCHAR ct15[]={ 2, BTH|VIP, 0x0F,0 }; // IRQ SET | ||
62 | static UCHAR ct16[] = { 2, INL, 0x10,0 }; // IXONOPTS | ||
63 | static UCHAR ct17[] = { 2, INL, 0x11,0 }; // OXONOPTS | ||
64 | static UCHAR ct18[] = { 1, INL, 0x12 }; // CTSENAB | ||
65 | static UCHAR ct19[] = { 1, BTH, 0x13 }; // CTSDSAB | ||
66 | static UCHAR ct20[] = { 1, INL, 0x14 }; // DCDENAB | ||
67 | static UCHAR ct21[] = { 1, BTH, 0x15 }; // DCDDSAB | ||
68 | static UCHAR ct22[] = { 1, BTH, 0x16 }; // DSRENAB | ||
69 | static UCHAR ct23[] = { 1, BTH, 0x17 }; // DSRDSAB | ||
70 | static UCHAR ct24[] = { 1, BTH, 0x18 }; // RIENAB | ||
71 | static UCHAR ct25[] = { 1, BTH, 0x19 }; // RIDSAB | ||
72 | static UCHAR ct26[] = { 2, BTH, 0x1A,0 }; // BRKENAB | ||
73 | static UCHAR ct27[] = { 1, BTH, 0x1B }; // BRKDSAB | ||
74 | //static UCHAR ct28[]={ 2, BTH, 0x1C,0 }; // MAXBLOKSIZE | ||
75 | //static UCHAR ct29[]={ 2, 0, 0x1D,0 }; // reserved | ||
76 | static UCHAR ct30[] = { 1, INL, 0x1E }; // CTSFLOWENAB | ||
77 | static UCHAR ct31[] = { 1, INL, 0x1F }; // CTSFLOWDSAB | ||
78 | static UCHAR ct32[] = { 1, INL, 0x20 }; // RTSFLOWENAB | ||
79 | static UCHAR ct33[] = { 1, INL, 0x21 }; // RTSFLOWDSAB | ||
80 | static UCHAR ct34[] = { 2, BTH, 0x22,0 }; // ISTRIPMODE | ||
81 | static UCHAR ct35[] = { 2, BTH|END, 0x23,0 }; // SENDBREAK | ||
82 | static UCHAR ct36[] = { 2, BTH, 0x24,0 }; // SETERRMODE | ||
83 | //static UCHAR ct36a[]={ 3, INL, 0x24,0,0 }; // SET_REPLACE | ||
84 | |||
85 | // The following is listed for completeness, but should never be sent directly | ||
86 | // by user-level code. It is sent only by library routines in response to data | ||
87 | // movement. | ||
88 | //static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0 }; // FLOW PACKET | ||
89 | |||
90 | // Back to normal | ||
91 | //static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ | ||
92 | //static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0 }; // OPOSTON | ||
93 | //static UCHAR ct40[]={ 1, BTH|END, 0x28 }; // OPOSTOFF | ||
94 | static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME | ||
95 | //static UCHAR ct42[]={ 2, BTH, 0x2A,0 }; // TXBAUD | ||
96 | //static UCHAR ct43[]={ 2, BTH, 0x2B,0 }; // RXBAUD | ||
97 | //static UCHAR ct44[]={ 2, BTH, 0x2C,0 }; // MS PING | ||
98 | //static UCHAR ct45[]={ 1, BTH, 0x2D }; // HOTENAB | ||
99 | //static UCHAR ct46[]={ 1, BTH, 0x2E }; // HOTDSAB | ||
100 | //static UCHAR ct47[]={ 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS | ||
101 | //static UCHAR ct48[]={ 1, BTH, 0x30 }; // DSRFLOWENAB | ||
102 | //static UCHAR ct49[]={ 1, BTH, 0x31 }; // DSRFLOWDSAB | ||
103 | //static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB | ||
104 | //static UCHAR ct51[]={ 1, BTH, 0x33 }; // DTRFLOWDSAB | ||
105 | //static UCHAR ct52[]={ 1, BTH, 0x34 }; // BAUDTABRESET | ||
106 | //static UCHAR ct53[] = { 3, BTH, 0x35,0,0 }; // BAUDREMAP | ||
107 | static UCHAR ct54[] = { 3, BTH, 0x36,0,0 }; // CUSTOMBAUD1 | ||
108 | static UCHAR ct55[] = { 3, BTH, 0x37,0,0 }; // CUSTOMBAUD2 | ||
109 | static UCHAR ct56[] = { 2, BTH|END, 0x38,0 }; // PAUSE | ||
110 | static UCHAR ct57[] = { 1, BYP, 0x39 }; // SUSPEND | ||
111 | static UCHAR ct58[] = { 1, BYP, 0x3A }; // UNSUSPEND | ||
112 | static UCHAR ct59[] = { 2, BTH, 0x3B,0 }; // PARITYCHK | ||
113 | static UCHAR ct60[] = { 1, INL|VIP, 0x3C }; // BOOKMARKREQ | ||
114 | //static UCHAR ct61[]={ 2, BTH, 0x3D,0 }; // INTERNALLOOP | ||
115 | //static UCHAR ct62[]={ 2, BTH, 0x3E,0 }; // HOTKTIMEOUT | ||
116 | static UCHAR ct63[] = { 2, INL, 0x3F,0 }; // SETTXON | ||
117 | static UCHAR ct64[] = { 2, INL, 0x40,0 }; // SETTXOFF | ||
118 | //static UCHAR ct65[]={ 2, BTH, 0x41,0 }; // SETAUTORTS | ||
119 | //static UCHAR ct66[]={ 2, BTH, 0x42,0 }; // SETHIGHWAT | ||
120 | //static UCHAR ct67[]={ 2, BYP, 0x43,0 }; // STARTSELFL | ||
121 | //static UCHAR ct68[]={ 2, INL, 0x44,0 }; // ENDSELFL | ||
122 | //static UCHAR ct69[]={ 1, BYP, 0x45 }; // HWFLOW_OFF | ||
123 | //static UCHAR ct70[]={ 1, BTH, 0x46 }; // ODSRFL_ENAB | ||
124 | //static UCHAR ct71[]={ 1, BTH, 0x47 }; // ODSRFL_DSAB | ||
125 | //static UCHAR ct72[]={ 1, BTH, 0x48 }; // ODCDFL_ENAB | ||
126 | //static UCHAR ct73[]={ 1, BTH, 0x49 }; // ODCDFL_DSAB | ||
127 | //static UCHAR ct74[]={ 2, BTH, 0x4A,0 }; // LOADLEVEL | ||
128 | //static UCHAR ct75[]={ 2, BTH, 0x4B,0 }; // STATDATA | ||
129 | //static UCHAR ct76[]={ 1, BYP, 0x4C }; // BREAK_ON | ||
130 | //static UCHAR ct77[]={ 1, BYP, 0x4D }; // BREAK_OFF | ||
131 | //static UCHAR ct78[]={ 1, BYP, 0x4E }; // GETFC | ||
132 | static UCHAR ct79[] = { 2, BYP, 0x4F,0 }; // XMIT_NOW | ||
133 | //static UCHAR ct80[]={ 4, BTH, 0x50,0,0,0 }; // DIVISOR_LATCH | ||
134 | //static UCHAR ct81[]={ 1, BYP, 0x51 }; // GET_STATUS | ||
135 | //static UCHAR ct82[]={ 1, BYP, 0x52 }; // GET_TXCNT | ||
136 | //static UCHAR ct83[]={ 1, BYP, 0x53 }; // GET_RXCNT | ||
137 | //static UCHAR ct84[]={ 1, BYP, 0x54 }; // GET_BOXIDS | ||
138 | //static UCHAR ct85[]={10, BYP, 0x55,0,0,0,0,0,0,0,0,0 }; // ENAB_MULT | ||
139 | //static UCHAR ct86[]={ 2, BTH, 0x56,0 }; // RCV_ENABLE | ||
140 | static UCHAR ct87[] = { 1, BYP, 0x57 }; // HW_TEST | ||
141 | //static UCHAR ct88[]={ 3, BTH, 0x58,0,0 }; // RCV_THRESHOLD | ||
142 | //static UCHAR ct90[]={ 3, BYP, 0x5A,0,0 }; // Set SILO | ||
143 | //static UCHAR ct91[]={ 2, BYP, 0x5B,0 }; // timed break | ||
144 | |||
145 | // Some composite commands as well | ||
146 | //static UCHAR cc01[]={ 2, BTH, 0x02,0x04 }; // DTR & RTS UP | ||
147 | //static UCHAR cc02[]={ 2, BTH, 0x03,0x05 }; // DTR & RTS DN | ||
148 | |||
149 | //******** | ||
150 | //* Code * | ||
151 | //******** | ||
152 | |||
153 | //****************************************************************************** | ||
154 | // Function: i2cmdUnixFlags(iflag, cflag, lflag) | ||
155 | // Parameters: Unix tty flags | ||
156 | // | ||
157 | // Returns: Pointer to command structure | ||
158 | // | ||
159 | // Description: | ||
160 | // | ||
161 | // This routine sets the parameters of command 47 and returns a pointer to the | ||
162 | // appropriate structure. | ||
163 | //****************************************************************************** | ||
164 | #if 0 | ||
165 | cmdSyntaxPtr | ||
166 | i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag) | ||
167 | { | ||
168 | cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct47; | ||
169 | |||
170 | pCM->cmd[1] = (unsigned char) iflag; | ||
171 | pCM->cmd[2] = (unsigned char) (iflag >> 8); | ||
172 | pCM->cmd[3] = (unsigned char) cflag; | ||
173 | pCM->cmd[4] = (unsigned char) (cflag >> 8); | ||
174 | pCM->cmd[5] = (unsigned char) lflag; | ||
175 | pCM->cmd[6] = (unsigned char) (lflag >> 8); | ||
176 | return pCM; | ||
177 | } | ||
178 | #endif /* 0 */ | ||
179 | |||
180 | //****************************************************************************** | ||
181 | // Function: i2cmdBaudDef(which, rate) | ||
182 | // Parameters: ? | ||
183 | // | ||
184 | // Returns: Pointer to command structure | ||
185 | // | ||
186 | // Description: | ||
187 | // | ||
188 | // This routine sets the parameters of commands 54 or 55 (according to the | ||
189 | // argument which), and returns a pointer to the appropriate structure. | ||
190 | //****************************************************************************** | ||
191 | static cmdSyntaxPtr | ||
192 | i2cmdBaudDef(int which, unsigned short rate) | ||
193 | { | ||
194 | cmdSyntaxPtr pCM; | ||
195 | |||
196 | switch(which) | ||
197 | { | ||
198 | case 1: | ||
199 | pCM = (cmdSyntaxPtr) ct54; | ||
200 | break; | ||
201 | default: | ||
202 | case 2: | ||
203 | pCM = (cmdSyntaxPtr) ct55; | ||
204 | break; | ||
205 | } | ||
206 | pCM->cmd[1] = (unsigned char) rate; | ||
207 | pCM->cmd[2] = (unsigned char) (rate >> 8); | ||
208 | return pCM; | ||
209 | } | ||
210 | |||
diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h deleted file mode 100644 index 29277ec6b8ed..000000000000 --- a/drivers/char/ip2/i2cmd.h +++ /dev/null | |||
@@ -1,630 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Definitions and support for In-line and Bypass commands. | ||
12 | * Applicable only when the standard loadware is active. | ||
13 | * | ||
14 | *******************************************************************************/ | ||
15 | //------------------------------------------------------------------------------ | ||
16 | // Revision History: | ||
17 | // | ||
18 | // 10 October 1991 MAG First Draft | ||
19 | // 7 November 1991 MAG Reflects some new commands | ||
20 | // 20 February 1992 MAG CMD_HOTACK corrected: no argument. | ||
21 | // 24 February 1992 MAG Support added for new commands for 1.4.x loadware. | ||
22 | // 11 March 1992 MAG Additional commands. | ||
23 | // 16 March 1992 MAG Additional commands. | ||
24 | // 30 March 1992 MAG Additional command: CMD_DSS_NOW | ||
25 | // 18 May 1992 MAG Changed CMD_OPOST | ||
26 | // | ||
27 | //------------------------------------------------------------------------------ | ||
28 | #ifndef I2CMD_H // To prevent multiple includes | ||
29 | #define I2CMD_H 1 | ||
30 | |||
31 | #include "ip2types.h" | ||
32 | |||
33 | // This module is designed to provide a uniform method of sending commands to | ||
34 | // the board through command packets. The difficulty is, some commands take | ||
35 | // parameters, others do not. Furthermore, it is often useful to send several | ||
36 | // commands to the same channel as part of the same packet. (See also i2pack.h.) | ||
37 | // | ||
38 | // This module is designed so that the caller should not be responsible for | ||
39 | // remembering the exact syntax of each command, or at least so that the | ||
40 | // compiler could check things somewhat. I'll explain as we go... | ||
41 | // | ||
42 | // First, a structure which can embody the syntax of each type of command. | ||
43 | // | ||
44 | typedef struct _cmdSyntax | ||
45 | { | ||
46 | UCHAR length; // Number of bytes in the command | ||
47 | UCHAR flags; // Information about the command (see below) | ||
48 | |||
49 | // The command and its parameters, which may be of arbitrary length. Don't | ||
50 | // worry yet how the parameters will be initialized; macros later take care | ||
51 | // of it. Also, don't worry about the arbitrary length issue; this structure | ||
52 | // is never used to allocate space (see i2cmd.c). | ||
53 | UCHAR cmd[2]; | ||
54 | } cmdSyntax, *cmdSyntaxPtr; | ||
55 | |||
56 | // Bit assignments for flags | ||
57 | |||
58 | #define INL 1 // Set if suitable for inline commands | ||
59 | #define BYP 2 // Set if suitable for bypass commands | ||
60 | #define BTH (INL|BYP) // suitable for either! | ||
61 | #define END 4 // Set if this must be the last command in a block | ||
62 | #define VIP 8 // Set if this command is special in some way and really | ||
63 | // should only be sent from the library-level and not | ||
64 | // directly from user-level | ||
65 | #define VAR 0x10 // This command is of variable length! | ||
66 | |||
67 | // Declarations for the global arrays used to bear the commands and their | ||
68 | // arguments. | ||
69 | // | ||
70 | // Note: Since these are globals and the arguments might change, it is important | ||
71 | // that the library routine COPY these into buffers from whence they would be | ||
72 | // sent, rather than merely storing the pointers. In multi-threaded | ||
73 | // environments, important that the copy should obtain before any context switch | ||
74 | // is allowed. Also, for parameterized commands, DO NOT ISSUE THE SAME COMMAND | ||
75 | // MORE THAN ONCE WITH THE SAME PARAMETERS in the same call. | ||
76 | // | ||
77 | static UCHAR ct02[]; | ||
78 | static UCHAR ct03[]; | ||
79 | static UCHAR ct04[]; | ||
80 | static UCHAR ct05[]; | ||
81 | static UCHAR ct06[]; | ||
82 | static UCHAR ct07[]; | ||
83 | static UCHAR ct08[]; | ||
84 | static UCHAR ct09[]; | ||
85 | static UCHAR ct10[]; | ||
86 | static UCHAR ct11[]; | ||
87 | static UCHAR ct12[]; | ||
88 | static UCHAR ct13[]; | ||
89 | static UCHAR ct14[]; | ||
90 | static UCHAR ct15[]; | ||
91 | static UCHAR ct16[]; | ||
92 | static UCHAR ct17[]; | ||
93 | static UCHAR ct18[]; | ||
94 | static UCHAR ct19[]; | ||
95 | static UCHAR ct20[]; | ||
96 | static UCHAR ct21[]; | ||
97 | static UCHAR ct22[]; | ||
98 | static UCHAR ct23[]; | ||
99 | static UCHAR ct24[]; | ||
100 | static UCHAR ct25[]; | ||
101 | static UCHAR ct26[]; | ||
102 | static UCHAR ct27[]; | ||
103 | static UCHAR ct28[]; | ||
104 | static UCHAR ct29[]; | ||
105 | static UCHAR ct30[]; | ||
106 | static UCHAR ct31[]; | ||
107 | static UCHAR ct32[]; | ||
108 | static UCHAR ct33[]; | ||
109 | static UCHAR ct34[]; | ||
110 | static UCHAR ct35[]; | ||
111 | static UCHAR ct36[]; | ||
112 | static UCHAR ct36a[]; | ||
113 | static UCHAR ct41[]; | ||
114 | static UCHAR ct42[]; | ||
115 | static UCHAR ct43[]; | ||
116 | static UCHAR ct44[]; | ||
117 | static UCHAR ct45[]; | ||
118 | static UCHAR ct46[]; | ||
119 | static UCHAR ct48[]; | ||
120 | static UCHAR ct49[]; | ||
121 | static UCHAR ct50[]; | ||
122 | static UCHAR ct51[]; | ||
123 | static UCHAR ct52[]; | ||
124 | static UCHAR ct56[]; | ||
125 | static UCHAR ct57[]; | ||
126 | static UCHAR ct58[]; | ||
127 | static UCHAR ct59[]; | ||
128 | static UCHAR ct60[]; | ||
129 | static UCHAR ct61[]; | ||
130 | static UCHAR ct62[]; | ||
131 | static UCHAR ct63[]; | ||
132 | static UCHAR ct64[]; | ||
133 | static UCHAR ct65[]; | ||
134 | static UCHAR ct66[]; | ||
135 | static UCHAR ct67[]; | ||
136 | static UCHAR ct68[]; | ||
137 | static UCHAR ct69[]; | ||
138 | static UCHAR ct70[]; | ||
139 | static UCHAR ct71[]; | ||
140 | static UCHAR ct72[]; | ||
141 | static UCHAR ct73[]; | ||
142 | static UCHAR ct74[]; | ||
143 | static UCHAR ct75[]; | ||
144 | static UCHAR ct76[]; | ||
145 | static UCHAR ct77[]; | ||
146 | static UCHAR ct78[]; | ||
147 | static UCHAR ct79[]; | ||
148 | static UCHAR ct80[]; | ||
149 | static UCHAR ct81[]; | ||
150 | static UCHAR ct82[]; | ||
151 | static UCHAR ct83[]; | ||
152 | static UCHAR ct84[]; | ||
153 | static UCHAR ct85[]; | ||
154 | static UCHAR ct86[]; | ||
155 | static UCHAR ct87[]; | ||
156 | static UCHAR ct88[]; | ||
157 | static UCHAR ct89[]; | ||
158 | static UCHAR ct90[]; | ||
159 | static UCHAR ct91[]; | ||
160 | static UCHAR cc01[]; | ||
161 | static UCHAR cc02[]; | ||
162 | |||
163 | // Now, refer to i2cmd.c, and see the character arrays defined there. They are | ||
164 | // cast here to cmdSyntaxPtr. | ||
165 | // | ||
166 | // There are library functions for issuing bypass or inline commands. These | ||
167 | // functions take one or more arguments of the type cmdSyntaxPtr. The routine | ||
168 | // then can figure out how long each command is supposed to be and easily add it | ||
169 | // to the list. | ||
170 | // | ||
171 | // For ease of use, we define manifests which return pointers to appropriate | ||
172 | // cmdSyntaxPtr things. But some commands also take arguments. If a single | ||
173 | // argument is used, we define a macro which performs the single assignment and | ||
174 | // (through the expedient of a comma expression) references the appropriate | ||
175 | // pointer. For commands requiring several arguments, we actually define a | ||
176 | // function to perform the assignments. | ||
177 | |||
178 | #define CMD_DTRUP (cmdSyntaxPtr)(ct02) // Raise DTR | ||
179 | #define CMD_DTRDN (cmdSyntaxPtr)(ct03) // Lower DTR | ||
180 | #define CMD_RTSUP (cmdSyntaxPtr)(ct04) // Raise RTS | ||
181 | #define CMD_RTSDN (cmdSyntaxPtr)(ct05) // Lower RTS | ||
182 | #define CMD_STARTFL (cmdSyntaxPtr)(ct06) // Start Flushing Data | ||
183 | |||
184 | #define CMD_DTRRTS_UP (cmdSyntaxPtr)(cc01) // Raise DTR and RTS | ||
185 | #define CMD_DTRRTS_DN (cmdSyntaxPtr)(cc02) // Lower DTR and RTS | ||
186 | |||
187 | // Set Baud Rate for transmit and receive | ||
188 | #define CMD_SETBAUD(arg) \ | ||
189 | (((cmdSyntaxPtr)(ct07))->cmd[1] = (arg),(cmdSyntaxPtr)(ct07)) | ||
190 | |||
191 | #define CBR_50 1 | ||
192 | #define CBR_75 2 | ||
193 | #define CBR_110 3 | ||
194 | #define CBR_134 4 | ||
195 | #define CBR_150 5 | ||
196 | #define CBR_200 6 | ||
197 | #define CBR_300 7 | ||
198 | #define CBR_600 8 | ||
199 | #define CBR_1200 9 | ||
200 | #define CBR_1800 10 | ||
201 | #define CBR_2400 11 | ||
202 | #define CBR_4800 12 | ||
203 | #define CBR_9600 13 | ||
204 | #define CBR_19200 14 | ||
205 | #define CBR_38400 15 | ||
206 | #define CBR_2000 16 | ||
207 | #define CBR_3600 17 | ||
208 | #define CBR_7200 18 | ||
209 | #define CBR_56000 19 | ||
210 | #define CBR_57600 20 | ||
211 | #define CBR_64000 21 | ||
212 | #define CBR_76800 22 | ||
213 | #define CBR_115200 23 | ||
214 | #define CBR_C1 24 // Custom baud rate 1 | ||
215 | #define CBR_C2 25 // Custom baud rate 2 | ||
216 | #define CBR_153600 26 | ||
217 | #define CBR_230400 27 | ||
218 | #define CBR_307200 28 | ||
219 | #define CBR_460800 29 | ||
220 | #define CBR_921600 30 | ||
221 | |||
222 | // Set Character size | ||
223 | // | ||
224 | #define CMD_SETBITS(arg) \ | ||
225 | (((cmdSyntaxPtr)(ct08))->cmd[1] = (arg),(cmdSyntaxPtr)(ct08)) | ||
226 | |||
227 | #define CSZ_5 0 | ||
228 | #define CSZ_6 1 | ||
229 | #define CSZ_7 2 | ||
230 | #define CSZ_8 3 | ||
231 | |||
232 | // Set number of stop bits | ||
233 | // | ||
234 | #define CMD_SETSTOP(arg) \ | ||
235 | (((cmdSyntaxPtr)(ct09))->cmd[1] = (arg),(cmdSyntaxPtr)(ct09)) | ||
236 | |||
237 | #define CST_1 0 | ||
238 | #define CST_15 1 // 1.5 stop bits | ||
239 | #define CST_2 2 | ||
240 | |||
241 | // Set parity option | ||
242 | // | ||
243 | #define CMD_SETPAR(arg) \ | ||
244 | (((cmdSyntaxPtr)(ct10))->cmd[1] = (arg),(cmdSyntaxPtr)(ct10)) | ||
245 | |||
246 | #define CSP_NP 0 // no parity | ||
247 | #define CSP_OD 1 // odd parity | ||
248 | #define CSP_EV 2 // Even parity | ||
249 | #define CSP_SP 3 // Space parity | ||
250 | #define CSP_MK 4 // Mark parity | ||
251 | |||
252 | // Define xon char for transmitter flow control | ||
253 | // | ||
254 | #define CMD_DEF_IXON(arg) \ | ||
255 | (((cmdSyntaxPtr)(ct11))->cmd[1] = (arg),(cmdSyntaxPtr)(ct11)) | ||
256 | |||
257 | // Define xoff char for transmitter flow control | ||
258 | // | ||
259 | #define CMD_DEF_IXOFF(arg) \ | ||
260 | (((cmdSyntaxPtr)(ct12))->cmd[1] = (arg),(cmdSyntaxPtr)(ct12)) | ||
261 | |||
262 | #define CMD_STOPFL (cmdSyntaxPtr)(ct13) // Stop Flushing data | ||
263 | |||
264 | // Acknowledge receipt of hotkey signal | ||
265 | // | ||
266 | #define CMD_HOTACK (cmdSyntaxPtr)(ct14) | ||
267 | |||
268 | // Define irq level to use. Should actually be sent by library-level code, not | ||
269 | // directly from user... | ||
270 | // | ||
271 | #define CMDVALUE_IRQ 15 // For library use at initialization. Until this command | ||
272 | // is sent, board processing doesn't really start. | ||
273 | #define CMD_SET_IRQ(arg) \ | ||
274 | (((cmdSyntaxPtr)(ct15))->cmd[1] = (arg),(cmdSyntaxPtr)(ct15)) | ||
275 | |||
276 | #define CIR_POLL 0 // No IRQ - Poll | ||
277 | #define CIR_3 3 // IRQ 3 | ||
278 | #define CIR_4 4 // IRQ 4 | ||
279 | #define CIR_5 5 // IRQ 5 | ||
280 | #define CIR_7 7 // IRQ 7 | ||
281 | #define CIR_10 10 // IRQ 10 | ||
282 | #define CIR_11 11 // IRQ 11 | ||
283 | #define CIR_12 12 // IRQ 12 | ||
284 | #define CIR_15 15 // IRQ 15 | ||
285 | |||
286 | // Select transmit flow xon/xoff options | ||
287 | // | ||
288 | #define CMD_IXON_OPT(arg) \ | ||
289 | (((cmdSyntaxPtr)(ct16))->cmd[1] = (arg),(cmdSyntaxPtr)(ct16)) | ||
290 | |||
291 | #define CIX_NONE 0 // Incoming Xon/Xoff characters not special | ||
292 | #define CIX_XON 1 // Xoff disable, Xon enable | ||
293 | #define CIX_XANY 2 // Xoff disable, any key enable | ||
294 | |||
295 | // Select receive flow xon/xoff options | ||
296 | // | ||
297 | #define CMD_OXON_OPT(arg) \ | ||
298 | (((cmdSyntaxPtr)(ct17))->cmd[1] = (arg),(cmdSyntaxPtr)(ct17)) | ||
299 | |||
300 | #define COX_NONE 0 // Don't send Xon/Xoff | ||
301 | #define COX_XON 1 // Send xon/xoff to start/stop incoming data | ||
302 | |||
303 | |||
304 | #define CMD_CTS_REP (cmdSyntaxPtr)(ct18) // Enable CTS reporting | ||
305 | #define CMD_CTS_NREP (cmdSyntaxPtr)(ct19) // Disable CTS reporting | ||
306 | |||
307 | #define CMD_DCD_REP (cmdSyntaxPtr)(ct20) // Enable DCD reporting | ||
308 | #define CMD_DCD_NREP (cmdSyntaxPtr)(ct21) // Disable DCD reporting | ||
309 | |||
310 | #define CMD_DSR_REP (cmdSyntaxPtr)(ct22) // Enable DSR reporting | ||
311 | #define CMD_DSR_NREP (cmdSyntaxPtr)(ct23) // Disable DSR reporting | ||
312 | |||
313 | #define CMD_RI_REP (cmdSyntaxPtr)(ct24) // Enable RI reporting | ||
314 | #define CMD_RI_NREP (cmdSyntaxPtr)(ct25) // Disable RI reporting | ||
315 | |||
316 | // Enable break reporting and select style | ||
317 | // | ||
318 | #define CMD_BRK_REP(arg) \ | ||
319 | (((cmdSyntaxPtr)(ct26))->cmd[1] = (arg),(cmdSyntaxPtr)(ct26)) | ||
320 | |||
321 | #define CBK_STAT 0x00 // Report breaks as a status (exception,irq) | ||
322 | #define CBK_NULL 0x01 // Report breaks as a good null | ||
323 | #define CBK_STAT_SEQ 0x02 // Report breaks as a status AND as in-band character | ||
324 | // sequence FFh, 01h, 10h | ||
325 | #define CBK_SEQ 0x03 // Report breaks as the in-band | ||
326 | //sequence FFh, 01h, 10h ONLY. | ||
327 | #define CBK_FLSH 0x04 // if this bit set also flush input data | ||
328 | #define CBK_POSIX 0x08 // if this bit set report as FF,0,0 sequence | ||
329 | #define CBK_SINGLE 0x10 // if this bit set with CBK_SEQ or CBK_STAT_SEQ | ||
330 | //then reports single null instead of triple | ||
331 | |||
332 | #define CMD_BRK_NREP (cmdSyntaxPtr)(ct27) // Disable break reporting | ||
333 | |||
334 | // Specify maximum block size for received data | ||
335 | // | ||
336 | #define CMD_MAX_BLOCK(arg) \ | ||
337 | (((cmdSyntaxPtr)(ct28))->cmd[1] = (arg),(cmdSyntaxPtr)(ct28)) | ||
338 | |||
339 | // -- COMMAND 29 is reserved -- | ||
340 | |||
341 | #define CMD_CTSFL_ENAB (cmdSyntaxPtr)(ct30) // Enable CTS flow control | ||
342 | #define CMD_CTSFL_DSAB (cmdSyntaxPtr)(ct31) // Disable CTS flow control | ||
343 | #define CMD_RTSFL_ENAB (cmdSyntaxPtr)(ct32) // Enable RTS flow control | ||
344 | #define CMD_RTSFL_DSAB (cmdSyntaxPtr)(ct33) // Disable RTS flow control | ||
345 | |||
346 | // Specify istrip option | ||
347 | // | ||
348 | #define CMD_ISTRIP_OPT(arg) \ | ||
349 | (((cmdSyntaxPtr)(ct34))->cmd[1] = (arg),(cmdSyntaxPtr)(ct34)) | ||
350 | |||
351 | #define CIS_NOSTRIP 0 // Strip characters to character size | ||
352 | #define CIS_STRIP 1 // Strip any 8-bit characters to 7 bits | ||
353 | |||
354 | // Send a break of arg milliseconds | ||
355 | // | ||
356 | #define CMD_SEND_BRK(arg) \ | ||
357 | (((cmdSyntaxPtr)(ct35))->cmd[1] = (arg),(cmdSyntaxPtr)(ct35)) | ||
358 | |||
359 | // Set error reporting mode | ||
360 | // | ||
361 | #define CMD_SET_ERROR(arg) \ | ||
362 | (((cmdSyntaxPtr)(ct36))->cmd[1] = (arg),(cmdSyntaxPtr)(ct36)) | ||
363 | |||
364 | #define CSE_ESTAT 0 // Report error in a status packet | ||
365 | #define CSE_NOREP 1 // Treat character as though it were good | ||
366 | #define CSE_DROP 2 // Discard the character | ||
367 | #define CSE_NULL 3 // Replace with a null | ||
368 | #define CSE_MARK 4 // Replace with a 3-character sequence (as Unix) | ||
369 | |||
370 | #define CSE_REPLACE 0x8 // Replace the errored character with the | ||
371 | // replacement character defined here | ||
372 | |||
373 | #define CSE_STAT_REPLACE 0x18 // Replace the errored character with the | ||
374 | // replacement character defined here AND | ||
375 | // report the error as a status packet (as in | ||
376 | // CSE_ESTAT). | ||
377 | |||
378 | |||
379 | // COMMAND 37, to send flow control packets, is handled only by low-level | ||
380 | // library code in response to data movement and shouldn't ever be sent by the | ||
381 | // user code. See i2pack.h and the body of i2lib.c for details. | ||
382 | |||
383 | // Enable on-board post-processing, using options given in oflag argument. | ||
384 | // Formerly, this command was automatically preceded by a CMD_OPOST_OFF command | ||
385 | // because the loadware does not permit sending back-to-back CMD_OPOST_ON | ||
386 | // commands without an intervening CMD_OPOST_OFF. BUT, WE LEARN 18 MAY 92, that | ||
387 | // CMD_OPOST_ON and CMD_OPOST_OFF must each be at the end of a packet (or in a | ||
388 | // solo packet). This means the caller must specify separately CMD_OPOST_OFF, | ||
389 | // CMD_OPOST_ON(parm) when he calls i2QueueCommands(). That function will ensure | ||
390 | // each gets a separate packet. Extra CMD_OPOST_OFF's are always ok. | ||
391 | // | ||
392 | #define CMD_OPOST_ON(oflag) \ | ||
393 | (*(USHORT *)(((cmdSyntaxPtr)(ct39))->cmd[1]) = (oflag), \ | ||
394 | (cmdSyntaxPtr)(ct39)) | ||
395 | |||
396 | #define CMD_OPOST_OFF (cmdSyntaxPtr)(ct40) // Disable on-board post-proc | ||
397 | |||
398 | #define CMD_RESUME (cmdSyntaxPtr)(ct41) // Resume: behave as though an XON | ||
399 | // were received; | ||
400 | |||
401 | // Set Transmit baud rate (see command 7 for arguments) | ||
402 | // | ||
403 | #define CMD_SETBAUD_TX(arg) \ | ||
404 | (((cmdSyntaxPtr)(ct42))->cmd[1] = (arg),(cmdSyntaxPtr)(ct42)) | ||
405 | |||
406 | // Set Receive baud rate (see command 7 for arguments) | ||
407 | // | ||
408 | #define CMD_SETBAUD_RX(arg) \ | ||
409 | (((cmdSyntaxPtr)(ct43))->cmd[1] = (arg),(cmdSyntaxPtr)(ct43)) | ||
410 | |||
411 | // Request interrupt from board each arg milliseconds. Interrupt will specify | ||
412 | // "received data", even though there may be no data present. If arg == 0, | ||
413 | // disables any such interrupts. | ||
414 | // | ||
415 | #define CMD_PING_REQ(arg) \ | ||
416 | (((cmdSyntaxPtr)(ct44))->cmd[1] = (arg),(cmdSyntaxPtr)(ct44)) | ||
417 | |||
418 | #define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking | ||
419 | #define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking | ||
420 | |||
421 | #if 0 | ||
422 | // COMMAND 47: Send Protocol info via Unix flags: | ||
423 | // iflag = Unix tty t_iflag | ||
424 | // cflag = Unix tty t_cflag | ||
425 | // lflag = Unix tty t_lflag | ||
426 | // See System V Unix/Xenix documentation for the meanings of the bit fields | ||
427 | // within these flags | ||
428 | // | ||
429 | #define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag) | ||
430 | #endif /* 0 */ | ||
431 | |||
432 | #define CMD_DSRFL_ENAB (cmdSyntaxPtr)(ct48) // Enable DSR receiver ctrl | ||
433 | #define CMD_DSRFL_DSAB (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl | ||
434 | #define CMD_DTRFL_ENAB (cmdSyntaxPtr)(ct50) // Enable DTR flow control | ||
435 | #define CMD_DTRFL_DSAB (cmdSyntaxPtr)(ct51) // Disable DTR flow control | ||
436 | #define CMD_BAUD_RESET (cmdSyntaxPtr)(ct52) // Reset baudrate table | ||
437 | |||
438 | // COMMAND 54: Define custom rate #1 | ||
439 | // rate = (short) 1/10 of the desired baud rate | ||
440 | // | ||
441 | #define CMD_BAUD_DEF1(rate) i2cmdBaudDef(1,rate) | ||
442 | |||
443 | // COMMAND 55: Define custom rate #2 | ||
444 | // rate = (short) 1/10 of the desired baud rate | ||
445 | // | ||
446 | #define CMD_BAUD_DEF2(rate) i2cmdBaudDef(2,rate) | ||
447 | |||
448 | // Pause arg hundredths of seconds. (Note, this is NOT milliseconds.) | ||
449 | // | ||
450 | #define CMD_PAUSE(arg) \ | ||
451 | (((cmdSyntaxPtr)(ct56))->cmd[1] = (arg),(cmdSyntaxPtr)(ct56)) | ||
452 | |||
453 | #define CMD_SUSPEND (cmdSyntaxPtr)(ct57) // Suspend output | ||
454 | #define CMD_UNSUSPEND (cmdSyntaxPtr)(ct58) // Un-Suspend output | ||
455 | |||
456 | // Set parity-checking options | ||
457 | // | ||
458 | #define CMD_PARCHK(arg) \ | ||
459 | (((cmdSyntaxPtr)(ct59))->cmd[1] = (arg),(cmdSyntaxPtr)(ct59)) | ||
460 | |||
461 | #define CPK_ENAB 0 // Enable parity checking on input | ||
462 | #define CPK_DSAB 1 // Disable parity checking on input | ||
463 | |||
464 | #define CMD_BMARK_REQ (cmdSyntaxPtr)(ct60) // Bookmark request | ||
465 | |||
466 | |||
467 | // Enable/Disable internal loopback mode | ||
468 | // | ||
469 | #define CMD_INLOOP(arg) \ | ||
470 | (((cmdSyntaxPtr)(ct61))->cmd[1] = (arg),(cmdSyntaxPtr)(ct61)) | ||
471 | |||
472 | #define CIN_DISABLE 0 // Normal operation (default) | ||
473 | #define CIN_ENABLE 1 // Internal (local) loopback | ||
474 | #define CIN_REMOTE 2 // Remote loopback | ||
475 | |||
476 | // Specify timeout for hotkeys: Delay will be (arg x 10) milliseconds, arg == 0 | ||
477 | // --> no timeout: wait forever. | ||
478 | // | ||
479 | #define CMD_HOT_TIME(arg) \ | ||
480 | (((cmdSyntaxPtr)(ct62))->cmd[1] = (arg),(cmdSyntaxPtr)(ct62)) | ||
481 | |||
482 | |||
483 | // Define (outgoing) xon for receive flow control | ||
484 | // | ||
485 | #define CMD_DEF_OXON(arg) \ | ||
486 | (((cmdSyntaxPtr)(ct63))->cmd[1] = (arg),(cmdSyntaxPtr)(ct63)) | ||
487 | |||
488 | // Define (outgoing) xoff for receiver flow control | ||
489 | // | ||
490 | #define CMD_DEF_OXOFF(arg) \ | ||
491 | (((cmdSyntaxPtr)(ct64))->cmd[1] = (arg),(cmdSyntaxPtr)(ct64)) | ||
492 | |||
493 | // Enable/Disable RTS on transmit (1/2 duplex-style) | ||
494 | // | ||
495 | #define CMD_RTS_XMIT(arg) \ | ||
496 | (((cmdSyntaxPtr)(ct65))->cmd[1] = (arg),(cmdSyntaxPtr)(ct65)) | ||
497 | |||
498 | #define CHD_DISABLE 0 | ||
499 | #define CHD_ENABLE 1 | ||
500 | |||
501 | // Set high-water-mark level (debugging use only) | ||
502 | // | ||
503 | #define CMD_SETHIGHWAT(arg) \ | ||
504 | (((cmdSyntaxPtr)(ct66))->cmd[1] = (arg),(cmdSyntaxPtr)(ct66)) | ||
505 | |||
506 | // Start flushing tagged data (tag = 0-14) | ||
507 | // | ||
508 | #define CMD_START_SELFL(tag) \ | ||
509 | (((cmdSyntaxPtr)(ct67))->cmd[1] = (tag),(cmdSyntaxPtr)(ct67)) | ||
510 | |||
511 | // End flushing tagged data (tag = 0-14) | ||
512 | // | ||
513 | #define CMD_END_SELFL(tag) \ | ||
514 | (((cmdSyntaxPtr)(ct68))->cmd[1] = (tag),(cmdSyntaxPtr)(ct68)) | ||
515 | |||
516 | #define CMD_HWFLOW_OFF (cmdSyntaxPtr)(ct69) // Disable HW TX flow control | ||
517 | #define CMD_ODSRFL_ENAB (cmdSyntaxPtr)(ct70) // Enable DSR output f/c | ||
518 | #define CMD_ODSRFL_DSAB (cmdSyntaxPtr)(ct71) // Disable DSR output f/c | ||
519 | #define CMD_ODCDFL_ENAB (cmdSyntaxPtr)(ct72) // Enable DCD output f/c | ||
520 | #define CMD_ODCDFL_DSAB (cmdSyntaxPtr)(ct73) // Disable DCD output f/c | ||
521 | |||
522 | // Set transmit interrupt load level. Count should be an even value 2-12 | ||
523 | // | ||
524 | #define CMD_LOADLEVEL(count) \ | ||
525 | (((cmdSyntaxPtr)(ct74))->cmd[1] = (count),(cmdSyntaxPtr)(ct74)) | ||
526 | |||
527 | // If reporting DSS changes, map to character sequence FFh, 2, MSR | ||
528 | // | ||
529 | #define CMD_STATDATA(arg) \ | ||
530 | (((cmdSyntaxPtr)(ct75))->cmd[1] = (arg),(cmdSyntaxPtr)(ct75)) | ||
531 | |||
532 | #define CSTD_DISABLE// Report DSS changes as status packets only (default) | ||
533 | #define CSTD_ENABLE // Report DSS changes as in-band data sequence as well as | ||
534 | // by status packet. | ||
535 | |||
536 | #define CMD_BREAK_ON (cmdSyntaxPtr)(ct76)// Set break and stop xmit | ||
537 | #define CMD_BREAK_OFF (cmdSyntaxPtr)(ct77)// End break and restart xmit | ||
538 | #define CMD_GETFC (cmdSyntaxPtr)(ct78)// Request for flow control packet | ||
539 | // from board. | ||
540 | |||
541 | // Transmit this character immediately | ||
542 | // | ||
543 | #define CMD_XMIT_NOW(ch) \ | ||
544 | (((cmdSyntaxPtr)(ct79))->cmd[1] = (ch),(cmdSyntaxPtr)(ct79)) | ||
545 | |||
546 | // Set baud rate via "divisor latch" | ||
547 | // | ||
548 | #define CMD_DIVISOR_LATCH(which,value) \ | ||
549 | (((cmdSyntaxPtr)(ct80))->cmd[1] = (which), \ | ||
550 | *(USHORT *)(((cmdSyntaxPtr)(ct80))->cmd[2]) = (value), \ | ||
551 | (cmdSyntaxPtr)(ct80)) | ||
552 | |||
553 | #define CDL_RX 1 // Set receiver rate | ||
554 | #define CDL_TX 2 // Set transmit rate | ||
555 | // (CDL_TX | CDL_RX) Set both rates | ||
556 | |||
557 | // Request for special diagnostic status pkt from the board. | ||
558 | // | ||
559 | #define CMD_GET_STATUS (cmdSyntaxPtr)(ct81) | ||
560 | |||
561 | // Request time-stamped transmit character count packet. | ||
562 | // | ||
563 | #define CMD_GET_TXCNT (cmdSyntaxPtr)(ct82) | ||
564 | |||
565 | // Request time-stamped receive character count packet. | ||
566 | // | ||
567 | #define CMD_GET_RXCNT (cmdSyntaxPtr)(ct83) | ||
568 | |||
569 | // Request for box/board I.D. packet. | ||
570 | #define CMD_GET_BOXIDS (cmdSyntaxPtr)(ct84) | ||
571 | |||
572 | // Enable or disable multiple channels according to bit-mapped ushorts box 1-4 | ||
573 | // | ||
574 | #define CMD_ENAB_MULT(enable, box1, box2, box3, box4) \ | ||
575 | (((cmdSytaxPtr)(ct85))->cmd[1] = (enable), \ | ||
576 | *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[2]) = (box1), \ | ||
577 | *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[4]) = (box2), \ | ||
578 | *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[6]) = (box3), \ | ||
579 | *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[8]) = (box4), \ | ||
580 | (cmdSyntaxPtr)(ct85)) | ||
581 | |||
582 | #define CEM_DISABLE 0 | ||
583 | #define CEM_ENABLE 1 | ||
584 | |||
585 | // Enable or disable receiver or receiver interrupts (default both enabled) | ||
586 | // | ||
587 | #define CMD_RCV_ENABLE(ch) \ | ||
588 | (((cmdSyntaxPtr)(ct86))->cmd[1] = (ch),(cmdSyntaxPtr)(ct86)) | ||
589 | |||
590 | #define CRE_OFF 0 // Disable the receiver | ||
591 | #define CRE_ON 1 // Enable the receiver | ||
592 | #define CRE_INTOFF 2 // Disable receiver interrupts (to loadware) | ||
593 | #define CRE_INTON 3 // Enable receiver interrupts (to loadware) | ||
594 | |||
595 | // Starts up a hardware test process, which runs transparently, and sends a | ||
596 | // STAT_HWFAIL packet in case a hardware failure is detected. | ||
597 | // | ||
598 | #define CMD_HW_TEST (cmdSyntaxPtr)(ct87) | ||
599 | |||
600 | // Change receiver threshold and timeout value: | ||
601 | // Defaults: timeout = 20mS | ||
602 | // threshold count = 8 when DTRflow not in use, | ||
603 | // threshold count = 5 when DTRflow in use. | ||
604 | // | ||
605 | #define CMD_RCV_THRESHOLD(count,ms) \ | ||
606 | (((cmdSyntaxPtr)(ct88))->cmd[1] = (count), \ | ||
607 | ((cmdSyntaxPtr)(ct88))->cmd[2] = (ms), \ | ||
608 | (cmdSyntaxPtr)(ct88)) | ||
609 | |||
610 | // Makes the loadware report DSS signals for this channel immediately. | ||
611 | // | ||
612 | #define CMD_DSS_NOW (cmdSyntaxPtr)(ct89) | ||
613 | |||
614 | // Set the receive silo parameters | ||
615 | // timeout is ms idle wait until delivery (~VTIME) | ||
616 | // threshold is max characters cause interrupt (~VMIN) | ||
617 | // | ||
618 | #define CMD_SET_SILO(timeout,threshold) \ | ||
619 | (((cmdSyntaxPtr)(ct90))->cmd[1] = (timeout), \ | ||
620 | ((cmdSyntaxPtr)(ct90))->cmd[2] = (threshold), \ | ||
621 | (cmdSyntaxPtr)(ct90)) | ||
622 | |||
623 | // Set timed break in decisecond (1/10s) | ||
624 | // | ||
625 | #define CMD_LBREAK(ds) \ | ||
626 | (((cmdSyntaxPtr)(ct91))->cmd[1] = (ds),(cmdSyntaxPtr)(ct66)) | ||
627 | |||
628 | |||
629 | |||
630 | #endif // I2CMD_H | ||
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c deleted file mode 100644 index 29db44de399f..000000000000 --- a/drivers/char/ip2/i2ellis.c +++ /dev/null | |||
@@ -1,1403 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Low-level interface code for the device driver | ||
12 | * (This is included source code, not a separate compilation | ||
13 | * module.) | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | //--------------------------------------------- | ||
17 | // Function declarations private to this module | ||
18 | //--------------------------------------------- | ||
19 | // Functions called only indirectly through i2eBordStr entries. | ||
20 | |||
21 | static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int); | ||
22 | static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int); | ||
23 | static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int); | ||
24 | static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int); | ||
25 | |||
26 | static unsigned short iiReadWord16(i2eBordStrPtr); | ||
27 | static unsigned short iiReadWord8(i2eBordStrPtr); | ||
28 | static void iiWriteWord16(i2eBordStrPtr, unsigned short); | ||
29 | static void iiWriteWord8(i2eBordStrPtr, unsigned short); | ||
30 | |||
31 | static int iiWaitForTxEmptyII(i2eBordStrPtr, int); | ||
32 | static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int); | ||
33 | static int iiTxMailEmptyII(i2eBordStrPtr); | ||
34 | static int iiTxMailEmptyIIEX(i2eBordStrPtr); | ||
35 | static int iiTrySendMailII(i2eBordStrPtr, unsigned char); | ||
36 | static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char); | ||
37 | |||
38 | static unsigned short iiGetMailII(i2eBordStrPtr); | ||
39 | static unsigned short iiGetMailIIEX(i2eBordStrPtr); | ||
40 | |||
41 | static void iiEnableMailIrqII(i2eBordStrPtr); | ||
42 | static void iiEnableMailIrqIIEX(i2eBordStrPtr); | ||
43 | static void iiWriteMaskII(i2eBordStrPtr, unsigned char); | ||
44 | static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char); | ||
45 | |||
46 | static void ii2Nop(void); | ||
47 | |||
48 | //*************** | ||
49 | //* Static Data * | ||
50 | //*************** | ||
51 | |||
52 | static int ii2Safe; // Safe I/O address for delay routine | ||
53 | |||
54 | static int iiDelayed; // Set when the iiResetDelay function is | ||
55 | // called. Cleared when ANY board is reset. | ||
56 | static DEFINE_RWLOCK(Dl_spinlock); | ||
57 | |||
58 | //******** | ||
59 | //* Code * | ||
60 | //******** | ||
61 | |||
62 | //======================================================= | ||
63 | // Initialization Routines | ||
64 | // | ||
65 | // iiSetAddress | ||
66 | // iiReset | ||
67 | // iiResetDelay | ||
68 | // iiInitialize | ||
69 | //======================================================= | ||
70 | |||
71 | //****************************************************************************** | ||
72 | // Function: iiSetAddress(pB, address, delay) | ||
73 | // Parameters: pB - pointer to the board structure | ||
74 | // address - the purported I/O address of the board | ||
75 | // delay - pointer to the 1-ms delay function to use | ||
76 | // in this and any future operations to this board | ||
77 | // | ||
78 | // Returns: True if everything appears copacetic. | ||
79 | // False if there is any error: the pB->i2eError field has the error | ||
80 | // | ||
81 | // Description: | ||
82 | // | ||
83 | // This routine (roughly) checks for address validity, sets the i2eValid OK and | ||
84 | // sets the state to II_STATE_COLD which means that we haven't even sent a reset | ||
85 | // yet. | ||
86 | // | ||
87 | //****************************************************************************** | ||
88 | static int | ||
89 | iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay ) | ||
90 | { | ||
91 | // Should any failure occur before init is finished... | ||
92 | pB->i2eValid = I2E_INCOMPLETE; | ||
93 | |||
94 | // Cannot check upper limit except extremely: Might be microchannel | ||
95 | // Address must be on an 8-byte boundary | ||
96 | |||
97 | if ((unsigned int)address <= 0x100 | ||
98 | || (unsigned int)address >= 0xfff8 | ||
99 | || (address & 0x7) | ||
100 | ) | ||
101 | { | ||
102 | I2_COMPLETE(pB, I2EE_BADADDR); | ||
103 | } | ||
104 | |||
105 | // Initialize accelerators | ||
106 | pB->i2eBase = address; | ||
107 | pB->i2eData = address + FIFO_DATA; | ||
108 | pB->i2eStatus = address + FIFO_STATUS; | ||
109 | pB->i2ePointer = address + FIFO_PTR; | ||
110 | pB->i2eXMail = address + FIFO_MAIL; | ||
111 | pB->i2eXMask = address + FIFO_MASK; | ||
112 | |||
113 | // Initialize i/o address for ii2DelayIO | ||
114 | ii2Safe = address + FIFO_NOP; | ||
115 | |||
116 | // Initialize the delay routine | ||
117 | pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop); | ||
118 | |||
119 | pB->i2eValid = I2E_MAGIC; | ||
120 | pB->i2eState = II_STATE_COLD; | ||
121 | |||
122 | I2_COMPLETE(pB, I2EE_GOOD); | ||
123 | } | ||
124 | |||
125 | //****************************************************************************** | ||
126 | // Function: iiReset(pB) | ||
127 | // Parameters: pB - pointer to the board structure | ||
128 | // | ||
129 | // Returns: True if everything appears copacetic. | ||
130 | // False if there is any error: the pB->i2eError field has the error | ||
131 | // | ||
132 | // Description: | ||
133 | // | ||
134 | // Attempts to reset the board (see also i2hw.h). Normally, we would use this to | ||
135 | // reset a board immediately after iiSetAddress(), but it is valid to reset a | ||
136 | // board from any state, say, in order to change or re-load loadware. (Under | ||
137 | // such circumstances, no reason to re-run iiSetAddress(), which is why it is a | ||
138 | // separate routine and not included in this routine. | ||
139 | // | ||
140 | //****************************************************************************** | ||
141 | static int | ||
142 | iiReset(i2eBordStrPtr pB) | ||
143 | { | ||
144 | // Magic number should be set, else even the address is suspect | ||
145 | if (pB->i2eValid != I2E_MAGIC) | ||
146 | { | ||
147 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
148 | } | ||
149 | |||
150 | outb(0, pB->i2eBase + FIFO_RESET); /* Any data will do */ | ||
151 | iiDelay(pB, 50); // Pause between resets | ||
152 | outb(0, pB->i2eBase + FIFO_RESET); /* Second reset */ | ||
153 | |||
154 | // We must wait before even attempting to read anything from the FIFO: the | ||
155 | // board's P.O.S.T may actually attempt to read and write its end of the | ||
156 | // FIFO in order to check flags, loop back (where supported), etc. On | ||
157 | // completion of this testing it would reset the FIFO, and on completion | ||
158 | // of all // P.O.S.T., write the message. We must not mistake data which | ||
159 | // might have been sent for testing as part of the reset message. To | ||
160 | // better utilize time, say, when resetting several boards, we allow the | ||
161 | // delay to be performed externally; in this way the caller can reset | ||
162 | // several boards, delay a single time, then call the initialization | ||
163 | // routine for all. | ||
164 | |||
165 | pB->i2eState = II_STATE_RESET; | ||
166 | |||
167 | iiDelayed = 0; // i.e., the delay routine hasn't been called since the most | ||
168 | // recent reset. | ||
169 | |||
170 | // Ensure anything which would have been of use to standard loadware is | ||
171 | // blanked out, since board has now forgotten everything!. | ||
172 | |||
173 | pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */ | ||
174 | pB->i2eWaitingForEmptyFifo = 0; | ||
175 | pB->i2eOutMailWaiting = 0; | ||
176 | pB->i2eChannelPtr = NULL; | ||
177 | pB->i2eChannelCnt = 0; | ||
178 | |||
179 | pB->i2eLeadoffWord[0] = 0; | ||
180 | pB->i2eFifoInInts = 0; | ||
181 | pB->i2eFifoOutInts = 0; | ||
182 | pB->i2eFatalTrap = NULL; | ||
183 | pB->i2eFatal = 0; | ||
184 | |||
185 | I2_COMPLETE(pB, I2EE_GOOD); | ||
186 | } | ||
187 | |||
188 | //****************************************************************************** | ||
189 | // Function: iiResetDelay(pB) | ||
190 | // Parameters: pB - pointer to the board structure | ||
191 | // | ||
192 | // Returns: True if everything appears copacetic. | ||
193 | // False if there is any error: the pB->i2eError field has the error | ||
194 | // | ||
195 | // Description: | ||
196 | // | ||
197 | // Using the delay defined in board structure, waits two seconds (for board to | ||
198 | // reset). | ||
199 | // | ||
200 | //****************************************************************************** | ||
201 | static int | ||
202 | iiResetDelay(i2eBordStrPtr pB) | ||
203 | { | ||
204 | if (pB->i2eValid != I2E_MAGIC) { | ||
205 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
206 | } | ||
207 | if (pB->i2eState != II_STATE_RESET) { | ||
208 | I2_COMPLETE(pB, I2EE_BADSTATE); | ||
209 | } | ||
210 | iiDelay(pB,2000); /* Now we wait for two seconds. */ | ||
211 | iiDelayed = 1; /* Delay has been called: ok to initialize */ | ||
212 | I2_COMPLETE(pB, I2EE_GOOD); | ||
213 | } | ||
214 | |||
215 | //****************************************************************************** | ||
216 | // Function: iiInitialize(pB) | ||
217 | // Parameters: pB - pointer to the board structure | ||
218 | // | ||
219 | // Returns: True if everything appears copacetic. | ||
220 | // False if there is any error: the pB->i2eError field has the error | ||
221 | // | ||
222 | // Description: | ||
223 | // | ||
224 | // Attempts to read the Power-on reset message. Initializes any remaining fields | ||
225 | // in the pB structure. | ||
226 | // | ||
227 | // This should be called as the third step of a process beginning with | ||
228 | // iiReset(), then iiResetDelay(). This routine checks to see that the structure | ||
229 | // is "valid" and in the reset state, also confirms that the delay routine has | ||
230 | // been called since the latest reset (to any board! overly strong!). | ||
231 | // | ||
232 | //****************************************************************************** | ||
233 | static int | ||
234 | iiInitialize(i2eBordStrPtr pB) | ||
235 | { | ||
236 | int itemp; | ||
237 | unsigned char c; | ||
238 | unsigned short utemp; | ||
239 | unsigned int ilimit; | ||
240 | |||
241 | if (pB->i2eValid != I2E_MAGIC) | ||
242 | { | ||
243 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
244 | } | ||
245 | |||
246 | if (pB->i2eState != II_STATE_RESET || !iiDelayed) | ||
247 | { | ||
248 | I2_COMPLETE(pB, I2EE_BADSTATE); | ||
249 | } | ||
250 | |||
251 | // In case there is a failure short of our completely reading the power-up | ||
252 | // message. | ||
253 | pB->i2eValid = I2E_INCOMPLETE; | ||
254 | |||
255 | |||
256 | // Now attempt to read the message. | ||
257 | |||
258 | for (itemp = 0; itemp < sizeof(porStr); itemp++) | ||
259 | { | ||
260 | // We expect the entire message is ready. | ||
261 | if (!I2_HAS_INPUT(pB)) { | ||
262 | pB->i2ePomSize = itemp; | ||
263 | I2_COMPLETE(pB, I2EE_PORM_SHORT); | ||
264 | } | ||
265 | |||
266 | pB->i2ePom.c[itemp] = c = inb(pB->i2eData); | ||
267 | |||
268 | // We check the magic numbers as soon as they are supposed to be read | ||
269 | // (rather than after) to minimize effect of reading something we | ||
270 | // already suspect can't be "us". | ||
271 | if ( (itemp == POR_1_INDEX && c != POR_MAGIC_1) || | ||
272 | (itemp == POR_2_INDEX && c != POR_MAGIC_2)) | ||
273 | { | ||
274 | pB->i2ePomSize = itemp+1; | ||
275 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | pB->i2ePomSize = itemp; | ||
280 | |||
281 | // Ensure that this was all the data... | ||
282 | if (I2_HAS_INPUT(pB)) | ||
283 | I2_COMPLETE(pB, I2EE_PORM_LONG); | ||
284 | |||
285 | // For now, we'll fail to initialize if P.O.S.T reports bad chip mapper: | ||
286 | // Implying we will not be able to download any code either: That's ok: the | ||
287 | // condition is pretty explicit. | ||
288 | if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER) | ||
289 | { | ||
290 | I2_COMPLETE(pB, I2EE_POSTERR); | ||
291 | } | ||
292 | |||
293 | // Determine anything which must be done differently depending on the family | ||
294 | // of boards! | ||
295 | switch (pB->i2ePom.e.porID & POR_ID_FAMILY) | ||
296 | { | ||
297 | case POR_ID_FII: // IntelliPort-II | ||
298 | |||
299 | pB->i2eFifoStyle = FIFO_II; | ||
300 | pB->i2eFifoSize = 512; // 512 bytes, always | ||
301 | pB->i2eDataWidth16 = false; | ||
302 | |||
303 | pB->i2eMaxIrq = 15; // Because board cannot tell us it is in an 8-bit | ||
304 | // slot, we do allow it to be done (documentation!) | ||
305 | |||
306 | pB->i2eGoodMap[1] = | ||
307 | pB->i2eGoodMap[2] = | ||
308 | pB->i2eGoodMap[3] = | ||
309 | pB->i2eChannelMap[1] = | ||
310 | pB->i2eChannelMap[2] = | ||
311 | pB->i2eChannelMap[3] = 0; | ||
312 | |||
313 | switch (pB->i2ePom.e.porID & POR_ID_SIZE) | ||
314 | { | ||
315 | case POR_ID_II_4: | ||
316 | pB->i2eGoodMap[0] = | ||
317 | pB->i2eChannelMap[0] = 0x0f; // four-port | ||
318 | |||
319 | // Since porPorts1 is based on the Hardware ID register, the numbers | ||
320 | // should always be consistent for IntelliPort-II. Ditto below... | ||
321 | if (pB->i2ePom.e.porPorts1 != 4) | ||
322 | { | ||
323 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
324 | } | ||
325 | break; | ||
326 | |||
327 | case POR_ID_II_8: | ||
328 | case POR_ID_II_8R: | ||
329 | pB->i2eGoodMap[0] = | ||
330 | pB->i2eChannelMap[0] = 0xff; // Eight port | ||
331 | if (pB->i2ePom.e.porPorts1 != 8) | ||
332 | { | ||
333 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
334 | } | ||
335 | break; | ||
336 | |||
337 | case POR_ID_II_6: | ||
338 | pB->i2eGoodMap[0] = | ||
339 | pB->i2eChannelMap[0] = 0x3f; // Six Port | ||
340 | if (pB->i2ePom.e.porPorts1 != 6) | ||
341 | { | ||
342 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
343 | } | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | // Fix up the "good channel list based on any errors reported. | ||
348 | if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1) | ||
349 | { | ||
350 | pB->i2eGoodMap[0] &= ~0x0f; | ||
351 | } | ||
352 | |||
353 | if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2) | ||
354 | { | ||
355 | pB->i2eGoodMap[0] &= ~0xf0; | ||
356 | } | ||
357 | |||
358 | break; // POR_ID_FII case | ||
359 | |||
360 | case POR_ID_FIIEX: // IntelliPort-IIEX | ||
361 | |||
362 | pB->i2eFifoStyle = FIFO_IIEX; | ||
363 | |||
364 | itemp = pB->i2ePom.e.porFifoSize; | ||
365 | |||
366 | // Implicit assumption that fifo would not grow beyond 32k, | ||
367 | // nor would ever be less than 256. | ||
368 | |||
369 | if (itemp < 8 || itemp > 15) | ||
370 | { | ||
371 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
372 | } | ||
373 | pB->i2eFifoSize = (1 << itemp); | ||
374 | |||
375 | // These are based on what P.O.S.T thinks should be there, based on | ||
376 | // box ID registers | ||
377 | ilimit = pB->i2ePom.e.porNumBoxes; | ||
378 | if (ilimit > ABS_MAX_BOXES) | ||
379 | { | ||
380 | ilimit = ABS_MAX_BOXES; | ||
381 | } | ||
382 | |||
383 | // For as many boxes as EXIST, gives the type of box. | ||
384 | // Added 8/6/93: check for the ISA-4 (asic) which looks like an | ||
385 | // expandable but for whom "8 or 16?" is not the right question. | ||
386 | |||
387 | utemp = pB->i2ePom.e.porFlags; | ||
388 | if (utemp & POR_CEX4) | ||
389 | { | ||
390 | pB->i2eChannelMap[0] = 0x000f; | ||
391 | } else { | ||
392 | utemp &= POR_BOXES; | ||
393 | for (itemp = 0; itemp < ilimit; itemp++) | ||
394 | { | ||
395 | pB->i2eChannelMap[itemp] = | ||
396 | ((utemp & POR_BOX_16) ? 0xffff : 0x00ff); | ||
397 | utemp >>= 1; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | // These are based on what P.O.S.T actually found. | ||
402 | |||
403 | utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1; | ||
404 | |||
405 | for (itemp = 0; itemp < ilimit; itemp++) | ||
406 | { | ||
407 | pB->i2eGoodMap[itemp] = 0; | ||
408 | if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f; | ||
409 | if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0; | ||
410 | if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00; | ||
411 | if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000; | ||
412 | utemp >>= 4; | ||
413 | } | ||
414 | |||
415 | // Now determine whether we should transfer in 8 or 16-bit mode. | ||
416 | switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) ) | ||
417 | { | ||
418 | case POR_BUS_SLOT16 | POR_BUS_DIP16: | ||
419 | pB->i2eDataWidth16 = true; | ||
420 | pB->i2eMaxIrq = 15; | ||
421 | break; | ||
422 | |||
423 | case POR_BUS_SLOT16: | ||
424 | pB->i2eDataWidth16 = false; | ||
425 | pB->i2eMaxIrq = 15; | ||
426 | break; | ||
427 | |||
428 | case 0: | ||
429 | case POR_BUS_DIP16: // In an 8-bit slot, DIP switch don't care. | ||
430 | default: | ||
431 | pB->i2eDataWidth16 = false; | ||
432 | pB->i2eMaxIrq = 7; | ||
433 | break; | ||
434 | } | ||
435 | break; // POR_ID_FIIEX case | ||
436 | |||
437 | default: // Unknown type of board | ||
438 | I2_COMPLETE(pB, I2EE_BAD_FAMILY); | ||
439 | break; | ||
440 | } // End the switch based on family | ||
441 | |||
442 | // Temporarily, claim there is no room in the outbound fifo. | ||
443 | // We will maintain this whenever we check for an empty outbound FIFO. | ||
444 | pB->i2eFifoRemains = 0; | ||
445 | |||
446 | // Now, based on the bus type, should we expect to be able to re-configure | ||
447 | // interrupts (say, for testing purposes). | ||
448 | switch (pB->i2ePom.e.porBus & POR_BUS_TYPE) | ||
449 | { | ||
450 | case POR_BUS_T_ISA: | ||
451 | case POR_BUS_T_UNK: // If the type of bus is undeclared, assume ok. | ||
452 | case POR_BUS_T_MCA: | ||
453 | case POR_BUS_T_EISA: | ||
454 | break; | ||
455 | default: | ||
456 | I2_COMPLETE(pB, I2EE_BADBUS); | ||
457 | } | ||
458 | |||
459 | if (pB->i2eDataWidth16) | ||
460 | { | ||
461 | pB->i2eWriteBuf = iiWriteBuf16; | ||
462 | pB->i2eReadBuf = iiReadBuf16; | ||
463 | pB->i2eWriteWord = iiWriteWord16; | ||
464 | pB->i2eReadWord = iiReadWord16; | ||
465 | } else { | ||
466 | pB->i2eWriteBuf = iiWriteBuf8; | ||
467 | pB->i2eReadBuf = iiReadBuf8; | ||
468 | pB->i2eWriteWord = iiWriteWord8; | ||
469 | pB->i2eReadWord = iiReadWord8; | ||
470 | } | ||
471 | |||
472 | switch(pB->i2eFifoStyle) | ||
473 | { | ||
474 | case FIFO_II: | ||
475 | pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII; | ||
476 | pB->i2eTxMailEmpty = iiTxMailEmptyII; | ||
477 | pB->i2eTrySendMail = iiTrySendMailII; | ||
478 | pB->i2eGetMail = iiGetMailII; | ||
479 | pB->i2eEnableMailIrq = iiEnableMailIrqII; | ||
480 | pB->i2eWriteMask = iiWriteMaskII; | ||
481 | |||
482 | break; | ||
483 | |||
484 | case FIFO_IIEX: | ||
485 | pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX; | ||
486 | pB->i2eTxMailEmpty = iiTxMailEmptyIIEX; | ||
487 | pB->i2eTrySendMail = iiTrySendMailIIEX; | ||
488 | pB->i2eGetMail = iiGetMailIIEX; | ||
489 | pB->i2eEnableMailIrq = iiEnableMailIrqIIEX; | ||
490 | pB->i2eWriteMask = iiWriteMaskIIEX; | ||
491 | |||
492 | break; | ||
493 | |||
494 | default: | ||
495 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
496 | } | ||
497 | |||
498 | // Initialize state information. | ||
499 | pB->i2eState = II_STATE_READY; // Ready to load loadware. | ||
500 | |||
501 | // Some Final cleanup: | ||
502 | // For some boards, the bootstrap firmware may perform some sort of test | ||
503 | // resulting in a stray character pending in the incoming mailbox. If one is | ||
504 | // there, it should be read and discarded, especially since for the standard | ||
505 | // firmware, it's the mailbox that interrupts the host. | ||
506 | |||
507 | pB->i2eStartMail = iiGetMail(pB); | ||
508 | |||
509 | // Throw it away and clear the mailbox structure element | ||
510 | pB->i2eStartMail = NO_MAIL_HERE; | ||
511 | |||
512 | // Everything is ok now, return with good status/ | ||
513 | |||
514 | pB->i2eValid = I2E_MAGIC; | ||
515 | I2_COMPLETE(pB, I2EE_GOOD); | ||
516 | } | ||
517 | |||
518 | //****************************************************************************** | ||
519 | // Function: ii2DelayTimer(mseconds) | ||
520 | // Parameters: mseconds - number of milliseconds to delay | ||
521 | // | ||
522 | // Returns: Nothing | ||
523 | // | ||
524 | // Description: | ||
525 | // | ||
526 | // This routine delays for approximately mseconds milliseconds and is intended | ||
527 | // to be called indirectly through i2Delay field in i2eBordStr. It uses the | ||
528 | // Linux timer_list mechanism. | ||
529 | // | ||
530 | // The Linux timers use a unit called "jiffies" which are 10mS in the Intel | ||
531 | // architecture. This function rounds the delay period up to the next "jiffy". | ||
532 | // In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended | ||
533 | // for Alpha platforms at this time. | ||
534 | // | ||
535 | //****************************************************************************** | ||
536 | static void | ||
537 | ii2DelayTimer(unsigned int mseconds) | ||
538 | { | ||
539 | msleep_interruptible(mseconds); | ||
540 | } | ||
541 | |||
542 | #if 0 | ||
543 | //static void ii2DelayIO(unsigned int); | ||
544 | //****************************************************************************** | ||
545 | // !!! Not Used, this is DOS crap, some of you young folks may be interested in | ||
546 | // in how things were done in the stone age of caculating machines !!! | ||
547 | // Function: ii2DelayIO(mseconds) | ||
548 | // Parameters: mseconds - number of milliseconds to delay | ||
549 | // | ||
550 | // Returns: Nothing | ||
551 | // | ||
552 | // Description: | ||
553 | // | ||
554 | // This routine delays for approximately mseconds milliseconds and is intended | ||
555 | // to be called indirectly through i2Delay field in i2eBordStr. It is intended | ||
556 | // for use where a clock-based function is impossible: for example, DOS drivers. | ||
557 | // | ||
558 | // This function uses the IN instruction to place bounds on the timing and | ||
559 | // assumes that ii2Safe has been set. This is because I/O instructions are not | ||
560 | // subject to caching and will therefore take a certain minimum time. To ensure | ||
561 | // the delay is at least long enough on fast machines, it is based on some | ||
562 | // fastest-case calculations. On slower machines this may cause VERY long | ||
563 | // delays. (3 x fastest case). In the fastest case, everything is cached except | ||
564 | // the I/O instruction itself. | ||
565 | // | ||
566 | // Timing calculations: | ||
567 | // The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O | ||
568 | // operation in question is a byte operation to an odd address. For 8-bit | ||
569 | // operations, the architecture generally enforces two wait states. At 10 MHz, a | ||
570 | // single cycle time is 100nS. A read operation at two wait states takes 6 | ||
571 | // cycles for a total time of 600nS. Therefore approximately 1666 iterations | ||
572 | // would be required to generate a single millisecond delay. The worst | ||
573 | // (reasonable) case would be an 8MHz system with no cacheing. In this case, the | ||
574 | // I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code | ||
575 | // fetch of other instructions in the loop would take time (zero wait states, | ||
576 | // however) and would be hard to estimate. This is minimized by using in-line | ||
577 | // assembler for the in inner loop of IN instructions. This consists of just a | ||
578 | // few bytes. So we'll guess about four code fetches per loop. Each code fetch | ||
579 | // should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is | ||
580 | // that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS. | ||
581 | // | ||
582 | // So much for theoretical timings: results using 1666 value on some actual | ||
583 | // machines: | ||
584 | // IBM 286 6MHz 3.15 mS | ||
585 | // Zenith 386 33MHz 2.45 mS | ||
586 | // (brandX) 386 33MHz 1.90 mS (has cache) | ||
587 | // (brandY) 486 33MHz 2.35 mS | ||
588 | // NCR 486 ?? 1.65 mS (microchannel) | ||
589 | // | ||
590 | // For most machines, it is probably safe to scale this number back (remember, | ||
591 | // for robust operation use an actual timed delay if possible), so we are using | ||
592 | // a value of 1190. This yields 1.17 mS for the fastest machine in our sample, | ||
593 | // 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine. | ||
594 | // | ||
595 | // 1/29/93: | ||
596 | // The above timings are too slow. Actual cycle times might be faster. ISA cycle | ||
597 | // times could approach 500 nS, and ... | ||
598 | // The IBM model 77 being microchannel has no wait states for 8-bit reads and | ||
599 | // seems to be accessing the I/O at 440 nS per access (from start of one to | ||
600 | // start of next). This would imply we need 1000/.440 = 2272 iterations to | ||
601 | // guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in | ||
602 | // fact enough. For diagnostics, we keep the level at 1190, but developers note | ||
603 | // this needs tuning. | ||
604 | // | ||
605 | // Safe assumption: 2270 i/o reads = 1 millisecond | ||
606 | // | ||
607 | //****************************************************************************** | ||
608 | |||
609 | |||
610 | static int ii2DelValue = 1190; // See timing calculations below | ||
611 | // 1666 for fastest theoretical machine | ||
612 | // 1190 safe for most fast 386 machines | ||
613 | // 1000 for fastest machine tested here | ||
614 | // 540 (sic) for AT286/6Mhz | ||
615 | static void | ||
616 | ii2DelayIO(unsigned int mseconds) | ||
617 | { | ||
618 | if (!ii2Safe) | ||
619 | return; /* Do nothing if this variable uninitialized */ | ||
620 | |||
621 | while(mseconds--) { | ||
622 | int i = ii2DelValue; | ||
623 | while ( i-- ) { | ||
624 | inb(ii2Safe); | ||
625 | } | ||
626 | } | ||
627 | } | ||
628 | #endif | ||
629 | |||
630 | //****************************************************************************** | ||
631 | // Function: ii2Nop() | ||
632 | // Parameters: None | ||
633 | // | ||
634 | // Returns: Nothing | ||
635 | // | ||
636 | // Description: | ||
637 | // | ||
638 | // iiInitialize will set i2eDelay to this if the delay parameter is NULL. This | ||
639 | // saves checking for a NULL pointer at every call. | ||
640 | //****************************************************************************** | ||
641 | static void | ||
642 | ii2Nop(void) | ||
643 | { | ||
644 | return; // no mystery here | ||
645 | } | ||
646 | |||
647 | //======================================================= | ||
648 | // Routines which are available in 8/16-bit versions, or | ||
649 | // in different fifo styles. These are ALL called | ||
650 | // indirectly through the board structure. | ||
651 | //======================================================= | ||
652 | |||
653 | //****************************************************************************** | ||
654 | // Function: iiWriteBuf16(pB, address, count) | ||
655 | // Parameters: pB - pointer to board structure | ||
656 | // address - address of data to write | ||
657 | // count - number of data bytes to write | ||
658 | // | ||
659 | // Returns: True if everything appears copacetic. | ||
660 | // False if there is any error: the pB->i2eError field has the error | ||
661 | // | ||
662 | // Description: | ||
663 | // | ||
664 | // Writes 'count' bytes from 'address' to the data fifo specified by the board | ||
665 | // structure pointer pB. Should count happen to be odd, an extra pad byte is | ||
666 | // sent (identity unknown...). Uses 16-bit (word) operations. Is called | ||
667 | // indirectly through pB->i2eWriteBuf. | ||
668 | // | ||
669 | //****************************************************************************** | ||
670 | static int | ||
671 | iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count) | ||
672 | { | ||
673 | // Rudimentary sanity checking here. | ||
674 | if (pB->i2eValid != I2E_MAGIC) | ||
675 | I2_COMPLETE(pB, I2EE_INVALID); | ||
676 | |||
677 | I2_OUTSW(pB->i2eData, address, count); | ||
678 | |||
679 | I2_COMPLETE(pB, I2EE_GOOD); | ||
680 | } | ||
681 | |||
682 | //****************************************************************************** | ||
683 | // Function: iiWriteBuf8(pB, address, count) | ||
684 | // Parameters: pB - pointer to board structure | ||
685 | // address - address of data to write | ||
686 | // count - number of data bytes to write | ||
687 | // | ||
688 | // Returns: True if everything appears copacetic. | ||
689 | // False if there is any error: the pB->i2eError field has the error | ||
690 | // | ||
691 | // Description: | ||
692 | // | ||
693 | // Writes 'count' bytes from 'address' to the data fifo specified by the board | ||
694 | // structure pointer pB. Should count happen to be odd, an extra pad byte is | ||
695 | // sent (identity unknown...). This is to be consistent with the 16-bit version. | ||
696 | // Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf. | ||
697 | // | ||
698 | //****************************************************************************** | ||
699 | static int | ||
700 | iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count) | ||
701 | { | ||
702 | /* Rudimentary sanity checking here */ | ||
703 | if (pB->i2eValid != I2E_MAGIC) | ||
704 | I2_COMPLETE(pB, I2EE_INVALID); | ||
705 | |||
706 | I2_OUTSB(pB->i2eData, address, count); | ||
707 | |||
708 | I2_COMPLETE(pB, I2EE_GOOD); | ||
709 | } | ||
710 | |||
711 | //****************************************************************************** | ||
712 | // Function: iiReadBuf16(pB, address, count) | ||
713 | // Parameters: pB - pointer to board structure | ||
714 | // address - address to put data read | ||
715 | // count - number of data bytes to read | ||
716 | // | ||
717 | // Returns: True if everything appears copacetic. | ||
718 | // False if there is any error: the pB->i2eError field has the error | ||
719 | // | ||
720 | // Description: | ||
721 | // | ||
722 | // Reads 'count' bytes into 'address' from the data fifo specified by the board | ||
723 | // structure pointer pB. Should count happen to be odd, an extra pad byte is | ||
724 | // received (identity unknown...). Uses 16-bit (word) operations. Is called | ||
725 | // indirectly through pB->i2eReadBuf. | ||
726 | // | ||
727 | //****************************************************************************** | ||
728 | static int | ||
729 | iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count) | ||
730 | { | ||
731 | // Rudimentary sanity checking here. | ||
732 | if (pB->i2eValid != I2E_MAGIC) | ||
733 | I2_COMPLETE(pB, I2EE_INVALID); | ||
734 | |||
735 | I2_INSW(pB->i2eData, address, count); | ||
736 | |||
737 | I2_COMPLETE(pB, I2EE_GOOD); | ||
738 | } | ||
739 | |||
740 | //****************************************************************************** | ||
741 | // Function: iiReadBuf8(pB, address, count) | ||
742 | // Parameters: pB - pointer to board structure | ||
743 | // address - address to put data read | ||
744 | // count - number of data bytes to read | ||
745 | // | ||
746 | // Returns: True if everything appears copacetic. | ||
747 | // False if there is any error: the pB->i2eError field has the error | ||
748 | // | ||
749 | // Description: | ||
750 | // | ||
751 | // Reads 'count' bytes into 'address' from the data fifo specified by the board | ||
752 | // structure pointer pB. Should count happen to be odd, an extra pad byte is | ||
753 | // received (identity unknown...). This to match the 16-bit behaviour. Uses | ||
754 | // 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf. | ||
755 | // | ||
756 | //****************************************************************************** | ||
757 | static int | ||
758 | iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count) | ||
759 | { | ||
760 | // Rudimentary sanity checking here. | ||
761 | if (pB->i2eValid != I2E_MAGIC) | ||
762 | I2_COMPLETE(pB, I2EE_INVALID); | ||
763 | |||
764 | I2_INSB(pB->i2eData, address, count); | ||
765 | |||
766 | I2_COMPLETE(pB, I2EE_GOOD); | ||
767 | } | ||
768 | |||
769 | //****************************************************************************** | ||
770 | // Function: iiReadWord16(pB) | ||
771 | // Parameters: pB - pointer to board structure | ||
772 | // | ||
773 | // Returns: True if everything appears copacetic. | ||
774 | // False if there is any error: the pB->i2eError field has the error | ||
775 | // | ||
776 | // Description: | ||
777 | // | ||
778 | // Returns the word read from the data fifo specified by the board-structure | ||
779 | // pointer pB. Uses a 16-bit operation. Is called indirectly through | ||
780 | // pB->i2eReadWord. | ||
781 | // | ||
782 | //****************************************************************************** | ||
783 | static unsigned short | ||
784 | iiReadWord16(i2eBordStrPtr pB) | ||
785 | { | ||
786 | return inw(pB->i2eData); | ||
787 | } | ||
788 | |||
789 | //****************************************************************************** | ||
790 | // Function: iiReadWord8(pB) | ||
791 | // Parameters: pB - pointer to board structure | ||
792 | // | ||
793 | // Returns: True if everything appears copacetic. | ||
794 | // False if there is any error: the pB->i2eError field has the error | ||
795 | // | ||
796 | // Description: | ||
797 | // | ||
798 | // Returns the word read from the data fifo specified by the board-structure | ||
799 | // pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is | ||
800 | // called indirectly through pB->i2eReadWord. | ||
801 | // | ||
802 | //****************************************************************************** | ||
803 | static unsigned short | ||
804 | iiReadWord8(i2eBordStrPtr pB) | ||
805 | { | ||
806 | unsigned short urs; | ||
807 | |||
808 | urs = inb(pB->i2eData); | ||
809 | |||
810 | return (inb(pB->i2eData) << 8) | urs; | ||
811 | } | ||
812 | |||
813 | //****************************************************************************** | ||
814 | // Function: iiWriteWord16(pB, value) | ||
815 | // Parameters: pB - pointer to board structure | ||
816 | // value - data to write | ||
817 | // | ||
818 | // Returns: True if everything appears copacetic. | ||
819 | // False if there is any error: the pB->i2eError field has the error | ||
820 | // | ||
821 | // Description: | ||
822 | // | ||
823 | // Writes the word 'value' to the data fifo specified by the board-structure | ||
824 | // pointer pB. Uses 16-bit operation. Is called indirectly through | ||
825 | // pB->i2eWriteWord. | ||
826 | // | ||
827 | //****************************************************************************** | ||
828 | static void | ||
829 | iiWriteWord16(i2eBordStrPtr pB, unsigned short value) | ||
830 | { | ||
831 | outw((int)value, pB->i2eData); | ||
832 | } | ||
833 | |||
834 | //****************************************************************************** | ||
835 | // Function: iiWriteWord8(pB, value) | ||
836 | // Parameters: pB - pointer to board structure | ||
837 | // value - data to write | ||
838 | // | ||
839 | // Returns: True if everything appears copacetic. | ||
840 | // False if there is any error: the pB->i2eError field has the error | ||
841 | // | ||
842 | // Description: | ||
843 | // | ||
844 | // Writes the word 'value' to the data fifo specified by the board-structure | ||
845 | // pointer pB. Uses two 8-bit operations (writes LSB first). Is called | ||
846 | // indirectly through pB->i2eWriteWord. | ||
847 | // | ||
848 | //****************************************************************************** | ||
849 | static void | ||
850 | iiWriteWord8(i2eBordStrPtr pB, unsigned short value) | ||
851 | { | ||
852 | outb((char)value, pB->i2eData); | ||
853 | outb((char)(value >> 8), pB->i2eData); | ||
854 | } | ||
855 | |||
856 | //****************************************************************************** | ||
857 | // Function: iiWaitForTxEmptyII(pB, mSdelay) | ||
858 | // Parameters: pB - pointer to board structure | ||
859 | // mSdelay - period to wait before returning | ||
860 | // | ||
861 | // Returns: True if the FIFO is empty. | ||
862 | // False if it not empty in the required time: the pB->i2eError | ||
863 | // field has the error. | ||
864 | // | ||
865 | // Description: | ||
866 | // | ||
867 | // Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if | ||
868 | // not empty by the required time, returns false and error in pB->i2eError, | ||
869 | // otherwise returns true. | ||
870 | // | ||
871 | // mSdelay == 0 is taken to mean must be empty on the first test. | ||
872 | // | ||
873 | // This version operates on IntelliPort-II - style FIFO's | ||
874 | // | ||
875 | // Note this routine is organized so that if status is ok there is no delay at | ||
876 | // all called either before or after the test. Is called indirectly through | ||
877 | // pB->i2eWaitForTxEmpty. | ||
878 | // | ||
879 | //****************************************************************************** | ||
880 | static int | ||
881 | iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay) | ||
882 | { | ||
883 | unsigned long flags; | ||
884 | int itemp; | ||
885 | |||
886 | for (;;) | ||
887 | { | ||
888 | // This routine hinges on being able to see the "other" status register | ||
889 | // (as seen by the local processor). His incoming fifo is our outgoing | ||
890 | // FIFO. | ||
891 | // | ||
892 | // By the nature of this routine, you would be using this as part of a | ||
893 | // larger atomic context: i.e., you would use this routine to ensure the | ||
894 | // fifo empty, then act on this information. Between these two halves, | ||
895 | // you will generally not want to service interrupts or in any way | ||
896 | // disrupt the assumptions implicit in the larger context. | ||
897 | // | ||
898 | // Even worse, however, this routine "shifts" the status register to | ||
899 | // point to the local status register which is not the usual situation. | ||
900 | // Therefore for extra safety, we force the critical section to be | ||
901 | // completely atomic, and pick up after ourselves before allowing any | ||
902 | // interrupts of any kind. | ||
903 | |||
904 | |||
905 | write_lock_irqsave(&Dl_spinlock, flags); | ||
906 | outb(SEL_COMMAND, pB->i2ePointer); | ||
907 | outb(SEL_CMD_SH, pB->i2ePointer); | ||
908 | |||
909 | itemp = inb(pB->i2eStatus); | ||
910 | |||
911 | outb(SEL_COMMAND, pB->i2ePointer); | ||
912 | outb(SEL_CMD_UNSH, pB->i2ePointer); | ||
913 | |||
914 | if (itemp & ST_IN_EMPTY) | ||
915 | { | ||
916 | I2_UPDATE_FIFO_ROOM(pB); | ||
917 | write_unlock_irqrestore(&Dl_spinlock, flags); | ||
918 | I2_COMPLETE(pB, I2EE_GOOD); | ||
919 | } | ||
920 | |||
921 | write_unlock_irqrestore(&Dl_spinlock, flags); | ||
922 | |||
923 | if (mSdelay-- == 0) | ||
924 | break; | ||
925 | |||
926 | iiDelay(pB, 1); /* 1 mS granularity on checking condition */ | ||
927 | } | ||
928 | I2_COMPLETE(pB, I2EE_TXE_TIME); | ||
929 | } | ||
930 | |||
931 | //****************************************************************************** | ||
932 | // Function: iiWaitForTxEmptyIIEX(pB, mSdelay) | ||
933 | // Parameters: pB - pointer to board structure | ||
934 | // mSdelay - period to wait before returning | ||
935 | // | ||
936 | // Returns: True if the FIFO is empty. | ||
937 | // False if it not empty in the required time: the pB->i2eError | ||
938 | // field has the error. | ||
939 | // | ||
940 | // Description: | ||
941 | // | ||
942 | // Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if | ||
943 | // not empty by the required time, returns false and error in pB->i2eError, | ||
944 | // otherwise returns true. | ||
945 | // | ||
946 | // mSdelay == 0 is taken to mean must be empty on the first test. | ||
947 | // | ||
948 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
949 | // | ||
950 | // Note this routine is organized so that if status is ok there is no delay at | ||
951 | // all called either before or after the test. Is called indirectly through | ||
952 | // pB->i2eWaitForTxEmpty. | ||
953 | // | ||
954 | //****************************************************************************** | ||
955 | static int | ||
956 | iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay) | ||
957 | { | ||
958 | unsigned long flags; | ||
959 | |||
960 | for (;;) | ||
961 | { | ||
962 | // By the nature of this routine, you would be using this as part of a | ||
963 | // larger atomic context: i.e., you would use this routine to ensure the | ||
964 | // fifo empty, then act on this information. Between these two halves, | ||
965 | // you will generally not want to service interrupts or in any way | ||
966 | // disrupt the assumptions implicit in the larger context. | ||
967 | |||
968 | write_lock_irqsave(&Dl_spinlock, flags); | ||
969 | |||
970 | if (inb(pB->i2eStatus) & STE_OUT_MT) { | ||
971 | I2_UPDATE_FIFO_ROOM(pB); | ||
972 | write_unlock_irqrestore(&Dl_spinlock, flags); | ||
973 | I2_COMPLETE(pB, I2EE_GOOD); | ||
974 | } | ||
975 | write_unlock_irqrestore(&Dl_spinlock, flags); | ||
976 | |||
977 | if (mSdelay-- == 0) | ||
978 | break; | ||
979 | |||
980 | iiDelay(pB, 1); // 1 mS granularity on checking condition | ||
981 | } | ||
982 | I2_COMPLETE(pB, I2EE_TXE_TIME); | ||
983 | } | ||
984 | |||
985 | //****************************************************************************** | ||
986 | // Function: iiTxMailEmptyII(pB) | ||
987 | // Parameters: pB - pointer to board structure | ||
988 | // | ||
989 | // Returns: True if the transmit mailbox is empty. | ||
990 | // False if it not empty. | ||
991 | // | ||
992 | // Description: | ||
993 | // | ||
994 | // Returns true or false according to whether the transmit mailbox is empty (and | ||
995 | // therefore able to accept more mail) | ||
996 | // | ||
997 | // This version operates on IntelliPort-II - style FIFO's | ||
998 | // | ||
999 | //****************************************************************************** | ||
1000 | static int | ||
1001 | iiTxMailEmptyII(i2eBordStrPtr pB) | ||
1002 | { | ||
1003 | int port = pB->i2ePointer; | ||
1004 | outb(SEL_OUTMAIL, port); | ||
1005 | return inb(port) == 0; | ||
1006 | } | ||
1007 | |||
1008 | //****************************************************************************** | ||
1009 | // Function: iiTxMailEmptyIIEX(pB) | ||
1010 | // Parameters: pB - pointer to board structure | ||
1011 | // | ||
1012 | // Returns: True if the transmit mailbox is empty. | ||
1013 | // False if it not empty. | ||
1014 | // | ||
1015 | // Description: | ||
1016 | // | ||
1017 | // Returns true or false according to whether the transmit mailbox is empty (and | ||
1018 | // therefore able to accept more mail) | ||
1019 | // | ||
1020 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1021 | // | ||
1022 | //****************************************************************************** | ||
1023 | static int | ||
1024 | iiTxMailEmptyIIEX(i2eBordStrPtr pB) | ||
1025 | { | ||
1026 | return !(inb(pB->i2eStatus) & STE_OUT_MAIL); | ||
1027 | } | ||
1028 | |||
1029 | //****************************************************************************** | ||
1030 | // Function: iiTrySendMailII(pB,mail) | ||
1031 | // Parameters: pB - pointer to board structure | ||
1032 | // mail - value to write to mailbox | ||
1033 | // | ||
1034 | // Returns: True if the transmit mailbox is empty, and mail is sent. | ||
1035 | // False if it not empty. | ||
1036 | // | ||
1037 | // Description: | ||
1038 | // | ||
1039 | // If outgoing mailbox is empty, sends mail and returns true. If outgoing | ||
1040 | // mailbox is not empty, returns false. | ||
1041 | // | ||
1042 | // This version operates on IntelliPort-II - style FIFO's | ||
1043 | // | ||
1044 | //****************************************************************************** | ||
1045 | static int | ||
1046 | iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail) | ||
1047 | { | ||
1048 | int port = pB->i2ePointer; | ||
1049 | |||
1050 | outb(SEL_OUTMAIL, port); | ||
1051 | if (inb(port) == 0) { | ||
1052 | outb(SEL_OUTMAIL, port); | ||
1053 | outb(mail, port); | ||
1054 | return 1; | ||
1055 | } | ||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | //****************************************************************************** | ||
1060 | // Function: iiTrySendMailIIEX(pB,mail) | ||
1061 | // Parameters: pB - pointer to board structure | ||
1062 | // mail - value to write to mailbox | ||
1063 | // | ||
1064 | // Returns: True if the transmit mailbox is empty, and mail is sent. | ||
1065 | // False if it not empty. | ||
1066 | // | ||
1067 | // Description: | ||
1068 | // | ||
1069 | // If outgoing mailbox is empty, sends mail and returns true. If outgoing | ||
1070 | // mailbox is not empty, returns false. | ||
1071 | // | ||
1072 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1073 | // | ||
1074 | //****************************************************************************** | ||
1075 | static int | ||
1076 | iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail) | ||
1077 | { | ||
1078 | if (inb(pB->i2eStatus) & STE_OUT_MAIL) | ||
1079 | return 0; | ||
1080 | outb(mail, pB->i2eXMail); | ||
1081 | return 1; | ||
1082 | } | ||
1083 | |||
1084 | //****************************************************************************** | ||
1085 | // Function: iiGetMailII(pB,mail) | ||
1086 | // Parameters: pB - pointer to board structure | ||
1087 | // | ||
1088 | // Returns: Mailbox data or NO_MAIL_HERE. | ||
1089 | // | ||
1090 | // Description: | ||
1091 | // | ||
1092 | // If no mail available, returns NO_MAIL_HERE otherwise returns the data from | ||
1093 | // the mailbox, which is guaranteed != NO_MAIL_HERE. | ||
1094 | // | ||
1095 | // This version operates on IntelliPort-II - style FIFO's | ||
1096 | // | ||
1097 | //****************************************************************************** | ||
1098 | static unsigned short | ||
1099 | iiGetMailII(i2eBordStrPtr pB) | ||
1100 | { | ||
1101 | if (I2_HAS_MAIL(pB)) { | ||
1102 | outb(SEL_INMAIL, pB->i2ePointer); | ||
1103 | return inb(pB->i2ePointer); | ||
1104 | } else { | ||
1105 | return NO_MAIL_HERE; | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | //****************************************************************************** | ||
1110 | // Function: iiGetMailIIEX(pB,mail) | ||
1111 | // Parameters: pB - pointer to board structure | ||
1112 | // | ||
1113 | // Returns: Mailbox data or NO_MAIL_HERE. | ||
1114 | // | ||
1115 | // Description: | ||
1116 | // | ||
1117 | // If no mail available, returns NO_MAIL_HERE otherwise returns the data from | ||
1118 | // the mailbox, which is guaranteed != NO_MAIL_HERE. | ||
1119 | // | ||
1120 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1121 | // | ||
1122 | //****************************************************************************** | ||
1123 | static unsigned short | ||
1124 | iiGetMailIIEX(i2eBordStrPtr pB) | ||
1125 | { | ||
1126 | if (I2_HAS_MAIL(pB)) | ||
1127 | return inb(pB->i2eXMail); | ||
1128 | else | ||
1129 | return NO_MAIL_HERE; | ||
1130 | } | ||
1131 | |||
1132 | //****************************************************************************** | ||
1133 | // Function: iiEnableMailIrqII(pB) | ||
1134 | // Parameters: pB - pointer to board structure | ||
1135 | // | ||
1136 | // Returns: Nothing | ||
1137 | // | ||
1138 | // Description: | ||
1139 | // | ||
1140 | // Enables board to interrupt host (only) by writing to host's in-bound mailbox. | ||
1141 | // | ||
1142 | // This version operates on IntelliPort-II - style FIFO's | ||
1143 | // | ||
1144 | //****************************************************************************** | ||
1145 | static void | ||
1146 | iiEnableMailIrqII(i2eBordStrPtr pB) | ||
1147 | { | ||
1148 | outb(SEL_MASK, pB->i2ePointer); | ||
1149 | outb(ST_IN_MAIL, pB->i2ePointer); | ||
1150 | } | ||
1151 | |||
1152 | //****************************************************************************** | ||
1153 | // Function: iiEnableMailIrqIIEX(pB) | ||
1154 | // Parameters: pB - pointer to board structure | ||
1155 | // | ||
1156 | // Returns: Nothing | ||
1157 | // | ||
1158 | // Description: | ||
1159 | // | ||
1160 | // Enables board to interrupt host (only) by writing to host's in-bound mailbox. | ||
1161 | // | ||
1162 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1163 | // | ||
1164 | //****************************************************************************** | ||
1165 | static void | ||
1166 | iiEnableMailIrqIIEX(i2eBordStrPtr pB) | ||
1167 | { | ||
1168 | outb(MX_IN_MAIL, pB->i2eXMask); | ||
1169 | } | ||
1170 | |||
1171 | //****************************************************************************** | ||
1172 | // Function: iiWriteMaskII(pB) | ||
1173 | // Parameters: pB - pointer to board structure | ||
1174 | // | ||
1175 | // Returns: Nothing | ||
1176 | // | ||
1177 | // Description: | ||
1178 | // | ||
1179 | // Writes arbitrary value to the mask register. | ||
1180 | // | ||
1181 | // This version operates on IntelliPort-II - style FIFO's | ||
1182 | // | ||
1183 | //****************************************************************************** | ||
1184 | static void | ||
1185 | iiWriteMaskII(i2eBordStrPtr pB, unsigned char value) | ||
1186 | { | ||
1187 | outb(SEL_MASK, pB->i2ePointer); | ||
1188 | outb(value, pB->i2ePointer); | ||
1189 | } | ||
1190 | |||
1191 | //****************************************************************************** | ||
1192 | // Function: iiWriteMaskIIEX(pB) | ||
1193 | // Parameters: pB - pointer to board structure | ||
1194 | // | ||
1195 | // Returns: Nothing | ||
1196 | // | ||
1197 | // Description: | ||
1198 | // | ||
1199 | // Writes arbitrary value to the mask register. | ||
1200 | // | ||
1201 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1202 | // | ||
1203 | //****************************************************************************** | ||
1204 | static void | ||
1205 | iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value) | ||
1206 | { | ||
1207 | outb(value, pB->i2eXMask); | ||
1208 | } | ||
1209 | |||
1210 | //****************************************************************************** | ||
1211 | // Function: iiDownloadBlock(pB, pSource, isStandard) | ||
1212 | // Parameters: pB - pointer to board structure | ||
1213 | // pSource - loadware block to download | ||
1214 | // isStandard - True if "standard" loadware, else false. | ||
1215 | // | ||
1216 | // Returns: Success or Failure | ||
1217 | // | ||
1218 | // Description: | ||
1219 | // | ||
1220 | // Downloads a single block (at pSource)to the board referenced by pB. Caller | ||
1221 | // sets isStandard to true/false according to whether the "standard" loadware is | ||
1222 | // what's being loaded. The normal process, then, is to perform an iiInitialize | ||
1223 | // to the board, then perform some number of iiDownloadBlocks using the returned | ||
1224 | // state to determine when download is complete. | ||
1225 | // | ||
1226 | // Possible return values: (see I2ELLIS.H) | ||
1227 | // II_DOWN_BADVALID | ||
1228 | // II_DOWN_BADFILE | ||
1229 | // II_DOWN_CONTINUING | ||
1230 | // II_DOWN_GOOD | ||
1231 | // II_DOWN_BAD | ||
1232 | // II_DOWN_BADSTATE | ||
1233 | // II_DOWN_TIMEOUT | ||
1234 | // | ||
1235 | // Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to | ||
1236 | // determine whether this is the first block, whether to check for magic | ||
1237 | // numbers, how many blocks there are to go... | ||
1238 | // | ||
1239 | //****************************************************************************** | ||
1240 | static int | ||
1241 | iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard) | ||
1242 | { | ||
1243 | int itemp; | ||
1244 | int loadedFirst; | ||
1245 | |||
1246 | if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID; | ||
1247 | |||
1248 | switch(pB->i2eState) | ||
1249 | { | ||
1250 | case II_STATE_READY: | ||
1251 | |||
1252 | // Loading the first block after reset. Must check the magic number of the | ||
1253 | // loadfile, store the number of blocks we expect to load. | ||
1254 | if (pSource->e.loadMagic != MAGIC_LOADFILE) | ||
1255 | { | ||
1256 | return II_DOWN_BADFILE; | ||
1257 | } | ||
1258 | |||
1259 | // Next we store the total number of blocks to load, including this one. | ||
1260 | pB->i2eToLoad = 1 + pSource->e.loadBlocksMore; | ||
1261 | |||
1262 | // Set the state, store the version numbers. ('Cause this may have come | ||
1263 | // from a file - we might want to report these versions and revisions in | ||
1264 | // case of an error! | ||
1265 | pB->i2eState = II_STATE_LOADING; | ||
1266 | pB->i2eLVersion = pSource->e.loadVersion; | ||
1267 | pB->i2eLRevision = pSource->e.loadRevision; | ||
1268 | pB->i2eLSub = pSource->e.loadSubRevision; | ||
1269 | |||
1270 | // The time and date of compilation is also available but don't bother | ||
1271 | // storing it for normal purposes. | ||
1272 | loadedFirst = 1; | ||
1273 | break; | ||
1274 | |||
1275 | case II_STATE_LOADING: | ||
1276 | loadedFirst = 0; | ||
1277 | break; | ||
1278 | |||
1279 | default: | ||
1280 | return II_DOWN_BADSTATE; | ||
1281 | } | ||
1282 | |||
1283 | // Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad | ||
1284 | // must be positive still, because otherwise we would have cleaned up last | ||
1285 | // time and set the state to II_STATE_LOADED. | ||
1286 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { | ||
1287 | return II_DOWN_TIMEOUT; | ||
1288 | } | ||
1289 | |||
1290 | if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) { | ||
1291 | return II_DOWN_BADVALID; | ||
1292 | } | ||
1293 | |||
1294 | // If we just loaded the first block, wait for the fifo to empty an extra | ||
1295 | // long time to allow for any special startup code in the firmware, like | ||
1296 | // sending status messages to the LCD's. | ||
1297 | |||
1298 | if (loadedFirst) { | ||
1299 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) { | ||
1300 | return II_DOWN_TIMEOUT; | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | // Determine whether this was our last block! | ||
1305 | if (--(pB->i2eToLoad)) { | ||
1306 | return II_DOWN_CONTINUING; // more to come... | ||
1307 | } | ||
1308 | |||
1309 | // It WAS our last block: Clean up operations... | ||
1310 | // ...Wait for last buffer to drain from the board... | ||
1311 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { | ||
1312 | return II_DOWN_TIMEOUT; | ||
1313 | } | ||
1314 | // If there were only a single block written, this would come back | ||
1315 | // immediately and be harmless, though not strictly necessary. | ||
1316 | itemp = MAX_DLOAD_ACK_TIME/10; | ||
1317 | while (--itemp) { | ||
1318 | if (I2_HAS_INPUT(pB)) { | ||
1319 | switch (inb(pB->i2eData)) { | ||
1320 | case LOADWARE_OK: | ||
1321 | pB->i2eState = | ||
1322 | isStandard ? II_STATE_STDLOADED :II_STATE_LOADED; | ||
1323 | |||
1324 | // Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2) | ||
1325 | // will, // if there is a debug port attached, require some | ||
1326 | // time to send information to the debug port now. It will do | ||
1327 | // this before // executing any of the code we just downloaded. | ||
1328 | // It may take up to 700 milliseconds. | ||
1329 | if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) { | ||
1330 | iiDelay(pB, 700); | ||
1331 | } | ||
1332 | |||
1333 | return II_DOWN_GOOD; | ||
1334 | |||
1335 | case LOADWARE_BAD: | ||
1336 | default: | ||
1337 | return II_DOWN_BAD; | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | iiDelay(pB, 10); // 10 mS granularity on checking condition | ||
1342 | } | ||
1343 | |||
1344 | // Drop-through --> timed out waiting for firmware confirmation | ||
1345 | |||
1346 | pB->i2eState = II_STATE_BADLOAD; | ||
1347 | return II_DOWN_TIMEOUT; | ||
1348 | } | ||
1349 | |||
1350 | //****************************************************************************** | ||
1351 | // Function: iiDownloadAll(pB, pSource, isStandard, size) | ||
1352 | // Parameters: pB - pointer to board structure | ||
1353 | // pSource - loadware block to download | ||
1354 | // isStandard - True if "standard" loadware, else false. | ||
1355 | // size - size of data to download (in bytes) | ||
1356 | // | ||
1357 | // Returns: Success or Failure | ||
1358 | // | ||
1359 | // Description: | ||
1360 | // | ||
1361 | // Given a pointer to a board structure, a pointer to the beginning of some | ||
1362 | // loadware, whether it is considered the "standard loadware", and the size of | ||
1363 | // the array in bytes loads the entire array to the board as loadware. | ||
1364 | // | ||
1365 | // Assumes the board has been freshly reset and the power-up reset message read. | ||
1366 | // (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be | ||
1367 | // too much or too little data to load, or if iiDownloadBlock complains. | ||
1368 | //****************************************************************************** | ||
1369 | static int | ||
1370 | iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size) | ||
1371 | { | ||
1372 | int status; | ||
1373 | |||
1374 | // We know (from context) board should be ready for the first block of | ||
1375 | // download. Complain if not. | ||
1376 | if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE; | ||
1377 | |||
1378 | while (size > 0) { | ||
1379 | size -= LOADWARE_BLOCK_SIZE; // How much data should there be left to | ||
1380 | // load after the following operation ? | ||
1381 | |||
1382 | // Note we just bump pSource by "one", because its size is actually that | ||
1383 | // of an entire block, same as LOADWARE_BLOCK_SIZE. | ||
1384 | status = iiDownloadBlock(pB, pSource++, isStandard); | ||
1385 | |||
1386 | switch(status) | ||
1387 | { | ||
1388 | case II_DOWN_GOOD: | ||
1389 | return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD); | ||
1390 | |||
1391 | case II_DOWN_CONTINUING: | ||
1392 | break; | ||
1393 | |||
1394 | default: | ||
1395 | return status; | ||
1396 | } | ||
1397 | } | ||
1398 | |||
1399 | // We shouldn't drop out: it means "while" caught us with nothing left to | ||
1400 | // download, yet the previous DownloadBlock did not return complete. Ergo, | ||
1401 | // not enough data to match the size byte in the header. | ||
1402 | return II_DOWN_UNDER; | ||
1403 | } | ||
diff --git a/drivers/char/ip2/i2ellis.h b/drivers/char/ip2/i2ellis.h deleted file mode 100644 index fb6df2456018..000000000000 --- a/drivers/char/ip2/i2ellis.h +++ /dev/null | |||
@@ -1,566 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Mainline code for the device driver | ||
12 | * | ||
13 | *******************************************************************************/ | ||
14 | //------------------------------------------------------------------------------ | ||
15 | // i2ellis.h | ||
16 | // | ||
17 | // IntelliPort-II and IntelliPort-IIEX | ||
18 | // | ||
19 | // Extremely | ||
20 | // Low | ||
21 | // Level | ||
22 | // Interface | ||
23 | // Services | ||
24 | // | ||
25 | // Structure Definitions and declarations for "ELLIS" service routines found in | ||
26 | // i2ellis.c | ||
27 | // | ||
28 | // These routines are based on properties of the IntelliPort-II and -IIEX | ||
29 | // hardware and bootstrap firmware, and are not sensitive to particular | ||
30 | // conventions of any particular loadware. | ||
31 | // | ||
32 | // Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material | ||
33 | // here and in i2ellis.c is intended to provice a useful, but not required, | ||
34 | // layer of insulation from the hardware specifics. | ||
35 | //------------------------------------------------------------------------------ | ||
36 | #ifndef I2ELLIS_H /* To prevent multiple includes */ | ||
37 | #define I2ELLIS_H 1 | ||
38 | //------------------------------------------------ | ||
39 | // Revision History: | ||
40 | // | ||
41 | // 30 September 1991 MAG First Draft Started | ||
42 | // 12 October 1991 ...continued... | ||
43 | // | ||
44 | // 20 December 1996 AKM Linux version | ||
45 | //------------------------------------------------- | ||
46 | |||
47 | //---------------------- | ||
48 | // Mandatory Includes: | ||
49 | //---------------------- | ||
50 | #include "ip2types.h" | ||
51 | #include "i2hw.h" // The hardware definitions | ||
52 | |||
53 | //------------------------------------------ | ||
54 | // STAT_BOXIDS packets | ||
55 | //------------------------------------------ | ||
56 | #define MAX_BOX 4 | ||
57 | |||
58 | typedef struct _bidStat | ||
59 | { | ||
60 | unsigned char bid_value[MAX_BOX]; | ||
61 | } bidStat, *bidStatPtr; | ||
62 | |||
63 | // This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX | ||
64 | // boards, reports the hardware-specific "asynchronous resource register" on | ||
65 | // each expansion box. Boxes not present report 0xff. For -II boards, the first | ||
66 | // element contains 0x80 for 8-port, 0x40 for 4-port boards. | ||
67 | |||
68 | // Box IDs aka ARR or Async Resource Register (more than you want to know) | ||
69 | // 7 6 5 4 3 2 1 0 | ||
70 | // F F N N L S S S | ||
71 | // ============================= | ||
72 | // F F - Product Family Designator | ||
73 | // =====+++++++++++++++++++++++++++++++ | ||
74 | // 0 0 - Intelliport II EX / ISA-8 | ||
75 | // 1 0 - IntelliServer | ||
76 | // 0 1 - SAC - Port Device (Intelliport III ??? ) | ||
77 | // =====+++++++++++++++++++++++++++++++++++++++ | ||
78 | // N N - Number of Ports | ||
79 | // 0 0 - 8 (eight) | ||
80 | // 0 1 - 4 (four) | ||
81 | // 1 0 - 12 (twelve) | ||
82 | // 1 1 - 16 (sixteen) | ||
83 | // =++++++++++++++++++++++++++++++++++ | ||
84 | // L - LCD Display Module Present | ||
85 | // 0 - No | ||
86 | // 1 - LCD module present | ||
87 | // =========+++++++++++++++++++++++++++++++++++++ | ||
88 | // S S S - Async Signals Supported Designator | ||
89 | // 0 0 0 - 8dss, Mod DCE DB25 Female | ||
90 | // 0 0 1 - 6dss, RJ-45 | ||
91 | // 0 1 0 - RS-232/422 dss, DB25 Female | ||
92 | // 0 1 1 - RS-232/422 dss, separate 232/422 DB25 Female | ||
93 | // 1 0 0 - 6dss, 921.6 I/F with ST654's | ||
94 | // 1 0 1 - RS-423/232 8dss, RJ-45 10Pin | ||
95 | // 1 1 0 - 6dss, Mod DCE DB25 Female | ||
96 | // 1 1 1 - NO BOX PRESENT | ||
97 | |||
98 | #define FF(c) ((c & 0xC0) >> 6) | ||
99 | #define NN(c) ((c & 0x30) >> 4) | ||
100 | #define L(c) ((c & 0x08) >> 3) | ||
101 | #define SSS(c) (c & 0x07) | ||
102 | |||
103 | #define BID_HAS_654(x) (SSS(x) == 0x04) | ||
104 | #define BID_NO_BOX 0xff /* no box */ | ||
105 | #define BID_8PORT 0x80 /* IP2-8 port */ | ||
106 | #define BID_4PORT 0x81 /* IP2-4 port */ | ||
107 | #define BID_EXP_MASK 0x30 /* IP2-EX */ | ||
108 | #define BID_EXP_8PORT 0x00 /* 8, */ | ||
109 | #define BID_EXP_4PORT 0x10 /* 4, */ | ||
110 | #define BID_EXP_UNDEF 0x20 /* UNDEF, */ | ||
111 | #define BID_EXP_16PORT 0x30 /* 16, */ | ||
112 | #define BID_LCD_CTRL 0x08 /* LCD Controller */ | ||
113 | #define BID_LCD_NONE 0x00 /* - no controller present */ | ||
114 | #define BID_LCD_PRES 0x08 /* - controller present */ | ||
115 | #define BID_CON_MASK 0x07 /* - connector pinouts */ | ||
116 | #define BID_CON_DB25 0x00 /* - DB-25 F */ | ||
117 | #define BID_CON_RJ45 0x01 /* - rj45 */ | ||
118 | |||
119 | //------------------------------------------------------------------------------ | ||
120 | // i2eBordStr | ||
121 | // | ||
122 | // This structure contains all the information the ELLIS routines require in | ||
123 | // dealing with a particular board. | ||
124 | //------------------------------------------------------------------------------ | ||
125 | // There are some queues here which are guaranteed to never contain the entry | ||
126 | // for a single channel twice. So they must be slightly larger to allow | ||
127 | // unambiguous full/empty management | ||
128 | // | ||
129 | #define CH_QUEUE_SIZE ABS_MOST_PORTS+2 | ||
130 | |||
131 | typedef struct _i2eBordStr | ||
132 | { | ||
133 | porStr i2ePom; // Structure containing the power-on message. | ||
134 | |||
135 | unsigned short i2ePomSize; | ||
136 | // The number of bytes actually read if | ||
137 | // different from sizeof i2ePom, indicates | ||
138 | // there is an error! | ||
139 | |||
140 | unsigned short i2eStartMail; | ||
141 | // Contains whatever inbound mailbox data | ||
142 | // present at startup. NO_MAIL_HERE indicates | ||
143 | // nothing was present. No special | ||
144 | // significance as of this writing, but may be | ||
145 | // useful for diagnostic reasons. | ||
146 | |||
147 | unsigned short i2eValid; | ||
148 | // Indicates validity of the structure; if | ||
149 | // i2eValid == I2E_MAGIC, then we can trust | ||
150 | // the other fields. Some (especially | ||
151 | // initialization) functions are good about | ||
152 | // checking for validity. Many functions do | ||
153 | // not, it being assumed that the larger | ||
154 | // context assures we are using a valid | ||
155 | // i2eBordStrPtr. | ||
156 | |||
157 | unsigned short i2eError; | ||
158 | // Used for returning an error condition from | ||
159 | // several functions which use i2eBordStrPtr | ||
160 | // as an argument. | ||
161 | |||
162 | // Accelerators to characterize separate features of a board, derived from a | ||
163 | // number of sources. | ||
164 | |||
165 | unsigned short i2eFifoSize; | ||
166 | // Always, the size of the FIFO. For | ||
167 | // IntelliPort-II, always the same, for -IIEX | ||
168 | // taken from the Power-On reset message. | ||
169 | |||
170 | volatile | ||
171 | unsigned short i2eFifoRemains; | ||
172 | // Used during normal operation to indicate a | ||
173 | // lower bound on the amount of data which | ||
174 | // might be in the outbound fifo. | ||
175 | |||
176 | unsigned char i2eFifoStyle; | ||
177 | // Accelerator which tells which style (-II or | ||
178 | // -IIEX) FIFO we are using. | ||
179 | |||
180 | unsigned char i2eDataWidth16; | ||
181 | // Accelerator which tells whether we should | ||
182 | // do 8 or 16-bit data transfers. | ||
183 | |||
184 | unsigned char i2eMaxIrq; | ||
185 | // The highest allowable IRQ, based on the | ||
186 | // slot size. | ||
187 | |||
188 | // Accelerators for various addresses on the board | ||
189 | int i2eBase; // I/O Address of the Board | ||
190 | int i2eData; // From here data transfers happen | ||
191 | int i2eStatus; // From here status reads happen | ||
192 | int i2ePointer; // (IntelliPort-II: pointer/commands) | ||
193 | int i2eXMail; // (IntelliPOrt-IIEX: mailboxes | ||
194 | int i2eXMask; // (IntelliPort-IIEX: mask write | ||
195 | |||
196 | //------------------------------------------------------- | ||
197 | // Information presented in a common format across boards | ||
198 | // For each box, bit map of the channels present. Box closest to | ||
199 | // the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable) | ||
200 | // is taken to be box 0. These are derived from product i.d. registers. | ||
201 | |||
202 | unsigned short i2eChannelMap[ABS_MAX_BOXES]; | ||
203 | |||
204 | // Same as above, except each is derived from firmware attempting to detect | ||
205 | // the uart presence (by reading a valid GFRCR register). If bits are set in | ||
206 | // i2eChannelMap and not in i2eGoodMap, there is a potential problem. | ||
207 | |||
208 | unsigned short i2eGoodMap[ABS_MAX_BOXES]; | ||
209 | |||
210 | // --------------------------- | ||
211 | // For indirect function calls | ||
212 | |||
213 | // Routine to cause an N-millisecond delay: Patched by the ii2Initialize | ||
214 | // function. | ||
215 | |||
216 | void (*i2eDelay)(unsigned int); | ||
217 | |||
218 | // Routine to write N bytes to the board through the FIFO. Returns true if | ||
219 | // all copacetic, otherwise returns false and error is in i2eError field. | ||
220 | // IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER. | ||
221 | |||
222 | int (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int); | ||
223 | |||
224 | // Routine to read N bytes from the board through the FIFO. Returns true if | ||
225 | // copacetic, otherwise returns false and error in i2eError. | ||
226 | // IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER. | ||
227 | |||
228 | int (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int); | ||
229 | |||
230 | // Returns a word from FIFO. Will use 2 byte operations if needed. | ||
231 | |||
232 | unsigned short (*i2eReadWord)(struct _i2eBordStr *); | ||
233 | |||
234 | // Writes a word to FIFO. Will use 2 byte operations if needed. | ||
235 | |||
236 | void (*i2eWriteWord)(struct _i2eBordStr *, unsigned short); | ||
237 | |||
238 | // Waits specified time for the Transmit FIFO to go empty. Returns true if | ||
239 | // ok, otherwise returns false and error in i2eError. | ||
240 | |||
241 | int (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int); | ||
242 | |||
243 | // Returns true or false according to whether the outgoing mailbox is empty. | ||
244 | |||
245 | int (*i2eTxMailEmpty)(struct _i2eBordStr *); | ||
246 | |||
247 | // Checks whether outgoing mailbox is empty. If so, sends mail and returns | ||
248 | // true. Otherwise returns false. | ||
249 | |||
250 | int (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char); | ||
251 | |||
252 | // If no mail available, returns NO_MAIL_HERE, else returns the value in the | ||
253 | // mailbox (guaranteed can't be NO_MAIL_HERE). | ||
254 | |||
255 | unsigned short (*i2eGetMail)(struct _i2eBordStr *); | ||
256 | |||
257 | // Enables the board to interrupt the host when it writes to the mailbox. | ||
258 | // Irqs will not occur, however, until the loadware separately enables | ||
259 | // interrupt generation to the host. The standard loadware does this in | ||
260 | // response to a command packet sent by the host. (Also, disables | ||
261 | // any other potential interrupt sources from the board -- other than the | ||
262 | // inbound mailbox). | ||
263 | |||
264 | void (*i2eEnableMailIrq)(struct _i2eBordStr *); | ||
265 | |||
266 | // Writes an arbitrary value to the mask register. | ||
267 | |||
268 | void (*i2eWriteMask)(struct _i2eBordStr *, unsigned char); | ||
269 | |||
270 | |||
271 | // State information | ||
272 | |||
273 | // During downloading, indicates the number of blocks remaining to download | ||
274 | // to the board. | ||
275 | |||
276 | short i2eToLoad; | ||
277 | |||
278 | // State of board (see manifests below) (e.g., whether in reset condition, | ||
279 | // whether standard loadware is installed, etc. | ||
280 | |||
281 | unsigned char i2eState; | ||
282 | |||
283 | // These three fields are only valid when there is loadware running on the | ||
284 | // board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED ) | ||
285 | |||
286 | unsigned char i2eLVersion; // Loadware version | ||
287 | unsigned char i2eLRevision; // Loadware revision | ||
288 | unsigned char i2eLSub; // Loadware subrevision | ||
289 | |||
290 | // Flags which only have meaning in the context of the standard loadware. | ||
291 | // Somewhat violates the layering concept, but there is so little additional | ||
292 | // needed at the board level (while much additional at the channel level), | ||
293 | // that this beats maintaining two different per-board structures. | ||
294 | |||
295 | // Indicates which IRQ the board has been initialized (from software) to use | ||
296 | // For MicroChannel boards, any value different from IRQ_UNDEFINED means | ||
297 | // that the software command has been sent to enable interrupts (or specify | ||
298 | // they are disabled). Special value: IRQ_UNDEFINED indicates that the | ||
299 | // software command to select the interrupt has not yet been sent, therefore | ||
300 | // (since the standard loadware insists that it be sent before any other | ||
301 | // packets are sent) no other packets should be sent yet. | ||
302 | |||
303 | unsigned short i2eUsingIrq; | ||
304 | |||
305 | // This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us | ||
306 | // putting more in the mailbox until an appropriate mailbox message is | ||
307 | // received. | ||
308 | |||
309 | unsigned char i2eWaitingForEmptyFifo; | ||
310 | |||
311 | // Any mailbox bits waiting to be sent to the board are OR'ed in here. | ||
312 | |||
313 | unsigned char i2eOutMailWaiting; | ||
314 | |||
315 | // The head of any incoming packet is read into here, is then examined and | ||
316 | // we dispatch accordingly. | ||
317 | |||
318 | unsigned short i2eLeadoffWord[1]; | ||
319 | |||
320 | // Running counter of interrupts where the mailbox indicated incoming data. | ||
321 | |||
322 | unsigned short i2eFifoInInts; | ||
323 | |||
324 | // Running counter of interrupts where the mailbox indicated outgoing data | ||
325 | // had been stripped. | ||
326 | |||
327 | unsigned short i2eFifoOutInts; | ||
328 | |||
329 | // If not void, gives the address of a routine to call if fatal board error | ||
330 | // is found (only applies to standard l/w). | ||
331 | |||
332 | void (*i2eFatalTrap)(struct _i2eBordStr *); | ||
333 | |||
334 | // Will point to an array of some sort of channel structures (whose format | ||
335 | // is unknown at this level, being a function of what loadware is | ||
336 | // installed and the code configuration (max sizes of buffers, etc.)). | ||
337 | |||
338 | void *i2eChannelPtr; | ||
339 | |||
340 | // Set indicates that the board has gone fatal. | ||
341 | |||
342 | unsigned short i2eFatal; | ||
343 | |||
344 | // The number of elements pointed to by i2eChannelPtr. | ||
345 | |||
346 | unsigned short i2eChannelCnt; | ||
347 | |||
348 | // Ring-buffers of channel structures whose channels have particular needs. | ||
349 | |||
350 | rwlock_t Fbuf_spinlock; | ||
351 | volatile | ||
352 | unsigned short i2Fbuf_strip; // Strip index | ||
353 | volatile | ||
354 | unsigned short i2Fbuf_stuff; // Stuff index | ||
355 | void *i2Fbuf[CH_QUEUE_SIZE]; // An array of channel pointers | ||
356 | // of channels who need to send | ||
357 | // flow control packets. | ||
358 | rwlock_t Dbuf_spinlock; | ||
359 | volatile | ||
360 | unsigned short i2Dbuf_strip; // Strip index | ||
361 | volatile | ||
362 | unsigned short i2Dbuf_stuff; // Stuff index | ||
363 | void *i2Dbuf[CH_QUEUE_SIZE]; // An array of channel pointers | ||
364 | // of channels who need to send | ||
365 | // data or in-line command packets. | ||
366 | rwlock_t Bbuf_spinlock; | ||
367 | volatile | ||
368 | unsigned short i2Bbuf_strip; // Strip index | ||
369 | volatile | ||
370 | unsigned short i2Bbuf_stuff; // Stuff index | ||
371 | void *i2Bbuf[CH_QUEUE_SIZE]; // An array of channel pointers | ||
372 | // of channels who need to send | ||
373 | // bypass command packets. | ||
374 | |||
375 | /* | ||
376 | * A set of flags to indicate that certain events have occurred on at least | ||
377 | * one of the ports on this board. We use this to decide whether to spin | ||
378 | * through the channels looking for breaks, etc. | ||
379 | */ | ||
380 | int got_input; | ||
381 | int status_change; | ||
382 | bidStat channelBtypes; | ||
383 | |||
384 | /* | ||
385 | * Debugging counters, etc. | ||
386 | */ | ||
387 | unsigned long debugFlowQueued; | ||
388 | unsigned long debugInlineQueued; | ||
389 | unsigned long debugDataQueued; | ||
390 | unsigned long debugBypassQueued; | ||
391 | unsigned long debugFlowCount; | ||
392 | unsigned long debugInlineCount; | ||
393 | unsigned long debugBypassCount; | ||
394 | |||
395 | rwlock_t read_fifo_spinlock; | ||
396 | rwlock_t write_fifo_spinlock; | ||
397 | |||
398 | // For queuing interrupt bottom half handlers. /\/\|=mhw=|\/\/ | ||
399 | struct work_struct tqueue_interrupt; | ||
400 | |||
401 | struct timer_list SendPendingTimer; // Used by iiSendPending | ||
402 | unsigned int SendPendingRetry; | ||
403 | } i2eBordStr, *i2eBordStrPtr; | ||
404 | |||
405 | //------------------------------------------------------------------- | ||
406 | // Macro Definitions for the indirect calls defined in the i2eBordStr | ||
407 | //------------------------------------------------------------------- | ||
408 | // | ||
409 | #define iiDelay(a,b) (*(a)->i2eDelay)(b) | ||
410 | #define iiWriteBuf(a,b,c) (*(a)->i2eWriteBuf)(a,b,c) | ||
411 | #define iiReadBuf(a,b,c) (*(a)->i2eReadBuf)(a,b,c) | ||
412 | |||
413 | #define iiWriteWord(a,b) (*(a)->i2eWriteWord)(a,b) | ||
414 | #define iiReadWord(a) (*(a)->i2eReadWord)(a) | ||
415 | |||
416 | #define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b) | ||
417 | |||
418 | #define iiTxMailEmpty(a) (*(a)->i2eTxMailEmpty)(a) | ||
419 | #define iiTrySendMail(a,b) (*(a)->i2eTrySendMail)(a,b) | ||
420 | |||
421 | #define iiGetMail(a) (*(a)->i2eGetMail)(a) | ||
422 | #define iiEnableMailIrq(a) (*(a)->i2eEnableMailIrq)(a) | ||
423 | #define iiDisableMailIrq(a) (*(a)->i2eWriteMask)(a,0) | ||
424 | #define iiWriteMask(a,b) (*(a)->i2eWriteMask)(a,b) | ||
425 | |||
426 | //------------------------------------------- | ||
427 | // Manifests for i2eBordStr: | ||
428 | //------------------------------------------- | ||
429 | |||
430 | typedef void (*delayFunc_t)(unsigned int); | ||
431 | |||
432 | // i2eValid | ||
433 | // | ||
434 | #define I2E_MAGIC 0x4251 // Structure is valid. | ||
435 | #define I2E_INCOMPLETE 0x1122 // Structure failed during init. | ||
436 | |||
437 | |||
438 | // i2eError | ||
439 | // | ||
440 | #define I2EE_GOOD 0 // Operation successful | ||
441 | #define I2EE_BADADDR 1 // Address out of range | ||
442 | #define I2EE_BADSTATE 2 // Attempt to perform a function when the board | ||
443 | // structure was in the incorrect state | ||
444 | #define I2EE_BADMAGIC 3 // Bad magic number from Power On test (i2ePomSize | ||
445 | // reflects what was read | ||
446 | #define I2EE_PORM_SHORT 4 // Power On message too short | ||
447 | #define I2EE_PORM_LONG 5 // Power On message too long | ||
448 | #define I2EE_BAD_FAMILY 6 // Un-supported board family type | ||
449 | #define I2EE_INCONSIST 7 // Firmware reports something impossible, | ||
450 | // e.g. unexpected number of ports... Almost no | ||
451 | // excuse other than bad FIFO... | ||
452 | #define I2EE_POSTERR 8 // Power-On self test reported a bad error | ||
453 | #define I2EE_BADBUS 9 // Unknown Bus type declared in message | ||
454 | #define I2EE_TXE_TIME 10 // Timed out waiting for TX Fifo to empty | ||
455 | #define I2EE_INVALID 11 // i2eValid field does not indicate a valid and | ||
456 | // complete board structure (for functions which | ||
457 | // require this be so.) | ||
458 | #define I2EE_BAD_PORT 12 // Discrepancy between channels actually found and | ||
459 | // what the product is supposed to have. Check | ||
460 | // i2eGoodMap vs i2eChannelMap for details. | ||
461 | #define I2EE_BAD_IRQ 13 // Someone specified an unsupported IRQ | ||
462 | #define I2EE_NOCHANNELS 14 // No channel structures have been defined (for | ||
463 | // functions requiring this). | ||
464 | |||
465 | // i2eFifoStyle | ||
466 | // | ||
467 | #define FIFO_II 0 /* IntelliPort-II style: see also i2hw.h */ | ||
468 | #define FIFO_IIEX 1 /* IntelliPort-IIEX style */ | ||
469 | |||
470 | // i2eGetMail | ||
471 | // | ||
472 | #define NO_MAIL_HERE 0x1111 // Since mail is unsigned char, cannot possibly | ||
473 | // promote to 0x1111. | ||
474 | // i2eState | ||
475 | // | ||
476 | #define II_STATE_COLD 0 // Addresses have been defined, but board not even | ||
477 | // reset yet. | ||
478 | #define II_STATE_RESET 1 // Board,if it exists, has just been reset | ||
479 | #define II_STATE_READY 2 // Board ready for its first block | ||
480 | #define II_STATE_LOADING 3 // Board continuing load | ||
481 | #define II_STATE_LOADED 4 // Board has finished load: status ok | ||
482 | #define II_STATE_BADLOAD 5 // Board has finished load: failed! | ||
483 | #define II_STATE_STDLOADED 6 // Board has finished load: standard firmware | ||
484 | |||
485 | // i2eUsingIrq | ||
486 | // | ||
487 | #define I2_IRQ_UNDEFINED 0x1352 /* No valid irq (or polling = 0) can | ||
488 | * ever promote to this! */ | ||
489 | //------------------------------------------ | ||
490 | // Handy Macros for i2ellis.c and others | ||
491 | // Note these are common to -II and -IIEX | ||
492 | //------------------------------------------ | ||
493 | |||
494 | // Given a pointer to the board structure, does the input FIFO have any data or | ||
495 | // not? | ||
496 | // | ||
497 | #define I2_HAS_INPUT(pB) !(inb(pB->i2eStatus) & ST_IN_EMPTY) | ||
498 | |||
499 | // Given a pointer to the board structure, is there anything in the incoming | ||
500 | // mailbox? | ||
501 | // | ||
502 | #define I2_HAS_MAIL(pB) (inb(pB->i2eStatus) & ST_IN_MAIL) | ||
503 | |||
504 | #define I2_UPDATE_FIFO_ROOM(pB) ((pB)->i2eFifoRemains = (pB)->i2eFifoSize) | ||
505 | |||
506 | //------------------------------------------ | ||
507 | // Function Declarations for i2ellis.c | ||
508 | //------------------------------------------ | ||
509 | // | ||
510 | // Functions called directly | ||
511 | // | ||
512 | // Initialization of a board & structure is in four (five!) parts: | ||
513 | // | ||
514 | // 1) iiSetAddress() - Define the board address & delay function for a board. | ||
515 | // 2) iiReset() - Reset the board (provided it exists) | ||
516 | // -- Note you may do this to several boards -- | ||
517 | // 3) iiResetDelay() - Delay for 2 seconds (once for all boards) | ||
518 | // 4) iiInitialize() - Attempt to read Power-up message; further initialize | ||
519 | // accelerators | ||
520 | // | ||
521 | // Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write | ||
522 | // loadware. To change loadware, you must begin again with step 2, resetting | ||
523 | // the board again (step 1 not needed). | ||
524 | |||
525 | static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t ); | ||
526 | static int iiReset(i2eBordStrPtr); | ||
527 | static int iiResetDelay(i2eBordStrPtr); | ||
528 | static int iiInitialize(i2eBordStrPtr); | ||
529 | |||
530 | // Routine to validate that all channels expected are there. | ||
531 | // | ||
532 | extern int iiValidateChannels(i2eBordStrPtr); | ||
533 | |||
534 | // Routine used to download a block of loadware. | ||
535 | // | ||
536 | static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int); | ||
537 | |||
538 | // Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile: | ||
539 | // | ||
540 | #define II_DOWN_BADVALID 0 // board structure is invalid | ||
541 | #define II_DOWN_CONTINUING 1 // So far, so good, firmware expects more | ||
542 | #define II_DOWN_GOOD 2 // Download complete, CRC good | ||
543 | #define II_DOWN_BAD 3 // Download complete, but CRC bad | ||
544 | #define II_DOWN_BADFILE 4 // Bad magic number in loadware file | ||
545 | #define II_DOWN_BADSTATE 5 // Board is in an inappropriate state for | ||
546 | // downloading loadware. (see i2eState) | ||
547 | #define II_DOWN_TIMEOUT 6 // Timeout waiting for firmware | ||
548 | #define II_DOWN_OVER 7 // Too much data | ||
549 | #define II_DOWN_UNDER 8 // Not enough data | ||
550 | #define II_DOWN_NOFILE 9 // Loadware file not found | ||
551 | |||
552 | // Routine to download an entire loadware module: Return values are a subset of | ||
553 | // iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING | ||
554 | // | ||
555 | static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int); | ||
556 | |||
557 | // Many functions defined here return True if good, False otherwise, with an | ||
558 | // error code in i2eError field. Here is a handy macro for setting the error | ||
559 | // code and returning. | ||
560 | // | ||
561 | #define I2_COMPLETE(pB,code) do { \ | ||
562 | pB->i2eError = code; \ | ||
563 | return (code == I2EE_GOOD);\ | ||
564 | } while (0) | ||
565 | |||
566 | #endif // I2ELLIS_H | ||
diff --git a/drivers/char/ip2/i2hw.h b/drivers/char/ip2/i2hw.h deleted file mode 100644 index c0ba6c05f0cd..000000000000 --- a/drivers/char/ip2/i2hw.h +++ /dev/null | |||
@@ -1,652 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Definitions limited to properties of the hardware or the | ||
12 | * bootstrap firmware. As such, they are applicable regardless of | ||
13 | * operating system or loadware (standard or diagnostic). | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | #ifndef I2HW_H | ||
17 | #define I2HW_H 1 | ||
18 | //------------------------------------------------------------------------------ | ||
19 | // Revision History: | ||
20 | // | ||
21 | // 23 September 1991 MAG First Draft Started...through... | ||
22 | // 11 October 1991 ... Continuing development... | ||
23 | // 6 August 1993 Added support for ISA-4 (asic) which is architected | ||
24 | // as an ISA-CEX with a single 4-port box. | ||
25 | // | ||
26 | // 20 December 1996 AKM Version for Linux | ||
27 | // | ||
28 | //------------------------------------------------------------------------------ | ||
29 | /*------------------------------------------------------------------------------ | ||
30 | |||
31 | HARDWARE DESCRIPTION: | ||
32 | |||
33 | Introduction: | ||
34 | |||
35 | The IntelliPort-II and IntelliPort-IIEX products occupy a block of eight (8) | ||
36 | addresses in the host's I/O space. | ||
37 | |||
38 | Some addresses are used to transfer data to/from the board, some to transfer | ||
39 | so-called "mailbox" messages, and some to read bit-mapped status information. | ||
40 | While all the products in the line are functionally similar, some use a 16-bit | ||
41 | data path to transfer data while others use an 8-bit path. Also, the use of | ||
42 | command /status/mailbox registers differs slightly between the II and IIEX | ||
43 | branches of the family. | ||
44 | |||
45 | The host determines what type of board it is dealing with by reading a string of | ||
46 | sixteen characters from the board. These characters are always placed in the | ||
47 | fifo by the board's local processor whenever the board is reset (either from | ||
48 | power-on or under software control) and are known as the "Power-on Reset | ||
49 | Message." In order that this message can be read from either type of board, the | ||
50 | hardware registers used in reading this message are the same. Once this message | ||
51 | has been read by the host, then it has the information required to operate. | ||
52 | |||
53 | General Differences between boards: | ||
54 | |||
55 | The greatest structural difference is between the -II and -IIEX families of | ||
56 | product. The -II boards use the Am4701 dual 512x8 bidirectional fifo to support | ||
57 | the data path, mailbox registers, and status registers. This chip contains some | ||
58 | features which are not used in the IntelliPort-II products; a description of | ||
59 | these is omitted here. Because of these many features, it contains many | ||
60 | registers, too many to access directly within a small address space. They are | ||
61 | accessed by first writing a value to a "pointer" register. This value selects | ||
62 | the register to be accessed. The next read or write to that address accesses | ||
63 | the selected register rather than the pointer register. | ||
64 | |||
65 | The -IIEX boards use a proprietary design similar to the Am4701 in function. But | ||
66 | because of a simpler, more streamlined design it doesn't require so many | ||
67 | registers. This means they can be accessed directly in single operations rather | ||
68 | than through a pointer register. | ||
69 | |||
70 | Besides these differences, there are differences in whether 8-bit or 16-bit | ||
71 | transfers are used to move data to the board. | ||
72 | |||
73 | The -II boards are capable only of 8-bit data transfers, while the -IIEX boards | ||
74 | may be configured for either 8-bit or 16-bit data transfers. If the on-board DIP | ||
75 | switch #8 is ON, and the card has been installed in a 16-bit slot, 16-bit | ||
76 | transfers are supported (and will be expected by the standard loadware). The | ||
77 | on-board firmware can determine the position of the switch, and whether the | ||
78 | board is installed in a 16-bit slot; it supplies this information to the host as | ||
79 | part of the power-up reset message. | ||
80 | |||
81 | The configuration switch (#8) and slot selection do not directly configure the | ||
82 | hardware. It is up to the on-board loadware and host-based drivers to act | ||
83 | according to the selected options. That is, loadware and drivers could be | ||
84 | written to perform 8-bit transfers regardless of the state of the DIP switch or | ||
85 | slot (and in a diagnostic environment might well do so). Likewise, 16-bit | ||
86 | transfers could be performed as long as the card is in a 16-bit slot. | ||
87 | |||
88 | Note the slot selection and DIP switch selection are provided separately: a | ||
89 | board running in 8-bit mode in a 16-bit slot has a greater range of possible | ||
90 | interrupts to choose from; information of potential use to the host. | ||
91 | |||
92 | All 8-bit data transfers are done in the same way, regardless of whether on a | ||
93 | -II board or a -IIEX board. | ||
94 | |||
95 | The host must consider two things then: 1) whether a -II or -IIEX product is | ||
96 | being used, and 2) whether an 8-bit or 16-bit data path is used. | ||
97 | |||
98 | A further difference is that -II boards always have a 512-byte fifo operating in | ||
99 | each direction. -IIEX boards may use fifos of varying size; this size is | ||
100 | reported as part of the power-up message. | ||
101 | |||
102 | I/O Map Of IntelliPort-II and IntelliPort-IIEX boards: | ||
103 | (Relative to the chosen base address) | ||
104 | |||
105 | Addr R/W IntelliPort-II IntelliPort-IIEX | ||
106 | ---- --- -------------- ---------------- | ||
107 | 0 R/W Data Port (byte) Data Port (byte or word) | ||
108 | 1 R/W (Not used) (MSB of word-wide data written to Data Port) | ||
109 | 2 R Status Register Status Register | ||
110 | 2 W Pointer Register Interrupt Mask Register | ||
111 | 3 R/W (Not used) Mailbox Registers (6 bits: 11111100) | ||
112 | 4,5 -- Reserved for future products | ||
113 | 6 -- Reserved for future products | ||
114 | 7 R Guaranteed to have no effect | ||
115 | 7 W Hardware reset of board. | ||
116 | |||
117 | |||
118 | Rules: | ||
119 | All data transfers are performed using the even i/o address. If byte-wide data | ||
120 | transfers are being used, do INB/OUTB operations on the data port. If word-wide | ||
121 | transfers are used, do INW/OUTW operations. In some circumstances (such as | ||
122 | reading the power-up message) you will do INB from the data port, but in this | ||
123 | case the MSB of each word read is lost. When accessing all other unreserved | ||
124 | registers, use byte operations only. | ||
125 | ------------------------------------------------------------------------------*/ | ||
126 | |||
127 | //------------------------------------------------ | ||
128 | // Mandatory Includes: | ||
129 | //------------------------------------------------ | ||
130 | // | ||
131 | #include "ip2types.h" | ||
132 | |||
133 | //------------------------------------------------------------------------- | ||
134 | // Manifests for the I/O map: | ||
135 | //------------------------------------------------------------------------- | ||
136 | // R/W: Data port (byte) for IntelliPort-II, | ||
137 | // R/W: Data port (byte or word) for IntelliPort-IIEX | ||
138 | // Incoming or outgoing data passes through a FIFO, the status of which is | ||
139 | // available in some of the bits in FIFO_STATUS. This (bidirectional) FIFO is | ||
140 | // the primary means of transferring data, commands, flow-control, and status | ||
141 | // information between the host and board. | ||
142 | // | ||
143 | #define FIFO_DATA 0 | ||
144 | |||
145 | // Another way of passing information between the board and the host is | ||
146 | // through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of | ||
147 | // data. Writing data to the mailbox causes a status bit to be set, and | ||
148 | // potentially interrupting the intended receiver. The sender has some way to | ||
149 | // determine whether the data has been read yet; as soon as it has, it may send | ||
150 | // more. The mailboxes are handled differently on -II and -IIEX products, as | ||
151 | // suggested below. | ||
152 | //------------------------------------------------------------------------------ | ||
153 | // Read: Status Register for IntelliPort-II or -IIEX | ||
154 | // The presence of any bit set here will cause an interrupt to the host, | ||
155 | // provided the corresponding bit has been unmasked in the interrupt mask | ||
156 | // register. Furthermore, interrupts to the host are disabled globally until the | ||
157 | // loadware selects the irq line to use. With the exception of STN_MR, the bits | ||
158 | // remain set so long as the associated condition is true. | ||
159 | // | ||
160 | #define FIFO_STATUS 2 | ||
161 | |||
162 | // Bit map of status bits which are identical for -II and -IIEX | ||
163 | // | ||
164 | #define ST_OUT_FULL 0x40 // Outbound FIFO full | ||
165 | #define ST_IN_EMPTY 0x20 // Inbound FIFO empty | ||
166 | #define ST_IN_MAIL 0x04 // Inbound Mailbox full | ||
167 | |||
168 | // The following exists only on the Intelliport-IIEX, and indicates that the | ||
169 | // board has not read the last outgoing mailbox data yet. In the IntelliPort-II, | ||
170 | // the outgoing mailbox may be read back: a zero indicates the board has read | ||
171 | // the data. | ||
172 | // | ||
173 | #define STE_OUT_MAIL 0x80 // Outbound mailbox full (!) | ||
174 | |||
175 | // The following bits are defined differently for -II and -IIEX boards. Code | ||
176 | // which relies on these bits will need to be functionally different for the two | ||
177 | // types of boards and should be generally avoided because of the additional | ||
178 | // complexity this creates: | ||
179 | |||
180 | // Bit map of status bits only on -II | ||
181 | |||
182 | // Fifo has been RESET (cleared when the status register is read). Note that | ||
183 | // this condition cannot be masked and would always interrupt the host, except | ||
184 | // that the hardware reset also disables interrupts globally from the board | ||
185 | // until re-enabled by loadware. This could also arise from the | ||
186 | // Am4701-supported command to reset the chip, but this command is generally not | ||
187 | // used here. | ||
188 | // | ||
189 | #define STN_MR 0x80 | ||
190 | |||
191 | // See the AMD Am4701 data sheet for details on the following four bits. They | ||
192 | // are not presently used by Computone drivers. | ||
193 | // | ||
194 | #define STN_OUT_AF 0x10 // Outbound FIFO almost full (programmable) | ||
195 | #define STN_IN_AE 0x08 // Inbound FIFO almost empty (programmable) | ||
196 | #define STN_BD 0x02 // Inbound byte detected | ||
197 | #define STN_PE 0x01 // Parity/Framing condition detected | ||
198 | |||
199 | // Bit-map of status bits only on -IIEX | ||
200 | // | ||
201 | #define STE_OUT_HF 0x10 // Outbound FIFO half full | ||
202 | #define STE_IN_HF 0x08 // Inbound FIFO half full | ||
203 | #define STE_IN_FULL 0x02 // Inbound FIFO full | ||
204 | #define STE_OUT_MT 0x01 // Outbound FIFO empty | ||
205 | |||
206 | //------------------------------------------------------------------------------ | ||
207 | |||
208 | // Intelliport-II -- Write Only: the pointer register. | ||
209 | // Values are written to this register to select the Am4701 internal register to | ||
210 | // be accessed on the next operation. | ||
211 | // | ||
212 | #define FIFO_PTR 0x02 | ||
213 | |||
214 | // Values for the pointer register | ||
215 | // | ||
216 | #define SEL_COMMAND 0x1 // Selects the Am4701 command register | ||
217 | |||
218 | // Some possible commands: | ||
219 | // | ||
220 | #define SEL_CMD_MR 0x80 // Am4701 command to reset the chip | ||
221 | #define SEL_CMD_SH 0x40 // Am4701 command to map the "other" port into the | ||
222 | // status register. | ||
223 | #define SEL_CMD_UNSH 0 // Am4701 command to "unshift": port maps into its | ||
224 | // own status register. | ||
225 | #define SEL_MASK 0x2 // Selects the Am4701 interrupt mask register. The | ||
226 | // interrupt mask register is bit-mapped to match | ||
227 | // the status register (FIFO_STATUS) except for | ||
228 | // STN_MR. (See above.) | ||
229 | #define SEL_BYTE_DET 0x3 // Selects the Am4701 byte-detect register. (Not | ||
230 | // normally used except in diagnostics.) | ||
231 | #define SEL_OUTMAIL 0x4 // Selects the outbound mailbox (R/W). Reading back | ||
232 | // a value of zero indicates that the mailbox has | ||
233 | // been read by the board and is available for more | ||
234 | // data./ Writing to the mailbox optionally | ||
235 | // interrupts the board, depending on the loadware's | ||
236 | // setting of its interrupt mask register. | ||
237 | #define SEL_AEAF 0x5 // Selects AE/AF threshold register. | ||
238 | #define SEL_INMAIL 0x6 // Selects the inbound mailbox (Read) | ||
239 | |||
240 | //------------------------------------------------------------------------------ | ||
241 | // IntelliPort-IIEX -- Write Only: interrupt mask (and misc flags) register: | ||
242 | // Unlike IntelliPort-II, bit assignments do NOT match those of the status | ||
243 | // register. | ||
244 | // | ||
245 | #define FIFO_MASK 0x2 | ||
246 | |||
247 | // Mailbox readback select: | ||
248 | // If set, reads to FIFO_MAIL will read the OUTBOUND mailbox (host to board). If | ||
249 | // clear (default on reset) reads to FIFO_MAIL will read the INBOUND mailbox. | ||
250 | // This is the normal situation. The clearing of a mailbox is determined on | ||
251 | // -IIEX boards by waiting for the STE_OUT_MAIL bit to clear. Readback | ||
252 | // capability is provided for diagnostic purposes only. | ||
253 | // | ||
254 | #define MX_OUTMAIL_RSEL 0x80 | ||
255 | |||
256 | #define MX_IN_MAIL 0x40 // Enables interrupts when incoming mailbox goes | ||
257 | // full (ST_IN_MAIL set). | ||
258 | #define MX_IN_FULL 0x20 // Enables interrupts when incoming FIFO goes full | ||
259 | // (STE_IN_FULL). | ||
260 | #define MX_IN_MT 0x08 // Enables interrupts when incoming FIFO goes empty | ||
261 | // (ST_IN_MT). | ||
262 | #define MX_OUT_FULL 0x04 // Enables interrupts when outgoing FIFO goes full | ||
263 | // (ST_OUT_FULL). | ||
264 | #define MX_OUT_MT 0x01 // Enables interrupts when outgoing FIFO goes empty | ||
265 | // (STE_OUT_MT). | ||
266 | |||
267 | // Any remaining bits are reserved, and should be written to ZERO for | ||
268 | // compatibility with future Computone products. | ||
269 | |||
270 | //------------------------------------------------------------------------------ | ||
271 | // IntelliPort-IIEX: -- These are only 6-bit mailboxes !!! -- 11111100 (low two | ||
272 | // bits always read back 0). | ||
273 | // Read: One of the mailboxes, usually Inbound. | ||
274 | // Inbound Mailbox (MX_OUTMAIL_RSEL = 0) | ||
275 | // Outbound Mailbox (MX_OUTMAIL_RSEL = 1) | ||
276 | // Write: Outbound Mailbox | ||
277 | // For the IntelliPort-II boards, the outbound mailbox is read back to determine | ||
278 | // whether the board has read the data (0 --> data has been read). For the | ||
279 | // IntelliPort-IIEX, this is done by reading a status register. To determine | ||
280 | // whether mailbox is available for more outbound data, use the STE_OUT_MAIL bit | ||
281 | // in FIFO_STATUS. Moreover, although the Outbound Mailbox can be read back by | ||
282 | // setting MX_OUTMAIL_RSEL, it is NOT cleared when the board reads it, as is the | ||
283 | // case with the -II boards. For this reason, FIFO_MAIL is normally used to read | ||
284 | // the inbound FIFO, and MX_OUTMAIL_RSEL kept clear. (See above for | ||
285 | // MX_OUTMAIL_RSEL description.) | ||
286 | // | ||
287 | #define FIFO_MAIL 0x3 | ||
288 | |||
289 | //------------------------------------------------------------------------------ | ||
290 | // WRITE ONLY: Resets the board. (Data doesn't matter). | ||
291 | // | ||
292 | #define FIFO_RESET 0x7 | ||
293 | |||
294 | //------------------------------------------------------------------------------ | ||
295 | // READ ONLY: Will have no effect. (Data is undefined.) | ||
296 | // Actually, there will be an effect, in that the operation is sure to generate | ||
297 | // a bus cycle: viz., an I/O byte Read. This fact can be used to enforce short | ||
298 | // delays when no comparable time constant is available. | ||
299 | // | ||
300 | #define FIFO_NOP 0x7 | ||
301 | |||
302 | //------------------------------------------------------------------------------ | ||
303 | // RESET & POWER-ON RESET MESSAGE | ||
304 | /*------------------------------------------------------------------------------ | ||
305 | RESET: | ||
306 | |||
307 | The IntelliPort-II and -IIEX boards are reset in three ways: Power-up, channel | ||
308 | reset, and via a write to the reset register described above. For products using | ||
309 | the ISA bus, these three sources of reset are equvalent. For MCA and EISA buses, | ||
310 | the Power-up and channel reset sources cause additional hardware initialization | ||
311 | which should only occur at system startup time. | ||
312 | |||
313 | The third type of reset, called a "command reset", is done by writing any data | ||
314 | to the FIFO_RESET address described above. This resets the on-board processor, | ||
315 | FIFO, UARTS, and associated hardware. | ||
316 | |||
317 | This passes control of the board to the bootstrap firmware, which performs a | ||
318 | Power-On Self Test and which detects its current configuration. For example, | ||
319 | -IIEX products determine the size of FIFO which has been installed, and the | ||
320 | number and type of expansion boxes attached. | ||
321 | |||
322 | This and other information is then written to the FIFO in a 16-byte data block | ||
323 | to be read by the host. This block is guaranteed to be present within two (2) | ||
324 | seconds of having received the command reset. The firmware is now ready to | ||
325 | receive loadware from the host. | ||
326 | |||
327 | It is good practice to perform a command reset to the board explicitly as part | ||
328 | of your software initialization. This allows your code to properly restart from | ||
329 | a soft boot. (Many systems do not issue channel reset on soft boot). | ||
330 | |||
331 | Because of a hardware reset problem on some of the Cirrus Logic 1400's which are | ||
332 | used on the product, it is recommended that you reset the board twice, separated | ||
333 | by an approximately 50 milliseconds delay. (VERY approximately: probably ok to | ||
334 | be off by a factor of five. The important point is that the first command reset | ||
335 | in fact generates a reset pulse on the board. This pulse is guaranteed to last | ||
336 | less than 10 milliseconds. The additional delay ensures the 1400 has had the | ||
337 | chance to respond sufficiently to the first reset. Why not a longer delay? Much | ||
338 | more than 50 milliseconds gets to be noticable, but the board would still work. | ||
339 | |||
340 | Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap | ||
341 | firmware is ready to receive loadware. | ||
342 | |||
343 | Note on Power-on Reset Message format: | ||
344 | The various fields have been designed with future expansion in view. | ||
345 | Combinations of bitfields and values have been defined which define products | ||
346 | which may not currently exist. This has been done to allow drivers to anticipate | ||
347 | the possible introduction of products in a systematic fashion. This is not | ||
348 | intended to suggest that each potential product is actually under consideration. | ||
349 | ------------------------------------------------------------------------------*/ | ||
350 | |||
351 | //---------------------------------------- | ||
352 | // Format of Power-on Reset Message | ||
353 | //---------------------------------------- | ||
354 | |||
355 | typedef union _porStr // "por" stands for Power On Reset | ||
356 | { | ||
357 | unsigned char c[16]; // array used when considering the message as a | ||
358 | // string of undifferentiated characters | ||
359 | |||
360 | struct // Elements used when considering values | ||
361 | { | ||
362 | // The first two bytes out of the FIFO are two magic numbers. These are | ||
363 | // intended to establish that there is indeed a member of the | ||
364 | // IntelliPort-II(EX) family present. The remaining bytes may be | ||
365 | // expected // to be valid. When reading the Power-on Reset message, | ||
366 | // if the magic numbers do not match it is probably best to stop | ||
367 | // reading immediately. You are certainly not reading our board (unless | ||
368 | // hardware is faulty), and may in fact be reading some other piece of | ||
369 | // hardware. | ||
370 | |||
371 | unsigned char porMagic1; // magic number: first byte == POR_MAGIC_1 | ||
372 | unsigned char porMagic2; // magic number: second byte == POR_MAGIC_2 | ||
373 | |||
374 | // The Version, Revision, and Subrevision are stored as absolute numbers | ||
375 | // and would normally be displayed in the format V.R.S (e.g. 1.0.2) | ||
376 | |||
377 | unsigned char porVersion; // Bootstrap firmware version number | ||
378 | unsigned char porRevision; // Bootstrap firmware revision number | ||
379 | unsigned char porSubRev; // Bootstrap firmware sub-revision number | ||
380 | |||
381 | unsigned char porID; // Product ID: Bit-mapped according to | ||
382 | // conventions described below. Among other | ||
383 | // things, this allows us to distinguish | ||
384 | // IntelliPort-II boards from IntelliPort-IIEX | ||
385 | // boards. | ||
386 | |||
387 | unsigned char porBus; // IntelliPort-II: Unused | ||
388 | // IntelliPort-IIEX: Bus Information: | ||
389 | // Bit-mapped below | ||
390 | |||
391 | unsigned char porMemory; // On-board DRAM size: in 32k blocks | ||
392 | |||
393 | // porPorts1 (and porPorts2) are used to determine the ports which are | ||
394 | // available to the board. For non-expandable product, a single number | ||
395 | // is sufficient. For expandable product, the board may be connected | ||
396 | // to as many as four boxes. Each box may be (so far) either a 16-port | ||
397 | // or an 8-port size. Whenever an 8-port box is used, the remaining 8 | ||
398 | // ports leave gaps between existing channels. For that reason, | ||
399 | // expandable products must report a MAP of available channels. Since | ||
400 | // each UART supports four ports, we represent each UART found by a | ||
401 | // single bit. Using two bytes to supply the mapping information we | ||
402 | // report the presense or absense of up to 16 UARTS, or 64 ports in | ||
403 | // steps of 4 ports. For -IIEX products, the ports are numbered | ||
404 | // starting at the box closest to the controller in the "chain". | ||
405 | |||
406 | // Interpreted Differently for IntelliPort-II and -IIEX. | ||
407 | // -II: Number of ports (Derived actually from product ID). See | ||
408 | // Diag1&2 to indicate if uart was actually detected. | ||
409 | // -IIEX: Bit-map of UARTS found, LSB (see below for MSB of this). This | ||
410 | // bitmap is based on detecting the uarts themselves; | ||
411 | // see porFlags for information from the box i.d's. | ||
412 | unsigned char porPorts1; | ||
413 | |||
414 | unsigned char porDiag1; // Results of on-board P.O.S.T, 1st byte | ||
415 | unsigned char porDiag2; // Results of on-board P.O.S.T, 2nd byte | ||
416 | unsigned char porSpeed; // Speed of local CPU: given as MHz x10 | ||
417 | // e.g., 16.0 MHz CPU is reported as 160 | ||
418 | unsigned char porFlags; // Misc information (see manifests below) | ||
419 | // Bit-mapped: CPU type, UART's present | ||
420 | |||
421 | unsigned char porPorts2; // -II: Undefined | ||
422 | // -IIEX: Bit-map of UARTS found, MSB (see | ||
423 | // above for LSB) | ||
424 | |||
425 | // IntelliPort-II: undefined | ||
426 | // IntelliPort-IIEX: 1 << porFifoSize gives the size, in bytes, of the | ||
427 | // host interface FIFO, in each direction. When running the -IIEX in | ||
428 | // 8-bit mode, fifo capacity is halved. The bootstrap firmware will | ||
429 | // have already accounted for this fact in generating this number. | ||
430 | unsigned char porFifoSize; | ||
431 | |||
432 | // IntelliPort-II: undefined | ||
433 | // IntelliPort-IIEX: The number of boxes connected. (Presently 1-4) | ||
434 | unsigned char porNumBoxes; | ||
435 | } e; | ||
436 | } porStr, *porStrPtr; | ||
437 | |||
438 | //-------------------------- | ||
439 | // Values for porStr fields | ||
440 | //-------------------------- | ||
441 | |||
442 | //--------------------- | ||
443 | // porMagic1, porMagic2 | ||
444 | //---------------------- | ||
445 | // | ||
446 | #define POR_MAGIC_1 0x96 // The only valid value for porMagic1 | ||
447 | #define POR_MAGIC_2 0x35 // The only valid value for porMagic2 | ||
448 | #define POR_1_INDEX 0 // Byte position of POR_MAGIC_1 | ||
449 | #define POR_2_INDEX 1 // Ditto for POR_MAGIC_2 | ||
450 | |||
451 | //---------------------- | ||
452 | // porID | ||
453 | //---------------------- | ||
454 | // | ||
455 | #define POR_ID_FAMILY 0xc0 // These bits indicate the general family of | ||
456 | // product. | ||
457 | #define POR_ID_FII 0x00 // Family is "IntelliPort-II" | ||
458 | #define POR_ID_FIIEX 0x40 // Family is "IntelliPort-IIEX" | ||
459 | |||
460 | // These bits are reserved, presently zero. May be used at a later date to | ||
461 | // convey other product information. | ||
462 | // | ||
463 | #define POR_ID_RESERVED 0x3c | ||
464 | |||
465 | #define POR_ID_SIZE 0x03 // Remaining bits indicate number of ports & | ||
466 | // Connector information. | ||
467 | #define POR_ID_II_8 0x00 // For IntelliPort-II, indicates 8-port using | ||
468 | // standard brick. | ||
469 | #define POR_ID_II_8R 0x01 // For IntelliPort-II, indicates 8-port using | ||
470 | // RJ11's (no CTS) | ||
471 | #define POR_ID_II_6 0x02 // For IntelliPort-II, indicates 6-port using | ||
472 | // RJ45's | ||
473 | #define POR_ID_II_4 0x03 // For IntelliPort-II, indicates 4-port using | ||
474 | // 4xRJ45 connectors | ||
475 | #define POR_ID_EX 0x00 // For IntelliPort-IIEX, indicates standard | ||
476 | // expandable controller (other values reserved) | ||
477 | |||
478 | //---------------------- | ||
479 | // porBus | ||
480 | //---------------------- | ||
481 | |||
482 | // IntelliPort-IIEX only: Board is installed in a 16-bit slot | ||
483 | // | ||
484 | #define POR_BUS_SLOT16 0x20 | ||
485 | |||
486 | // IntelliPort-IIEX only: DIP switch #8 is on, selecting 16-bit host interface | ||
487 | // operation. | ||
488 | // | ||
489 | #define POR_BUS_DIP16 0x10 | ||
490 | |||
491 | // Bits 0-2 indicate type of bus: This information is stored in the bootstrap | ||
492 | // loadware, different loadware being used on different products for different | ||
493 | // buses. For most situations, the drivers do not need this information; but it | ||
494 | // is handy in a diagnostic environment. For example, on microchannel boards, | ||
495 | // you would not want to try to test several interrupts, only the one for which | ||
496 | // you were configured. | ||
497 | // | ||
498 | #define POR_BUS_TYPE 0x07 | ||
499 | |||
500 | // Unknown: this product doesn't know what bus it is running in. (e.g. if same | ||
501 | // bootstrap firmware were wanted for two different buses.) | ||
502 | // | ||
503 | #define POR_BUS_T_UNK 0 | ||
504 | |||
505 | // Note: existing firmware for ISA-8 and MC-8 currently report the POR_BUS_T_UNK | ||
506 | // state, since the same bootstrap firmware is used for each. | ||
507 | |||
508 | #define POR_BUS_T_MCA 1 // MCA BUS */ | ||
509 | #define POR_BUS_T_EISA 2 // EISA BUS */ | ||
510 | #define POR_BUS_T_ISA 3 // ISA BUS */ | ||
511 | |||
512 | // Values 4-7 Reserved | ||
513 | |||
514 | // Remaining bits are reserved | ||
515 | |||
516 | //---------------------- | ||
517 | // porDiag1 | ||
518 | //---------------------- | ||
519 | |||
520 | #define POR_BAD_MAPPER 0x80 // HW failure on P.O.S.T: Chip mapper failed | ||
521 | |||
522 | // These two bits valid only for the IntelliPort-II | ||
523 | // | ||
524 | #define POR_BAD_UART1 0x01 // First 1400 bad | ||
525 | #define POR_BAD_UART2 0x02 // Second 1400 bad | ||
526 | |||
527 | //---------------------- | ||
528 | // porDiag2 | ||
529 | //---------------------- | ||
530 | |||
531 | #define POR_DEBUG_PORT 0x80 // debug port was detected by the P.O.S.T | ||
532 | #define POR_DIAG_OK 0x00 // Indicates passage: Failure codes not yet | ||
533 | // available. | ||
534 | // Other bits undefined. | ||
535 | //---------------------- | ||
536 | // porFlags | ||
537 | //---------------------- | ||
538 | |||
539 | #define POR_CPU 0x03 // These bits indicate supposed CPU type | ||
540 | #define POR_CPU_8 0x01 // Board uses an 80188 (no such thing yet) | ||
541 | #define POR_CPU_6 0x02 // Board uses an 80186 (all existing products) | ||
542 | #define POR_CEX4 0x04 // If set, this is an ISA-CEX/4: An ISA-4 (asic) | ||
543 | // which is architected like an ISA-CEX connected | ||
544 | // to a (hitherto impossible) 4-port box. | ||
545 | #define POR_BOXES 0xf0 // Valid for IntelliPort-IIEX only: Map of Box | ||
546 | // sizes based on box I.D. | ||
547 | #define POR_BOX_16 0x10 // Set indicates 16-port, clear 8-port | ||
548 | |||
549 | //------------------------------------- | ||
550 | // LOADWARE and DOWNLOADING CODE | ||
551 | //------------------------------------- | ||
552 | |||
553 | /* | ||
554 | Loadware may be sent to the board in two ways: | ||
555 | 1) It may be read from a (binary image) data file block by block as each block | ||
556 | is sent to the board. This is only possible when the initialization is | ||
557 | performed by code which can access your file system. This is most suitable | ||
558 | for diagnostics and appications which use the interface library directly. | ||
559 | |||
560 | 2) It may be hard-coded into your source by including a .h file (typically | ||
561 | supplied by Computone), which declares a data array and initializes every | ||
562 | element. This achieves the same result as if an entire loadware file had | ||
563 | been read into the array. | ||
564 | |||
565 | This requires more data space in your program, but access to the file system | ||
566 | is not required. This method is more suited to driver code, which typically | ||
567 | is running at a level too low to access the file system directly. | ||
568 | |||
569 | At present, loadware can only be generated at Computone. | ||
570 | |||
571 | All Loadware begins with a header area which has a particular format. This | ||
572 | includes a magic number which identifies the file as being (purportedly) | ||
573 | loadware, CRC (for the loader), and version information. | ||
574 | */ | ||
575 | |||
576 | |||
577 | //----------------------------------------------------------------------------- | ||
578 | // Format of loadware block | ||
579 | // | ||
580 | // This is defined as a union so we can pass a pointer to one of these items | ||
581 | // and (if it is the first block) pick out the version information, etc. | ||
582 | // | ||
583 | // Otherwise, to deal with this as a simple character array | ||
584 | //------------------------------------------------------------------------------ | ||
585 | |||
586 | #define LOADWARE_BLOCK_SIZE 512 // Number of bytes in each block of loadware | ||
587 | |||
588 | typedef union _loadHdrStr | ||
589 | { | ||
590 | unsigned char c[LOADWARE_BLOCK_SIZE]; // Valid for every block | ||
591 | |||
592 | struct // These fields are valid for only the first block of loadware. | ||
593 | { | ||
594 | unsigned char loadMagic; // Magic number: see below | ||
595 | unsigned char loadBlocksMore; // How many more blocks? | ||
596 | unsigned char loadCRC[2]; // Two CRC bytes: used by loader | ||
597 | unsigned char loadVersion; // Version number | ||
598 | unsigned char loadRevision; // Revision number | ||
599 | unsigned char loadSubRevision; // Sub-revision number | ||
600 | unsigned char loadSpares[9]; // Presently unused | ||
601 | unsigned char loadDates[32]; // Null-terminated string which can give | ||
602 | // date and time of compilation | ||
603 | } e; | ||
604 | } loadHdrStr, *loadHdrStrPtr; | ||
605 | |||
606 | //------------------------------------ | ||
607 | // Defines for downloading code: | ||
608 | //------------------------------------ | ||
609 | |||
610 | // The loadMagic field in the first block of the loadfile must be this, else the | ||
611 | // file is not valid. | ||
612 | // | ||
613 | #define MAGIC_LOADFILE 0x3c | ||
614 | |||
615 | // How do we know the load was successful? On completion of the load, the | ||
616 | // bootstrap firmware returns a code to indicate whether it thought the download | ||
617 | // was valid and intends to execute it. These are the only possible valid codes: | ||
618 | // | ||
619 | #define LOADWARE_OK 0xc3 // Download was ok | ||
620 | #define LOADWARE_BAD 0x5a // Download was bad (CRC error) | ||
621 | |||
622 | // Constants applicable to writing blocks of loadware: | ||
623 | // The first block of loadware might take 600 mS to load, in extreme cases. | ||
624 | // (Expandable board: worst case for sending startup messages to the LCD's). | ||
625 | // The 600mS figure is not really a calculation, but a conservative | ||
626 | // guess/guarantee. Usually this will be within 100 mS, like subsequent blocks. | ||
627 | // | ||
628 | #define MAX_DLOAD_START_TIME 1000 // 1000 mS | ||
629 | #define MAX_DLOAD_READ_TIME 100 // 100 mS | ||
630 | |||
631 | // Firmware should respond with status (see above) within this long of host | ||
632 | // having sent the final block. | ||
633 | // | ||
634 | #define MAX_DLOAD_ACK_TIME 100 // 100 mS, again! | ||
635 | |||
636 | //------------------------------------------------------ | ||
637 | // MAXIMUM NUMBER OF PORTS PER BOARD: | ||
638 | // This is fixed for now (with the expandable), but may | ||
639 | // be expanding according to even newer products. | ||
640 | //------------------------------------------------------ | ||
641 | // | ||
642 | #define ABS_MAX_BOXES 4 // Absolute most boxes per board | ||
643 | #define ABS_BIGGEST_BOX 16 // Absolute the most ports per box | ||
644 | #define ABS_MOST_PORTS (ABS_MAX_BOXES * ABS_BIGGEST_BOX) | ||
645 | |||
646 | #define I2_OUTSW(port, addr, count) outsw((port), (addr), (((count)+1)/2)) | ||
647 | #define I2_OUTSB(port, addr, count) outsb((port), (addr), (((count)+1))&-2) | ||
648 | #define I2_INSW(port, addr, count) insw((port), (addr), (((count)+1)/2)) | ||
649 | #define I2_INSB(port, addr, count) insb((port), (addr), (((count)+1))&-2) | ||
650 | |||
651 | #endif // I2HW_H | ||
652 | |||
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c deleted file mode 100644 index 0d10b89218ed..000000000000 --- a/drivers/char/ip2/i2lib.c +++ /dev/null | |||
@@ -1,2214 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: High-level interface code for the device driver. Uses the | ||
12 | * Extremely Low Level Interface Support (i2ellis.c). Provides an | ||
13 | * interface to the standard loadware, to support drivers or | ||
14 | * application code. (This is included source code, not a separate | ||
15 | * compilation module.) | ||
16 | * | ||
17 | *******************************************************************************/ | ||
18 | //------------------------------------------------------------------------------ | ||
19 | // Note on Strategy: | ||
20 | // Once the board has been initialized, it will interrupt us when: | ||
21 | // 1) It has something in the fifo for us to read (incoming data, flow control | ||
22 | // packets, or whatever). | ||
23 | // 2) It has stripped whatever we have sent last time in the FIFO (and | ||
24 | // consequently is ready for more). | ||
25 | // | ||
26 | // Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This | ||
27 | // worsens performance considerably, but is done so that a great many channels | ||
28 | // might use only a little memory. | ||
29 | //------------------------------------------------------------------------------ | ||
30 | |||
31 | //------------------------------------------------------------------------------ | ||
32 | // Revision History: | ||
33 | // | ||
34 | // 0.00 - 4/16/91 --- First Draft | ||
35 | // 0.01 - 4/29/91 --- 1st beta release | ||
36 | // 0.02 - 6/14/91 --- Changes to allow small model compilation | ||
37 | // 0.03 - 6/17/91 MAG Break reporting protected from interrupts routines with | ||
38 | // in-line asm added for moving data to/from ring buffers, | ||
39 | // replacing a variety of methods used previously. | ||
40 | // 0.04 - 6/21/91 MAG Initial flow-control packets not queued until | ||
41 | // i2_enable_interrupts time. Former versions would enqueue | ||
42 | // them at i2_init_channel time, before we knew how many | ||
43 | // channels were supposed to exist! | ||
44 | // 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now; | ||
45 | // supports new 16-bit protocol and expandable boards. | ||
46 | // - 10/24/91 MAG Most changes in place and stable. | ||
47 | // 0.06 - 2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no | ||
48 | // argument. | ||
49 | // 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt | ||
50 | // level (mostly responses to specific commands.) | ||
51 | // 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet | ||
52 | // 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE | ||
53 | // turning on the interrupt. | ||
54 | // 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check | ||
55 | // some incoming. | ||
56 | // | ||
57 | // 1.1 - 12/25/96 AKM Linux version. | ||
58 | // - 10/09/98 DMC Revised Linux version. | ||
59 | //------------------------------------------------------------------------------ | ||
60 | |||
61 | //************ | ||
62 | //* Includes * | ||
63 | //************ | ||
64 | |||
65 | #include <linux/sched.h> | ||
66 | #include "i2lib.h" | ||
67 | |||
68 | |||
69 | //*********************** | ||
70 | //* Function Prototypes * | ||
71 | //*********************** | ||
72 | static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int); | ||
73 | static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int ); | ||
74 | static void i2StripFifo(i2eBordStrPtr); | ||
75 | static void i2StuffFifoBypass(i2eBordStrPtr); | ||
76 | static void i2StuffFifoFlow(i2eBordStrPtr); | ||
77 | static void i2StuffFifoInline(i2eBordStrPtr); | ||
78 | static int i2RetryFlushOutput(i2ChanStrPtr); | ||
79 | |||
80 | // Not a documented part of the library routines (careful...) but the Diagnostic | ||
81 | // i2diag.c finds them useful to help the throughput in certain limited | ||
82 | // single-threaded operations. | ||
83 | static void iiSendPendingMail(i2eBordStrPtr); | ||
84 | static void serviceOutgoingFifo(i2eBordStrPtr); | ||
85 | |||
86 | // Functions defined in ip2.c as part of interrupt handling | ||
87 | static void do_input(struct work_struct *); | ||
88 | static void do_status(struct work_struct *); | ||
89 | |||
90 | //*************** | ||
91 | //* Debug Data * | ||
92 | //*************** | ||
93 | #ifdef DEBUG_FIFO | ||
94 | |||
95 | unsigned char DBGBuf[0x4000]; | ||
96 | unsigned short I = 0; | ||
97 | |||
98 | static void | ||
99 | WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) | ||
100 | { | ||
101 | char *p = src; | ||
102 | |||
103 | // XXX: We need a spin lock here if we ever use this again | ||
104 | |||
105 | while (*s) { // copy label | ||
106 | DBGBuf[I] = *s++; | ||
107 | I = I++ & 0x3fff; | ||
108 | } | ||
109 | while (n--) { // copy data | ||
110 | DBGBuf[I] = *p++; | ||
111 | I = I++ & 0x3fff; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static void | ||
116 | fatality(i2eBordStrPtr pB ) | ||
117 | { | ||
118 | int i; | ||
119 | |||
120 | for (i=0;i<sizeof(DBGBuf);i++) { | ||
121 | if ((i%16) == 0) | ||
122 | printk("\n%4x:",i); | ||
123 | printk("%02x ",DBGBuf[i]); | ||
124 | } | ||
125 | printk("\n"); | ||
126 | for (i=0;i<sizeof(DBGBuf);i++) { | ||
127 | if ((i%16) == 0) | ||
128 | printk("\n%4x:",i); | ||
129 | if (DBGBuf[i] >= ' ' && DBGBuf[i] <= '~') { | ||
130 | printk(" %c ",DBGBuf[i]); | ||
131 | } else { | ||
132 | printk(" . "); | ||
133 | } | ||
134 | } | ||
135 | printk("\n"); | ||
136 | printk("Last index %x\n",I); | ||
137 | } | ||
138 | #endif /* DEBUG_FIFO */ | ||
139 | |||
140 | //******** | ||
141 | //* Code * | ||
142 | //******** | ||
143 | |||
144 | static inline int | ||
145 | i2Validate ( i2ChanStrPtr pCh ) | ||
146 | { | ||
147 | //ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity, | ||
148 | // (CHANNEL_MAGIC | CHANNEL_SUPPORT)); | ||
149 | return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) | ||
150 | == (CHANNEL_MAGIC | CHANNEL_SUPPORT)); | ||
151 | } | ||
152 | |||
153 | static void iiSendPendingMail_t(unsigned long data) | ||
154 | { | ||
155 | i2eBordStrPtr pB = (i2eBordStrPtr)data; | ||
156 | |||
157 | iiSendPendingMail(pB); | ||
158 | } | ||
159 | |||
160 | //****************************************************************************** | ||
161 | // Function: iiSendPendingMail(pB) | ||
162 | // Parameters: Pointer to a board structure | ||
163 | // Returns: Nothing | ||
164 | // | ||
165 | // Description: | ||
166 | // If any outgoing mail bits are set and there is outgoing mailbox is empty, | ||
167 | // send the mail and clear the bits. | ||
168 | //****************************************************************************** | ||
169 | static void | ||
170 | iiSendPendingMail(i2eBordStrPtr pB) | ||
171 | { | ||
172 | if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) ) | ||
173 | { | ||
174 | if (iiTrySendMail(pB, pB->i2eOutMailWaiting)) | ||
175 | { | ||
176 | /* If we were already waiting for fifo to empty, | ||
177 | * or just sent MB_OUT_STUFFED, then we are | ||
178 | * still waiting for it to empty, until we should | ||
179 | * receive an MB_IN_STRIPPED from the board. | ||
180 | */ | ||
181 | pB->i2eWaitingForEmptyFifo |= | ||
182 | (pB->i2eOutMailWaiting & MB_OUT_STUFFED); | ||
183 | pB->i2eOutMailWaiting = 0; | ||
184 | pB->SendPendingRetry = 0; | ||
185 | } else { | ||
186 | /* The only time we hit this area is when "iiTrySendMail" has | ||
187 | failed. That only occurs when the outbound mailbox is | ||
188 | still busy with the last message. We take a short breather | ||
189 | to let the board catch up with itself and then try again. | ||
190 | 16 Retries is the limit - then we got a borked board. | ||
191 | /\/\|=mhw=|\/\/ */ | ||
192 | |||
193 | if( ++pB->SendPendingRetry < 16 ) { | ||
194 | setup_timer(&pB->SendPendingTimer, | ||
195 | iiSendPendingMail_t, (unsigned long)pB); | ||
196 | mod_timer(&pB->SendPendingTimer, jiffies + 1); | ||
197 | } else { | ||
198 | printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" ); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | |||
204 | //****************************************************************************** | ||
205 | // Function: i2InitChannels(pB, nChannels, pCh) | ||
206 | // Parameters: Pointer to Ellis Board structure | ||
207 | // Number of channels to initialize | ||
208 | // Pointer to first element in an array of channel structures | ||
209 | // Returns: Success or failure | ||
210 | // | ||
211 | // Description: | ||
212 | // | ||
213 | // This function patches pointers, back-pointers, and initializes all the | ||
214 | // elements in the channel structure array. | ||
215 | // | ||
216 | // This should be run after the board structure is initialized, through having | ||
217 | // loaded the standard loadware (otherwise it complains). | ||
218 | // | ||
219 | // In any case, it must be done before any serious work begins initializing the | ||
220 | // irq's or sending commands... | ||
221 | // | ||
222 | //****************************************************************************** | ||
223 | static int | ||
224 | i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh) | ||
225 | { | ||
226 | int index, stuffIndex; | ||
227 | i2ChanStrPtr *ppCh; | ||
228 | |||
229 | if (pB->i2eValid != I2E_MAGIC) { | ||
230 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
231 | } | ||
232 | if (pB->i2eState != II_STATE_STDLOADED) { | ||
233 | I2_COMPLETE(pB, I2EE_BADSTATE); | ||
234 | } | ||
235 | |||
236 | rwlock_init(&pB->read_fifo_spinlock); | ||
237 | rwlock_init(&pB->write_fifo_spinlock); | ||
238 | rwlock_init(&pB->Dbuf_spinlock); | ||
239 | rwlock_init(&pB->Bbuf_spinlock); | ||
240 | rwlock_init(&pB->Fbuf_spinlock); | ||
241 | |||
242 | // NO LOCK needed yet - this is init | ||
243 | |||
244 | pB->i2eChannelPtr = pCh; | ||
245 | pB->i2eChannelCnt = nChannels; | ||
246 | |||
247 | pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0; | ||
248 | pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0; | ||
249 | pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0; | ||
250 | |||
251 | pB->SendPendingRetry = 0; | ||
252 | |||
253 | memset ( pCh, 0, sizeof (i2ChanStr) * nChannels ); | ||
254 | |||
255 | for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf); | ||
256 | nChannels && index < ABS_MOST_PORTS; | ||
257 | index++) | ||
258 | { | ||
259 | if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) { | ||
260 | continue; | ||
261 | } | ||
262 | rwlock_init(&pCh->Ibuf_spinlock); | ||
263 | rwlock_init(&pCh->Obuf_spinlock); | ||
264 | rwlock_init(&pCh->Cbuf_spinlock); | ||
265 | rwlock_init(&pCh->Pbuf_spinlock); | ||
266 | // NO LOCK needed yet - this is init | ||
267 | // Set up validity flag according to support level | ||
268 | if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) { | ||
269 | pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT; | ||
270 | } else { | ||
271 | pCh->validity = CHANNEL_MAGIC; | ||
272 | } | ||
273 | pCh->pMyBord = pB; /* Back-pointer */ | ||
274 | |||
275 | // Prepare an outgoing flow-control packet to send as soon as the chance | ||
276 | // occurs. | ||
277 | if ( pCh->validity & CHANNEL_SUPPORT ) { | ||
278 | pCh->infl.hd.i2sChannel = index; | ||
279 | pCh->infl.hd.i2sCount = 5; | ||
280 | pCh->infl.hd.i2sType = PTYPE_BYPASS; | ||
281 | pCh->infl.fcmd = 37; | ||
282 | pCh->infl.asof = 0; | ||
283 | pCh->infl.room = IBUF_SIZE - 1; | ||
284 | |||
285 | pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full | ||
286 | |||
287 | // The following is similar to calling i2QueueNeeds, except that this | ||
288 | // is done in longhand, since we are setting up initial conditions on | ||
289 | // many channels at once. | ||
290 | pCh->channelNeeds = NEED_FLOW; // Since starting from scratch | ||
291 | pCh->sinceLastFlow = 0; // No bytes received since last flow | ||
292 | // control packet was queued | ||
293 | stuffIndex++; | ||
294 | *ppCh++ = pCh; // List this channel as needing | ||
295 | // initial flow control packet sent | ||
296 | } | ||
297 | |||
298 | // Don't allow anything to be sent until the status packets come in from | ||
299 | // the board. | ||
300 | |||
301 | pCh->outfl.asof = 0; | ||
302 | pCh->outfl.room = 0; | ||
303 | |||
304 | // Initialize all the ring buffers | ||
305 | |||
306 | pCh->Ibuf_stuff = pCh->Ibuf_strip = 0; | ||
307 | pCh->Obuf_stuff = pCh->Obuf_strip = 0; | ||
308 | pCh->Cbuf_stuff = pCh->Cbuf_strip = 0; | ||
309 | |||
310 | memset( &pCh->icount, 0, sizeof (struct async_icount) ); | ||
311 | pCh->hotKeyIn = HOT_CLEAR; | ||
312 | pCh->channelOptions = 0; | ||
313 | pCh->bookMarks = 0; | ||
314 | init_waitqueue_head(&pCh->pBookmarkWait); | ||
315 | |||
316 | init_waitqueue_head(&pCh->open_wait); | ||
317 | init_waitqueue_head(&pCh->close_wait); | ||
318 | init_waitqueue_head(&pCh->delta_msr_wait); | ||
319 | |||
320 | // Set base and divisor so default custom rate is 9600 | ||
321 | pCh->BaudBase = 921600; // MAX for ST654, changed after we get | ||
322 | pCh->BaudDivisor = 96; // the boxids (UART types) later | ||
323 | |||
324 | pCh->dataSetIn = 0; | ||
325 | pCh->dataSetOut = 0; | ||
326 | |||
327 | pCh->wopen = 0; | ||
328 | pCh->throttled = 0; | ||
329 | |||
330 | pCh->speed = CBR_9600; | ||
331 | |||
332 | pCh->flags = 0; | ||
333 | |||
334 | pCh->ClosingDelay = 5*HZ/10; | ||
335 | pCh->ClosingWaitTime = 30*HZ; | ||
336 | |||
337 | // Initialize task queue objects | ||
338 | INIT_WORK(&pCh->tqueue_input, do_input); | ||
339 | INIT_WORK(&pCh->tqueue_status, do_status); | ||
340 | |||
341 | #ifdef IP2DEBUG_TRACE | ||
342 | pCh->trace = ip2trace; | ||
343 | #endif | ||
344 | |||
345 | ++pCh; | ||
346 | --nChannels; | ||
347 | } | ||
348 | // No need to check for wrap here; this is initialization. | ||
349 | pB->i2Fbuf_stuff = stuffIndex; | ||
350 | I2_COMPLETE(pB, I2EE_GOOD); | ||
351 | |||
352 | } | ||
353 | |||
354 | //****************************************************************************** | ||
355 | // Function: i2DeQueueNeeds(pB, type) | ||
356 | // Parameters: Pointer to a board structure | ||
357 | // type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW | ||
358 | // Returns: | ||
359 | // Pointer to a channel structure | ||
360 | // | ||
361 | // Description: Returns pointer struct of next channel that needs service of | ||
362 | // the type specified. Otherwise returns a NULL reference. | ||
363 | // | ||
364 | //****************************************************************************** | ||
365 | static i2ChanStrPtr | ||
366 | i2DeQueueNeeds(i2eBordStrPtr pB, int type) | ||
367 | { | ||
368 | unsigned short queueIndex; | ||
369 | unsigned long flags; | ||
370 | |||
371 | i2ChanStrPtr pCh = NULL; | ||
372 | |||
373 | switch(type) { | ||
374 | |||
375 | case NEED_INLINE: | ||
376 | |||
377 | write_lock_irqsave(&pB->Dbuf_spinlock, flags); | ||
378 | if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip) | ||
379 | { | ||
380 | queueIndex = pB->i2Dbuf_strip; | ||
381 | pCh = pB->i2Dbuf[queueIndex]; | ||
382 | queueIndex++; | ||
383 | if (queueIndex >= CH_QUEUE_SIZE) { | ||
384 | queueIndex = 0; | ||
385 | } | ||
386 | pB->i2Dbuf_strip = queueIndex; | ||
387 | pCh->channelNeeds &= ~NEED_INLINE; | ||
388 | } | ||
389 | write_unlock_irqrestore(&pB->Dbuf_spinlock, flags); | ||
390 | break; | ||
391 | |||
392 | case NEED_BYPASS: | ||
393 | |||
394 | write_lock_irqsave(&pB->Bbuf_spinlock, flags); | ||
395 | if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip) | ||
396 | { | ||
397 | queueIndex = pB->i2Bbuf_strip; | ||
398 | pCh = pB->i2Bbuf[queueIndex]; | ||
399 | queueIndex++; | ||
400 | if (queueIndex >= CH_QUEUE_SIZE) { | ||
401 | queueIndex = 0; | ||
402 | } | ||
403 | pB->i2Bbuf_strip = queueIndex; | ||
404 | pCh->channelNeeds &= ~NEED_BYPASS; | ||
405 | } | ||
406 | write_unlock_irqrestore(&pB->Bbuf_spinlock, flags); | ||
407 | break; | ||
408 | |||
409 | case NEED_FLOW: | ||
410 | |||
411 | write_lock_irqsave(&pB->Fbuf_spinlock, flags); | ||
412 | if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip) | ||
413 | { | ||
414 | queueIndex = pB->i2Fbuf_strip; | ||
415 | pCh = pB->i2Fbuf[queueIndex]; | ||
416 | queueIndex++; | ||
417 | if (queueIndex >= CH_QUEUE_SIZE) { | ||
418 | queueIndex = 0; | ||
419 | } | ||
420 | pB->i2Fbuf_strip = queueIndex; | ||
421 | pCh->channelNeeds &= ~NEED_FLOW; | ||
422 | } | ||
423 | write_unlock_irqrestore(&pB->Fbuf_spinlock, flags); | ||
424 | break; | ||
425 | default: | ||
426 | printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type); | ||
427 | break; | ||
428 | } | ||
429 | return pCh; | ||
430 | } | ||
431 | |||
432 | //****************************************************************************** | ||
433 | // Function: i2QueueNeeds(pB, pCh, type) | ||
434 | // Parameters: Pointer to a board structure | ||
435 | // Pointer to a channel structure | ||
436 | // type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW | ||
437 | // Returns: Nothing | ||
438 | // | ||
439 | // Description: | ||
440 | // For each type of need selected, if the given channel is not already in the | ||
441 | // queue, adds it, and sets the flag indicating it is in the queue. | ||
442 | //****************************************************************************** | ||
443 | static void | ||
444 | i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type) | ||
445 | { | ||
446 | unsigned short queueIndex; | ||
447 | unsigned long flags; | ||
448 | |||
449 | // We turn off all the interrupts during this brief process, since the | ||
450 | // interrupt-level code might want to put things on the queue as well. | ||
451 | |||
452 | switch (type) { | ||
453 | |||
454 | case NEED_INLINE: | ||
455 | |||
456 | write_lock_irqsave(&pB->Dbuf_spinlock, flags); | ||
457 | if ( !(pCh->channelNeeds & NEED_INLINE) ) | ||
458 | { | ||
459 | pCh->channelNeeds |= NEED_INLINE; | ||
460 | queueIndex = pB->i2Dbuf_stuff; | ||
461 | pB->i2Dbuf[queueIndex++] = pCh; | ||
462 | if (queueIndex >= CH_QUEUE_SIZE) | ||
463 | queueIndex = 0; | ||
464 | pB->i2Dbuf_stuff = queueIndex; | ||
465 | } | ||
466 | write_unlock_irqrestore(&pB->Dbuf_spinlock, flags); | ||
467 | break; | ||
468 | |||
469 | case NEED_BYPASS: | ||
470 | |||
471 | write_lock_irqsave(&pB->Bbuf_spinlock, flags); | ||
472 | if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS)) | ||
473 | { | ||
474 | pCh->channelNeeds |= NEED_BYPASS; | ||
475 | queueIndex = pB->i2Bbuf_stuff; | ||
476 | pB->i2Bbuf[queueIndex++] = pCh; | ||
477 | if (queueIndex >= CH_QUEUE_SIZE) | ||
478 | queueIndex = 0; | ||
479 | pB->i2Bbuf_stuff = queueIndex; | ||
480 | } | ||
481 | write_unlock_irqrestore(&pB->Bbuf_spinlock, flags); | ||
482 | break; | ||
483 | |||
484 | case NEED_FLOW: | ||
485 | |||
486 | write_lock_irqsave(&pB->Fbuf_spinlock, flags); | ||
487 | if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW)) | ||
488 | { | ||
489 | pCh->channelNeeds |= NEED_FLOW; | ||
490 | queueIndex = pB->i2Fbuf_stuff; | ||
491 | pB->i2Fbuf[queueIndex++] = pCh; | ||
492 | if (queueIndex >= CH_QUEUE_SIZE) | ||
493 | queueIndex = 0; | ||
494 | pB->i2Fbuf_stuff = queueIndex; | ||
495 | } | ||
496 | write_unlock_irqrestore(&pB->Fbuf_spinlock, flags); | ||
497 | break; | ||
498 | |||
499 | case NEED_CREDIT: | ||
500 | pCh->channelNeeds |= NEED_CREDIT; | ||
501 | break; | ||
502 | default: | ||
503 | printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type); | ||
504 | break; | ||
505 | } | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | //****************************************************************************** | ||
510 | // Function: i2QueueCommands(type, pCh, timeout, nCommands, pCs,...) | ||
511 | // Parameters: type - PTYPE_BYPASS or PTYPE_INLINE | ||
512 | // pointer to the channel structure | ||
513 | // maximum period to wait | ||
514 | // number of commands (n) | ||
515 | // n commands | ||
516 | // Returns: Number of commands sent, or -1 for error | ||
517 | // | ||
518 | // get board lock before calling | ||
519 | // | ||
520 | // Description: | ||
521 | // Queues up some commands to be sent to a channel. To send possibly several | ||
522 | // bypass or inline commands to the given channel. The timeout parameter | ||
523 | // indicates how many HUNDREDTHS OF SECONDS to wait until there is room: | ||
524 | // 0 = return immediately if no room, -ive = wait forever, +ive = number of | ||
525 | // 1/100 seconds to wait. Return values: | ||
526 | // -1 Some kind of nasty error: bad channel structure or invalid arguments. | ||
527 | // 0 No room to send all the commands | ||
528 | // (+) Number of commands sent | ||
529 | //****************************************************************************** | ||
530 | static int | ||
531 | i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands, | ||
532 | cmdSyntaxPtr pCs0,...) | ||
533 | { | ||
534 | int totalsize = 0; | ||
535 | int blocksize; | ||
536 | int lastended; | ||
537 | cmdSyntaxPtr *ppCs; | ||
538 | cmdSyntaxPtr pCs; | ||
539 | int count; | ||
540 | int flag; | ||
541 | i2eBordStrPtr pB; | ||
542 | |||
543 | unsigned short maxBlock; | ||
544 | unsigned short maxBuff; | ||
545 | short bufroom; | ||
546 | unsigned short stuffIndex; | ||
547 | unsigned char *pBuf; | ||
548 | unsigned char *pInsert; | ||
549 | unsigned char *pDest, *pSource; | ||
550 | unsigned short channel; | ||
551 | int cnt; | ||
552 | unsigned long flags = 0; | ||
553 | rwlock_t *lock_var_p = NULL; | ||
554 | |||
555 | // Make sure the channel exists, otherwise do nothing | ||
556 | if ( !i2Validate ( pCh ) ) { | ||
557 | return -1; | ||
558 | } | ||
559 | |||
560 | ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 ); | ||
561 | |||
562 | pB = pCh->pMyBord; | ||
563 | |||
564 | // Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT | ||
565 | if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED) | ||
566 | return -2; | ||
567 | // If the board has gone fatal, return bad, and also hit the trap routine if | ||
568 | // it exists. | ||
569 | if (pB->i2eFatal) { | ||
570 | if ( pB->i2eFatalTrap ) { | ||
571 | (*(pB)->i2eFatalTrap)(pB); | ||
572 | } | ||
573 | return -3; | ||
574 | } | ||
575 | // Set up some variables, Which buffers are we using? How big are they? | ||
576 | switch(type) | ||
577 | { | ||
578 | case PTYPE_INLINE: | ||
579 | flag = INL; | ||
580 | maxBlock = MAX_OBUF_BLOCK; | ||
581 | maxBuff = OBUF_SIZE; | ||
582 | pBuf = pCh->Obuf; | ||
583 | break; | ||
584 | case PTYPE_BYPASS: | ||
585 | flag = BYP; | ||
586 | maxBlock = MAX_CBUF_BLOCK; | ||
587 | maxBuff = CBUF_SIZE; | ||
588 | pBuf = pCh->Cbuf; | ||
589 | break; | ||
590 | default: | ||
591 | return -4; | ||
592 | } | ||
593 | // Determine the total size required for all the commands | ||
594 | totalsize = blocksize = sizeof(i2CmdHeader); | ||
595 | lastended = 0; | ||
596 | ppCs = &pCs0; | ||
597 | for ( count = nCommands; count; count--, ppCs++) | ||
598 | { | ||
599 | pCs = *ppCs; | ||
600 | cnt = pCs->length; | ||
601 | // Will a new block be needed for this one? | ||
602 | // Two possible reasons: too | ||
603 | // big or previous command has to be at the end of a packet. | ||
604 | if ((blocksize + cnt > maxBlock) || lastended) { | ||
605 | blocksize = sizeof(i2CmdHeader); | ||
606 | totalsize += sizeof(i2CmdHeader); | ||
607 | } | ||
608 | totalsize += cnt; | ||
609 | blocksize += cnt; | ||
610 | |||
611 | // If this command had to end a block, then we will make sure to | ||
612 | // account for it should there be any more blocks. | ||
613 | lastended = pCs->flags & END; | ||
614 | } | ||
615 | for (;;) { | ||
616 | // Make sure any pending flush commands go out before we add more data. | ||
617 | if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) { | ||
618 | // How much room (this time through) ? | ||
619 | switch(type) { | ||
620 | case PTYPE_INLINE: | ||
621 | lock_var_p = &pCh->Obuf_spinlock; | ||
622 | write_lock_irqsave(lock_var_p, flags); | ||
623 | stuffIndex = pCh->Obuf_stuff; | ||
624 | bufroom = pCh->Obuf_strip - stuffIndex; | ||
625 | break; | ||
626 | case PTYPE_BYPASS: | ||
627 | lock_var_p = &pCh->Cbuf_spinlock; | ||
628 | write_lock_irqsave(lock_var_p, flags); | ||
629 | stuffIndex = pCh->Cbuf_stuff; | ||
630 | bufroom = pCh->Cbuf_strip - stuffIndex; | ||
631 | break; | ||
632 | default: | ||
633 | return -5; | ||
634 | } | ||
635 | if (--bufroom < 0) { | ||
636 | bufroom += maxBuff; | ||
637 | } | ||
638 | |||
639 | ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom ); | ||
640 | |||
641 | // Check for overflow | ||
642 | if (totalsize <= bufroom) { | ||
643 | // Normal Expected path - We still hold LOCK | ||
644 | break; /* from for()- Enough room: goto proceed */ | ||
645 | } | ||
646 | ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); | ||
647 | write_unlock_irqrestore(lock_var_p, flags); | ||
648 | } else | ||
649 | ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); | ||
650 | |||
651 | /* Prepare to wait for buffers to empty */ | ||
652 | serviceOutgoingFifo(pB); // Dump what we got | ||
653 | |||
654 | if (timeout == 0) { | ||
655 | return 0; // Tired of waiting | ||
656 | } | ||
657 | if (timeout > 0) | ||
658 | timeout--; // So negative values == forever | ||
659 | |||
660 | if (!in_interrupt()) { | ||
661 | schedule_timeout_interruptible(1); // short nap | ||
662 | } else { | ||
663 | // we cannot sched/sleep in interrupt silly | ||
664 | return 0; | ||
665 | } | ||
666 | if (signal_pending(current)) { | ||
667 | return 0; // Wake up! Time to die!!! | ||
668 | } | ||
669 | |||
670 | ip2trace (CHANN, ITRC_QUEUE, 4, 0 ); | ||
671 | |||
672 | } // end of for(;;) | ||
673 | |||
674 | // At this point we have room and the lock - stick them in. | ||
675 | channel = pCh->infl.hd.i2sChannel; | ||
676 | pInsert = &pBuf[stuffIndex]; // Pointer to start of packet | ||
677 | pDest = CMD_OF(pInsert); // Pointer to start of command | ||
678 | |||
679 | // When we start counting, the block is the size of the header | ||
680 | for (blocksize = sizeof(i2CmdHeader), count = nCommands, | ||
681 | lastended = 0, ppCs = &pCs0; | ||
682 | count; | ||
683 | count--, ppCs++) | ||
684 | { | ||
685 | pCs = *ppCs; // Points to command protocol structure | ||
686 | |||
687 | // If this is a bookmark request command, post the fact that a bookmark | ||
688 | // request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ | ||
689 | // has no parameters! The more general solution would be to reference | ||
690 | // pCs->cmd[0]. | ||
691 | if (pCs == CMD_BMARK_REQ) { | ||
692 | pCh->bookMarks++; | ||
693 | |||
694 | ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks ); | ||
695 | |||
696 | } | ||
697 | cnt = pCs->length; | ||
698 | |||
699 | // If this command would put us over the maximum block size or | ||
700 | // if the last command had to be at the end of a block, we end | ||
701 | // the existing block here and start a new one. | ||
702 | if ((blocksize + cnt > maxBlock) || lastended) { | ||
703 | |||
704 | ip2trace (CHANN, ITRC_QUEUE, 5, 0 ); | ||
705 | |||
706 | PTYPE_OF(pInsert) = type; | ||
707 | CHANNEL_OF(pInsert) = channel; | ||
708 | // count here does not include the header | ||
709 | CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); | ||
710 | stuffIndex += blocksize; | ||
711 | if(stuffIndex >= maxBuff) { | ||
712 | stuffIndex = 0; | ||
713 | pInsert = pBuf; | ||
714 | } | ||
715 | pInsert = &pBuf[stuffIndex]; // Pointer to start of next pkt | ||
716 | pDest = CMD_OF(pInsert); | ||
717 | blocksize = sizeof(i2CmdHeader); | ||
718 | } | ||
719 | // Now we know there is room for this one in the current block | ||
720 | |||
721 | blocksize += cnt; // Total bytes in this command | ||
722 | pSource = pCs->cmd; // Copy the command into the buffer | ||
723 | while (cnt--) { | ||
724 | *pDest++ = *pSource++; | ||
725 | } | ||
726 | // If this command had to end a block, then we will make sure to account | ||
727 | // for it should there be any more blocks. | ||
728 | lastended = pCs->flags & END; | ||
729 | } // end for | ||
730 | // Clean up the final block by writing header, etc | ||
731 | |||
732 | PTYPE_OF(pInsert) = type; | ||
733 | CHANNEL_OF(pInsert) = channel; | ||
734 | // count here does not include the header | ||
735 | CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); | ||
736 | stuffIndex += blocksize; | ||
737 | if(stuffIndex >= maxBuff) { | ||
738 | stuffIndex = 0; | ||
739 | pInsert = pBuf; | ||
740 | } | ||
741 | // Updates the index, and post the need for service. When adding these to | ||
742 | // the queue of channels, we turn off the interrupt while doing so, | ||
743 | // because at interrupt level we might want to push a channel back to the | ||
744 | // end of the queue. | ||
745 | switch(type) | ||
746 | { | ||
747 | case PTYPE_INLINE: | ||
748 | pCh->Obuf_stuff = stuffIndex; // Store buffer pointer | ||
749 | write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
750 | |||
751 | pB->debugInlineQueued++; | ||
752 | // Add the channel pointer to list of channels needing service (first | ||
753 | // come...), if it's not already there. | ||
754 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
755 | break; | ||
756 | |||
757 | case PTYPE_BYPASS: | ||
758 | pCh->Cbuf_stuff = stuffIndex; // Store buffer pointer | ||
759 | write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags); | ||
760 | |||
761 | pB->debugBypassQueued++; | ||
762 | // Add the channel pointer to list of channels needing service (first | ||
763 | // come...), if it's not already there. | ||
764 | i2QueueNeeds(pB, pCh, NEED_BYPASS); | ||
765 | break; | ||
766 | } | ||
767 | |||
768 | ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands ); | ||
769 | |||
770 | return nCommands; // Good status: number of commands sent | ||
771 | } | ||
772 | |||
773 | //****************************************************************************** | ||
774 | // Function: i2GetStatus(pCh,resetBits) | ||
775 | // Parameters: Pointer to a channel structure | ||
776 | // Bit map of status bits to clear | ||
777 | // Returns: Bit map of current status bits | ||
778 | // | ||
779 | // Description: | ||
780 | // Returns the state of data set signals, and whether a break has been received, | ||
781 | // (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status | ||
782 | // bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared | ||
783 | // AFTER the condition is passed. If pCh does not point to a valid channel, | ||
784 | // returns -1 (which would be impossible otherwise. | ||
785 | //****************************************************************************** | ||
786 | static int | ||
787 | i2GetStatus(i2ChanStrPtr pCh, int resetBits) | ||
788 | { | ||
789 | unsigned short status; | ||
790 | i2eBordStrPtr pB; | ||
791 | |||
792 | ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits ); | ||
793 | |||
794 | // Make sure the channel exists, otherwise do nothing */ | ||
795 | if ( !i2Validate ( pCh ) ) | ||
796 | return -1; | ||
797 | |||
798 | pB = pCh->pMyBord; | ||
799 | |||
800 | status = pCh->dataSetIn; | ||
801 | |||
802 | // Clear any specified error bits: but note that only actual error bits can | ||
803 | // be cleared, regardless of the value passed. | ||
804 | if (resetBits) | ||
805 | { | ||
806 | pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR)); | ||
807 | pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI); | ||
808 | } | ||
809 | |||
810 | ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn ); | ||
811 | |||
812 | return status; | ||
813 | } | ||
814 | |||
815 | //****************************************************************************** | ||
816 | // Function: i2Input(pChpDest,count) | ||
817 | // Parameters: Pointer to a channel structure | ||
818 | // Pointer to data buffer | ||
819 | // Number of bytes to read | ||
820 | // Returns: Number of bytes read, or -1 for error | ||
821 | // | ||
822 | // Description: | ||
823 | // Strips data from the input buffer and writes it to pDest. If there is a | ||
824 | // collosal blunder, (invalid structure pointers or the like), returns -1. | ||
825 | // Otherwise, returns the number of bytes read. | ||
826 | //****************************************************************************** | ||
827 | static int | ||
828 | i2Input(i2ChanStrPtr pCh) | ||
829 | { | ||
830 | int amountToMove; | ||
831 | unsigned short stripIndex; | ||
832 | int count; | ||
833 | unsigned long flags = 0; | ||
834 | |||
835 | ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0); | ||
836 | |||
837 | // Ensure channel structure seems real | ||
838 | if ( !i2Validate( pCh ) ) { | ||
839 | count = -1; | ||
840 | goto i2Input_exit; | ||
841 | } | ||
842 | write_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
843 | |||
844 | // initialize some accelerators and private copies | ||
845 | stripIndex = pCh->Ibuf_strip; | ||
846 | |||
847 | count = pCh->Ibuf_stuff - stripIndex; | ||
848 | |||
849 | // If buffer is empty or requested data count was 0, (trivial case) return | ||
850 | // without any further thought. | ||
851 | if ( count == 0 ) { | ||
852 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
853 | goto i2Input_exit; | ||
854 | } | ||
855 | // Adjust for buffer wrap | ||
856 | if ( count < 0 ) { | ||
857 | count += IBUF_SIZE; | ||
858 | } | ||
859 | // Don't give more than can be taken by the line discipline | ||
860 | amountToMove = pCh->pTTY->receive_room; | ||
861 | if (count > amountToMove) { | ||
862 | count = amountToMove; | ||
863 | } | ||
864 | // How much could we copy without a wrap? | ||
865 | amountToMove = IBUF_SIZE - stripIndex; | ||
866 | |||
867 | if (amountToMove > count) { | ||
868 | amountToMove = count; | ||
869 | } | ||
870 | // Move the first block | ||
871 | pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, | ||
872 | &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); | ||
873 | // If we needed to wrap, do the second data move | ||
874 | if (count > amountToMove) { | ||
875 | pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, | ||
876 | pCh->Ibuf, NULL, count - amountToMove ); | ||
877 | } | ||
878 | // Bump and wrap the stripIndex all at once by the amount of data read. This | ||
879 | // method is good regardless of whether the data was in one or two pieces. | ||
880 | stripIndex += count; | ||
881 | if (stripIndex >= IBUF_SIZE) { | ||
882 | stripIndex -= IBUF_SIZE; | ||
883 | } | ||
884 | pCh->Ibuf_strip = stripIndex; | ||
885 | |||
886 | // Update our flow control information and possibly queue ourselves to send | ||
887 | // it, depending on how much data has been stripped since the last time a | ||
888 | // packet was sent. | ||
889 | pCh->infl.asof += count; | ||
890 | |||
891 | if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) { | ||
892 | pCh->sinceLastFlow -= pCh->whenSendFlow; | ||
893 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
894 | i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); | ||
895 | } else { | ||
896 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
897 | } | ||
898 | |||
899 | i2Input_exit: | ||
900 | |||
901 | ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count); | ||
902 | |||
903 | return count; | ||
904 | } | ||
905 | |||
906 | //****************************************************************************** | ||
907 | // Function: i2InputFlush(pCh) | ||
908 | // Parameters: Pointer to a channel structure | ||
909 | // Returns: Number of bytes stripped, or -1 for error | ||
910 | // | ||
911 | // Description: | ||
912 | // Strips any data from the input buffer. If there is a collosal blunder, | ||
913 | // (invalid structure pointers or the like), returns -1. Otherwise, returns the | ||
914 | // number of bytes stripped. | ||
915 | //****************************************************************************** | ||
916 | static int | ||
917 | i2InputFlush(i2ChanStrPtr pCh) | ||
918 | { | ||
919 | int count; | ||
920 | unsigned long flags; | ||
921 | |||
922 | // Ensure channel structure seems real | ||
923 | if ( !i2Validate ( pCh ) ) | ||
924 | return -1; | ||
925 | |||
926 | ip2trace (CHANN, ITRC_INPUT, 10, 0); | ||
927 | |||
928 | write_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
929 | count = pCh->Ibuf_stuff - pCh->Ibuf_strip; | ||
930 | |||
931 | // Adjust for buffer wrap | ||
932 | if (count < 0) { | ||
933 | count += IBUF_SIZE; | ||
934 | } | ||
935 | |||
936 | // Expedient way to zero out the buffer | ||
937 | pCh->Ibuf_strip = pCh->Ibuf_stuff; | ||
938 | |||
939 | |||
940 | // Update our flow control information and possibly queue ourselves to send | ||
941 | // it, depending on how much data has been stripped since the last time a | ||
942 | // packet was sent. | ||
943 | |||
944 | pCh->infl.asof += count; | ||
945 | |||
946 | if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow ) | ||
947 | { | ||
948 | pCh->sinceLastFlow -= pCh->whenSendFlow; | ||
949 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
950 | i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); | ||
951 | } else { | ||
952 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
953 | } | ||
954 | |||
955 | ip2trace (CHANN, ITRC_INPUT, 19, 1, count); | ||
956 | |||
957 | return count; | ||
958 | } | ||
959 | |||
960 | //****************************************************************************** | ||
961 | // Function: i2InputAvailable(pCh) | ||
962 | // Parameters: Pointer to a channel structure | ||
963 | // Returns: Number of bytes available, or -1 for error | ||
964 | // | ||
965 | // Description: | ||
966 | // If there is a collosal blunder, (invalid structure pointers or the like), | ||
967 | // returns -1. Otherwise, returns the number of bytes stripped. Otherwise, | ||
968 | // returns the number of bytes available in the buffer. | ||
969 | //****************************************************************************** | ||
970 | #if 0 | ||
971 | static int | ||
972 | i2InputAvailable(i2ChanStrPtr pCh) | ||
973 | { | ||
974 | int count; | ||
975 | |||
976 | // Ensure channel structure seems real | ||
977 | if ( !i2Validate ( pCh ) ) return -1; | ||
978 | |||
979 | |||
980 | // initialize some accelerators and private copies | ||
981 | read_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
982 | count = pCh->Ibuf_stuff - pCh->Ibuf_strip; | ||
983 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
984 | |||
985 | // Adjust for buffer wrap | ||
986 | if (count < 0) | ||
987 | { | ||
988 | count += IBUF_SIZE; | ||
989 | } | ||
990 | |||
991 | return count; | ||
992 | } | ||
993 | #endif | ||
994 | |||
995 | //****************************************************************************** | ||
996 | // Function: i2Output(pCh, pSource, count) | ||
997 | // Parameters: Pointer to channel structure | ||
998 | // Pointer to source data | ||
999 | // Number of bytes to send | ||
1000 | // Returns: Number of bytes sent, or -1 for error | ||
1001 | // | ||
1002 | // Description: | ||
1003 | // Queues the data at pSource to be sent as data packets to the board. If there | ||
1004 | // is a collosal blunder, (invalid structure pointers or the like), returns -1. | ||
1005 | // Otherwise, returns the number of bytes written. What if there is not enough | ||
1006 | // room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then | ||
1007 | // we transfer as many characters as we can now, then return. If this bit is | ||
1008 | // clear (default), routine will spin along until all the data is buffered. | ||
1009 | // Should this occur, the 1-ms delay routine is called while waiting to avoid | ||
1010 | // applications that one cannot break out of. | ||
1011 | //****************************************************************************** | ||
1012 | static int | ||
1013 | i2Output(i2ChanStrPtr pCh, const char *pSource, int count) | ||
1014 | { | ||
1015 | i2eBordStrPtr pB; | ||
1016 | unsigned char *pInsert; | ||
1017 | int amountToMove; | ||
1018 | int countOriginal = count; | ||
1019 | unsigned short channel; | ||
1020 | unsigned short stuffIndex; | ||
1021 | unsigned long flags; | ||
1022 | |||
1023 | int bailout = 10; | ||
1024 | |||
1025 | ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 ); | ||
1026 | |||
1027 | // Ensure channel structure seems real | ||
1028 | if ( !i2Validate ( pCh ) ) | ||
1029 | return -1; | ||
1030 | |||
1031 | // initialize some accelerators and private copies | ||
1032 | pB = pCh->pMyBord; | ||
1033 | channel = pCh->infl.hd.i2sChannel; | ||
1034 | |||
1035 | // If the board has gone fatal, return bad, and also hit the trap routine if | ||
1036 | // it exists. | ||
1037 | if (pB->i2eFatal) { | ||
1038 | if (pB->i2eFatalTrap) { | ||
1039 | (*(pB)->i2eFatalTrap)(pB); | ||
1040 | } | ||
1041 | return -1; | ||
1042 | } | ||
1043 | // Proceed as though we would do everything | ||
1044 | while ( count > 0 ) { | ||
1045 | |||
1046 | // How much room in output buffer is there? | ||
1047 | read_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
1048 | amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; | ||
1049 | read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
1050 | if (amountToMove < 0) { | ||
1051 | amountToMove += OBUF_SIZE; | ||
1052 | } | ||
1053 | // Subtract off the headers size and see how much room there is for real | ||
1054 | // data. If this is negative, we will discover later. | ||
1055 | amountToMove -= sizeof (i2DataHeader); | ||
1056 | |||
1057 | // Don't move more (now) than can go in a single packet | ||
1058 | if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) { | ||
1059 | amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader); | ||
1060 | } | ||
1061 | // Don't move more than the count we were given | ||
1062 | if (amountToMove > count) { | ||
1063 | amountToMove = count; | ||
1064 | } | ||
1065 | // Now we know how much we must move: NB because the ring buffers have | ||
1066 | // an overflow area at the end, we needn't worry about wrapping in the | ||
1067 | // middle of a packet. | ||
1068 | |||
1069 | // Small WINDOW here with no LOCK but I can't call Flush with LOCK | ||
1070 | // We would be flushing (or ending flush) anyway | ||
1071 | |||
1072 | ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove ); | ||
1073 | |||
1074 | if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) | ||
1075 | && amountToMove > 0 ) | ||
1076 | { | ||
1077 | write_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
1078 | stuffIndex = pCh->Obuf_stuff; | ||
1079 | |||
1080 | // Had room to move some data: don't know whether the block size, | ||
1081 | // buffer space, or what was the limiting factor... | ||
1082 | pInsert = &(pCh->Obuf[stuffIndex]); | ||
1083 | |||
1084 | // Set up the header | ||
1085 | CHANNEL_OF(pInsert) = channel; | ||
1086 | PTYPE_OF(pInsert) = PTYPE_DATA; | ||
1087 | TAG_OF(pInsert) = 0; | ||
1088 | ID_OF(pInsert) = ID_ORDINARY_DATA; | ||
1089 | DATA_COUNT_OF(pInsert) = amountToMove; | ||
1090 | |||
1091 | // Move the data | ||
1092 | memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove ); | ||
1093 | // Adjust pointers and indices | ||
1094 | pSource += amountToMove; | ||
1095 | pCh->Obuf_char_count += amountToMove; | ||
1096 | stuffIndex += amountToMove + sizeof(i2DataHeader); | ||
1097 | count -= amountToMove; | ||
1098 | |||
1099 | if (stuffIndex >= OBUF_SIZE) { | ||
1100 | stuffIndex = 0; | ||
1101 | } | ||
1102 | pCh->Obuf_stuff = stuffIndex; | ||
1103 | |||
1104 | write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
1105 | |||
1106 | ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex ); | ||
1107 | |||
1108 | } else { | ||
1109 | |||
1110 | // Cannot move data | ||
1111 | // becuz we need to stuff a flush | ||
1112 | // or amount to move is <= 0 | ||
1113 | |||
1114 | ip2trace(CHANN, ITRC_OUTPUT, 14, 3, | ||
1115 | amountToMove, pB->i2eFifoRemains, | ||
1116 | pB->i2eWaitingForEmptyFifo ); | ||
1117 | |||
1118 | // Put this channel back on queue | ||
1119 | // this ultimatly gets more data or wakes write output | ||
1120 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
1121 | |||
1122 | if ( pB->i2eWaitingForEmptyFifo ) { | ||
1123 | |||
1124 | ip2trace (CHANN, ITRC_OUTPUT, 16, 0 ); | ||
1125 | |||
1126 | // or schedule | ||
1127 | if (!in_interrupt()) { | ||
1128 | |||
1129 | ip2trace (CHANN, ITRC_OUTPUT, 61, 0 ); | ||
1130 | |||
1131 | schedule_timeout_interruptible(2); | ||
1132 | if (signal_pending(current)) { | ||
1133 | break; | ||
1134 | } | ||
1135 | continue; | ||
1136 | } else { | ||
1137 | |||
1138 | ip2trace (CHANN, ITRC_OUTPUT, 62, 0 ); | ||
1139 | |||
1140 | // let interrupt in = WAS restore_flags() | ||
1141 | // We hold no lock nor is irq off anymore??? | ||
1142 | |||
1143 | break; | ||
1144 | } | ||
1145 | break; // from while(count) | ||
1146 | } | ||
1147 | else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) ) | ||
1148 | { | ||
1149 | ip2trace (CHANN, ITRC_OUTPUT, 19, 2, | ||
1150 | pB->i2eFifoRemains, | ||
1151 | pB->i2eTxMailEmpty ); | ||
1152 | |||
1153 | break; // from while(count) | ||
1154 | } else if ( pCh->channelNeeds & NEED_CREDIT ) { | ||
1155 | |||
1156 | ip2trace (CHANN, ITRC_OUTPUT, 22, 0 ); | ||
1157 | |||
1158 | break; // from while(count) | ||
1159 | } else if ( --bailout) { | ||
1160 | |||
1161 | // Try to throw more things (maybe not us) in the fifo if we're | ||
1162 | // not already waiting for it. | ||
1163 | |||
1164 | ip2trace (CHANN, ITRC_OUTPUT, 20, 0 ); | ||
1165 | |||
1166 | serviceOutgoingFifo(pB); | ||
1167 | //break; CONTINUE; | ||
1168 | } else { | ||
1169 | ip2trace (CHANN, ITRC_OUTPUT, 21, 3, | ||
1170 | pB->i2eFifoRemains, | ||
1171 | pB->i2eOutMailWaiting, | ||
1172 | pB->i2eWaitingForEmptyFifo ); | ||
1173 | |||
1174 | break; // from while(count) | ||
1175 | } | ||
1176 | } | ||
1177 | } // End of while(count) | ||
1178 | |||
1179 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
1180 | |||
1181 | // We drop through either when the count expires, or when there is some | ||
1182 | // count left, but there was a non-blocking write. | ||
1183 | if (countOriginal > count) { | ||
1184 | |||
1185 | ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count ); | ||
1186 | |||
1187 | serviceOutgoingFifo( pB ); | ||
1188 | } | ||
1189 | |||
1190 | ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count ); | ||
1191 | |||
1192 | return countOriginal - count; | ||
1193 | } | ||
1194 | |||
1195 | //****************************************************************************** | ||
1196 | // Function: i2FlushOutput(pCh) | ||
1197 | // Parameters: Pointer to a channel structure | ||
1198 | // Returns: Nothing | ||
1199 | // | ||
1200 | // Description: | ||
1201 | // Sends bypass command to start flushing (waiting possibly forever until there | ||
1202 | // is room), then sends inline command to stop flushing output, (again waiting | ||
1203 | // possibly forever). | ||
1204 | //****************************************************************************** | ||
1205 | static inline void | ||
1206 | i2FlushOutput(i2ChanStrPtr pCh) | ||
1207 | { | ||
1208 | |||
1209 | ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags ); | ||
1210 | |||
1211 | if (pCh->flush_flags) | ||
1212 | return; | ||
1213 | |||
1214 | if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { | ||
1215 | pCh->flush_flags = STARTFL_FLAG; // Failed - flag for later | ||
1216 | |||
1217 | ip2trace (CHANN, ITRC_FLUSH, 2, 0 ); | ||
1218 | |||
1219 | } else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) { | ||
1220 | pCh->flush_flags = STOPFL_FLAG; // Failed - flag for later | ||
1221 | |||
1222 | ip2trace (CHANN, ITRC_FLUSH, 3, 0 ); | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | static int | ||
1227 | i2RetryFlushOutput(i2ChanStrPtr pCh) | ||
1228 | { | ||
1229 | int old_flags = pCh->flush_flags; | ||
1230 | |||
1231 | ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags ); | ||
1232 | |||
1233 | pCh->flush_flags = 0; // Clear flag so we can avoid recursion | ||
1234 | // and queue the commands | ||
1235 | |||
1236 | if ( old_flags & STARTFL_FLAG ) { | ||
1237 | if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { | ||
1238 | old_flags = STOPFL_FLAG; //Success - send stop flush | ||
1239 | } else { | ||
1240 | old_flags = STARTFL_FLAG; //Failure - Flag for retry later | ||
1241 | } | ||
1242 | |||
1243 | ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags ); | ||
1244 | |||
1245 | } | ||
1246 | if ( old_flags & STOPFL_FLAG ) { | ||
1247 | if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) { | ||
1248 | old_flags = 0; // Success - clear flags | ||
1249 | } | ||
1250 | |||
1251 | ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags ); | ||
1252 | } | ||
1253 | pCh->flush_flags = old_flags; | ||
1254 | |||
1255 | ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags ); | ||
1256 | |||
1257 | return old_flags; | ||
1258 | } | ||
1259 | |||
1260 | //****************************************************************************** | ||
1261 | // Function: i2DrainOutput(pCh,timeout) | ||
1262 | // Parameters: Pointer to a channel structure | ||
1263 | // Maximum period to wait | ||
1264 | // Returns: ? | ||
1265 | // | ||
1266 | // Description: | ||
1267 | // Uses the bookmark request command to ask the board to send a bookmark back as | ||
1268 | // soon as all the data is completely sent. | ||
1269 | //****************************************************************************** | ||
1270 | static void | ||
1271 | i2DrainWakeup(unsigned long d) | ||
1272 | { | ||
1273 | i2ChanStrPtr pCh = (i2ChanStrPtr)d; | ||
1274 | |||
1275 | ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires ); | ||
1276 | |||
1277 | pCh->BookmarkTimer.expires = 0; | ||
1278 | wake_up_interruptible( &pCh->pBookmarkWait ); | ||
1279 | } | ||
1280 | |||
1281 | static void | ||
1282 | i2DrainOutput(i2ChanStrPtr pCh, int timeout) | ||
1283 | { | ||
1284 | wait_queue_t wait; | ||
1285 | i2eBordStrPtr pB; | ||
1286 | |||
1287 | ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires); | ||
1288 | |||
1289 | pB = pCh->pMyBord; | ||
1290 | // If the board has gone fatal, return bad, | ||
1291 | // and also hit the trap routine if it exists. | ||
1292 | if (pB->i2eFatal) { | ||
1293 | if (pB->i2eFatalTrap) { | ||
1294 | (*(pB)->i2eFatalTrap)(pB); | ||
1295 | } | ||
1296 | return; | ||
1297 | } | ||
1298 | if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) { | ||
1299 | // One per customer (channel) | ||
1300 | setup_timer(&pCh->BookmarkTimer, i2DrainWakeup, | ||
1301 | (unsigned long)pCh); | ||
1302 | |||
1303 | ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires ); | ||
1304 | |||
1305 | mod_timer(&pCh->BookmarkTimer, jiffies + timeout); | ||
1306 | } | ||
1307 | |||
1308 | i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ ); | ||
1309 | |||
1310 | init_waitqueue_entry(&wait, current); | ||
1311 | add_wait_queue(&(pCh->pBookmarkWait), &wait); | ||
1312 | set_current_state( TASK_INTERRUPTIBLE ); | ||
1313 | |||
1314 | serviceOutgoingFifo( pB ); | ||
1315 | |||
1316 | schedule(); // Now we take our interruptible sleep on | ||
1317 | |||
1318 | // Clean up the queue | ||
1319 | set_current_state( TASK_RUNNING ); | ||
1320 | remove_wait_queue(&(pCh->pBookmarkWait), &wait); | ||
1321 | |||
1322 | // if expires == 0 then timer poped, then do not need to del_timer | ||
1323 | if ((timeout > 0) && pCh->BookmarkTimer.expires && | ||
1324 | time_before(jiffies, pCh->BookmarkTimer.expires)) { | ||
1325 | del_timer( &(pCh->BookmarkTimer) ); | ||
1326 | pCh->BookmarkTimer.expires = 0; | ||
1327 | |||
1328 | ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires ); | ||
1329 | |||
1330 | } | ||
1331 | ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires ); | ||
1332 | return; | ||
1333 | } | ||
1334 | |||
1335 | //****************************************************************************** | ||
1336 | // Function: i2OutputFree(pCh) | ||
1337 | // Parameters: Pointer to a channel structure | ||
1338 | // Returns: Space in output buffer | ||
1339 | // | ||
1340 | // Description: | ||
1341 | // Returns -1 if very gross error. Otherwise returns the amount of bytes still | ||
1342 | // free in the output buffer. | ||
1343 | //****************************************************************************** | ||
1344 | static int | ||
1345 | i2OutputFree(i2ChanStrPtr pCh) | ||
1346 | { | ||
1347 | int amountToMove; | ||
1348 | unsigned long flags; | ||
1349 | |||
1350 | // Ensure channel structure seems real | ||
1351 | if ( !i2Validate ( pCh ) ) { | ||
1352 | return -1; | ||
1353 | } | ||
1354 | read_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
1355 | amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; | ||
1356 | read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
1357 | |||
1358 | if (amountToMove < 0) { | ||
1359 | amountToMove += OBUF_SIZE; | ||
1360 | } | ||
1361 | // If this is negative, we will discover later | ||
1362 | amountToMove -= sizeof(i2DataHeader); | ||
1363 | |||
1364 | return (amountToMove < 0) ? 0 : amountToMove; | ||
1365 | } | ||
1366 | static void | ||
1367 | |||
1368 | ip2_owake( PTTY tp) | ||
1369 | { | ||
1370 | i2ChanStrPtr pCh; | ||
1371 | |||
1372 | if (tp == NULL) return; | ||
1373 | |||
1374 | pCh = tp->driver_data; | ||
1375 | |||
1376 | ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags, | ||
1377 | (1 << TTY_DO_WRITE_WAKEUP) ); | ||
1378 | |||
1379 | tty_wakeup(tp); | ||
1380 | } | ||
1381 | |||
1382 | static inline void | ||
1383 | set_baud_params(i2eBordStrPtr pB) | ||
1384 | { | ||
1385 | int i,j; | ||
1386 | i2ChanStrPtr *pCh; | ||
1387 | |||
1388 | pCh = (i2ChanStrPtr *) pB->i2eChannelPtr; | ||
1389 | |||
1390 | for (i = 0; i < ABS_MAX_BOXES; i++) { | ||
1391 | if (pB->channelBtypes.bid_value[i]) { | ||
1392 | if (BID_HAS_654(pB->channelBtypes.bid_value[i])) { | ||
1393 | for (j = 0; j < ABS_BIGGEST_BOX; j++) { | ||
1394 | if (pCh[i*16+j] == NULL) | ||
1395 | break; | ||
1396 | (pCh[i*16+j])->BaudBase = 921600; // MAX for ST654 | ||
1397 | (pCh[i*16+j])->BaudDivisor = 96; | ||
1398 | } | ||
1399 | } else { // has cirrus cd1400 | ||
1400 | for (j = 0; j < ABS_BIGGEST_BOX; j++) { | ||
1401 | if (pCh[i*16+j] == NULL) | ||
1402 | break; | ||
1403 | (pCh[i*16+j])->BaudBase = 115200; // MAX for CD1400 | ||
1404 | (pCh[i*16+j])->BaudDivisor = 12; | ||
1405 | } | ||
1406 | } | ||
1407 | } | ||
1408 | } | ||
1409 | } | ||
1410 | |||
1411 | //****************************************************************************** | ||
1412 | // Function: i2StripFifo(pB) | ||
1413 | // Parameters: Pointer to a board structure | ||
1414 | // Returns: ? | ||
1415 | // | ||
1416 | // Description: | ||
1417 | // Strips all the available data from the incoming FIFO, identifies the type of | ||
1418 | // packet, and either buffers the data or does what needs to be done. | ||
1419 | // | ||
1420 | // Note there is no overflow checking here: if the board sends more data than it | ||
1421 | // ought to, we will not detect it here, but blindly overflow... | ||
1422 | //****************************************************************************** | ||
1423 | |||
1424 | // A buffer for reading in blocks for unknown channels | ||
1425 | static unsigned char junkBuffer[IBUF_SIZE]; | ||
1426 | |||
1427 | // A buffer to read in a status packet. Because of the size of the count field | ||
1428 | // for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE | ||
1429 | static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4]; | ||
1430 | |||
1431 | // This table changes the bit order from MSR order given by STAT_MODEM packet to | ||
1432 | // status bits used in our library. | ||
1433 | static char xlatDss[16] = { | ||
1434 | 0 | 0 | 0 | 0 , | ||
1435 | 0 | 0 | 0 | I2_CTS , | ||
1436 | 0 | 0 | I2_DSR | 0 , | ||
1437 | 0 | 0 | I2_DSR | I2_CTS , | ||
1438 | 0 | I2_RI | 0 | 0 , | ||
1439 | 0 | I2_RI | 0 | I2_CTS , | ||
1440 | 0 | I2_RI | I2_DSR | 0 , | ||
1441 | 0 | I2_RI | I2_DSR | I2_CTS , | ||
1442 | I2_DCD | 0 | 0 | 0 , | ||
1443 | I2_DCD | 0 | 0 | I2_CTS , | ||
1444 | I2_DCD | 0 | I2_DSR | 0 , | ||
1445 | I2_DCD | 0 | I2_DSR | I2_CTS , | ||
1446 | I2_DCD | I2_RI | 0 | 0 , | ||
1447 | I2_DCD | I2_RI | 0 | I2_CTS , | ||
1448 | I2_DCD | I2_RI | I2_DSR | 0 , | ||
1449 | I2_DCD | I2_RI | I2_DSR | I2_CTS }; | ||
1450 | |||
1451 | static inline void | ||
1452 | i2StripFifo(i2eBordStrPtr pB) | ||
1453 | { | ||
1454 | i2ChanStrPtr pCh; | ||
1455 | int channel; | ||
1456 | int count; | ||
1457 | unsigned short stuffIndex; | ||
1458 | int amountToRead; | ||
1459 | unsigned char *pc, *pcLimit; | ||
1460 | unsigned char uc; | ||
1461 | unsigned char dss_change; | ||
1462 | unsigned long bflags,cflags; | ||
1463 | |||
1464 | // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 ); | ||
1465 | |||
1466 | while (I2_HAS_INPUT(pB)) { | ||
1467 | // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 ); | ||
1468 | |||
1469 | // Process packet from fifo a one atomic unit | ||
1470 | write_lock_irqsave(&pB->read_fifo_spinlock, bflags); | ||
1471 | |||
1472 | // The first word (or two bytes) will have channel number and type of | ||
1473 | // packet, possibly other information | ||
1474 | pB->i2eLeadoffWord[0] = iiReadWord(pB); | ||
1475 | |||
1476 | switch(PTYPE_OF(pB->i2eLeadoffWord)) | ||
1477 | { | ||
1478 | case PTYPE_DATA: | ||
1479 | pB->got_input = 1; | ||
1480 | |||
1481 | // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 ); | ||
1482 | |||
1483 | channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */ | ||
1484 | count = iiReadWord(pB); /* Count is in the next word */ | ||
1485 | |||
1486 | // NEW: Check the count for sanity! Should the hardware fail, our death | ||
1487 | // is more pleasant. While an oversize channel is acceptable (just more | ||
1488 | // than the driver supports), an over-length count clearly means we are | ||
1489 | // sick! | ||
1490 | if ( ((unsigned int)count) > IBUF_SIZE ) { | ||
1491 | pB->i2eFatal = 2; | ||
1492 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1493 | bflags); | ||
1494 | return; /* Bail out ASAP */ | ||
1495 | } | ||
1496 | // Channel is illegally big ? | ||
1497 | if ((channel >= pB->i2eChannelCnt) || | ||
1498 | (NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel]))) | ||
1499 | { | ||
1500 | iiReadBuf(pB, junkBuffer, count); | ||
1501 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1502 | bflags); | ||
1503 | break; /* From switch: ready for next packet */ | ||
1504 | } | ||
1505 | |||
1506 | // Channel should be valid, then | ||
1507 | |||
1508 | // If this is a hot-key, merely post its receipt for now. These are | ||
1509 | // always supposed to be 1-byte packets, so we won't even check the | ||
1510 | // count. Also we will post an acknowledgement to the board so that | ||
1511 | // more data can be forthcoming. Note that we are not trying to use | ||
1512 | // these sequences in this driver, merely to robustly ignore them. | ||
1513 | if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY) | ||
1514 | { | ||
1515 | pCh->hotKeyIn = iiReadWord(pB) & 0xff; | ||
1516 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1517 | bflags); | ||
1518 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK); | ||
1519 | break; /* From the switch: ready for next packet */ | ||
1520 | } | ||
1521 | |||
1522 | // Normal data! We crudely assume there is room for the data in our | ||
1523 | // buffer because the board wouldn't have exceeded his credit limit. | ||
1524 | write_lock_irqsave(&pCh->Ibuf_spinlock, cflags); | ||
1525 | // We have 2 locks now | ||
1526 | stuffIndex = pCh->Ibuf_stuff; | ||
1527 | amountToRead = IBUF_SIZE - stuffIndex; | ||
1528 | if (amountToRead > count) | ||
1529 | amountToRead = count; | ||
1530 | |||
1531 | // stuffIndex would have been already adjusted so there would | ||
1532 | // always be room for at least one, and count is always at least | ||
1533 | // one. | ||
1534 | |||
1535 | iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); | ||
1536 | pCh->icount.rx += amountToRead; | ||
1537 | |||
1538 | // Update the stuffIndex by the amount of data moved. Note we could | ||
1539 | // never ask for more data than would just fit. However, we might | ||
1540 | // have read in one more byte than we wanted because the read | ||
1541 | // rounds up to even bytes. If this byte is on the end of the | ||
1542 | // packet, and is padding, we ignore it. If the byte is part of | ||
1543 | // the actual data, we need to move it. | ||
1544 | |||
1545 | stuffIndex += amountToRead; | ||
1546 | |||
1547 | if (stuffIndex >= IBUF_SIZE) { | ||
1548 | if ((amountToRead & 1) && (count > amountToRead)) { | ||
1549 | pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE]; | ||
1550 | amountToRead++; | ||
1551 | stuffIndex = 1; | ||
1552 | } else { | ||
1553 | stuffIndex = 0; | ||
1554 | } | ||
1555 | } | ||
1556 | |||
1557 | // If there is anything left over, read it as well | ||
1558 | if (count > amountToRead) { | ||
1559 | amountToRead = count - amountToRead; | ||
1560 | iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); | ||
1561 | pCh->icount.rx += amountToRead; | ||
1562 | stuffIndex += amountToRead; | ||
1563 | } | ||
1564 | |||
1565 | // Update stuff index | ||
1566 | pCh->Ibuf_stuff = stuffIndex; | ||
1567 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags); | ||
1568 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1569 | bflags); | ||
1570 | |||
1571 | #ifdef USE_IQ | ||
1572 | schedule_work(&pCh->tqueue_input); | ||
1573 | #else | ||
1574 | do_input(&pCh->tqueue_input); | ||
1575 | #endif | ||
1576 | |||
1577 | // Note we do not need to maintain any flow-control credits at this | ||
1578 | // time: if we were to increment .asof and decrement .room, there | ||
1579 | // would be no net effect. Instead, when we strip data, we will | ||
1580 | // increment .asof and leave .room unchanged. | ||
1581 | |||
1582 | break; // From switch: ready for next packet | ||
1583 | |||
1584 | case PTYPE_STATUS: | ||
1585 | ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 ); | ||
1586 | |||
1587 | count = CMD_COUNT_OF(pB->i2eLeadoffWord); | ||
1588 | |||
1589 | iiReadBuf(pB, cmdBuffer, count); | ||
1590 | // We can release early with buffer grab | ||
1591 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1592 | bflags); | ||
1593 | |||
1594 | pc = cmdBuffer; | ||
1595 | pcLimit = &(cmdBuffer[count]); | ||
1596 | |||
1597 | while (pc < pcLimit) { | ||
1598 | channel = *pc++; | ||
1599 | |||
1600 | ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc ); | ||
1601 | |||
1602 | /* check for valid channel */ | ||
1603 | if (channel < pB->i2eChannelCnt | ||
1604 | && | ||
1605 | (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL | ||
1606 | ) | ||
1607 | { | ||
1608 | dss_change = 0; | ||
1609 | |||
1610 | switch (uc = *pc++) | ||
1611 | { | ||
1612 | /* Breaks and modem signals are easy: just update status */ | ||
1613 | case STAT_CTS_UP: | ||
1614 | if ( !(pCh->dataSetIn & I2_CTS) ) | ||
1615 | { | ||
1616 | pCh->dataSetIn |= I2_DCTS; | ||
1617 | pCh->icount.cts++; | ||
1618 | dss_change = 1; | ||
1619 | } | ||
1620 | pCh->dataSetIn |= I2_CTS; | ||
1621 | break; | ||
1622 | |||
1623 | case STAT_CTS_DN: | ||
1624 | if ( pCh->dataSetIn & I2_CTS ) | ||
1625 | { | ||
1626 | pCh->dataSetIn |= I2_DCTS; | ||
1627 | pCh->icount.cts++; | ||
1628 | dss_change = 1; | ||
1629 | } | ||
1630 | pCh->dataSetIn &= ~I2_CTS; | ||
1631 | break; | ||
1632 | |||
1633 | case STAT_DCD_UP: | ||
1634 | ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn ); | ||
1635 | |||
1636 | if ( !(pCh->dataSetIn & I2_DCD) ) | ||
1637 | { | ||
1638 | ip2trace (CHANN, ITRC_MODEM, 2, 0 ); | ||
1639 | pCh->dataSetIn |= I2_DDCD; | ||
1640 | pCh->icount.dcd++; | ||
1641 | dss_change = 1; | ||
1642 | } | ||
1643 | pCh->dataSetIn |= I2_DCD; | ||
1644 | |||
1645 | ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn ); | ||
1646 | break; | ||
1647 | |||
1648 | case STAT_DCD_DN: | ||
1649 | ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn ); | ||
1650 | if ( pCh->dataSetIn & I2_DCD ) | ||
1651 | { | ||
1652 | ip2trace (channel, ITRC_MODEM, 5, 0 ); | ||
1653 | pCh->dataSetIn |= I2_DDCD; | ||
1654 | pCh->icount.dcd++; | ||
1655 | dss_change = 1; | ||
1656 | } | ||
1657 | pCh->dataSetIn &= ~I2_DCD; | ||
1658 | |||
1659 | ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn ); | ||
1660 | break; | ||
1661 | |||
1662 | case STAT_DSR_UP: | ||
1663 | if ( !(pCh->dataSetIn & I2_DSR) ) | ||
1664 | { | ||
1665 | pCh->dataSetIn |= I2_DDSR; | ||
1666 | pCh->icount.dsr++; | ||
1667 | dss_change = 1; | ||
1668 | } | ||
1669 | pCh->dataSetIn |= I2_DSR; | ||
1670 | break; | ||
1671 | |||
1672 | case STAT_DSR_DN: | ||
1673 | if ( pCh->dataSetIn & I2_DSR ) | ||
1674 | { | ||
1675 | pCh->dataSetIn |= I2_DDSR; | ||
1676 | pCh->icount.dsr++; | ||
1677 | dss_change = 1; | ||
1678 | } | ||
1679 | pCh->dataSetIn &= ~I2_DSR; | ||
1680 | break; | ||
1681 | |||
1682 | case STAT_RI_UP: | ||
1683 | if ( !(pCh->dataSetIn & I2_RI) ) | ||
1684 | { | ||
1685 | pCh->dataSetIn |= I2_DRI; | ||
1686 | pCh->icount.rng++; | ||
1687 | dss_change = 1; | ||
1688 | } | ||
1689 | pCh->dataSetIn |= I2_RI ; | ||
1690 | break; | ||
1691 | |||
1692 | case STAT_RI_DN: | ||
1693 | // to be compat with serial.c | ||
1694 | //if ( pCh->dataSetIn & I2_RI ) | ||
1695 | //{ | ||
1696 | // pCh->dataSetIn |= I2_DRI; | ||
1697 | // pCh->icount.rng++; | ||
1698 | // dss_change = 1; | ||
1699 | //} | ||
1700 | pCh->dataSetIn &= ~I2_RI ; | ||
1701 | break; | ||
1702 | |||
1703 | case STAT_BRK_DET: | ||
1704 | pCh->dataSetIn |= I2_BRK; | ||
1705 | pCh->icount.brk++; | ||
1706 | dss_change = 1; | ||
1707 | break; | ||
1708 | |||
1709 | // Bookmarks? one less request we're waiting for | ||
1710 | case STAT_BMARK: | ||
1711 | pCh->bookMarks--; | ||
1712 | if (pCh->bookMarks <= 0 ) { | ||
1713 | pCh->bookMarks = 0; | ||
1714 | wake_up_interruptible( &pCh->pBookmarkWait ); | ||
1715 | |||
1716 | ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires ); | ||
1717 | } | ||
1718 | break; | ||
1719 | |||
1720 | // Flow control packets? Update the new credits, and if | ||
1721 | // someone was waiting for output, queue him up again. | ||
1722 | case STAT_FLOW: | ||
1723 | pCh->outfl.room = | ||
1724 | ((flowStatPtr)pc)->room - | ||
1725 | (pCh->outfl.asof - ((flowStatPtr)pc)->asof); | ||
1726 | |||
1727 | ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room ); | ||
1728 | |||
1729 | if (pCh->channelNeeds & NEED_CREDIT) | ||
1730 | { | ||
1731 | ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds); | ||
1732 | |||
1733 | pCh->channelNeeds &= ~NEED_CREDIT; | ||
1734 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
1735 | if ( pCh->pTTY ) | ||
1736 | ip2_owake(pCh->pTTY); | ||
1737 | } | ||
1738 | |||
1739 | ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds); | ||
1740 | |||
1741 | pc += sizeof(flowStat); | ||
1742 | break; | ||
1743 | |||
1744 | /* Special packets: */ | ||
1745 | /* Just copy the information into the channel structure */ | ||
1746 | |||
1747 | case STAT_STATUS: | ||
1748 | |||
1749 | pCh->channelStatus = *((debugStatPtr)pc); | ||
1750 | pc += sizeof(debugStat); | ||
1751 | break; | ||
1752 | |||
1753 | case STAT_TXCNT: | ||
1754 | |||
1755 | pCh->channelTcount = *((cntStatPtr)pc); | ||
1756 | pc += sizeof(cntStat); | ||
1757 | break; | ||
1758 | |||
1759 | case STAT_RXCNT: | ||
1760 | |||
1761 | pCh->channelRcount = *((cntStatPtr)pc); | ||
1762 | pc += sizeof(cntStat); | ||
1763 | break; | ||
1764 | |||
1765 | case STAT_BOXIDS: | ||
1766 | pB->channelBtypes = *((bidStatPtr)pc); | ||
1767 | pc += sizeof(bidStat); | ||
1768 | set_baud_params(pB); | ||
1769 | break; | ||
1770 | |||
1771 | case STAT_HWFAIL: | ||
1772 | i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST); | ||
1773 | pCh->channelFail = *((failStatPtr)pc); | ||
1774 | pc += sizeof(failStat); | ||
1775 | break; | ||
1776 | |||
1777 | /* No explicit match? then | ||
1778 | * Might be an error packet... | ||
1779 | */ | ||
1780 | default: | ||
1781 | switch (uc & STAT_MOD_ERROR) | ||
1782 | { | ||
1783 | case STAT_ERROR: | ||
1784 | if (uc & STAT_E_PARITY) { | ||
1785 | pCh->dataSetIn |= I2_PAR; | ||
1786 | pCh->icount.parity++; | ||
1787 | } | ||
1788 | if (uc & STAT_E_FRAMING){ | ||
1789 | pCh->dataSetIn |= I2_FRA; | ||
1790 | pCh->icount.frame++; | ||
1791 | } | ||
1792 | if (uc & STAT_E_OVERRUN){ | ||
1793 | pCh->dataSetIn |= I2_OVR; | ||
1794 | pCh->icount.overrun++; | ||
1795 | } | ||
1796 | break; | ||
1797 | |||
1798 | case STAT_MODEM: | ||
1799 | // the answer to DSS_NOW request (not change) | ||
1800 | pCh->dataSetIn = (pCh->dataSetIn | ||
1801 | & ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) ) | ||
1802 | | xlatDss[uc & 0xf]; | ||
1803 | wake_up_interruptible ( &pCh->dss_now_wait ); | ||
1804 | default: | ||
1805 | break; | ||
1806 | } | ||
1807 | } /* End of switch on status type */ | ||
1808 | if (dss_change) { | ||
1809 | #ifdef USE_IQ | ||
1810 | schedule_work(&pCh->tqueue_status); | ||
1811 | #else | ||
1812 | do_status(&pCh->tqueue_status); | ||
1813 | #endif | ||
1814 | } | ||
1815 | } | ||
1816 | else /* Or else, channel is invalid */ | ||
1817 | { | ||
1818 | // Even though the channel is invalid, we must test the | ||
1819 | // status to see how much additional data it has (to be | ||
1820 | // skipped) | ||
1821 | switch (*pc++) | ||
1822 | { | ||
1823 | case STAT_FLOW: | ||
1824 | pc += 4; /* Skip the data */ | ||
1825 | break; | ||
1826 | |||
1827 | default: | ||
1828 | break; | ||
1829 | } | ||
1830 | } | ||
1831 | } // End of while (there is still some status packet left) | ||
1832 | break; | ||
1833 | |||
1834 | default: // Neither packet? should be impossible | ||
1835 | ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1, | ||
1836 | PTYPE_OF(pB->i2eLeadoffWord) ); | ||
1837 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1838 | bflags); | ||
1839 | |||
1840 | break; | ||
1841 | } // End of switch on type of packets | ||
1842 | } /*while(board I2_HAS_INPUT)*/ | ||
1843 | |||
1844 | ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 ); | ||
1845 | |||
1846 | // Send acknowledgement to the board even if there was no data! | ||
1847 | pB->i2eOutMailWaiting |= MB_IN_STRIPPED; | ||
1848 | return; | ||
1849 | } | ||
1850 | |||
1851 | //****************************************************************************** | ||
1852 | // Function: i2Write2Fifo(pB,address,count) | ||
1853 | // Parameters: Pointer to a board structure, source address, byte count | ||
1854 | // Returns: bytes written | ||
1855 | // | ||
1856 | // Description: | ||
1857 | // Writes count bytes to board io address(implied) from source | ||
1858 | // Adjusts count, leaves reserve for next time around bypass cmds | ||
1859 | //****************************************************************************** | ||
1860 | static int | ||
1861 | i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve) | ||
1862 | { | ||
1863 | int rc = 0; | ||
1864 | unsigned long flags; | ||
1865 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
1866 | if (!pB->i2eWaitingForEmptyFifo) { | ||
1867 | if (pB->i2eFifoRemains > (count+reserve)) { | ||
1868 | pB->i2eFifoRemains -= count; | ||
1869 | iiWriteBuf(pB, source, count); | ||
1870 | pB->i2eOutMailWaiting |= MB_OUT_STUFFED; | ||
1871 | rc = count; | ||
1872 | } | ||
1873 | } | ||
1874 | write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); | ||
1875 | return rc; | ||
1876 | } | ||
1877 | //****************************************************************************** | ||
1878 | // Function: i2StuffFifoBypass(pB) | ||
1879 | // Parameters: Pointer to a board structure | ||
1880 | // Returns: Nothing | ||
1881 | // | ||
1882 | // Description: | ||
1883 | // Stuffs as many bypass commands into the fifo as possible. This is simpler | ||
1884 | // than stuffing data or inline commands to fifo, since we do not have | ||
1885 | // flow-control to deal with. | ||
1886 | //****************************************************************************** | ||
1887 | static inline void | ||
1888 | i2StuffFifoBypass(i2eBordStrPtr pB) | ||
1889 | { | ||
1890 | i2ChanStrPtr pCh; | ||
1891 | unsigned char *pRemove; | ||
1892 | unsigned short stripIndex; | ||
1893 | unsigned short packetSize; | ||
1894 | unsigned short paddedSize; | ||
1895 | unsigned short notClogged = 1; | ||
1896 | unsigned long flags; | ||
1897 | |||
1898 | int bailout = 1000; | ||
1899 | |||
1900 | // Continue processing so long as there are entries, or there is room in the | ||
1901 | // fifo. Each entry represents a channel with something to do. | ||
1902 | while ( --bailout && notClogged && | ||
1903 | (NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS)))) | ||
1904 | { | ||
1905 | write_lock_irqsave(&pCh->Cbuf_spinlock, flags); | ||
1906 | stripIndex = pCh->Cbuf_strip; | ||
1907 | |||
1908 | // as long as there are packets for this channel... | ||
1909 | |||
1910 | while (stripIndex != pCh->Cbuf_stuff) { | ||
1911 | pRemove = &(pCh->Cbuf[stripIndex]); | ||
1912 | packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader); | ||
1913 | paddedSize = roundup(packetSize, 2); | ||
1914 | |||
1915 | if (paddedSize > 0) { | ||
1916 | if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) { | ||
1917 | notClogged = 0; /* fifo full */ | ||
1918 | i2QueueNeeds(pB, pCh, NEED_BYPASS); // Put back on queue | ||
1919 | break; // Break from the channel | ||
1920 | } | ||
1921 | } | ||
1922 | #ifdef DEBUG_FIFO | ||
1923 | WriteDBGBuf("BYPS", pRemove, paddedSize); | ||
1924 | #endif /* DEBUG_FIFO */ | ||
1925 | pB->debugBypassCount++; | ||
1926 | |||
1927 | pRemove += packetSize; | ||
1928 | stripIndex += packetSize; | ||
1929 | if (stripIndex >= CBUF_SIZE) { | ||
1930 | stripIndex = 0; | ||
1931 | pRemove = pCh->Cbuf; | ||
1932 | } | ||
1933 | } | ||
1934 | // Done with this channel. Move to next, removing this one from | ||
1935 | // the queue of channels if we cleaned it out (i.e., didn't get clogged. | ||
1936 | pCh->Cbuf_strip = stripIndex; | ||
1937 | write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags); | ||
1938 | } // Either clogged or finished all the work | ||
1939 | |||
1940 | #ifdef IP2DEBUG_TRACE | ||
1941 | if ( !bailout ) { | ||
1942 | ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 ); | ||
1943 | } | ||
1944 | #endif | ||
1945 | } | ||
1946 | |||
1947 | //****************************************************************************** | ||
1948 | // Function: i2StuffFifoFlow(pB) | ||
1949 | // Parameters: Pointer to a board structure | ||
1950 | // Returns: Nothing | ||
1951 | // | ||
1952 | // Description: | ||
1953 | // Stuffs as many flow control packets into the fifo as possible. This is easier | ||
1954 | // even than doing normal bypass commands, because there is always at most one | ||
1955 | // packet, already assembled, for each channel. | ||
1956 | //****************************************************************************** | ||
1957 | static inline void | ||
1958 | i2StuffFifoFlow(i2eBordStrPtr pB) | ||
1959 | { | ||
1960 | i2ChanStrPtr pCh; | ||
1961 | unsigned short paddedSize = roundup(sizeof(flowIn), 2); | ||
1962 | |||
1963 | ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2, | ||
1964 | pB->i2eFifoRemains, paddedSize ); | ||
1965 | |||
1966 | // Continue processing so long as there are entries, or there is room in the | ||
1967 | // fifo. Each entry represents a channel with something to do. | ||
1968 | while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) { | ||
1969 | pB->debugFlowCount++; | ||
1970 | |||
1971 | // NO Chan LOCK needed ??? | ||
1972 | if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) { | ||
1973 | break; | ||
1974 | } | ||
1975 | #ifdef DEBUG_FIFO | ||
1976 | WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize); | ||
1977 | #endif /* DEBUG_FIFO */ | ||
1978 | |||
1979 | } // Either clogged or finished all the work | ||
1980 | |||
1981 | ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 ); | ||
1982 | } | ||
1983 | |||
1984 | //****************************************************************************** | ||
1985 | // Function: i2StuffFifoInline(pB) | ||
1986 | // Parameters: Pointer to a board structure | ||
1987 | // Returns: Nothing | ||
1988 | // | ||
1989 | // Description: | ||
1990 | // Stuffs as much data and inline commands into the fifo as possible. This is | ||
1991 | // the most complex fifo-stuffing operation, since there if now the channel | ||
1992 | // flow-control issue to deal with. | ||
1993 | //****************************************************************************** | ||
1994 | static inline void | ||
1995 | i2StuffFifoInline(i2eBordStrPtr pB) | ||
1996 | { | ||
1997 | i2ChanStrPtr pCh; | ||
1998 | unsigned char *pRemove; | ||
1999 | unsigned short stripIndex; | ||
2000 | unsigned short packetSize; | ||
2001 | unsigned short paddedSize; | ||
2002 | unsigned short notClogged = 1; | ||
2003 | unsigned short flowsize; | ||
2004 | unsigned long flags; | ||
2005 | |||
2006 | int bailout = 1000; | ||
2007 | int bailout2; | ||
2008 | |||
2009 | ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, | ||
2010 | pB->i2Dbuf_strip, pB->i2Dbuf_stuff ); | ||
2011 | |||
2012 | // Continue processing so long as there are entries, or there is room in the | ||
2013 | // fifo. Each entry represents a channel with something to do. | ||
2014 | while ( --bailout && notClogged && | ||
2015 | (NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) ) | ||
2016 | { | ||
2017 | write_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
2018 | stripIndex = pCh->Obuf_strip; | ||
2019 | |||
2020 | ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff ); | ||
2021 | |||
2022 | // as long as there are packets for this channel... | ||
2023 | bailout2 = 1000; | ||
2024 | while ( --bailout2 && stripIndex != pCh->Obuf_stuff) { | ||
2025 | pRemove = &(pCh->Obuf[stripIndex]); | ||
2026 | |||
2027 | // Must determine whether this be a data or command packet to | ||
2028 | // calculate correctly the header size and the amount of | ||
2029 | // flow-control credit this type of packet will use. | ||
2030 | if (PTYPE_OF(pRemove) == PTYPE_DATA) { | ||
2031 | flowsize = DATA_COUNT_OF(pRemove); | ||
2032 | packetSize = flowsize + sizeof(i2DataHeader); | ||
2033 | } else { | ||
2034 | flowsize = CMD_COUNT_OF(pRemove); | ||
2035 | packetSize = flowsize + sizeof(i2CmdHeader); | ||
2036 | } | ||
2037 | flowsize = CREDIT_USAGE(flowsize); | ||
2038 | paddedSize = roundup(packetSize, 2); | ||
2039 | |||
2040 | ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize ); | ||
2041 | |||
2042 | // If we don't have enough credits from the board to send the data, | ||
2043 | // flag the channel that we are waiting for flow control credit, and | ||
2044 | // break out. This will clean up this channel and remove us from the | ||
2045 | // queue of hot things to do. | ||
2046 | |||
2047 | ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize ); | ||
2048 | |||
2049 | if (pCh->outfl.room <= flowsize) { | ||
2050 | // Do Not have the credits to send this packet. | ||
2051 | i2QueueNeeds(pB, pCh, NEED_CREDIT); | ||
2052 | notClogged = 0; | ||
2053 | break; // So to do next channel | ||
2054 | } | ||
2055 | if ( (paddedSize > 0) | ||
2056 | && ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) { | ||
2057 | // Do Not have room in fifo to send this packet. | ||
2058 | notClogged = 0; | ||
2059 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
2060 | break; // Break from the channel | ||
2061 | } | ||
2062 | #ifdef DEBUG_FIFO | ||
2063 | WriteDBGBuf("DATA", pRemove, paddedSize); | ||
2064 | #endif /* DEBUG_FIFO */ | ||
2065 | pB->debugInlineCount++; | ||
2066 | |||
2067 | pCh->icount.tx += flowsize; | ||
2068 | // Update current credits | ||
2069 | pCh->outfl.room -= flowsize; | ||
2070 | pCh->outfl.asof += flowsize; | ||
2071 | if (PTYPE_OF(pRemove) == PTYPE_DATA) { | ||
2072 | pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove); | ||
2073 | } | ||
2074 | pRemove += packetSize; | ||
2075 | stripIndex += packetSize; | ||
2076 | |||
2077 | ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip); | ||
2078 | |||
2079 | if (stripIndex >= OBUF_SIZE) { | ||
2080 | stripIndex = 0; | ||
2081 | pRemove = pCh->Obuf; | ||
2082 | |||
2083 | ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex ); | ||
2084 | |||
2085 | } | ||
2086 | } /* while */ | ||
2087 | if ( !bailout2 ) { | ||
2088 | ip2trace (CHANN, ITRC_ERROR, 3, 0 ); | ||
2089 | } | ||
2090 | // Done with this channel. Move to next, removing this one from the | ||
2091 | // queue of channels if we cleaned it out (i.e., didn't get clogged. | ||
2092 | pCh->Obuf_strip = stripIndex; | ||
2093 | write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
2094 | if ( notClogged ) | ||
2095 | { | ||
2096 | |||
2097 | ip2trace (CHANN, ITRC_SICMD, 8, 0 ); | ||
2098 | |||
2099 | if ( pCh->pTTY ) { | ||
2100 | ip2_owake(pCh->pTTY); | ||
2101 | } | ||
2102 | } | ||
2103 | } // Either clogged or finished all the work | ||
2104 | |||
2105 | if ( !bailout ) { | ||
2106 | ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 ); | ||
2107 | } | ||
2108 | |||
2109 | ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip); | ||
2110 | } | ||
2111 | |||
2112 | //****************************************************************************** | ||
2113 | // Function: serviceOutgoingFifo(pB) | ||
2114 | // Parameters: Pointer to a board structure | ||
2115 | // Returns: Nothing | ||
2116 | // | ||
2117 | // Description: | ||
2118 | // Helper routine to put data in the outgoing fifo, if we aren't already waiting | ||
2119 | // for something to be there. If the fifo has only room for a very little data, | ||
2120 | // go head and hit the board with a mailbox hit immediately. Otherwise, it will | ||
2121 | // have to happen later in the interrupt processing. Since this routine may be | ||
2122 | // called both at interrupt and foreground time, we must turn off interrupts | ||
2123 | // during the entire process. | ||
2124 | //****************************************************************************** | ||
2125 | static void | ||
2126 | serviceOutgoingFifo(i2eBordStrPtr pB) | ||
2127 | { | ||
2128 | // If we aren't currently waiting for the board to empty our fifo, service | ||
2129 | // everything that is pending, in priority order (especially, Bypass before | ||
2130 | // Inline). | ||
2131 | if ( ! pB->i2eWaitingForEmptyFifo ) | ||
2132 | { | ||
2133 | i2StuffFifoFlow(pB); | ||
2134 | i2StuffFifoBypass(pB); | ||
2135 | i2StuffFifoInline(pB); | ||
2136 | |||
2137 | iiSendPendingMail(pB); | ||
2138 | } | ||
2139 | } | ||
2140 | |||
2141 | //****************************************************************************** | ||
2142 | // Function: i2ServiceBoard(pB) | ||
2143 | // Parameters: Pointer to a board structure | ||
2144 | // Returns: Nothing | ||
2145 | // | ||
2146 | // Description: | ||
2147 | // Normally this is called from interrupt level, but there is deliberately | ||
2148 | // nothing in here specific to being called from interrupt level. All the | ||
2149 | // hardware-specific, interrupt-specific things happen at the outer levels. | ||
2150 | // | ||
2151 | // For example, a timer interrupt could drive this routine for some sort of | ||
2152 | // polled operation. The only requirement is that the programmer deal with any | ||
2153 | // atomiticity/concurrency issues that result. | ||
2154 | // | ||
2155 | // This routine responds to the board's having sent mailbox information to the | ||
2156 | // host (which would normally cause an interrupt). This routine reads the | ||
2157 | // incoming mailbox. If there is no data in it, this board did not create the | ||
2158 | // interrupt and/or has nothing to be done to it. (Except, if we have been | ||
2159 | // waiting to write mailbox data to it, we may do so. | ||
2160 | // | ||
2161 | // Based on the value in the mailbox, we may take various actions. | ||
2162 | // | ||
2163 | // No checking here of pB validity: after all, it shouldn't have been called by | ||
2164 | // the handler unless pB were on the list. | ||
2165 | //****************************************************************************** | ||
2166 | static inline int | ||
2167 | i2ServiceBoard ( i2eBordStrPtr pB ) | ||
2168 | { | ||
2169 | unsigned inmail; | ||
2170 | unsigned long flags; | ||
2171 | |||
2172 | |||
2173 | /* This should be atomic because of the way we are called... */ | ||
2174 | if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) { | ||
2175 | inmail = iiGetMail(pB); | ||
2176 | } | ||
2177 | pB->i2eStartMail = NO_MAIL_HERE; | ||
2178 | |||
2179 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail ); | ||
2180 | |||
2181 | if (inmail != NO_MAIL_HERE) { | ||
2182 | // If the board has gone fatal, nothing to do but hit a bit that will | ||
2183 | // alert foreground tasks to protest! | ||
2184 | if ( inmail & MB_FATAL_ERROR ) { | ||
2185 | pB->i2eFatal = 1; | ||
2186 | goto exit_i2ServiceBoard; | ||
2187 | } | ||
2188 | |||
2189 | /* Assuming no fatal condition, we proceed to do work */ | ||
2190 | if ( inmail & MB_IN_STUFFED ) { | ||
2191 | pB->i2eFifoInInts++; | ||
2192 | i2StripFifo(pB); /* There might be incoming packets */ | ||
2193 | } | ||
2194 | |||
2195 | if (inmail & MB_OUT_STRIPPED) { | ||
2196 | pB->i2eFifoOutInts++; | ||
2197 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
2198 | pB->i2eFifoRemains = pB->i2eFifoSize; | ||
2199 | pB->i2eWaitingForEmptyFifo = 0; | ||
2200 | write_unlock_irqrestore(&pB->write_fifo_spinlock, | ||
2201 | flags); | ||
2202 | |||
2203 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains ); | ||
2204 | |||
2205 | } | ||
2206 | serviceOutgoingFifo(pB); | ||
2207 | } | ||
2208 | |||
2209 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 ); | ||
2210 | |||
2211 | exit_i2ServiceBoard: | ||
2212 | |||
2213 | return 0; | ||
2214 | } | ||
diff --git a/drivers/char/ip2/i2lib.h b/drivers/char/ip2/i2lib.h deleted file mode 100644 index e559e9bac06d..000000000000 --- a/drivers/char/ip2/i2lib.h +++ /dev/null | |||
@@ -1,351 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Header file for high level library functions | ||
12 | * | ||
13 | *******************************************************************************/ | ||
14 | #ifndef I2LIB_H | ||
15 | #define I2LIB_H 1 | ||
16 | //------------------------------------------------------------------------------ | ||
17 | // I2LIB.H | ||
18 | // | ||
19 | // IntelliPort-II and IntelliPort-IIEX | ||
20 | // | ||
21 | // Defines, structure definitions, and external declarations for i2lib.c | ||
22 | //------------------------------------------------------------------------------ | ||
23 | //-------------------------------------- | ||
24 | // Mandatory Includes: | ||
25 | //-------------------------------------- | ||
26 | #include "ip2types.h" | ||
27 | #include "i2ellis.h" | ||
28 | #include "i2pack.h" | ||
29 | #include "i2cmd.h" | ||
30 | #include <linux/workqueue.h> | ||
31 | |||
32 | //------------------------------------------------------------------------------ | ||
33 | // i2ChanStr -- Channel Structure: | ||
34 | // Used to track per-channel information for the library routines using standard | ||
35 | // loadware. Note also, a pointer to an array of these structures is patched | ||
36 | // into the i2eBordStr (see i2ellis.h) | ||
37 | //------------------------------------------------------------------------------ | ||
38 | // | ||
39 | // If we make some limits on the maximum block sizes, we can avoid dealing with | ||
40 | // buffer wrap. The wrapping of the buffer is based on where the start of the | ||
41 | // packet is. Then there is always room for the packet contiguously. | ||
42 | // | ||
43 | // Maximum total length of an outgoing data or in-line command block. The limit | ||
44 | // of 36 on data is quite arbitrary and based more on DOS memory limitations | ||
45 | // than the board interface. However, for commands, the maximum packet length is | ||
46 | // MAX_CMD_PACK_SIZE, because the field size for the count is only a few bits | ||
47 | // (see I2PACK.H) in such packets. For data packets, the count field size is not | ||
48 | // the limiting factor. As of this writing, MAX_OBUF_BLOCK < MAX_CMD_PACK_SIZE, | ||
49 | // but be careful if wanting to modify either. | ||
50 | // | ||
51 | #define MAX_OBUF_BLOCK 36 | ||
52 | |||
53 | // Another note on maximum block sizes: we are buffering packets here. Data is | ||
54 | // put into the buffer (if there is room) regardless of the credits from the | ||
55 | // board. The board sends new credits whenever it has removed from his buffers a | ||
56 | // number of characters equal to 80% of total buffer size. (Of course, the total | ||
57 | // buffer size is what is reported when the very first set of flow control | ||
58 | // status packets are received from the board. Therefore, to be robust, you must | ||
59 | // always fill the board to at least 80% of the current credit limit, else you | ||
60 | // might not give it enough to trigger a new report. These conditions are | ||
61 | // obtained here so long as the maximum output block size is less than 20% the | ||
62 | // size of the board's output buffers. This is true at present by "coincidence" | ||
63 | // or "infernal knowledge": the board's output buffers are at least 700 bytes | ||
64 | // long (20% = 140 bytes, at least). The 80% figure is "official", so the safest | ||
65 | // strategy might be to trap the first flow control report and guarantee that | ||
66 | // the effective maxObufBlock is the minimum of MAX_OBUF_BLOCK and 20% of first | ||
67 | // reported buffer credit. | ||
68 | // | ||
69 | #define MAX_CBUF_BLOCK 6 // Maximum total length of a bypass command block | ||
70 | |||
71 | #define IBUF_SIZE 512 // character capacity of input buffer per channel | ||
72 | #define OBUF_SIZE 1024// character capacity of output buffer per channel | ||
73 | #define CBUF_SIZE 10 // character capacity of output bypass buffer | ||
74 | |||
75 | typedef struct _i2ChanStr | ||
76 | { | ||
77 | // First, back-pointers so that given a pointer to this structure, you can | ||
78 | // determine the correct board and channel number to reference, (say, when | ||
79 | // issuing commands, etc. (Note, channel number is in infl.hd.i2sChannel.) | ||
80 | |||
81 | int port_index; // Index of port in channel structure array attached | ||
82 | // to board structure. | ||
83 | PTTY pTTY; // Pointer to tty structure for port (OS specific) | ||
84 | USHORT validity; // Indicates whether the given channel has been | ||
85 | // initialized, really exists (or is a missing | ||
86 | // channel, e.g. channel 9 on an 8-port box.) | ||
87 | |||
88 | i2eBordStrPtr pMyBord; // Back-pointer to this channel's board structure | ||
89 | |||
90 | int wopen; // waiting fer carrier | ||
91 | |||
92 | int throttled; // Set if upper layer can take no data | ||
93 | |||
94 | int flags; // Defined in tty.h | ||
95 | |||
96 | PWAITQ open_wait; // Pointer for OS sleep function. | ||
97 | PWAITQ close_wait; // Pointer for OS sleep function. | ||
98 | PWAITQ delta_msr_wait;// Pointer for OS sleep function. | ||
99 | PWAITQ dss_now_wait; // Pointer for OS sleep function. | ||
100 | |||
101 | struct timer_list BookmarkTimer; // Used by i2DrainOutput | ||
102 | wait_queue_head_t pBookmarkWait; // Used by i2DrainOutput | ||
103 | |||
104 | int BaudBase; | ||
105 | int BaudDivisor; | ||
106 | |||
107 | USHORT ClosingDelay; | ||
108 | USHORT ClosingWaitTime; | ||
109 | |||
110 | volatile | ||
111 | flowIn infl; // This structure is initialized as a completely | ||
112 | // formed flow-control command packet, and as such | ||
113 | // has the channel number, also the capacity and | ||
114 | // "as-of" data needed continuously. | ||
115 | |||
116 | USHORT sinceLastFlow; // Counts the number of characters read from input | ||
117 | // buffers, since the last time flow control info | ||
118 | // was sent. | ||
119 | |||
120 | USHORT whenSendFlow; // Determines when new flow control is to be sent to | ||
121 | // the board. Note unlike earlier manifestations of | ||
122 | // the driver, these packets can be sent from | ||
123 | // in-place. | ||
124 | |||
125 | USHORT channelNeeds; // Bit map of important things which must be done | ||
126 | // for this channel. (See bits below ) | ||
127 | |||
128 | volatile | ||
129 | flowStat outfl; // Same type of structure is used to hold current | ||
130 | // flow control information used to control our | ||
131 | // output. "asof" is kept updated as data is sent, | ||
132 | // and "room" never goes to zero. | ||
133 | |||
134 | // The incoming ring buffer | ||
135 | // Unlike the outgoing buffers, this holds raw data, not packets. The two | ||
136 | // extra bytes are used to hold the byte-padding when there is room for an | ||
137 | // odd number of bytes before we must wrap. | ||
138 | // | ||
139 | UCHAR Ibuf[IBUF_SIZE + 2]; | ||
140 | volatile | ||
141 | USHORT Ibuf_stuff; // Stuffing index | ||
142 | volatile | ||
143 | USHORT Ibuf_strip; // Stripping index | ||
144 | |||
145 | // The outgoing ring-buffer: Holds Data and command packets. N.B., even | ||
146 | // though these are in the channel structure, the channel is also written | ||
147 | // here, the easier to send it to the fifo when ready. HOWEVER, individual | ||
148 | // packets here are NOT padded to even length: the routines for writing | ||
149 | // blocks to the fifo will pad to even byte counts. | ||
150 | // | ||
151 | UCHAR Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4]; | ||
152 | volatile | ||
153 | USHORT Obuf_stuff; // Stuffing index | ||
154 | volatile | ||
155 | USHORT Obuf_strip; // Stripping index | ||
156 | int Obuf_char_count; | ||
157 | |||
158 | // The outgoing bypass-command buffer. Unlike earlier manifestations, the | ||
159 | // flow control packets are sent directly from the structures. As above, the | ||
160 | // channel number is included in the packet, but they are NOT padded to even | ||
161 | // size. | ||
162 | // | ||
163 | UCHAR Cbuf[CBUF_SIZE+MAX_CBUF_BLOCK+2]; | ||
164 | volatile | ||
165 | USHORT Cbuf_stuff; // Stuffing index | ||
166 | volatile | ||
167 | USHORT Cbuf_strip; // Stripping index | ||
168 | |||
169 | // The temporary buffer for the Linux tty driver PutChar entry. | ||
170 | // | ||
171 | UCHAR Pbuf[MAX_OBUF_BLOCK - sizeof (i2DataHeader)]; | ||
172 | volatile | ||
173 | USHORT Pbuf_stuff; // Stuffing index | ||
174 | |||
175 | // The state of incoming data-set signals | ||
176 | // | ||
177 | USHORT dataSetIn; // Bit-mapped according to below. Also indicates | ||
178 | // whether a break has been detected since last | ||
179 | // inquiry. | ||
180 | |||
181 | // The state of outcoming data-set signals (as far as we can tell!) | ||
182 | // | ||
183 | USHORT dataSetOut; // Bit-mapped according to below. | ||
184 | |||
185 | // Most recent hot-key identifier detected | ||
186 | // | ||
187 | USHORT hotKeyIn; // Hot key as sent by the board, HOT_CLEAR indicates | ||
188 | // no hot key detected since last examined. | ||
189 | |||
190 | // Counter of outstanding requests for bookmarks | ||
191 | // | ||
192 | short bookMarks; // Number of outstanding bookmark requests, (+ive | ||
193 | // whenever a bookmark request if queued up, -ive | ||
194 | // whenever a bookmark is received). | ||
195 | |||
196 | // Misc options | ||
197 | // | ||
198 | USHORT channelOptions; // See below | ||
199 | |||
200 | // To store various incoming special packets | ||
201 | // | ||
202 | debugStat channelStatus; | ||
203 | cntStat channelRcount; | ||
204 | cntStat channelTcount; | ||
205 | failStat channelFail; | ||
206 | |||
207 | // To store the last values for line characteristics we sent to the board. | ||
208 | // | ||
209 | int speed; | ||
210 | |||
211 | int flush_flags; | ||
212 | |||
213 | void (*trace)(unsigned short,unsigned char,unsigned char,unsigned long,...); | ||
214 | |||
215 | /* | ||
216 | * Kernel counters for the 4 input interrupts | ||
217 | */ | ||
218 | struct async_icount icount; | ||
219 | |||
220 | /* | ||
221 | * Task queues for processing input packets from the board. | ||
222 | */ | ||
223 | struct work_struct tqueue_input; | ||
224 | struct work_struct tqueue_status; | ||
225 | struct work_struct tqueue_hangup; | ||
226 | |||
227 | rwlock_t Ibuf_spinlock; | ||
228 | rwlock_t Obuf_spinlock; | ||
229 | rwlock_t Cbuf_spinlock; | ||
230 | rwlock_t Pbuf_spinlock; | ||
231 | |||
232 | } i2ChanStr, *i2ChanStrPtr; | ||
233 | |||
234 | //--------------------------------------------------- | ||
235 | // Manifests and bit-maps for elements in i2ChanStr | ||
236 | //--------------------------------------------------- | ||
237 | // | ||
238 | // flush flags | ||
239 | // | ||
240 | #define STARTFL_FLAG 1 | ||
241 | #define STOPFL_FLAG 2 | ||
242 | |||
243 | // validity | ||
244 | // | ||
245 | #define CHANNEL_MAGIC_BITS 0xff00 | ||
246 | #define CHANNEL_MAGIC 0x5300 // (validity & CHANNEL_MAGIC_BITS) == | ||
247 | // CHANNEL_MAGIC --> structure good | ||
248 | |||
249 | #define CHANNEL_SUPPORT 0x0001 // Indicates channel is supported, exists, | ||
250 | // and passed P.O.S.T. | ||
251 | |||
252 | // channelNeeds | ||
253 | // | ||
254 | #define NEED_FLOW 1 // Indicates flow control has been queued | ||
255 | #define NEED_INLINE 2 // Indicates inline commands or data queued | ||
256 | #define NEED_BYPASS 4 // Indicates bypass commands queued | ||
257 | #define NEED_CREDIT 8 // Indicates would be sending except has not sufficient | ||
258 | // credit. The data is still in the channel structure, | ||
259 | // but the channel is not enqueued in the board | ||
260 | // structure again until there is a credit received from | ||
261 | // the board. | ||
262 | |||
263 | // dataSetIn (Also the bits for i2GetStatus return value) | ||
264 | // | ||
265 | #define I2_DCD 1 | ||
266 | #define I2_CTS 2 | ||
267 | #define I2_DSR 4 | ||
268 | #define I2_RI 8 | ||
269 | |||
270 | // dataSetOut (Also the bits for i2GetStatus return value) | ||
271 | // | ||
272 | #define I2_DTR 1 | ||
273 | #define I2_RTS 2 | ||
274 | |||
275 | // i2GetStatus() can optionally clear these bits | ||
276 | // | ||
277 | #define I2_BRK 0x10 // A break was detected | ||
278 | #define I2_PAR 0x20 // A parity error was received | ||
279 | #define I2_FRA 0x40 // A framing error was received | ||
280 | #define I2_OVR 0x80 // An overrun error was received | ||
281 | |||
282 | // i2GetStatus() automatically clears these bits */ | ||
283 | // | ||
284 | #define I2_DDCD 0x100 // DCD changed from its former value | ||
285 | #define I2_DCTS 0x200 // CTS changed from its former value | ||
286 | #define I2_DDSR 0x400 // DSR changed from its former value | ||
287 | #define I2_DRI 0x800 // RI changed from its former value | ||
288 | |||
289 | // hotKeyIn | ||
290 | // | ||
291 | #define HOT_CLEAR 0x1322 // Indicates that no hot-key has been detected | ||
292 | |||
293 | // channelOptions | ||
294 | // | ||
295 | #define CO_NBLOCK_WRITE 1 // Writes don't block waiting for buffer. (Default | ||
296 | // is, they do wait.) | ||
297 | |||
298 | // fcmodes | ||
299 | // | ||
300 | #define I2_OUTFLOW_CTS 0x0001 | ||
301 | #define I2_INFLOW_RTS 0x0002 | ||
302 | #define I2_INFLOW_DSR 0x0004 | ||
303 | #define I2_INFLOW_DTR 0x0008 | ||
304 | #define I2_OUTFLOW_DSR 0x0010 | ||
305 | #define I2_OUTFLOW_DTR 0x0020 | ||
306 | #define I2_OUTFLOW_XON 0x0040 | ||
307 | #define I2_OUTFLOW_XANY 0x0080 | ||
308 | #define I2_INFLOW_XON 0x0100 | ||
309 | |||
310 | #define I2_CRTSCTS (I2_OUTFLOW_CTS|I2_INFLOW_RTS) | ||
311 | #define I2_IXANY_MODE (I2_OUTFLOW_XON|I2_OUTFLOW_XANY) | ||
312 | |||
313 | //------------------------------------------- | ||
314 | // Macros used from user level like functions | ||
315 | //------------------------------------------- | ||
316 | |||
317 | // Macros to set and clear channel options | ||
318 | // | ||
319 | #define i2SetOption(pCh, option) pCh->channelOptions |= option | ||
320 | #define i2ClrOption(pCh, option) pCh->channelOptions &= ~option | ||
321 | |||
322 | // Macro to set fatal-error trap | ||
323 | // | ||
324 | #define i2SetFatalTrap(pB, routine) pB->i2eFatalTrap = routine | ||
325 | |||
326 | //-------------------------------------------- | ||
327 | // Declarations and prototypes for i2lib.c | ||
328 | //-------------------------------------------- | ||
329 | // | ||
330 | static int i2InitChannels(i2eBordStrPtr, int, i2ChanStrPtr); | ||
331 | static int i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...); | ||
332 | static int i2GetStatus(i2ChanStrPtr, int); | ||
333 | static int i2Input(i2ChanStrPtr); | ||
334 | static int i2InputFlush(i2ChanStrPtr); | ||
335 | static int i2Output(i2ChanStrPtr, const char *, int); | ||
336 | static int i2OutputFree(i2ChanStrPtr); | ||
337 | static int i2ServiceBoard(i2eBordStrPtr); | ||
338 | static void i2DrainOutput(i2ChanStrPtr, int); | ||
339 | |||
340 | #ifdef IP2DEBUG_TRACE | ||
341 | void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...); | ||
342 | #else | ||
343 | #define ip2trace(a,b,c,d...) do {} while (0) | ||
344 | #endif | ||
345 | |||
346 | // Argument to i2QueueCommands | ||
347 | // | ||
348 | #define C_IN_LINE 1 | ||
349 | #define C_BYPASS 0 | ||
350 | |||
351 | #endif // I2LIB_H | ||
diff --git a/drivers/char/ip2/i2pack.h b/drivers/char/ip2/i2pack.h deleted file mode 100644 index 00342a677c90..000000000000 --- a/drivers/char/ip2/i2pack.h +++ /dev/null | |||
@@ -1,364 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Definitions of the packets used to transfer data and commands | ||
12 | * Host <--> Board. Information provided here is only applicable | ||
13 | * when the standard loadware is active. | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | #ifndef I2PACK_H | ||
17 | #define I2PACK_H 1 | ||
18 | |||
19 | //----------------------------------------------- | ||
20 | // Revision History: | ||
21 | // | ||
22 | // 10 October 1991 MAG First draft | ||
23 | // 24 February 1992 MAG Additions for 1.4.x loadware | ||
24 | // 11 March 1992 MAG New status packets | ||
25 | // | ||
26 | //----------------------------------------------- | ||
27 | |||
28 | //------------------------------------------------------------------------------ | ||
29 | // Packet Formats: | ||
30 | // | ||
31 | // Information passes between the host and board through the FIFO in packets. | ||
32 | // These have headers which indicate the type of packet. Because the fifo data | ||
33 | // path may be 16-bits wide, the protocol is constrained such that each packet | ||
34 | // is always padded to an even byte count. (The lower-level interface routines | ||
35 | // -- i2ellis.c -- are designed to do this). | ||
36 | // | ||
37 | // The sender (be it host or board) must place some number of complete packets | ||
38 | // in the fifo, then place a message in the mailbox that packets are available. | ||
39 | // Placing such a message interrupts the "receiver" (be it board or host), who | ||
40 | // reads the mailbox message and determines that there are incoming packets | ||
41 | // ready. Since there are no partial packets, and the length of a packet is | ||
42 | // given in the header, the remainder of the packet can be read without checking | ||
43 | // for FIFO empty condition. The process is repeated, packet by packet, until | ||
44 | // the incoming FIFO is empty. Then the receiver uses the outbound mailbox to | ||
45 | // signal the board that it has read the data. Only then can the sender place | ||
46 | // additional data in the fifo. | ||
47 | //------------------------------------------------------------------------------ | ||
48 | // | ||
49 | //------------------------------------------------ | ||
50 | // Definition of Packet Header Area | ||
51 | //------------------------------------------------ | ||
52 | // | ||
53 | // Caution: these only define header areas. In actual use the data runs off | ||
54 | // beyond the end of these structures. | ||
55 | // | ||
56 | // Since these structures are based on sequences of bytes which go to the board, | ||
57 | // there cannot be ANY padding between the elements. | ||
58 | #pragma pack(1) | ||
59 | |||
60 | //---------------------------- | ||
61 | // DATA PACKETS | ||
62 | //---------------------------- | ||
63 | |||
64 | typedef struct _i2DataHeader | ||
65 | { | ||
66 | unsigned char i2sChannel; /* The channel number: 0-255 */ | ||
67 | |||
68 | // -- Bitfields are allocated LSB first -- | ||
69 | |||
70 | // For incoming data, indicates whether this is an ordinary packet or a | ||
71 | // special one (e.g., hot key hit). | ||
72 | unsigned i2sId : 2 __attribute__ ((__packed__)); | ||
73 | |||
74 | // For tagging data packets. There are flush commands which flush only data | ||
75 | // packets bearing a particular tag. (used in implementing IntelliView and | ||
76 | // IntelliPrint). THE TAG VALUE 0xf is RESERVED and must not be used (it has | ||
77 | // meaning internally to the loadware). | ||
78 | unsigned i2sTag : 4; | ||
79 | |||
80 | // These two bits determine the type of packet sent/received. | ||
81 | unsigned i2sType : 2; | ||
82 | |||
83 | // The count of data to follow: does not include the possible additional | ||
84 | // padding byte. MAXIMUM COUNT: 4094. The top four bits must be 0. | ||
85 | unsigned short i2sCount; | ||
86 | |||
87 | } i2DataHeader, *i2DataHeaderPtr; | ||
88 | |||
89 | // Structure is immediately followed by the data, proper. | ||
90 | |||
91 | //---------------------------- | ||
92 | // NON-DATA PACKETS | ||
93 | //---------------------------- | ||
94 | |||
95 | typedef struct _i2CmdHeader | ||
96 | { | ||
97 | unsigned char i2sChannel; // The channel number: 0-255 (Except where noted | ||
98 | // - see below | ||
99 | |||
100 | // Number of bytes of commands, status or whatever to follow | ||
101 | unsigned i2sCount : 6; | ||
102 | |||
103 | // These two bits determine the type of packet sent/received. | ||
104 | unsigned i2sType : 2; | ||
105 | |||
106 | } i2CmdHeader, *i2CmdHeaderPtr; | ||
107 | |||
108 | // Structure is immediately followed by the applicable data. | ||
109 | |||
110 | //--------------------------------------- | ||
111 | // Flow Control Packets (Outbound) | ||
112 | //--------------------------------------- | ||
113 | |||
114 | // One type of outbound command packet is so important that the entire structure | ||
115 | // is explicitly defined here. That is the flow-control packet. This is never | ||
116 | // sent by user-level code (as would be the commands to raise/lower DTR, for | ||
117 | // example). These are only sent by the library routines in response to reading | ||
118 | // incoming data into the buffers. | ||
119 | // | ||
120 | // The parameters inside the command block are maintained in place, then the | ||
121 | // block is sent at the appropriate time. | ||
122 | |||
123 | typedef struct _flowIn | ||
124 | { | ||
125 | i2CmdHeader hd; // Channel #, count, type (see above) | ||
126 | unsigned char fcmd; // The flow control command (37) | ||
127 | unsigned short asof; // As of byte number "asof" (LSB first!) I have room | ||
128 | // for "room" bytes | ||
129 | unsigned short room; | ||
130 | } flowIn, *flowInPtr; | ||
131 | |||
132 | //---------------------------------------- | ||
133 | // (Incoming) Status Packets | ||
134 | //---------------------------------------- | ||
135 | |||
136 | // Incoming packets which are non-data packets are status packets. In this case, | ||
137 | // the channel number in the header is unimportant. What follows are one or more | ||
138 | // sub-packets, the first word of which consists of the channel (first or low | ||
139 | // byte) and the status indicator (second or high byte), followed by possibly | ||
140 | // more data. | ||
141 | |||
142 | #define STAT_CTS_UP 0 /* CTS raised (no other bytes) */ | ||
143 | #define STAT_CTS_DN 1 /* CTS dropped (no other bytes) */ | ||
144 | #define STAT_DCD_UP 2 /* DCD raised (no other bytes) */ | ||
145 | #define STAT_DCD_DN 3 /* DCD dropped (no other bytes) */ | ||
146 | #define STAT_DSR_UP 4 /* DSR raised (no other bytes) */ | ||
147 | #define STAT_DSR_DN 5 /* DSR dropped (no other bytes) */ | ||
148 | #define STAT_RI_UP 6 /* RI raised (no other bytes) */ | ||
149 | #define STAT_RI_DN 7 /* RI dropped (no other bytes) */ | ||
150 | #define STAT_BRK_DET 8 /* BRK detect (no other bytes) */ | ||
151 | #define STAT_FLOW 9 /* Flow control(-- more: see below */ | ||
152 | #define STAT_BMARK 10 /* Bookmark (no other bytes) | ||
153 | * Bookmark is sent as a response to | ||
154 | * a command 60: request for bookmark | ||
155 | */ | ||
156 | #define STAT_STATUS 11 /* Special packet: see below */ | ||
157 | #define STAT_TXCNT 12 /* Special packet: see below */ | ||
158 | #define STAT_RXCNT 13 /* Special packet: see below */ | ||
159 | #define STAT_BOXIDS 14 /* Special packet: see below */ | ||
160 | #define STAT_HWFAIL 15 /* Special packet: see below */ | ||
161 | |||
162 | #define STAT_MOD_ERROR 0xc0 | ||
163 | #define STAT_MODEM 0xc0/* If status & STAT_MOD_ERROR: | ||
164 | * == STAT_MODEM, then this is a modem | ||
165 | * status packet, given in response to a | ||
166 | * CMD_DSS_NOW command. | ||
167 | * The low nibble has each data signal: | ||
168 | */ | ||
169 | #define STAT_MOD_DCD 0x8 | ||
170 | #define STAT_MOD_RI 0x4 | ||
171 | #define STAT_MOD_DSR 0x2 | ||
172 | #define STAT_MOD_CTS 0x1 | ||
173 | |||
174 | #define STAT_ERROR 0x80/* If status & STAT_MOD_ERROR | ||
175 | * == STAT_ERROR, then | ||
176 | * sort of error on the channel. | ||
177 | * The remaining seven bits indicate | ||
178 | * what sort of error it is. | ||
179 | */ | ||
180 | /* The low three bits indicate parity, framing, or overrun errors */ | ||
181 | |||
182 | #define STAT_E_PARITY 4 /* Parity error */ | ||
183 | #define STAT_E_FRAMING 2 /* Framing error */ | ||
184 | #define STAT_E_OVERRUN 1 /* (uxart) overrun error */ | ||
185 | |||
186 | //--------------------------------------- | ||
187 | // STAT_FLOW packets | ||
188 | //--------------------------------------- | ||
189 | |||
190 | typedef struct _flowStat | ||
191 | { | ||
192 | unsigned short asof; | ||
193 | unsigned short room; | ||
194 | }flowStat, *flowStatPtr; | ||
195 | |||
196 | // flowStat packets are received from the board to regulate the flow of outgoing | ||
197 | // data. A local copy of this structure is also kept to track the amount of | ||
198 | // credits used and credits remaining. "room" is the amount of space in the | ||
199 | // board's buffers, "as of" having received a certain byte number. When sending | ||
200 | // data to the fifo, you must calculate how much buffer space your packet will | ||
201 | // use. Add this to the current "asof" and subtract it from the current "room". | ||
202 | // | ||
203 | // The calculation for the board's buffer is given by CREDIT_USAGE, where size | ||
204 | // is the un-rounded count of either data characters or command characters. | ||
205 | // (Which is to say, the count rounded up, plus two). | ||
206 | |||
207 | #define CREDIT_USAGE(size) (((size) + 3) & ~1) | ||
208 | |||
209 | //--------------------------------------- | ||
210 | // STAT_STATUS packets | ||
211 | //--------------------------------------- | ||
212 | |||
213 | typedef struct _debugStat | ||
214 | { | ||
215 | unsigned char d_ccsr; | ||
216 | unsigned char d_txinh; | ||
217 | unsigned char d_stat1; | ||
218 | unsigned char d_stat2; | ||
219 | } debugStat, *debugStatPtr; | ||
220 | |||
221 | // debugStat packets are sent to the host in response to a CMD_GET_STATUS | ||
222 | // command. Each byte is bit-mapped as described below: | ||
223 | |||
224 | #define D_CCSR_XON 2 /* Has received XON, ready to transmit */ | ||
225 | #define D_CCSR_XOFF 4 /* Has received XOFF, not transmitting */ | ||
226 | #define D_CCSR_TXENAB 8 /* Transmitter is enabled */ | ||
227 | #define D_CCSR_RXENAB 0x80 /* Receiver is enabled */ | ||
228 | |||
229 | #define D_TXINH_BREAK 1 /* We are sending a break */ | ||
230 | #define D_TXINH_EMPTY 2 /* No data to send */ | ||
231 | #define D_TXINH_SUSP 4 /* Output suspended via command 57 */ | ||
232 | #define D_TXINH_CMD 8 /* We are processing an in-line command */ | ||
233 | #define D_TXINH_LCD 0x10 /* LCD diagnostics are running */ | ||
234 | #define D_TXINH_PAUSE 0x20 /* We are processing a PAUSE command */ | ||
235 | #define D_TXINH_DCD 0x40 /* DCD is low, preventing transmission */ | ||
236 | #define D_TXINH_DSR 0x80 /* DSR is low, preventing transmission */ | ||
237 | |||
238 | #define D_STAT1_TXEN 1 /* Transmit INTERRUPTS enabled */ | ||
239 | #define D_STAT1_RXEN 2 /* Receiver INTERRUPTS enabled */ | ||
240 | #define D_STAT1_MDEN 4 /* Modem (data set sigs) interrupts enabled */ | ||
241 | #define D_STAT1_RLM 8 /* Remote loopback mode selected */ | ||
242 | #define D_STAT1_LLM 0x10 /* Local internal loopback mode selected */ | ||
243 | #define D_STAT1_CTS 0x20 /* CTS is low, preventing transmission */ | ||
244 | #define D_STAT1_DTR 0x40 /* DTR is low, to stop remote transmission */ | ||
245 | #define D_STAT1_RTS 0x80 /* RTS is low, to stop remote transmission */ | ||
246 | |||
247 | #define D_STAT2_TXMT 1 /* Transmit buffers are all empty */ | ||
248 | #define D_STAT2_RXMT 2 /* Receive buffers are all empty */ | ||
249 | #define D_STAT2_RXINH 4 /* Loadware has tried to inhibit remote | ||
250 | * transmission: dropped DTR, sent XOFF, | ||
251 | * whatever... | ||
252 | */ | ||
253 | #define D_STAT2_RXFLO 8 /* Loadware can send no more data to host | ||
254 | * until it receives a flow-control packet | ||
255 | */ | ||
256 | //----------------------------------------- | ||
257 | // STAT_TXCNT and STAT_RXCNT packets | ||
258 | //---------------------------------------- | ||
259 | |||
260 | typedef struct _cntStat | ||
261 | { | ||
262 | unsigned short cs_time; // (Assumes host is little-endian!) | ||
263 | unsigned short cs_count; | ||
264 | } cntStat, *cntStatPtr; | ||
265 | |||
266 | // These packets are sent in response to a CMD_GET_RXCNT or a CMD_GET_TXCNT | ||
267 | // bypass command. cs_time is a running 1 Millisecond counter which acts as a | ||
268 | // time stamp. cs_count is a running counter of data sent or received from the | ||
269 | // uxarts. (Not including data added by the chip itself, as with CRLF | ||
270 | // processing). | ||
271 | //------------------------------------------ | ||
272 | // STAT_HWFAIL packets | ||
273 | //------------------------------------------ | ||
274 | |||
275 | typedef struct _failStat | ||
276 | { | ||
277 | unsigned char fs_written; | ||
278 | unsigned char fs_read; | ||
279 | unsigned short fs_address; | ||
280 | } failStat, *failStatPtr; | ||
281 | |||
282 | // This packet is sent whenever the on-board diagnostic process detects an | ||
283 | // error. At startup, this process is dormant. The host can wake it up by | ||
284 | // issuing the bypass command CMD_HW_TEST. The process runs at low priority and | ||
285 | // performs continuous hardware verification; writing data to certain on-board | ||
286 | // registers, reading it back, and comparing. If it detects an error, this | ||
287 | // packet is sent to the host, and the process goes dormant again until the host | ||
288 | // sends another CMD_HW_TEST. It then continues with the next register to be | ||
289 | // tested. | ||
290 | |||
291 | //------------------------------------------------------------------------------ | ||
292 | // Macros to deal with the headers more easily! Note that these are defined so | ||
293 | // they may be used as "left" as well as "right" expressions. | ||
294 | //------------------------------------------------------------------------------ | ||
295 | |||
296 | // Given a pointer to the packet, reference the channel number | ||
297 | // | ||
298 | #define CHANNEL_OF(pP) ((i2DataHeaderPtr)(pP))->i2sChannel | ||
299 | |||
300 | // Given a pointer to the packet, reference the Packet type | ||
301 | // | ||
302 | #define PTYPE_OF(pP) ((i2DataHeaderPtr)(pP))->i2sType | ||
303 | |||
304 | // The possible types of packets | ||
305 | // | ||
306 | #define PTYPE_DATA 0 /* Host <--> Board */ | ||
307 | #define PTYPE_BYPASS 1 /* Host ---> Board */ | ||
308 | #define PTYPE_INLINE 2 /* Host ---> Board */ | ||
309 | #define PTYPE_STATUS 2 /* Host <--- Board */ | ||
310 | |||
311 | // Given a pointer to a Data packet, reference the Tag | ||
312 | // | ||
313 | #define TAG_OF(pP) ((i2DataHeaderPtr)(pP))->i2sTag | ||
314 | |||
315 | // Given a pointer to a Data packet, reference the data i.d. | ||
316 | // | ||
317 | #define ID_OF(pP) ((i2DataHeaderPtr)(pP))->i2sId | ||
318 | |||
319 | // The possible types of ID's | ||
320 | // | ||
321 | #define ID_ORDINARY_DATA 0 | ||
322 | #define ID_HOT_KEY 1 | ||
323 | |||
324 | // Given a pointer to a Data packet, reference the count | ||
325 | // | ||
326 | #define DATA_COUNT_OF(pP) ((i2DataHeaderPtr)(pP))->i2sCount | ||
327 | |||
328 | // Given a pointer to a Data packet, reference the beginning of data | ||
329 | // | ||
330 | #define DATA_OF(pP) &((unsigned char *)(pP))[4] // 4 = size of header | ||
331 | |||
332 | // Given a pointer to a Non-Data packet, reference the count | ||
333 | // | ||
334 | #define CMD_COUNT_OF(pP) ((i2CmdHeaderPtr)(pP))->i2sCount | ||
335 | |||
336 | #define MAX_CMD_PACK_SIZE 62 // Maximum size of such a count | ||
337 | |||
338 | // Given a pointer to a Non-Data packet, reference the beginning of data | ||
339 | // | ||
340 | #define CMD_OF(pP) &((unsigned char *)(pP))[2] // 2 = size of header | ||
341 | |||
342 | //-------------------------------- | ||
343 | // MailBox Bits: | ||
344 | //-------------------------------- | ||
345 | |||
346 | //-------------------------- | ||
347 | // Outgoing (host to board) | ||
348 | //-------------------------- | ||
349 | // | ||
350 | #define MB_OUT_STUFFED 0x80 // Host has placed output in fifo | ||
351 | #define MB_IN_STRIPPED 0x40 // Host has read in all input from fifo | ||
352 | |||
353 | //-------------------------- | ||
354 | // Incoming (board to host) | ||
355 | //-------------------------- | ||
356 | // | ||
357 | #define MB_IN_STUFFED 0x80 // Board has placed input in fifo | ||
358 | #define MB_OUT_STRIPPED 0x40 // Board has read all output from fifo | ||
359 | #define MB_FATAL_ERROR 0x20 // Board has encountered a fatal error | ||
360 | |||
361 | #pragma pack() // Reset padding to command-line default | ||
362 | |||
363 | #endif // I2PACK_H | ||
364 | |||
diff --git a/drivers/char/ip2/ip2.h b/drivers/char/ip2/ip2.h deleted file mode 100644 index 936ccc533949..000000000000 --- a/drivers/char/ip2/ip2.h +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Driver constants for configuration and tuning | ||
12 | * | ||
13 | * NOTES: | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | #ifndef IP2_H | ||
17 | #define IP2_H | ||
18 | |||
19 | #include "ip2types.h" | ||
20 | #include "i2cmd.h" | ||
21 | |||
22 | /*************/ | ||
23 | /* Constants */ | ||
24 | /*************/ | ||
25 | |||
26 | /* Device major numbers - since version 2.0.26. */ | ||
27 | #define IP2_TTY_MAJOR 71 | ||
28 | #define IP2_CALLOUT_MAJOR 72 | ||
29 | #define IP2_IPL_MAJOR 73 | ||
30 | |||
31 | /* Board configuration array. | ||
32 | * This array defines the hardware irq and address for up to IP2_MAX_BOARDS | ||
33 | * (4 supported per ip2_types.h) ISA board addresses and irqs MUST be specified, | ||
34 | * PCI and EISA boards are probed for and automagicly configed | ||
35 | * iff the addresses are set to 1 and 2 respectivily. | ||
36 | * 0x0100 - 0x03f0 == ISA | ||
37 | * 1 == PCI | ||
38 | * 2 == EISA | ||
39 | * 0 == (skip this board) | ||
40 | * This array defines the hardware addresses for them. Special | ||
41 | * addresses are EISA and PCI which go sniffing for boards. | ||
42 | |||
43 | * In a multiboard system the position in the array determines which port | ||
44 | * devices are assigned to each board: | ||
45 | * board 0 is assigned ttyF0.. to ttyF63, | ||
46 | * board 1 is assigned ttyF64 to ttyF127, | ||
47 | * board 2 is assigned ttyF128 to ttyF191, | ||
48 | * board 3 is assigned ttyF192 to ttyF255. | ||
49 | * | ||
50 | * In PCI and EISA bus systems each range is mapped to card in | ||
51 | * monotonically increasing slot number order, ISA position is as specified | ||
52 | * here. | ||
53 | |||
54 | * If the irqs are ALL set to 0,0,0,0 all boards operate in | ||
55 | * polled mode. For interrupt operation ISA boards require that the IRQ be | ||
56 | * specified, while PCI and EISA boards any nonzero entry | ||
57 | * will enable interrupts using the BIOS configured irq for the board. | ||
58 | * An invalid irq entry will default to polled mode for that card and print | ||
59 | * console warning. | ||
60 | |||
61 | * When the driver is loaded as a module these setting can be overridden on the | ||
62 | * modprobe command line or on an option line in /etc/modprobe.conf. | ||
63 | * If the driver is built-in the configuration must be | ||
64 | * set here for ISA cards and address set to 1 and 2 for PCI and EISA. | ||
65 | * | ||
66 | * Here is an example that shows most if not all possibe combinations: | ||
67 | |||
68 | *static ip2config_t ip2config = | ||
69 | *{ | ||
70 | * {11,1,0,0}, // irqs | ||
71 | * { // Addresses | ||
72 | * 0x0308, // Board 0, ttyF0 - ttyF63// ISA card at io=0x308, irq=11 | ||
73 | * 0x0001, // Board 1, ttyF64 - ttyF127//PCI card configured by BIOS | ||
74 | * 0x0000, // Board 2, ttyF128 - ttyF191// Slot skipped | ||
75 | * 0x0002 // Board 3, ttyF192 - ttyF255//EISA card configured by BIOS | ||
76 | * // but polled not irq driven | ||
77 | * } | ||
78 | *}; | ||
79 | */ | ||
80 | |||
81 | /* this structure is zeroed out because the suggested method is to configure | ||
82 | * the driver as a module, set up the parameters with an options line in | ||
83 | * /etc/modprobe.conf and load with modprobe or kmod, the kernel | ||
84 | * module loader | ||
85 | */ | ||
86 | |||
87 | /* This structure is NOW always initialized when the driver is initialized. | ||
88 | * Compiled in defaults MUST be added to the io and irq arrays in | ||
89 | * ip2.c. Those values are configurable from insmod parameters in the | ||
90 | * case of modules or from command line parameters (ip2=io,irq) when | ||
91 | * compiled in. | ||
92 | */ | ||
93 | |||
94 | static ip2config_t ip2config = | ||
95 | { | ||
96 | {0,0,0,0}, // irqs | ||
97 | { // Addresses | ||
98 | /* Do NOT set compile time defaults HERE! Use the arrays in | ||
99 | ip2.c! These WILL be overwritten! =mhw= */ | ||
100 | 0x0000, // Board 0, ttyF0 - ttyF63 | ||
101 | 0x0000, // Board 1, ttyF64 - ttyF127 | ||
102 | 0x0000, // Board 2, ttyF128 - ttyF191 | ||
103 | 0x0000 // Board 3, ttyF192 - ttyF255 | ||
104 | } | ||
105 | }; | ||
106 | |||
107 | #endif | ||
diff --git a/drivers/char/ip2/ip2ioctl.h b/drivers/char/ip2/ip2ioctl.h deleted file mode 100644 index aa0a9da85e05..000000000000 --- a/drivers/char/ip2/ip2ioctl.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Driver constants for configuration and tuning | ||
12 | * | ||
13 | * NOTES: | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | |||
17 | #ifndef IP2IOCTL_H | ||
18 | #define IP2IOCTL_H | ||
19 | |||
20 | //************* | ||
21 | //* Constants * | ||
22 | //************* | ||
23 | |||
24 | // High baud rates (if not defined elsewhere. | ||
25 | #ifndef B153600 | ||
26 | # define B153600 0010005 | ||
27 | #endif | ||
28 | #ifndef B307200 | ||
29 | # define B307200 0010006 | ||
30 | #endif | ||
31 | #ifndef B921600 | ||
32 | # define B921600 0010007 | ||
33 | #endif | ||
34 | |||
35 | #endif | ||
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c deleted file mode 100644 index ea7a8fb08283..000000000000 --- a/drivers/char/ip2/ip2main.c +++ /dev/null | |||
@@ -1,3234 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport | ||
8 | * serial I/O controllers. | ||
9 | * | ||
10 | * DESCRIPTION: Mainline code for the device driver | ||
11 | * | ||
12 | *******************************************************************************/ | ||
13 | // ToDo: | ||
14 | // | ||
15 | // Fix the immediate DSS_NOW problem. | ||
16 | // Work over the channel stats return logic in ip2_ipl_ioctl so they | ||
17 | // make sense for all 256 possible channels and so the user space | ||
18 | // utilities will compile and work properly. | ||
19 | // | ||
20 | // Done: | ||
21 | // | ||
22 | // 1.2.14 /\/\|=mhw=|\/\/ | ||
23 | // Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts. | ||
24 | // Changed the definition of ip2trace to be more consistent with kernel style | ||
25 | // Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates | ||
26 | // | ||
27 | // 1.2.13 /\/\|=mhw=|\/\/ | ||
28 | // DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform | ||
29 | // to agreed devfs serial device naming convention. | ||
30 | // | ||
31 | // 1.2.12 /\/\|=mhw=|\/\/ | ||
32 | // Cleaned up some remove queue cut and paste errors | ||
33 | // | ||
34 | // 1.2.11 /\/\|=mhw=|\/\/ | ||
35 | // Clean up potential NULL pointer dereferences | ||
36 | // Clean up devfs registration | ||
37 | // Add kernel command line parsing for io and irq | ||
38 | // Compile defaults for io and irq are now set in ip2.c not ip2.h! | ||
39 | // Reworked poll_only hack for explicit parameter setting | ||
40 | // You must now EXPLICITLY set poll_only = 1 or set all irqs to 0 | ||
41 | // Merged ip2_loadmain and old_ip2_init | ||
42 | // Converted all instances of interruptible_sleep_on into queue calls | ||
43 | // Most of these had no race conditions but better to clean up now | ||
44 | // | ||
45 | // 1.2.10 /\/\|=mhw=|\/\/ | ||
46 | // Fixed the bottom half interrupt handler and enabled USE_IQI | ||
47 | // to split the interrupt handler into a formal top-half / bottom-half | ||
48 | // Fixed timing window on high speed processors that queued messages to | ||
49 | // the outbound mail fifo faster than the board could handle. | ||
50 | // | ||
51 | // 1.2.9 | ||
52 | // Four box EX was barfing on >128k kmalloc, made structure smaller by | ||
53 | // reducing output buffer size | ||
54 | // | ||
55 | // 1.2.8 | ||
56 | // Device file system support (MHW) | ||
57 | // | ||
58 | // 1.2.7 | ||
59 | // Fixed | ||
60 | // Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules | ||
61 | // | ||
62 | // 1.2.6 | ||
63 | //Fixes DCD problems | ||
64 | // DCD was not reported when CLOCAL was set on call to TIOCMGET | ||
65 | // | ||
66 | //Enhancements: | ||
67 | // TIOCMGET requests and waits for status return | ||
68 | // No DSS interrupts enabled except for DCD when needed | ||
69 | // | ||
70 | // For internal use only | ||
71 | // | ||
72 | //#define IP2DEBUG_INIT | ||
73 | //#define IP2DEBUG_OPEN | ||
74 | //#define IP2DEBUG_WRITE | ||
75 | //#define IP2DEBUG_READ | ||
76 | //#define IP2DEBUG_IOCTL | ||
77 | //#define IP2DEBUG_IPL | ||
78 | |||
79 | //#define IP2DEBUG_TRACE | ||
80 | //#define DEBUG_FIFO | ||
81 | |||
82 | /************/ | ||
83 | /* Includes */ | ||
84 | /************/ | ||
85 | |||
86 | #include <linux/ctype.h> | ||
87 | #include <linux/string.h> | ||
88 | #include <linux/fcntl.h> | ||
89 | #include <linux/errno.h> | ||
90 | #include <linux/module.h> | ||
91 | #include <linux/signal.h> | ||
92 | #include <linux/sched.h> | ||
93 | #include <linux/timer.h> | ||
94 | #include <linux/interrupt.h> | ||
95 | #include <linux/pci.h> | ||
96 | #include <linux/mm.h> | ||
97 | #include <linux/slab.h> | ||
98 | #include <linux/major.h> | ||
99 | #include <linux/wait.h> | ||
100 | #include <linux/device.h> | ||
101 | #include <linux/mutex.h> | ||
102 | #include <linux/firmware.h> | ||
103 | #include <linux/platform_device.h> | ||
104 | |||
105 | #include <linux/tty.h> | ||
106 | #include <linux/tty_flip.h> | ||
107 | #include <linux/termios.h> | ||
108 | #include <linux/tty_driver.h> | ||
109 | #include <linux/serial.h> | ||
110 | #include <linux/ptrace.h> | ||
111 | #include <linux/ioport.h> | ||
112 | |||
113 | #include <linux/cdk.h> | ||
114 | #include <linux/comstats.h> | ||
115 | #include <linux/delay.h> | ||
116 | #include <linux/bitops.h> | ||
117 | |||
118 | #include <asm/system.h> | ||
119 | #include <asm/io.h> | ||
120 | #include <asm/irq.h> | ||
121 | |||
122 | #include <linux/vmalloc.h> | ||
123 | #include <linux/init.h> | ||
124 | |||
125 | #include <asm/uaccess.h> | ||
126 | |||
127 | #include "ip2types.h" | ||
128 | #include "ip2trace.h" | ||
129 | #include "ip2ioctl.h" | ||
130 | #include "ip2.h" | ||
131 | #include "i2ellis.h" | ||
132 | #include "i2lib.h" | ||
133 | |||
134 | /***************** | ||
135 | * /proc/ip2mem * | ||
136 | *****************/ | ||
137 | |||
138 | #include <linux/proc_fs.h> | ||
139 | #include <linux/seq_file.h> | ||
140 | |||
141 | static DEFINE_MUTEX(ip2_mutex); | ||
142 | static const struct file_operations ip2mem_proc_fops; | ||
143 | static const struct file_operations ip2_proc_fops; | ||
144 | |||
145 | /********************/ | ||
146 | /* Type Definitions */ | ||
147 | /********************/ | ||
148 | |||
149 | /*************/ | ||
150 | /* Constants */ | ||
151 | /*************/ | ||
152 | |||
153 | /* String constants to identify ourselves */ | ||
154 | static const char pcName[] = "Computone IntelliPort Plus multiport driver"; | ||
155 | static const char pcVersion[] = "1.2.14"; | ||
156 | |||
157 | /* String constants for port names */ | ||
158 | static const char pcDriver_name[] = "ip2"; | ||
159 | static const char pcIpl[] = "ip2ipl"; | ||
160 | |||
161 | /***********************/ | ||
162 | /* Function Prototypes */ | ||
163 | /***********************/ | ||
164 | |||
165 | /* Global module entry functions */ | ||
166 | |||
167 | /* Private (static) functions */ | ||
168 | static int ip2_open(PTTY, struct file *); | ||
169 | static void ip2_close(PTTY, struct file *); | ||
170 | static int ip2_write(PTTY, const unsigned char *, int); | ||
171 | static int ip2_putchar(PTTY, unsigned char); | ||
172 | static void ip2_flush_chars(PTTY); | ||
173 | static int ip2_write_room(PTTY); | ||
174 | static int ip2_chars_in_buf(PTTY); | ||
175 | static void ip2_flush_buffer(PTTY); | ||
176 | static int ip2_ioctl(PTTY, UINT, ULONG); | ||
177 | static void ip2_set_termios(PTTY, struct ktermios *); | ||
178 | static void ip2_set_line_discipline(PTTY); | ||
179 | static void ip2_throttle(PTTY); | ||
180 | static void ip2_unthrottle(PTTY); | ||
181 | static void ip2_stop(PTTY); | ||
182 | static void ip2_start(PTTY); | ||
183 | static void ip2_hangup(PTTY); | ||
184 | static int ip2_tiocmget(struct tty_struct *tty); | ||
185 | static int ip2_tiocmset(struct tty_struct *tty, | ||
186 | unsigned int set, unsigned int clear); | ||
187 | static int ip2_get_icount(struct tty_struct *tty, | ||
188 | struct serial_icounter_struct *icount); | ||
189 | |||
190 | static void set_irq(int, int); | ||
191 | static void ip2_interrupt_bh(struct work_struct *work); | ||
192 | static irqreturn_t ip2_interrupt(int irq, void *dev_id); | ||
193 | static void ip2_poll(unsigned long arg); | ||
194 | static inline void service_all_boards(void); | ||
195 | static void do_input(struct work_struct *); | ||
196 | static void do_status(struct work_struct *); | ||
197 | |||
198 | static void ip2_wait_until_sent(PTTY,int); | ||
199 | |||
200 | static void set_params (i2ChanStrPtr, struct ktermios *); | ||
201 | static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); | ||
202 | static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); | ||
203 | |||
204 | static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); | ||
205 | static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); | ||
206 | static long ip2_ipl_ioctl(struct file *, UINT, ULONG); | ||
207 | static int ip2_ipl_open(struct inode *, struct file *); | ||
208 | |||
209 | static int DumpTraceBuffer(char __user *, int); | ||
210 | static int DumpFifoBuffer( char __user *, int); | ||
211 | |||
212 | static void ip2_init_board(int, const struct firmware *); | ||
213 | static unsigned short find_eisa_board(int); | ||
214 | static int ip2_setup(char *str); | ||
215 | |||
216 | /***************/ | ||
217 | /* Static Data */ | ||
218 | /***************/ | ||
219 | |||
220 | static struct tty_driver *ip2_tty_driver; | ||
221 | |||
222 | /* Here, then is a table of board pointers which the interrupt routine should | ||
223 | * scan through to determine who it must service. | ||
224 | */ | ||
225 | static unsigned short i2nBoards; // Number of boards here | ||
226 | |||
227 | static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS]; | ||
228 | |||
229 | static i2ChanStrPtr DevTable[IP2_MAX_PORTS]; | ||
230 | //DevTableMem just used to save addresses for kfree | ||
231 | static void *DevTableMem[IP2_MAX_BOARDS]; | ||
232 | |||
233 | /* This is the driver descriptor for the ip2ipl device, which is used to | ||
234 | * download the loadware to the boards. | ||
235 | */ | ||
236 | static const struct file_operations ip2_ipl = { | ||
237 | .owner = THIS_MODULE, | ||
238 | .read = ip2_ipl_read, | ||
239 | .write = ip2_ipl_write, | ||
240 | .unlocked_ioctl = ip2_ipl_ioctl, | ||
241 | .open = ip2_ipl_open, | ||
242 | .llseek = noop_llseek, | ||
243 | }; | ||
244 | |||
245 | static unsigned long irq_counter; | ||
246 | static unsigned long bh_counter; | ||
247 | |||
248 | // Use immediate queue to service interrupts | ||
249 | #define USE_IQI | ||
250 | //#define USE_IQ // PCI&2.2 needs work | ||
251 | |||
252 | /* The timer_list entry for our poll routine. If interrupt operation is not | ||
253 | * selected, the board is serviced periodically to see if anything needs doing. | ||
254 | */ | ||
255 | #define POLL_TIMEOUT (jiffies + 1) | ||
256 | static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); | ||
257 | |||
258 | #ifdef IP2DEBUG_TRACE | ||
259 | /* Trace (debug) buffer data */ | ||
260 | #define TRACEMAX 1000 | ||
261 | static unsigned long tracebuf[TRACEMAX]; | ||
262 | static int tracestuff; | ||
263 | static int tracestrip; | ||
264 | static int tracewrap; | ||
265 | #endif | ||
266 | |||
267 | /**********/ | ||
268 | /* Macros */ | ||
269 | /**********/ | ||
270 | |||
271 | #ifdef IP2DEBUG_OPEN | ||
272 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ | ||
273 | tty->name,(pCh->flags), \ | ||
274 | tty->count,/*GET_USE_COUNT(module)*/0,s) | ||
275 | #else | ||
276 | #define DBG_CNT(s) | ||
277 | #endif | ||
278 | |||
279 | /********/ | ||
280 | /* Code */ | ||
281 | /********/ | ||
282 | |||
283 | #include "i2ellis.c" /* Extremely low-level interface services */ | ||
284 | #include "i2cmd.c" /* Standard loadware command definitions */ | ||
285 | #include "i2lib.c" /* High level interface services */ | ||
286 | |||
287 | /* Configuration area for modprobe */ | ||
288 | |||
289 | MODULE_AUTHOR("Doug McNash"); | ||
290 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | ||
291 | MODULE_LICENSE("GPL"); | ||
292 | |||
293 | #define MAX_CMD_STR 50 | ||
294 | |||
295 | static int poll_only; | ||
296 | static char cmd[MAX_CMD_STR]; | ||
297 | |||
298 | static int Eisa_irq; | ||
299 | static int Eisa_slot; | ||
300 | |||
301 | static int iindx; | ||
302 | static char rirqs[IP2_MAX_BOARDS]; | ||
303 | static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; | ||
304 | |||
305 | /* Note: Add compiled in defaults to these arrays, not to the structure | ||
306 | in ip2.h any longer. That structure WILL get overridden | ||
307 | by these values, or command line values, or insmod values!!! =mhw= | ||
308 | */ | ||
309 | static int io[IP2_MAX_BOARDS]; | ||
310 | static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; | ||
311 | |||
312 | MODULE_AUTHOR("Doug McNash"); | ||
313 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | ||
314 | module_param_array(irq, int, NULL, 0); | ||
315 | MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards"); | ||
316 | module_param_array(io, int, NULL, 0); | ||
317 | MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); | ||
318 | module_param(poll_only, bool, 0); | ||
319 | MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); | ||
320 | module_param_string(ip2, cmd, MAX_CMD_STR, 0); | ||
321 | MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='"); | ||
322 | |||
323 | /* for sysfs class support */ | ||
324 | static struct class *ip2_class; | ||
325 | |||
326 | /* Some functions to keep track of what irqs we have */ | ||
327 | |||
328 | static int __init is_valid_irq(int irq) | ||
329 | { | ||
330 | int *i = Valid_Irqs; | ||
331 | |||
332 | while (*i != 0 && *i != irq) | ||
333 | i++; | ||
334 | |||
335 | return *i; | ||
336 | } | ||
337 | |||
338 | static void __init mark_requested_irq(char irq) | ||
339 | { | ||
340 | rirqs[iindx++] = irq; | ||
341 | } | ||
342 | |||
343 | static int __exit clear_requested_irq(char irq) | ||
344 | { | ||
345 | int i; | ||
346 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
347 | if (rirqs[i] == irq) { | ||
348 | rirqs[i] = 0; | ||
349 | return 1; | ||
350 | } | ||
351 | } | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int have_requested_irq(char irq) | ||
356 | { | ||
357 | /* array init to zeros so 0 irq will not be requested as a side | ||
358 | * effect */ | ||
359 | int i; | ||
360 | for (i = 0; i < IP2_MAX_BOARDS; ++i) | ||
361 | if (rirqs[i] == irq) | ||
362 | return 1; | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | /******************************************************************************/ | ||
367 | /* Function: cleanup_module() */ | ||
368 | /* Parameters: None */ | ||
369 | /* Returns: Nothing */ | ||
370 | /* */ | ||
371 | /* Description: */ | ||
372 | /* This is a required entry point for an installable module. It has to return */ | ||
373 | /* the device and the driver to a passive state. It should not be necessary */ | ||
374 | /* to reset the board fully, especially as the loadware is downloaded */ | ||
375 | /* externally rather than in the driver. We just want to disable the board */ | ||
376 | /* and clear the loadware to a reset state. To allow this there has to be a */ | ||
377 | /* way to detect whether the board has the loadware running at init time to */ | ||
378 | /* handle subsequent installations of the driver. All memory allocated by the */ | ||
379 | /* driver should be returned since it may be unloaded from memory. */ | ||
380 | /******************************************************************************/ | ||
381 | static void __exit ip2_cleanup_module(void) | ||
382 | { | ||
383 | int err; | ||
384 | int i; | ||
385 | |||
386 | del_timer_sync(&PollTimer); | ||
387 | |||
388 | /* Reset the boards we have. */ | ||
389 | for (i = 0; i < IP2_MAX_BOARDS; i++) | ||
390 | if (i2BoardPtrTable[i]) | ||
391 | iiReset(i2BoardPtrTable[i]); | ||
392 | |||
393 | /* The following is done at most once, if any boards were installed. */ | ||
394 | for (i = 0; i < IP2_MAX_BOARDS; i++) { | ||
395 | if (i2BoardPtrTable[i]) { | ||
396 | iiResetDelay(i2BoardPtrTable[i]); | ||
397 | /* free io addresses and Tibet */ | ||
398 | release_region(ip2config.addr[i], 8); | ||
399 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); | ||
400 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, | ||
401 | 4 * i + 1)); | ||
402 | } | ||
403 | /* Disable and remove interrupt handler. */ | ||
404 | if (ip2config.irq[i] > 0 && | ||
405 | have_requested_irq(ip2config.irq[i])) { | ||
406 | free_irq(ip2config.irq[i], (void *)&pcName); | ||
407 | clear_requested_irq(ip2config.irq[i]); | ||
408 | } | ||
409 | } | ||
410 | class_destroy(ip2_class); | ||
411 | err = tty_unregister_driver(ip2_tty_driver); | ||
412 | if (err) | ||
413 | printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", | ||
414 | err); | ||
415 | put_tty_driver(ip2_tty_driver); | ||
416 | unregister_chrdev(IP2_IPL_MAJOR, pcIpl); | ||
417 | remove_proc_entry("ip2mem", NULL); | ||
418 | |||
419 | /* free memory */ | ||
420 | for (i = 0; i < IP2_MAX_BOARDS; i++) { | ||
421 | void *pB; | ||
422 | #ifdef CONFIG_PCI | ||
423 | if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { | ||
424 | pci_disable_device(ip2config.pci_dev[i]); | ||
425 | pci_dev_put(ip2config.pci_dev[i]); | ||
426 | ip2config.pci_dev[i] = NULL; | ||
427 | } | ||
428 | #endif | ||
429 | pB = i2BoardPtrTable[i]; | ||
430 | if (pB != NULL) { | ||
431 | kfree(pB); | ||
432 | i2BoardPtrTable[i] = NULL; | ||
433 | } | ||
434 | if (DevTableMem[i] != NULL) { | ||
435 | kfree(DevTableMem[i]); | ||
436 | DevTableMem[i] = NULL; | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | module_exit(ip2_cleanup_module); | ||
441 | |||
442 | static const struct tty_operations ip2_ops = { | ||
443 | .open = ip2_open, | ||
444 | .close = ip2_close, | ||
445 | .write = ip2_write, | ||
446 | .put_char = ip2_putchar, | ||
447 | .flush_chars = ip2_flush_chars, | ||
448 | .write_room = ip2_write_room, | ||
449 | .chars_in_buffer = ip2_chars_in_buf, | ||
450 | .flush_buffer = ip2_flush_buffer, | ||
451 | .ioctl = ip2_ioctl, | ||
452 | .throttle = ip2_throttle, | ||
453 | .unthrottle = ip2_unthrottle, | ||
454 | .set_termios = ip2_set_termios, | ||
455 | .set_ldisc = ip2_set_line_discipline, | ||
456 | .stop = ip2_stop, | ||
457 | .start = ip2_start, | ||
458 | .hangup = ip2_hangup, | ||
459 | .tiocmget = ip2_tiocmget, | ||
460 | .tiocmset = ip2_tiocmset, | ||
461 | .get_icount = ip2_get_icount, | ||
462 | .proc_fops = &ip2_proc_fops, | ||
463 | }; | ||
464 | |||
465 | /******************************************************************************/ | ||
466 | /* Function: ip2_loadmain() */ | ||
467 | /* Parameters: irq, io from command line of insmod et. al. */ | ||
468 | /* pointer to fip firmware and firmware size for boards */ | ||
469 | /* Returns: Success (0) */ | ||
470 | /* */ | ||
471 | /* Description: */ | ||
472 | /* This was the required entry point for all drivers (now in ip2.c) */ | ||
473 | /* It performs all */ | ||
474 | /* initialisation of the devices and driver structures, and registers itself */ | ||
475 | /* with the relevant kernel modules. */ | ||
476 | /******************************************************************************/ | ||
477 | /* IRQF_DISABLED - if set blocks all interrupts else only this line */ | ||
478 | /* IRQF_SHARED - for shared irq PCI or maybe EISA only */ | ||
479 | /* SA_RANDOM - can be source for cert. random number generators */ | ||
480 | #define IP2_SA_FLAGS 0 | ||
481 | |||
482 | |||
483 | static const struct firmware *ip2_request_firmware(void) | ||
484 | { | ||
485 | struct platform_device *pdev; | ||
486 | const struct firmware *fw; | ||
487 | |||
488 | pdev = platform_device_register_simple("ip2", 0, NULL, 0); | ||
489 | if (IS_ERR(pdev)) { | ||
490 | printk(KERN_ERR "Failed to register platform device for ip2\n"); | ||
491 | return NULL; | ||
492 | } | ||
493 | if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) { | ||
494 | printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n"); | ||
495 | fw = NULL; | ||
496 | } | ||
497 | platform_device_unregister(pdev); | ||
498 | return fw; | ||
499 | } | ||
500 | |||
501 | /****************************************************************************** | ||
502 | * ip2_setup: | ||
503 | * str: kernel command line string | ||
504 | * | ||
505 | * Can't autoprobe the boards so user must specify configuration on | ||
506 | * kernel command line. Sane people build it modular but the others | ||
507 | * come here. | ||
508 | * | ||
509 | * Alternating pairs of io,irq for up to 4 boards. | ||
510 | * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 | ||
511 | * | ||
512 | * io=0 => No board | ||
513 | * io=1 => PCI | ||
514 | * io=2 => EISA | ||
515 | * else => ISA I/O address | ||
516 | * | ||
517 | * irq=0 or invalid for ISA will revert to polling mode | ||
518 | * | ||
519 | * Any value = -1, do not overwrite compiled in value. | ||
520 | * | ||
521 | ******************************************************************************/ | ||
522 | static int __init ip2_setup(char *str) | ||
523 | { | ||
524 | int j, ints[10]; /* 4 boards, 2 parameters + 2 */ | ||
525 | unsigned int i; | ||
526 | |||
527 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
528 | |||
529 | for (i = 0, j = 1; i < 4; i++) { | ||
530 | if (j > ints[0]) | ||
531 | break; | ||
532 | if (ints[j] >= 0) | ||
533 | io[i] = ints[j]; | ||
534 | j++; | ||
535 | if (j > ints[0]) | ||
536 | break; | ||
537 | if (ints[j] >= 0) | ||
538 | irq[i] = ints[j]; | ||
539 | j++; | ||
540 | } | ||
541 | return 1; | ||
542 | } | ||
543 | __setup("ip2=", ip2_setup); | ||
544 | |||
545 | static int __init ip2_loadmain(void) | ||
546 | { | ||
547 | int i, j, box; | ||
548 | int err = 0; | ||
549 | i2eBordStrPtr pB = NULL; | ||
550 | int rc = -1; | ||
551 | const struct firmware *fw = NULL; | ||
552 | char *str; | ||
553 | |||
554 | str = cmd; | ||
555 | |||
556 | if (poll_only) { | ||
557 | /* Hard lock the interrupts to zero */ | ||
558 | irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; | ||
559 | } | ||
560 | |||
561 | /* Check module parameter with 'ip2=' has been passed or not */ | ||
562 | if (!poll_only && (!strncmp(str, "ip2=", 4))) | ||
563 | ip2_setup(str); | ||
564 | |||
565 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); | ||
566 | |||
567 | /* process command line arguments to modprobe or | ||
568 | insmod i.e. iop & irqp */ | ||
569 | /* irqp and iop should ALWAYS be specified now... But we check | ||
570 | them individually just to be sure, anyways... */ | ||
571 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
572 | ip2config.addr[i] = io[i]; | ||
573 | if (irq[i] >= 0) | ||
574 | ip2config.irq[i] = irq[i]; | ||
575 | else | ||
576 | ip2config.irq[i] = 0; | ||
577 | /* This is a little bit of a hack. If poll_only=1 on command | ||
578 | line back in ip2.c OR all IRQs on all specified boards are | ||
579 | explicitly set to 0, then drop to poll only mode and override | ||
580 | PCI or EISA interrupts. This superceeds the old hack of | ||
581 | triggering if all interrupts were zero (like da default). | ||
582 | Still a hack but less prone to random acts of terrorism. | ||
583 | |||
584 | What we really should do, now that the IRQ default is set | ||
585 | to -1, is to use 0 as a hard coded, do not probe. | ||
586 | |||
587 | /\/\|=mhw=|\/\/ | ||
588 | */ | ||
589 | poll_only |= irq[i]; | ||
590 | } | ||
591 | poll_only = !poll_only; | ||
592 | |||
593 | /* Announce our presence */ | ||
594 | printk(KERN_INFO "%s version %s\n", pcName, pcVersion); | ||
595 | |||
596 | ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); | ||
597 | if (!ip2_tty_driver) | ||
598 | return -ENOMEM; | ||
599 | |||
600 | /* Initialise all the boards we can find (up to the maximum). */ | ||
601 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
602 | switch (ip2config.addr[i]) { | ||
603 | case 0: /* skip this slot even if card is present */ | ||
604 | break; | ||
605 | default: /* ISA */ | ||
606 | /* ISA address must be specified */ | ||
607 | if (ip2config.addr[i] < 0x100 || | ||
608 | ip2config.addr[i] > 0x3f8) { | ||
609 | printk(KERN_ERR "IP2: Bad ISA board %d " | ||
610 | "address %x\n", i, | ||
611 | ip2config.addr[i]); | ||
612 | ip2config.addr[i] = 0; | ||
613 | break; | ||
614 | } | ||
615 | ip2config.type[i] = ISA; | ||
616 | |||
617 | /* Check for valid irq argument, set for polling if | ||
618 | * invalid */ | ||
619 | if (ip2config.irq[i] && | ||
620 | !is_valid_irq(ip2config.irq[i])) { | ||
621 | printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n", | ||
622 | ip2config.irq[i]); | ||
623 | /* 0 is polling and is valid in that sense */ | ||
624 | ip2config.irq[i] = 0; | ||
625 | } | ||
626 | break; | ||
627 | case PCI: | ||
628 | #ifdef CONFIG_PCI | ||
629 | { | ||
630 | struct pci_dev *pdev = NULL; | ||
631 | u32 addr; | ||
632 | int status; | ||
633 | |||
634 | pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE, | ||
635 | PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev); | ||
636 | if (pdev == NULL) { | ||
637 | ip2config.addr[i] = 0; | ||
638 | printk(KERN_ERR "IP2: PCI board %d not " | ||
639 | "found\n", i); | ||
640 | break; | ||
641 | } | ||
642 | |||
643 | if (pci_enable_device(pdev)) { | ||
644 | dev_err(&pdev->dev, "can't enable device\n"); | ||
645 | goto out; | ||
646 | } | ||
647 | ip2config.type[i] = PCI; | ||
648 | ip2config.pci_dev[i] = pci_dev_get(pdev); | ||
649 | status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, | ||
650 | &addr); | ||
651 | if (addr & 1) | ||
652 | ip2config.addr[i] = (USHORT)(addr & 0xfffe); | ||
653 | else | ||
654 | dev_err(&pdev->dev, "I/O address error\n"); | ||
655 | |||
656 | ip2config.irq[i] = pdev->irq; | ||
657 | out: | ||
658 | pci_dev_put(pdev); | ||
659 | } | ||
660 | #else | ||
661 | printk(KERN_ERR "IP2: PCI card specified but PCI " | ||
662 | "support not enabled.\n"); | ||
663 | printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI " | ||
664 | "defined!\n"); | ||
665 | #endif /* CONFIG_PCI */ | ||
666 | break; | ||
667 | case EISA: | ||
668 | ip2config.addr[i] = find_eisa_board(Eisa_slot + 1); | ||
669 | if (ip2config.addr[i] != 0) { | ||
670 | /* Eisa_irq set as side effect, boo */ | ||
671 | ip2config.type[i] = EISA; | ||
672 | } | ||
673 | ip2config.irq[i] = Eisa_irq; | ||
674 | break; | ||
675 | } /* switch */ | ||
676 | } /* for */ | ||
677 | |||
678 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
679 | if (ip2config.addr[i]) { | ||
680 | pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL); | ||
681 | if (pB) { | ||
682 | i2BoardPtrTable[i] = pB; | ||
683 | iiSetAddress(pB, ip2config.addr[i], | ||
684 | ii2DelayTimer); | ||
685 | iiReset(pB); | ||
686 | } else | ||
687 | printk(KERN_ERR "IP2: board memory allocation " | ||
688 | "error\n"); | ||
689 | } | ||
690 | } | ||
691 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
692 | pB = i2BoardPtrTable[i]; | ||
693 | if (pB != NULL) { | ||
694 | iiResetDelay(pB); | ||
695 | break; | ||
696 | } | ||
697 | } | ||
698 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
699 | /* We don't want to request the firmware unless we have at | ||
700 | least one board */ | ||
701 | if (i2BoardPtrTable[i] != NULL) { | ||
702 | if (!fw) | ||
703 | fw = ip2_request_firmware(); | ||
704 | if (!fw) | ||
705 | break; | ||
706 | ip2_init_board(i, fw); | ||
707 | } | ||
708 | } | ||
709 | if (fw) | ||
710 | release_firmware(fw); | ||
711 | |||
712 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0); | ||
713 | |||
714 | ip2_tty_driver->owner = THIS_MODULE; | ||
715 | ip2_tty_driver->name = "ttyF"; | ||
716 | ip2_tty_driver->driver_name = pcDriver_name; | ||
717 | ip2_tty_driver->major = IP2_TTY_MAJOR; | ||
718 | ip2_tty_driver->minor_start = 0; | ||
719 | ip2_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
720 | ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; | ||
721 | ip2_tty_driver->init_termios = tty_std_termios; | ||
722 | ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; | ||
723 | ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | | ||
724 | TTY_DRIVER_DYNAMIC_DEV; | ||
725 | tty_set_operations(ip2_tty_driver, &ip2_ops); | ||
726 | |||
727 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0); | ||
728 | |||
729 | err = tty_register_driver(ip2_tty_driver); | ||
730 | if (err) { | ||
731 | printk(KERN_ERR "IP2: failed to register tty driver\n"); | ||
732 | put_tty_driver(ip2_tty_driver); | ||
733 | return err; /* leaking resources */ | ||
734 | } | ||
735 | |||
736 | err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl); | ||
737 | if (err) { | ||
738 | printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", | ||
739 | err); | ||
740 | } else { | ||
741 | /* create the sysfs class */ | ||
742 | ip2_class = class_create(THIS_MODULE, "ip2"); | ||
743 | if (IS_ERR(ip2_class)) { | ||
744 | err = PTR_ERR(ip2_class); | ||
745 | goto out_chrdev; | ||
746 | } | ||
747 | } | ||
748 | /* Register the read_procmem thing */ | ||
749 | if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) { | ||
750 | printk(KERN_ERR "IP2: failed to register read_procmem\n"); | ||
751 | return -EIO; /* leaking resources */ | ||
752 | } | ||
753 | |||
754 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0); | ||
755 | /* Register the interrupt handler or poll handler, depending upon the | ||
756 | * specified interrupt. | ||
757 | */ | ||
758 | |||
759 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
760 | if (ip2config.addr[i] == 0) | ||
761 | continue; | ||
762 | |||
763 | pB = i2BoardPtrTable[i]; | ||
764 | if (pB != NULL) { | ||
765 | device_create(ip2_class, NULL, | ||
766 | MKDEV(IP2_IPL_MAJOR, 4 * i), | ||
767 | NULL, "ipl%d", i); | ||
768 | device_create(ip2_class, NULL, | ||
769 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), | ||
770 | NULL, "stat%d", i); | ||
771 | |||
772 | for (box = 0; box < ABS_MAX_BOXES; box++) | ||
773 | for (j = 0; j < ABS_BIGGEST_BOX; j++) | ||
774 | if (pB->i2eChannelMap[box] & (1 << j)) | ||
775 | tty_register_device( | ||
776 | ip2_tty_driver, | ||
777 | j + ABS_BIGGEST_BOX * | ||
778 | (box+i*ABS_MAX_BOXES), | ||
779 | NULL); | ||
780 | } | ||
781 | |||
782 | if (poll_only) { | ||
783 | /* Poll only forces driver to only use polling and | ||
784 | to ignore the probed PCI or EISA interrupts. */ | ||
785 | ip2config.irq[i] = CIR_POLL; | ||
786 | } | ||
787 | if (ip2config.irq[i] == CIR_POLL) { | ||
788 | retry: | ||
789 | if (!timer_pending(&PollTimer)) { | ||
790 | mod_timer(&PollTimer, POLL_TIMEOUT); | ||
791 | printk(KERN_INFO "IP2: polling\n"); | ||
792 | } | ||
793 | } else { | ||
794 | if (have_requested_irq(ip2config.irq[i])) | ||
795 | continue; | ||
796 | rc = request_irq(ip2config.irq[i], ip2_interrupt, | ||
797 | IP2_SA_FLAGS | | ||
798 | (ip2config.type[i] == PCI ? IRQF_SHARED : 0), | ||
799 | pcName, i2BoardPtrTable[i]); | ||
800 | if (rc) { | ||
801 | printk(KERN_ERR "IP2: request_irq failed: " | ||
802 | "error %d\n", rc); | ||
803 | ip2config.irq[i] = CIR_POLL; | ||
804 | printk(KERN_INFO "IP2: Polling %ld/sec.\n", | ||
805 | (POLL_TIMEOUT - jiffies)); | ||
806 | goto retry; | ||
807 | } | ||
808 | mark_requested_irq(ip2config.irq[i]); | ||
809 | /* Initialise the interrupt handler bottom half | ||
810 | * (aka slih). */ | ||
811 | } | ||
812 | } | ||
813 | |||
814 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
815 | if (i2BoardPtrTable[i]) { | ||
816 | /* set and enable board interrupt */ | ||
817 | set_irq(i, ip2config.irq[i]); | ||
818 | } | ||
819 | } | ||
820 | |||
821 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0); | ||
822 | |||
823 | return 0; | ||
824 | |||
825 | out_chrdev: | ||
826 | unregister_chrdev(IP2_IPL_MAJOR, "ip2"); | ||
827 | /* unregister and put tty here */ | ||
828 | return err; | ||
829 | } | ||
830 | module_init(ip2_loadmain); | ||
831 | |||
832 | /******************************************************************************/ | ||
833 | /* Function: ip2_init_board() */ | ||
834 | /* Parameters: Index of board in configuration structure */ | ||
835 | /* Returns: Success (0) */ | ||
836 | /* */ | ||
837 | /* Description: */ | ||
838 | /* This function initializes the specified board. The loadware is copied to */ | ||
839 | /* the board, the channel structures are initialized, and the board details */ | ||
840 | /* are reported on the console. */ | ||
841 | /******************************************************************************/ | ||
842 | static void | ||
843 | ip2_init_board(int boardnum, const struct firmware *fw) | ||
844 | { | ||
845 | int i; | ||
846 | int nports = 0, nboxes = 0; | ||
847 | i2ChanStrPtr pCh; | ||
848 | i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; | ||
849 | |||
850 | if ( !iiInitialize ( pB ) ) { | ||
851 | printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n", | ||
852 | pB->i2eBase, pB->i2eError ); | ||
853 | goto err_initialize; | ||
854 | } | ||
855 | printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1, | ||
856 | ip2config.addr[boardnum], ip2config.irq[boardnum] ); | ||
857 | |||
858 | if (!request_region( ip2config.addr[boardnum], 8, pcName )) { | ||
859 | printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]); | ||
860 | goto err_initialize; | ||
861 | } | ||
862 | |||
863 | if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size ) | ||
864 | != II_DOWN_GOOD ) { | ||
865 | printk ( KERN_ERR "IP2: failed to download loadware\n" ); | ||
866 | goto err_release_region; | ||
867 | } else { | ||
868 | printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n", | ||
869 | pB->i2ePom.e.porVersion, | ||
870 | pB->i2ePom.e.porRevision, | ||
871 | pB->i2ePom.e.porSubRev, pB->i2eLVersion, | ||
872 | pB->i2eLRevision, pB->i2eLSub ); | ||
873 | } | ||
874 | |||
875 | switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) { | ||
876 | |||
877 | default: | ||
878 | printk( KERN_ERR "IP2: Unknown board type, ID = %x\n", | ||
879 | pB->i2ePom.e.porID ); | ||
880 | nports = 0; | ||
881 | goto err_release_region; | ||
882 | break; | ||
883 | |||
884 | case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */ | ||
885 | printk ( KERN_INFO "IP2: ISA-4\n" ); | ||
886 | nports = 4; | ||
887 | break; | ||
888 | |||
889 | case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */ | ||
890 | printk ( KERN_INFO "IP2: ISA-8 std\n" ); | ||
891 | nports = 8; | ||
892 | break; | ||
893 | |||
894 | case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */ | ||
895 | printk ( KERN_INFO "IP2: ISA-8 RJ11\n" ); | ||
896 | nports = 8; | ||
897 | break; | ||
898 | |||
899 | case POR_ID_FIIEX: /* IntelliPort IIEX */ | ||
900 | { | ||
901 | int portnum = IP2_PORTS_PER_BOARD * boardnum; | ||
902 | int box; | ||
903 | |||
904 | for( box = 0; box < ABS_MAX_BOXES; ++box ) { | ||
905 | if ( pB->i2eChannelMap[box] != 0 ) { | ||
906 | ++nboxes; | ||
907 | } | ||
908 | for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { | ||
909 | if ( pB->i2eChannelMap[box] & 1<< i ) { | ||
910 | ++nports; | ||
911 | } | ||
912 | } | ||
913 | } | ||
914 | DevTableMem[boardnum] = pCh = | ||
915 | kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL ); | ||
916 | if ( !pCh ) { | ||
917 | printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); | ||
918 | goto err_release_region; | ||
919 | } | ||
920 | if ( !i2InitChannels( pB, nports, pCh ) ) { | ||
921 | printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); | ||
922 | kfree ( pCh ); | ||
923 | goto err_release_region; | ||
924 | } | ||
925 | pB->i2eChannelPtr = &DevTable[portnum]; | ||
926 | pB->i2eChannelCnt = ABS_MOST_PORTS; | ||
927 | |||
928 | for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) { | ||
929 | for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { | ||
930 | if ( pB->i2eChannelMap[box] & (1 << i) ) { | ||
931 | DevTable[portnum + i] = pCh; | ||
932 | pCh->port_index = portnum + i; | ||
933 | pCh++; | ||
934 | } | ||
935 | } | ||
936 | } | ||
937 | printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n", | ||
938 | nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 ); | ||
939 | } | ||
940 | goto ex_exit; | ||
941 | } | ||
942 | DevTableMem[boardnum] = pCh = | ||
943 | kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL ); | ||
944 | if ( !pCh ) { | ||
945 | printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); | ||
946 | goto err_release_region; | ||
947 | } | ||
948 | pB->i2eChannelPtr = pCh; | ||
949 | pB->i2eChannelCnt = nports; | ||
950 | if ( !i2InitChannels( pB, nports, pCh ) ) { | ||
951 | printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); | ||
952 | kfree ( pCh ); | ||
953 | goto err_release_region; | ||
954 | } | ||
955 | pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum]; | ||
956 | |||
957 | for( i = 0; i < pB->i2eChannelCnt; ++i ) { | ||
958 | DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh; | ||
959 | pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i; | ||
960 | pCh++; | ||
961 | } | ||
962 | ex_exit: | ||
963 | INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh); | ||
964 | return; | ||
965 | |||
966 | err_release_region: | ||
967 | release_region(ip2config.addr[boardnum], 8); | ||
968 | err_initialize: | ||
969 | kfree ( pB ); | ||
970 | i2BoardPtrTable[boardnum] = NULL; | ||
971 | return; | ||
972 | } | ||
973 | |||
974 | /******************************************************************************/ | ||
975 | /* Function: find_eisa_board ( int start_slot ) */ | ||
976 | /* Parameters: First slot to check */ | ||
977 | /* Returns: Address of EISA IntelliPort II controller */ | ||
978 | /* */ | ||
979 | /* Description: */ | ||
980 | /* This function searches for an EISA IntelliPort controller, starting */ | ||
981 | /* from the specified slot number. If the motherboard is not identified as an */ | ||
982 | /* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */ | ||
983 | /* it returns the base address of the controller. */ | ||
984 | /******************************************************************************/ | ||
985 | static unsigned short | ||
986 | find_eisa_board( int start_slot ) | ||
987 | { | ||
988 | int i, j; | ||
989 | unsigned int idm = 0; | ||
990 | unsigned int idp = 0; | ||
991 | unsigned int base = 0; | ||
992 | unsigned int value; | ||
993 | int setup_address; | ||
994 | int setup_irq; | ||
995 | int ismine = 0; | ||
996 | |||
997 | /* | ||
998 | * First a check for an EISA motherboard, which we do by comparing the | ||
999 | * EISA ID registers for the system board and the first couple of slots. | ||
1000 | * No slot ID should match the system board ID, but on an ISA or PCI | ||
1001 | * machine the odds are that an empty bus will return similar values for | ||
1002 | * each slot. | ||
1003 | */ | ||
1004 | i = 0x0c80; | ||
1005 | value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3); | ||
1006 | for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) { | ||
1007 | j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3); | ||
1008 | if ( value == j ) | ||
1009 | return 0; | ||
1010 | } | ||
1011 | |||
1012 | /* | ||
1013 | * OK, so we are inclined to believe that this is an EISA machine. Find | ||
1014 | * an IntelliPort controller. | ||
1015 | */ | ||
1016 | for( i = start_slot; i < 16; i++ ) { | ||
1017 | base = i << 12; | ||
1018 | idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff); | ||
1019 | idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff); | ||
1020 | ismine = 0; | ||
1021 | if ( idm == 0x0e8e ) { | ||
1022 | if ( idp == 0x0281 || idp == 0x0218 ) { | ||
1023 | ismine = 1; | ||
1024 | } else if ( idp == 0x0282 || idp == 0x0283 ) { | ||
1025 | ismine = 3; /* Can do edge-trigger */ | ||
1026 | } | ||
1027 | if ( ismine ) { | ||
1028 | Eisa_slot = i; | ||
1029 | break; | ||
1030 | } | ||
1031 | } | ||
1032 | } | ||
1033 | if ( !ismine ) | ||
1034 | return 0; | ||
1035 | |||
1036 | /* It's some sort of EISA card, but at what address is it configured? */ | ||
1037 | |||
1038 | setup_address = base + 0xc88; | ||
1039 | value = inb(base + 0xc86); | ||
1040 | setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0; | ||
1041 | |||
1042 | if ( (ismine & 2) && !(value & 0x10) ) { | ||
1043 | ismine = 1; /* Could be edging, but not */ | ||
1044 | } | ||
1045 | |||
1046 | if ( Eisa_irq == 0 ) { | ||
1047 | Eisa_irq = setup_irq; | ||
1048 | } else if ( Eisa_irq != setup_irq ) { | ||
1049 | printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" ); | ||
1050 | } | ||
1051 | |||
1052 | #ifdef IP2DEBUG_INIT | ||
1053 | printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x", | ||
1054 | base >> 12, idm, idp, setup_address); | ||
1055 | if ( Eisa_irq ) { | ||
1056 | printk(KERN_DEBUG ", Interrupt %d %s\n", | ||
1057 | setup_irq, (ismine & 2) ? "(edge)" : "(level)"); | ||
1058 | } else { | ||
1059 | printk(KERN_DEBUG ", (polled)\n"); | ||
1060 | } | ||
1061 | #endif | ||
1062 | return setup_address; | ||
1063 | } | ||
1064 | |||
1065 | /******************************************************************************/ | ||
1066 | /* Function: set_irq() */ | ||
1067 | /* Parameters: index to board in board table */ | ||
1068 | /* IRQ to use */ | ||
1069 | /* Returns: Success (0) */ | ||
1070 | /* */ | ||
1071 | /* Description: */ | ||
1072 | /******************************************************************************/ | ||
1073 | static void | ||
1074 | set_irq( int boardnum, int boardIrq ) | ||
1075 | { | ||
1076 | unsigned char tempCommand[16]; | ||
1077 | i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; | ||
1078 | unsigned long flags; | ||
1079 | |||
1080 | /* | ||
1081 | * Notify the boards they may generate interrupts. This is done by | ||
1082 | * sending an in-line command to channel 0 on each board. This is why | ||
1083 | * the channels have to be defined already. For each board, if the | ||
1084 | * interrupt has never been defined, we must do so NOW, directly, since | ||
1085 | * board will not send flow control or even give an interrupt until this | ||
1086 | * is done. If polling we must send 0 as the interrupt parameter. | ||
1087 | */ | ||
1088 | |||
1089 | // We will get an interrupt here at the end of this function | ||
1090 | |||
1091 | iiDisableMailIrq(pB); | ||
1092 | |||
1093 | /* We build up the entire packet header. */ | ||
1094 | CHANNEL_OF(tempCommand) = 0; | ||
1095 | PTYPE_OF(tempCommand) = PTYPE_INLINE; | ||
1096 | CMD_COUNT_OF(tempCommand) = 2; | ||
1097 | (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ; | ||
1098 | (CMD_OF(tempCommand))[1] = boardIrq; | ||
1099 | /* | ||
1100 | * Write to FIFO; don't bother to adjust fifo capacity for this, since | ||
1101 | * board will respond almost immediately after SendMail hit. | ||
1102 | */ | ||
1103 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
1104 | iiWriteBuf(pB, tempCommand, 4); | ||
1105 | write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); | ||
1106 | pB->i2eUsingIrq = boardIrq; | ||
1107 | pB->i2eOutMailWaiting |= MB_OUT_STUFFED; | ||
1108 | |||
1109 | /* Need to update number of boards before you enable mailbox int */ | ||
1110 | ++i2nBoards; | ||
1111 | |||
1112 | CHANNEL_OF(tempCommand) = 0; | ||
1113 | PTYPE_OF(tempCommand) = PTYPE_BYPASS; | ||
1114 | CMD_COUNT_OF(tempCommand) = 6; | ||
1115 | (CMD_OF(tempCommand))[0] = 88; // SILO | ||
1116 | (CMD_OF(tempCommand))[1] = 64; // chars | ||
1117 | (CMD_OF(tempCommand))[2] = 32; // ms | ||
1118 | |||
1119 | (CMD_OF(tempCommand))[3] = 28; // MAX_BLOCK | ||
1120 | (CMD_OF(tempCommand))[4] = 64; // chars | ||
1121 | |||
1122 | (CMD_OF(tempCommand))[5] = 87; // HW_TEST | ||
1123 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
1124 | iiWriteBuf(pB, tempCommand, 8); | ||
1125 | write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); | ||
1126 | |||
1127 | CHANNEL_OF(tempCommand) = 0; | ||
1128 | PTYPE_OF(tempCommand) = PTYPE_BYPASS; | ||
1129 | CMD_COUNT_OF(tempCommand) = 1; | ||
1130 | (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */ | ||
1131 | iiWriteBuf(pB, tempCommand, 3); | ||
1132 | |||
1133 | #ifdef XXX | ||
1134 | // enable heartbeat for test porpoises | ||
1135 | CHANNEL_OF(tempCommand) = 0; | ||
1136 | PTYPE_OF(tempCommand) = PTYPE_BYPASS; | ||
1137 | CMD_COUNT_OF(tempCommand) = 2; | ||
1138 | (CMD_OF(tempCommand))[0] = 44; /* get ping */ | ||
1139 | (CMD_OF(tempCommand))[1] = 200; /* 200 ms */ | ||
1140 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
1141 | iiWriteBuf(pB, tempCommand, 4); | ||
1142 | write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); | ||
1143 | #endif | ||
1144 | |||
1145 | iiEnableMailIrq(pB); | ||
1146 | iiSendPendingMail(pB); | ||
1147 | } | ||
1148 | |||
1149 | /******************************************************************************/ | ||
1150 | /* Interrupt Handler Section */ | ||
1151 | /******************************************************************************/ | ||
1152 | |||
1153 | static inline void | ||
1154 | service_all_boards(void) | ||
1155 | { | ||
1156 | int i; | ||
1157 | i2eBordStrPtr pB; | ||
1158 | |||
1159 | /* Service every board on the list */ | ||
1160 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | ||
1161 | pB = i2BoardPtrTable[i]; | ||
1162 | if ( pB ) { | ||
1163 | i2ServiceBoard( pB ); | ||
1164 | } | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | |||
1169 | /******************************************************************************/ | ||
1170 | /* Function: ip2_interrupt_bh(work) */ | ||
1171 | /* Parameters: work - pointer to the board structure */ | ||
1172 | /* Returns: Nothing */ | ||
1173 | /* */ | ||
1174 | /* Description: */ | ||
1175 | /* Service the board in a bottom half interrupt handler and then */ | ||
1176 | /* reenable the board's interrupts if it has an IRQ number */ | ||
1177 | /* */ | ||
1178 | /******************************************************************************/ | ||
1179 | static void | ||
1180 | ip2_interrupt_bh(struct work_struct *work) | ||
1181 | { | ||
1182 | i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt); | ||
1183 | // pB better well be set or we have a problem! We can only get | ||
1184 | // here from the IMMEDIATE queue. Here, we process the boards. | ||
1185 | // Checking pB doesn't cost much and it saves us from the sanity checkers. | ||
1186 | |||
1187 | bh_counter++; | ||
1188 | |||
1189 | if ( pB ) { | ||
1190 | i2ServiceBoard( pB ); | ||
1191 | if( pB->i2eUsingIrq ) { | ||
1192 | // Re-enable his interrupts | ||
1193 | iiEnableMailIrq(pB); | ||
1194 | } | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | |||
1199 | /******************************************************************************/ | ||
1200 | /* Function: ip2_interrupt(int irq, void *dev_id) */ | ||
1201 | /* Parameters: irq - interrupt number */ | ||
1202 | /* pointer to optional device ID structure */ | ||
1203 | /* Returns: Nothing */ | ||
1204 | /* */ | ||
1205 | /* Description: */ | ||
1206 | /* */ | ||
1207 | /* Our task here is simply to identify each board which needs servicing. */ | ||
1208 | /* If we are queuing then, queue it to be serviced, and disable its irq */ | ||
1209 | /* mask otherwise process the board directly. */ | ||
1210 | /* */ | ||
1211 | /* We could queue by IRQ but that just complicates things on both ends */ | ||
1212 | /* with very little gain in performance (how many instructions does */ | ||
1213 | /* it take to iterate on the immediate queue). */ | ||
1214 | /* */ | ||
1215 | /* */ | ||
1216 | /******************************************************************************/ | ||
1217 | static void | ||
1218 | ip2_irq_work(i2eBordStrPtr pB) | ||
1219 | { | ||
1220 | #ifdef USE_IQI | ||
1221 | if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) { | ||
1222 | // Disable his interrupt (will be enabled when serviced) | ||
1223 | // This is mostly to protect from reentrancy. | ||
1224 | iiDisableMailIrq(pB); | ||
1225 | |||
1226 | // Park the board on the immediate queue for processing. | ||
1227 | schedule_work(&pB->tqueue_interrupt); | ||
1228 | |||
1229 | // Make sure the immediate queue is flagged to fire. | ||
1230 | } | ||
1231 | #else | ||
1232 | |||
1233 | // We are using immediate servicing here. This sucks and can | ||
1234 | // cause all sorts of havoc with ppp and others. The failsafe | ||
1235 | // check on iiSendPendingMail could also throw a hairball. | ||
1236 | |||
1237 | i2ServiceBoard( pB ); | ||
1238 | |||
1239 | #endif /* USE_IQI */ | ||
1240 | } | ||
1241 | |||
1242 | static void | ||
1243 | ip2_polled_interrupt(void) | ||
1244 | { | ||
1245 | int i; | ||
1246 | i2eBordStrPtr pB; | ||
1247 | |||
1248 | ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0); | ||
1249 | |||
1250 | /* Service just the boards on the list using this irq */ | ||
1251 | for( i = 0; i < i2nBoards; ++i ) { | ||
1252 | pB = i2BoardPtrTable[i]; | ||
1253 | |||
1254 | // Only process those boards which match our IRQ. | ||
1255 | // IRQ = 0 for polled boards, we won't poll "IRQ" boards | ||
1256 | |||
1257 | if (pB && pB->i2eUsingIrq == 0) | ||
1258 | ip2_irq_work(pB); | ||
1259 | } | ||
1260 | |||
1261 | ++irq_counter; | ||
1262 | |||
1263 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); | ||
1264 | } | ||
1265 | |||
1266 | static irqreturn_t | ||
1267 | ip2_interrupt(int irq, void *dev_id) | ||
1268 | { | ||
1269 | i2eBordStrPtr pB = dev_id; | ||
1270 | |||
1271 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq ); | ||
1272 | |||
1273 | ip2_irq_work(pB); | ||
1274 | |||
1275 | ++irq_counter; | ||
1276 | |||
1277 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); | ||
1278 | return IRQ_HANDLED; | ||
1279 | } | ||
1280 | |||
1281 | /******************************************************************************/ | ||
1282 | /* Function: ip2_poll(unsigned long arg) */ | ||
1283 | /* Parameters: ? */ | ||
1284 | /* Returns: Nothing */ | ||
1285 | /* */ | ||
1286 | /* Description: */ | ||
1287 | /* This function calls the library routine i2ServiceBoard for each board in */ | ||
1288 | /* the board table. This is used instead of the interrupt routine when polled */ | ||
1289 | /* mode is specified. */ | ||
1290 | /******************************************************************************/ | ||
1291 | static void | ||
1292 | ip2_poll(unsigned long arg) | ||
1293 | { | ||
1294 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); | ||
1295 | |||
1296 | // Just polled boards, IRQ = 0 will hit all non-interrupt boards. | ||
1297 | // It will NOT poll boards handled by hard interrupts. | ||
1298 | // The issue of queued BH interrupts is handled in ip2_interrupt(). | ||
1299 | ip2_polled_interrupt(); | ||
1300 | |||
1301 | mod_timer(&PollTimer, POLL_TIMEOUT); | ||
1302 | |||
1303 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); | ||
1304 | } | ||
1305 | |||
1306 | static void do_input(struct work_struct *work) | ||
1307 | { | ||
1308 | i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input); | ||
1309 | unsigned long flags; | ||
1310 | |||
1311 | ip2trace(CHANN, ITRC_INPUT, 21, 0 ); | ||
1312 | |||
1313 | // Data input | ||
1314 | if ( pCh->pTTY != NULL ) { | ||
1315 | read_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
1316 | if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) { | ||
1317 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
1318 | i2Input( pCh ); | ||
1319 | } else | ||
1320 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
1321 | } else { | ||
1322 | ip2trace(CHANN, ITRC_INPUT, 22, 0 ); | ||
1323 | |||
1324 | i2InputFlush( pCh ); | ||
1325 | } | ||
1326 | } | ||
1327 | |||
1328 | // code duplicated from n_tty (ldisc) | ||
1329 | static inline void isig(int sig, struct tty_struct *tty, int flush) | ||
1330 | { | ||
1331 | /* FIXME: This is completely bogus */ | ||
1332 | if (tty->pgrp) | ||
1333 | kill_pgrp(tty->pgrp, sig, 1); | ||
1334 | if (flush || !L_NOFLSH(tty)) { | ||
1335 | if ( tty->ldisc->ops->flush_buffer ) | ||
1336 | tty->ldisc->ops->flush_buffer(tty); | ||
1337 | i2InputFlush( tty->driver_data ); | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | static void do_status(struct work_struct *work) | ||
1342 | { | ||
1343 | i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status); | ||
1344 | int status; | ||
1345 | |||
1346 | status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); | ||
1347 | |||
1348 | ip2trace (CHANN, ITRC_STATUS, 21, 1, status ); | ||
1349 | |||
1350 | if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) { | ||
1351 | if ( (status & I2_BRK) ) { | ||
1352 | // code duplicated from n_tty (ldisc) | ||
1353 | if (I_IGNBRK(pCh->pTTY)) | ||
1354 | goto skip_this; | ||
1355 | if (I_BRKINT(pCh->pTTY)) { | ||
1356 | isig(SIGINT, pCh->pTTY, 1); | ||
1357 | goto skip_this; | ||
1358 | } | ||
1359 | wake_up_interruptible(&pCh->pTTY->read_wait); | ||
1360 | } | ||
1361 | #ifdef NEVER_HAPPENS_AS_SETUP_XXX | ||
1362 | // and can't work because we don't know the_char | ||
1363 | // as the_char is reported on a separate path | ||
1364 | // The intelligent board does this stuff as setup | ||
1365 | { | ||
1366 | char brkf = TTY_NORMAL; | ||
1367 | unsigned char brkc = '\0'; | ||
1368 | unsigned char tmp; | ||
1369 | if ( (status & I2_BRK) ) { | ||
1370 | brkf = TTY_BREAK; | ||
1371 | brkc = '\0'; | ||
1372 | } | ||
1373 | else if (status & I2_PAR) { | ||
1374 | brkf = TTY_PARITY; | ||
1375 | brkc = the_char; | ||
1376 | } else if (status & I2_FRA) { | ||
1377 | brkf = TTY_FRAME; | ||
1378 | brkc = the_char; | ||
1379 | } else if (status & I2_OVR) { | ||
1380 | brkf = TTY_OVERRUN; | ||
1381 | brkc = the_char; | ||
1382 | } | ||
1383 | tmp = pCh->pTTY->real_raw; | ||
1384 | pCh->pTTY->real_raw = 0; | ||
1385 | pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); | ||
1386 | pCh->pTTY->real_raw = tmp; | ||
1387 | } | ||
1388 | #endif /* NEVER_HAPPENS_AS_SETUP_XXX */ | ||
1389 | } | ||
1390 | skip_this: | ||
1391 | |||
1392 | if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) { | ||
1393 | wake_up_interruptible(&pCh->delta_msr_wait); | ||
1394 | |||
1395 | if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) { | ||
1396 | if ( status & I2_DCD ) { | ||
1397 | if ( pCh->wopen ) { | ||
1398 | wake_up_interruptible ( &pCh->open_wait ); | ||
1399 | } | ||
1400 | } else { | ||
1401 | if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) { | ||
1402 | tty_hangup( pCh->pTTY ); | ||
1403 | } | ||
1404 | } | ||
1405 | } | ||
1406 | } | ||
1407 | |||
1408 | ip2trace (CHANN, ITRC_STATUS, 26, 0 ); | ||
1409 | } | ||
1410 | |||
1411 | /******************************************************************************/ | ||
1412 | /* Device Open/Close/Ioctl Entry Point Section */ | ||
1413 | /******************************************************************************/ | ||
1414 | |||
1415 | /******************************************************************************/ | ||
1416 | /* Function: open_sanity_check() */ | ||
1417 | /* Parameters: Pointer to tty structure */ | ||
1418 | /* Pointer to file structure */ | ||
1419 | /* Returns: Success or failure */ | ||
1420 | /* */ | ||
1421 | /* Description: */ | ||
1422 | /* Verifies the structure magic numbers and cross links. */ | ||
1423 | /******************************************************************************/ | ||
1424 | #ifdef IP2DEBUG_OPEN | ||
1425 | static void | ||
1426 | open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd ) | ||
1427 | { | ||
1428 | if ( pBrd->i2eValid != I2E_MAGIC ) { | ||
1429 | printk(KERN_ERR "IP2: invalid board structure\n" ); | ||
1430 | } else if ( pBrd != pCh->pMyBord ) { | ||
1431 | printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n", | ||
1432 | pCh->pMyBord ); | ||
1433 | } else if ( pBrd->i2eChannelCnt < pCh->port_index ) { | ||
1434 | printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index ); | ||
1435 | } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) { | ||
1436 | } else { | ||
1437 | printk(KERN_INFO "IP2: all pointers check out!\n" ); | ||
1438 | } | ||
1439 | } | ||
1440 | #endif | ||
1441 | |||
1442 | |||
1443 | /******************************************************************************/ | ||
1444 | /* Function: ip2_open() */ | ||
1445 | /* Parameters: Pointer to tty structure */ | ||
1446 | /* Pointer to file structure */ | ||
1447 | /* Returns: Success or failure */ | ||
1448 | /* */ | ||
1449 | /* Description: (MANDATORY) */ | ||
1450 | /* A successful device open has to run a gauntlet of checks before it */ | ||
1451 | /* completes. After some sanity checking and pointer setup, the function */ | ||
1452 | /* blocks until all conditions are satisfied. It then initialises the port to */ | ||
1453 | /* the default characteristics and returns. */ | ||
1454 | /******************************************************************************/ | ||
1455 | static int | ||
1456 | ip2_open( PTTY tty, struct file *pFile ) | ||
1457 | { | ||
1458 | wait_queue_t wait; | ||
1459 | int rc = 0; | ||
1460 | int do_clocal = 0; | ||
1461 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
1462 | |||
1463 | ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 ); | ||
1464 | |||
1465 | if ( pCh == NULL ) { | ||
1466 | return -ENODEV; | ||
1467 | } | ||
1468 | /* Setup pointer links in device and tty structures */ | ||
1469 | pCh->pTTY = tty; | ||
1470 | tty->driver_data = pCh; | ||
1471 | |||
1472 | #ifdef IP2DEBUG_OPEN | ||
1473 | printk(KERN_DEBUG \ | ||
1474 | "IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n", | ||
1475 | tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index); | ||
1476 | open_sanity_check ( pCh, pCh->pMyBord ); | ||
1477 | #endif | ||
1478 | |||
1479 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP); | ||
1480 | pCh->dataSetOut |= (I2_DTR | I2_RTS); | ||
1481 | serviceOutgoingFifo( pCh->pMyBord ); | ||
1482 | |||
1483 | /* Block here until the port is ready (per serial and istallion) */ | ||
1484 | /* | ||
1485 | * 1. If the port is in the middle of closing wait for the completion | ||
1486 | * and then return the appropriate error. | ||
1487 | */ | ||
1488 | init_waitqueue_entry(&wait, current); | ||
1489 | add_wait_queue(&pCh->close_wait, &wait); | ||
1490 | set_current_state( TASK_INTERRUPTIBLE ); | ||
1491 | |||
1492 | if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { | ||
1493 | if ( pCh->flags & ASYNC_CLOSING ) { | ||
1494 | tty_unlock(); | ||
1495 | schedule(); | ||
1496 | tty_lock(); | ||
1497 | } | ||
1498 | if ( tty_hung_up_p(pFile) ) { | ||
1499 | set_current_state( TASK_RUNNING ); | ||
1500 | remove_wait_queue(&pCh->close_wait, &wait); | ||
1501 | return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS; | ||
1502 | } | ||
1503 | } | ||
1504 | set_current_state( TASK_RUNNING ); | ||
1505 | remove_wait_queue(&pCh->close_wait, &wait); | ||
1506 | |||
1507 | /* | ||
1508 | * 3. Handle a non-blocking open of a normal port. | ||
1509 | */ | ||
1510 | if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) { | ||
1511 | pCh->flags |= ASYNC_NORMAL_ACTIVE; | ||
1512 | goto noblock; | ||
1513 | } | ||
1514 | /* | ||
1515 | * 4. Now loop waiting for the port to be free and carrier present | ||
1516 | * (if required). | ||
1517 | */ | ||
1518 | if ( tty->termios->c_cflag & CLOCAL ) | ||
1519 | do_clocal = 1; | ||
1520 | |||
1521 | #ifdef IP2DEBUG_OPEN | ||
1522 | printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal); | ||
1523 | #endif | ||
1524 | |||
1525 | ++pCh->wopen; | ||
1526 | |||
1527 | init_waitqueue_entry(&wait, current); | ||
1528 | add_wait_queue(&pCh->open_wait, &wait); | ||
1529 | |||
1530 | for(;;) { | ||
1531 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); | ||
1532 | pCh->dataSetOut |= (I2_DTR | I2_RTS); | ||
1533 | set_current_state( TASK_INTERRUPTIBLE ); | ||
1534 | serviceOutgoingFifo( pCh->pMyBord ); | ||
1535 | if ( tty_hung_up_p(pFile) ) { | ||
1536 | set_current_state( TASK_RUNNING ); | ||
1537 | remove_wait_queue(&pCh->open_wait, &wait); | ||
1538 | return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS; | ||
1539 | } | ||
1540 | if (!(pCh->flags & ASYNC_CLOSING) && | ||
1541 | (do_clocal || (pCh->dataSetIn & I2_DCD) )) { | ||
1542 | rc = 0; | ||
1543 | break; | ||
1544 | } | ||
1545 | |||
1546 | #ifdef IP2DEBUG_OPEN | ||
1547 | printk(KERN_DEBUG "ASYNC_CLOSING = %s\n", | ||
1548 | (pCh->flags & ASYNC_CLOSING)?"True":"False"); | ||
1549 | printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n"); | ||
1550 | #endif | ||
1551 | ip2trace (CHANN, ITRC_OPEN, 3, 2, 0, | ||
1552 | (pCh->flags & ASYNC_CLOSING) ); | ||
1553 | /* check for signal */ | ||
1554 | if (signal_pending(current)) { | ||
1555 | rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); | ||
1556 | break; | ||
1557 | } | ||
1558 | tty_unlock(); | ||
1559 | schedule(); | ||
1560 | tty_lock(); | ||
1561 | } | ||
1562 | set_current_state( TASK_RUNNING ); | ||
1563 | remove_wait_queue(&pCh->open_wait, &wait); | ||
1564 | |||
1565 | --pCh->wopen; //why count? | ||
1566 | |||
1567 | ip2trace (CHANN, ITRC_OPEN, 4, 0 ); | ||
1568 | |||
1569 | if (rc != 0 ) { | ||
1570 | return rc; | ||
1571 | } | ||
1572 | pCh->flags |= ASYNC_NORMAL_ACTIVE; | ||
1573 | |||
1574 | noblock: | ||
1575 | |||
1576 | /* first open - Assign termios structure to port */ | ||
1577 | if ( tty->count == 1 ) { | ||
1578 | i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); | ||
1579 | /* Now we must send the termios settings to the loadware */ | ||
1580 | set_params( pCh, NULL ); | ||
1581 | } | ||
1582 | |||
1583 | /* | ||
1584 | * Now set any i2lib options. These may go away if the i2lib code ends | ||
1585 | * up rolled into the mainline. | ||
1586 | */ | ||
1587 | pCh->channelOptions |= CO_NBLOCK_WRITE; | ||
1588 | |||
1589 | #ifdef IP2DEBUG_OPEN | ||
1590 | printk (KERN_DEBUG "IP2: open completed\n" ); | ||
1591 | #endif | ||
1592 | serviceOutgoingFifo( pCh->pMyBord ); | ||
1593 | |||
1594 | ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 ); | ||
1595 | |||
1596 | return 0; | ||
1597 | } | ||
1598 | |||
1599 | /******************************************************************************/ | ||
1600 | /* Function: ip2_close() */ | ||
1601 | /* Parameters: Pointer to tty structure */ | ||
1602 | /* Pointer to file structure */ | ||
1603 | /* Returns: Nothing */ | ||
1604 | /* */ | ||
1605 | /* Description: */ | ||
1606 | /* */ | ||
1607 | /* */ | ||
1608 | /******************************************************************************/ | ||
1609 | static void | ||
1610 | ip2_close( PTTY tty, struct file *pFile ) | ||
1611 | { | ||
1612 | i2ChanStrPtr pCh = tty->driver_data; | ||
1613 | |||
1614 | if ( !pCh ) { | ||
1615 | return; | ||
1616 | } | ||
1617 | |||
1618 | ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 ); | ||
1619 | |||
1620 | #ifdef IP2DEBUG_OPEN | ||
1621 | printk(KERN_DEBUG "IP2:close %s:\n",tty->name); | ||
1622 | #endif | ||
1623 | |||
1624 | if ( tty_hung_up_p ( pFile ) ) { | ||
1625 | |||
1626 | ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); | ||
1627 | |||
1628 | return; | ||
1629 | } | ||
1630 | if ( tty->count > 1 ) { /* not the last close */ | ||
1631 | |||
1632 | ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); | ||
1633 | |||
1634 | return; | ||
1635 | } | ||
1636 | pCh->flags |= ASYNC_CLOSING; // last close actually | ||
1637 | |||
1638 | tty->closing = 1; | ||
1639 | |||
1640 | if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) { | ||
1641 | /* | ||
1642 | * Before we drop DTR, make sure the transmitter has completely drained. | ||
1643 | * This uses an timeout, after which the close | ||
1644 | * completes. | ||
1645 | */ | ||
1646 | ip2_wait_until_sent(tty, pCh->ClosingWaitTime ); | ||
1647 | } | ||
1648 | /* | ||
1649 | * At this point we stop accepting input. Here we flush the channel | ||
1650 | * input buffer which will allow the board to send up more data. Any | ||
1651 | * additional input is tossed at interrupt/poll time. | ||
1652 | */ | ||
1653 | i2InputFlush( pCh ); | ||
1654 | |||
1655 | /* disable DSS reporting */ | ||
1656 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, | ||
1657 | CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); | ||
1658 | if (tty->termios->c_cflag & HUPCL) { | ||
1659 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); | ||
1660 | pCh->dataSetOut &= ~(I2_DTR | I2_RTS); | ||
1661 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); | ||
1662 | } | ||
1663 | |||
1664 | serviceOutgoingFifo ( pCh->pMyBord ); | ||
1665 | |||
1666 | tty_ldisc_flush(tty); | ||
1667 | tty_driver_flush_buffer(tty); | ||
1668 | tty->closing = 0; | ||
1669 | |||
1670 | pCh->pTTY = NULL; | ||
1671 | |||
1672 | if (pCh->wopen) { | ||
1673 | if (pCh->ClosingDelay) { | ||
1674 | msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay)); | ||
1675 | } | ||
1676 | wake_up_interruptible(&pCh->open_wait); | ||
1677 | } | ||
1678 | |||
1679 | pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
1680 | wake_up_interruptible(&pCh->close_wait); | ||
1681 | |||
1682 | #ifdef IP2DEBUG_OPEN | ||
1683 | DBG_CNT("ip2_close: after wakeups--"); | ||
1684 | #endif | ||
1685 | |||
1686 | |||
1687 | ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); | ||
1688 | |||
1689 | return; | ||
1690 | } | ||
1691 | |||
1692 | /******************************************************************************/ | ||
1693 | /* Function: ip2_hangup() */ | ||
1694 | /* Parameters: Pointer to tty structure */ | ||
1695 | /* Returns: Nothing */ | ||
1696 | /* */ | ||
1697 | /* Description: */ | ||
1698 | /* */ | ||
1699 | /* */ | ||
1700 | /******************************************************************************/ | ||
1701 | static void | ||
1702 | ip2_hangup ( PTTY tty ) | ||
1703 | { | ||
1704 | i2ChanStrPtr pCh = tty->driver_data; | ||
1705 | |||
1706 | if( !pCh ) { | ||
1707 | return; | ||
1708 | } | ||
1709 | |||
1710 | ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 ); | ||
1711 | |||
1712 | ip2_flush_buffer(tty); | ||
1713 | |||
1714 | /* disable DSS reporting */ | ||
1715 | |||
1716 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP); | ||
1717 | i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); | ||
1718 | if ( (tty->termios->c_cflag & HUPCL) ) { | ||
1719 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN); | ||
1720 | pCh->dataSetOut &= ~(I2_DTR | I2_RTS); | ||
1721 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); | ||
1722 | } | ||
1723 | i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, | ||
1724 | CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); | ||
1725 | serviceOutgoingFifo ( pCh->pMyBord ); | ||
1726 | |||
1727 | wake_up_interruptible ( &pCh->delta_msr_wait ); | ||
1728 | |||
1729 | pCh->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1730 | pCh->pTTY = NULL; | ||
1731 | wake_up_interruptible ( &pCh->open_wait ); | ||
1732 | |||
1733 | ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 ); | ||
1734 | } | ||
1735 | |||
1736 | /******************************************************************************/ | ||
1737 | /******************************************************************************/ | ||
1738 | /* Device Output Section */ | ||
1739 | /******************************************************************************/ | ||
1740 | /******************************************************************************/ | ||
1741 | |||
1742 | /******************************************************************************/ | ||
1743 | /* Function: ip2_write() */ | ||
1744 | /* Parameters: Pointer to tty structure */ | ||
1745 | /* Flag denoting data is in user (1) or kernel (0) space */ | ||
1746 | /* Pointer to data */ | ||
1747 | /* Number of bytes to write */ | ||
1748 | /* Returns: Number of bytes actually written */ | ||
1749 | /* */ | ||
1750 | /* Description: (MANDATORY) */ | ||
1751 | /* */ | ||
1752 | /* */ | ||
1753 | /******************************************************************************/ | ||
1754 | static int | ||
1755 | ip2_write( PTTY tty, const unsigned char *pData, int count) | ||
1756 | { | ||
1757 | i2ChanStrPtr pCh = tty->driver_data; | ||
1758 | int bytesSent = 0; | ||
1759 | unsigned long flags; | ||
1760 | |||
1761 | ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 ); | ||
1762 | |||
1763 | /* Flush out any buffered data left over from ip2_putchar() calls. */ | ||
1764 | ip2_flush_chars( tty ); | ||
1765 | |||
1766 | /* This is the actual move bit. Make sure it does what we need!!!!! */ | ||
1767 | write_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1768 | bytesSent = i2Output( pCh, pData, count); | ||
1769 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1770 | |||
1771 | ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); | ||
1772 | |||
1773 | return bytesSent > 0 ? bytesSent : 0; | ||
1774 | } | ||
1775 | |||
1776 | /******************************************************************************/ | ||
1777 | /* Function: ip2_putchar() */ | ||
1778 | /* Parameters: Pointer to tty structure */ | ||
1779 | /* Character to write */ | ||
1780 | /* Returns: Nothing */ | ||
1781 | /* */ | ||
1782 | /* Description: */ | ||
1783 | /* */ | ||
1784 | /* */ | ||
1785 | /******************************************************************************/ | ||
1786 | static int | ||
1787 | ip2_putchar( PTTY tty, unsigned char ch ) | ||
1788 | { | ||
1789 | i2ChanStrPtr pCh = tty->driver_data; | ||
1790 | unsigned long flags; | ||
1791 | |||
1792 | // ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch ); | ||
1793 | |||
1794 | write_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1795 | pCh->Pbuf[pCh->Pbuf_stuff++] = ch; | ||
1796 | if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) { | ||
1797 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1798 | ip2_flush_chars( tty ); | ||
1799 | } else | ||
1800 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1801 | return 1; | ||
1802 | |||
1803 | // ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); | ||
1804 | } | ||
1805 | |||
1806 | /******************************************************************************/ | ||
1807 | /* Function: ip2_flush_chars() */ | ||
1808 | /* Parameters: Pointer to tty structure */ | ||
1809 | /* Returns: Nothing */ | ||
1810 | /* */ | ||
1811 | /* Description: */ | ||
1812 | /* */ | ||
1813 | /******************************************************************************/ | ||
1814 | static void | ||
1815 | ip2_flush_chars( PTTY tty ) | ||
1816 | { | ||
1817 | int strip; | ||
1818 | i2ChanStrPtr pCh = tty->driver_data; | ||
1819 | unsigned long flags; | ||
1820 | |||
1821 | write_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1822 | if ( pCh->Pbuf_stuff ) { | ||
1823 | |||
1824 | // ip2trace (CHANN, ITRC_PUTC, 10, 1, strip ); | ||
1825 | |||
1826 | // | ||
1827 | // We may need to restart i2Output if it does not fullfill this request | ||
1828 | // | ||
1829 | strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff); | ||
1830 | if ( strip != pCh->Pbuf_stuff ) { | ||
1831 | memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); | ||
1832 | } | ||
1833 | pCh->Pbuf_stuff -= strip; | ||
1834 | } | ||
1835 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1836 | } | ||
1837 | |||
1838 | /******************************************************************************/ | ||
1839 | /* Function: ip2_write_room() */ | ||
1840 | /* Parameters: Pointer to tty structure */ | ||
1841 | /* Returns: Number of bytes that the driver can accept */ | ||
1842 | /* */ | ||
1843 | /* Description: */ | ||
1844 | /* */ | ||
1845 | /******************************************************************************/ | ||
1846 | static int | ||
1847 | ip2_write_room ( PTTY tty ) | ||
1848 | { | ||
1849 | int bytesFree; | ||
1850 | i2ChanStrPtr pCh = tty->driver_data; | ||
1851 | unsigned long flags; | ||
1852 | |||
1853 | read_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1854 | bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff; | ||
1855 | read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1856 | |||
1857 | ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree ); | ||
1858 | |||
1859 | return ((bytesFree > 0) ? bytesFree : 0); | ||
1860 | } | ||
1861 | |||
1862 | /******************************************************************************/ | ||
1863 | /* Function: ip2_chars_in_buf() */ | ||
1864 | /* Parameters: Pointer to tty structure */ | ||
1865 | /* Returns: Number of bytes queued for transmission */ | ||
1866 | /* */ | ||
1867 | /* Description: */ | ||
1868 | /* */ | ||
1869 | /* */ | ||
1870 | /******************************************************************************/ | ||
1871 | static int | ||
1872 | ip2_chars_in_buf ( PTTY tty ) | ||
1873 | { | ||
1874 | i2ChanStrPtr pCh = tty->driver_data; | ||
1875 | int rc; | ||
1876 | unsigned long flags; | ||
1877 | |||
1878 | ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff ); | ||
1879 | |||
1880 | #ifdef IP2DEBUG_WRITE | ||
1881 | printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n", | ||
1882 | pCh->Obuf_char_count + pCh->Pbuf_stuff, | ||
1883 | pCh->Obuf_char_count, pCh->Pbuf_stuff ); | ||
1884 | #endif | ||
1885 | read_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
1886 | rc = pCh->Obuf_char_count; | ||
1887 | read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
1888 | read_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1889 | rc += pCh->Pbuf_stuff; | ||
1890 | read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1891 | return rc; | ||
1892 | } | ||
1893 | |||
1894 | /******************************************************************************/ | ||
1895 | /* Function: ip2_flush_buffer() */ | ||
1896 | /* Parameters: Pointer to tty structure */ | ||
1897 | /* Returns: Nothing */ | ||
1898 | /* */ | ||
1899 | /* Description: */ | ||
1900 | /* */ | ||
1901 | /* */ | ||
1902 | /******************************************************************************/ | ||
1903 | static void | ||
1904 | ip2_flush_buffer( PTTY tty ) | ||
1905 | { | ||
1906 | i2ChanStrPtr pCh = tty->driver_data; | ||
1907 | unsigned long flags; | ||
1908 | |||
1909 | ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 ); | ||
1910 | |||
1911 | #ifdef IP2DEBUG_WRITE | ||
1912 | printk (KERN_DEBUG "IP2: flush buffer\n" ); | ||
1913 | #endif | ||
1914 | write_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1915 | pCh->Pbuf_stuff = 0; | ||
1916 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1917 | i2FlushOutput( pCh ); | ||
1918 | ip2_owake(tty); | ||
1919 | |||
1920 | ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 ); | ||
1921 | |||
1922 | } | ||
1923 | |||
1924 | /******************************************************************************/ | ||
1925 | /* Function: ip2_wait_until_sent() */ | ||
1926 | /* Parameters: Pointer to tty structure */ | ||
1927 | /* Timeout for wait. */ | ||
1928 | /* Returns: Nothing */ | ||
1929 | /* */ | ||
1930 | /* Description: */ | ||
1931 | /* This function is used in place of the normal tty_wait_until_sent, which */ | ||
1932 | /* only waits for the driver buffers to be empty (or rather, those buffers */ | ||
1933 | /* reported by chars_in_buffer) which doesn't work for IP2 due to the */ | ||
1934 | /* indeterminate number of bytes buffered on the board. */ | ||
1935 | /******************************************************************************/ | ||
1936 | static void | ||
1937 | ip2_wait_until_sent ( PTTY tty, int timeout ) | ||
1938 | { | ||
1939 | int i = jiffies; | ||
1940 | i2ChanStrPtr pCh = tty->driver_data; | ||
1941 | |||
1942 | tty_wait_until_sent(tty, timeout ); | ||
1943 | if ( (i = timeout - (jiffies -i)) > 0) | ||
1944 | i2DrainOutput( pCh, i ); | ||
1945 | } | ||
1946 | |||
1947 | /******************************************************************************/ | ||
1948 | /******************************************************************************/ | ||
1949 | /* Device Input Section */ | ||
1950 | /******************************************************************************/ | ||
1951 | /******************************************************************************/ | ||
1952 | |||
1953 | /******************************************************************************/ | ||
1954 | /* Function: ip2_throttle() */ | ||
1955 | /* Parameters: Pointer to tty structure */ | ||
1956 | /* Returns: Nothing */ | ||
1957 | /* */ | ||
1958 | /* Description: */ | ||
1959 | /* */ | ||
1960 | /* */ | ||
1961 | /******************************************************************************/ | ||
1962 | static void | ||
1963 | ip2_throttle ( PTTY tty ) | ||
1964 | { | ||
1965 | i2ChanStrPtr pCh = tty->driver_data; | ||
1966 | |||
1967 | #ifdef IP2DEBUG_READ | ||
1968 | printk (KERN_DEBUG "IP2: throttle\n" ); | ||
1969 | #endif | ||
1970 | /* | ||
1971 | * Signal the poll/interrupt handlers not to forward incoming data to | ||
1972 | * the line discipline. This will cause the buffers to fill up in the | ||
1973 | * library and thus cause the library routines to send the flow control | ||
1974 | * stuff. | ||
1975 | */ | ||
1976 | pCh->throttled = 1; | ||
1977 | } | ||
1978 | |||
1979 | /******************************************************************************/ | ||
1980 | /* Function: ip2_unthrottle() */ | ||
1981 | /* Parameters: Pointer to tty structure */ | ||
1982 | /* Returns: Nothing */ | ||
1983 | /* */ | ||
1984 | /* Description: */ | ||
1985 | /* */ | ||
1986 | /* */ | ||
1987 | /******************************************************************************/ | ||
1988 | static void | ||
1989 | ip2_unthrottle ( PTTY tty ) | ||
1990 | { | ||
1991 | i2ChanStrPtr pCh = tty->driver_data; | ||
1992 | unsigned long flags; | ||
1993 | |||
1994 | #ifdef IP2DEBUG_READ | ||
1995 | printk (KERN_DEBUG "IP2: unthrottle\n" ); | ||
1996 | #endif | ||
1997 | |||
1998 | /* Pass incoming data up to the line discipline again. */ | ||
1999 | pCh->throttled = 0; | ||
2000 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); | ||
2001 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2002 | read_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
2003 | if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) { | ||
2004 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
2005 | #ifdef IP2DEBUG_READ | ||
2006 | printk (KERN_DEBUG "i2Input called from unthrottle\n" ); | ||
2007 | #endif | ||
2008 | i2Input( pCh ); | ||
2009 | } else | ||
2010 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
2011 | } | ||
2012 | |||
2013 | static void | ||
2014 | ip2_start ( PTTY tty ) | ||
2015 | { | ||
2016 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2017 | |||
2018 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); | ||
2019 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND); | ||
2020 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME); | ||
2021 | #ifdef IP2DEBUG_WRITE | ||
2022 | printk (KERN_DEBUG "IP2: start tx\n" ); | ||
2023 | #endif | ||
2024 | } | ||
2025 | |||
2026 | static void | ||
2027 | ip2_stop ( PTTY tty ) | ||
2028 | { | ||
2029 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2030 | |||
2031 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND); | ||
2032 | #ifdef IP2DEBUG_WRITE | ||
2033 | printk (KERN_DEBUG "IP2: stop tx\n" ); | ||
2034 | #endif | ||
2035 | } | ||
2036 | |||
2037 | /******************************************************************************/ | ||
2038 | /* Device Ioctl Section */ | ||
2039 | /******************************************************************************/ | ||
2040 | |||
2041 | static int ip2_tiocmget(struct tty_struct *tty) | ||
2042 | { | ||
2043 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2044 | #ifdef ENABLE_DSSNOW | ||
2045 | wait_queue_t wait; | ||
2046 | #endif | ||
2047 | |||
2048 | if (pCh == NULL) | ||
2049 | return -ENODEV; | ||
2050 | |||
2051 | /* | ||
2052 | FIXME - the following code is causing a NULL pointer dereference in | ||
2053 | 2.3.51 in an interrupt handler. It's suppose to prompt the board | ||
2054 | to return the DSS signal status immediately. Why doesn't it do | ||
2055 | the same thing in 2.2.14? | ||
2056 | */ | ||
2057 | |||
2058 | /* This thing is still busted in the 1.2.12 driver on 2.4.x | ||
2059 | and even hoses the serial console so the oops can be trapped. | ||
2060 | /\/\|=mhw=|\/\/ */ | ||
2061 | |||
2062 | #ifdef ENABLE_DSSNOW | ||
2063 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW); | ||
2064 | |||
2065 | init_waitqueue_entry(&wait, current); | ||
2066 | add_wait_queue(&pCh->dss_now_wait, &wait); | ||
2067 | set_current_state( TASK_INTERRUPTIBLE ); | ||
2068 | |||
2069 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2070 | |||
2071 | schedule(); | ||
2072 | |||
2073 | set_current_state( TASK_RUNNING ); | ||
2074 | remove_wait_queue(&pCh->dss_now_wait, &wait); | ||
2075 | |||
2076 | if (signal_pending(current)) { | ||
2077 | return -EINTR; | ||
2078 | } | ||
2079 | #endif | ||
2080 | return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) | ||
2081 | | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) | ||
2082 | | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) | ||
2083 | | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0) | ||
2084 | | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0) | ||
2085 | | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0); | ||
2086 | } | ||
2087 | |||
2088 | static int ip2_tiocmset(struct tty_struct *tty, | ||
2089 | unsigned int set, unsigned int clear) | ||
2090 | { | ||
2091 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2092 | |||
2093 | if (pCh == NULL) | ||
2094 | return -ENODEV; | ||
2095 | |||
2096 | if (set & TIOCM_RTS) { | ||
2097 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); | ||
2098 | pCh->dataSetOut |= I2_RTS; | ||
2099 | } | ||
2100 | if (set & TIOCM_DTR) { | ||
2101 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); | ||
2102 | pCh->dataSetOut |= I2_DTR; | ||
2103 | } | ||
2104 | |||
2105 | if (clear & TIOCM_RTS) { | ||
2106 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); | ||
2107 | pCh->dataSetOut &= ~I2_RTS; | ||
2108 | } | ||
2109 | if (clear & TIOCM_DTR) { | ||
2110 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); | ||
2111 | pCh->dataSetOut &= ~I2_DTR; | ||
2112 | } | ||
2113 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2114 | return 0; | ||
2115 | } | ||
2116 | |||
2117 | /******************************************************************************/ | ||
2118 | /* Function: ip2_ioctl() */ | ||
2119 | /* Parameters: Pointer to tty structure */ | ||
2120 | /* Pointer to file structure */ | ||
2121 | /* Command */ | ||
2122 | /* Argument */ | ||
2123 | /* Returns: Success or failure */ | ||
2124 | /* */ | ||
2125 | /* Description: */ | ||
2126 | /* */ | ||
2127 | /* */ | ||
2128 | /******************************************************************************/ | ||
2129 | static int | ||
2130 | ip2_ioctl ( PTTY tty, UINT cmd, ULONG arg ) | ||
2131 | { | ||
2132 | wait_queue_t wait; | ||
2133 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2134 | i2eBordStrPtr pB; | ||
2135 | struct async_icount cprev, cnow; /* kernel counter temps */ | ||
2136 | int rc = 0; | ||
2137 | unsigned long flags; | ||
2138 | void __user *argp = (void __user *)arg; | ||
2139 | |||
2140 | if ( pCh == NULL ) | ||
2141 | return -ENODEV; | ||
2142 | |||
2143 | pB = pCh->pMyBord; | ||
2144 | |||
2145 | ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg ); | ||
2146 | |||
2147 | #ifdef IP2DEBUG_IOCTL | ||
2148 | printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg ); | ||
2149 | #endif | ||
2150 | |||
2151 | switch(cmd) { | ||
2152 | case TIOCGSERIAL: | ||
2153 | |||
2154 | ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc ); | ||
2155 | |||
2156 | rc = get_serial_info(pCh, argp); | ||
2157 | if (rc) | ||
2158 | return rc; | ||
2159 | break; | ||
2160 | |||
2161 | case TIOCSSERIAL: | ||
2162 | |||
2163 | ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc ); | ||
2164 | |||
2165 | rc = set_serial_info(pCh, argp); | ||
2166 | if (rc) | ||
2167 | return rc; | ||
2168 | break; | ||
2169 | |||
2170 | case TCXONC: | ||
2171 | rc = tty_check_change(tty); | ||
2172 | if (rc) | ||
2173 | return rc; | ||
2174 | switch (arg) { | ||
2175 | case TCOOFF: | ||
2176 | //return -ENOIOCTLCMD; | ||
2177 | break; | ||
2178 | case TCOON: | ||
2179 | //return -ENOIOCTLCMD; | ||
2180 | break; | ||
2181 | case TCIOFF: | ||
2182 | if (STOP_CHAR(tty) != __DISABLED_CHAR) { | ||
2183 | i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, | ||
2184 | CMD_XMIT_NOW(STOP_CHAR(tty))); | ||
2185 | } | ||
2186 | break; | ||
2187 | case TCION: | ||
2188 | if (START_CHAR(tty) != __DISABLED_CHAR) { | ||
2189 | i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, | ||
2190 | CMD_XMIT_NOW(START_CHAR(tty))); | ||
2191 | } | ||
2192 | break; | ||
2193 | default: | ||
2194 | return -EINVAL; | ||
2195 | } | ||
2196 | return 0; | ||
2197 | |||
2198 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | ||
2199 | rc = tty_check_change(tty); | ||
2200 | |||
2201 | ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc ); | ||
2202 | |||
2203 | if (!rc) { | ||
2204 | ip2_wait_until_sent(tty,0); | ||
2205 | if (!arg) { | ||
2206 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250)); | ||
2207 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2208 | } | ||
2209 | } | ||
2210 | break; | ||
2211 | |||
2212 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
2213 | rc = tty_check_change(tty); | ||
2214 | |||
2215 | ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc ); | ||
2216 | |||
2217 | if (!rc) { | ||
2218 | ip2_wait_until_sent(tty,0); | ||
2219 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, | ||
2220 | CMD_SEND_BRK(arg ? arg*100 : 250)); | ||
2221 | serviceOutgoingFifo ( pCh->pMyBord ); | ||
2222 | } | ||
2223 | break; | ||
2224 | |||
2225 | case TIOCGSOFTCAR: | ||
2226 | |||
2227 | ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc ); | ||
2228 | |||
2229 | rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); | ||
2230 | if (rc) | ||
2231 | return rc; | ||
2232 | break; | ||
2233 | |||
2234 | case TIOCSSOFTCAR: | ||
2235 | |||
2236 | ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc ); | ||
2237 | |||
2238 | rc = get_user(arg,(unsigned long __user *) argp); | ||
2239 | if (rc) | ||
2240 | return rc; | ||
2241 | tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | ||
2242 | | (arg ? CLOCAL : 0)); | ||
2243 | |||
2244 | break; | ||
2245 | |||
2246 | /* | ||
2247 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask | ||
2248 | * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS | ||
2249 | * for masking). Caller should use TIOCGICOUNT to see which one it was | ||
2250 | */ | ||
2251 | case TIOCMIWAIT: | ||
2252 | write_lock_irqsave(&pB->read_fifo_spinlock, flags); | ||
2253 | cprev = pCh->icount; /* note the counters on entry */ | ||
2254 | write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); | ||
2255 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, | ||
2256 | CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP); | ||
2257 | init_waitqueue_entry(&wait, current); | ||
2258 | add_wait_queue(&pCh->delta_msr_wait, &wait); | ||
2259 | set_current_state( TASK_INTERRUPTIBLE ); | ||
2260 | |||
2261 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2262 | for(;;) { | ||
2263 | ip2trace (CHANN, ITRC_IOCTL, 10, 0 ); | ||
2264 | |||
2265 | schedule(); | ||
2266 | |||
2267 | ip2trace (CHANN, ITRC_IOCTL, 11, 0 ); | ||
2268 | |||
2269 | /* see if a signal did it */ | ||
2270 | if (signal_pending(current)) { | ||
2271 | rc = -ERESTARTSYS; | ||
2272 | break; | ||
2273 | } | ||
2274 | write_lock_irqsave(&pB->read_fifo_spinlock, flags); | ||
2275 | cnow = pCh->icount; /* atomic copy */ | ||
2276 | write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); | ||
2277 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
2278 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { | ||
2279 | rc = -EIO; /* no change => rc */ | ||
2280 | break; | ||
2281 | } | ||
2282 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
2283 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
2284 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
2285 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { | ||
2286 | rc = 0; | ||
2287 | break; | ||
2288 | } | ||
2289 | cprev = cnow; | ||
2290 | } | ||
2291 | set_current_state( TASK_RUNNING ); | ||
2292 | remove_wait_queue(&pCh->delta_msr_wait, &wait); | ||
2293 | |||
2294 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, | ||
2295 | CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); | ||
2296 | if ( ! (pCh->flags & ASYNC_CHECK_CD)) { | ||
2297 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP); | ||
2298 | } | ||
2299 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2300 | return rc; | ||
2301 | break; | ||
2302 | |||
2303 | /* | ||
2304 | * The rest are not supported by this driver. By returning -ENOIOCTLCMD they | ||
2305 | * will be passed to the line discipline for it to handle. | ||
2306 | */ | ||
2307 | case TIOCSERCONFIG: | ||
2308 | case TIOCSERGWILD: | ||
2309 | case TIOCSERGETLSR: | ||
2310 | case TIOCSERSWILD: | ||
2311 | case TIOCSERGSTRUCT: | ||
2312 | case TIOCSERGETMULTI: | ||
2313 | case TIOCSERSETMULTI: | ||
2314 | |||
2315 | default: | ||
2316 | ip2trace (CHANN, ITRC_IOCTL, 12, 0 ); | ||
2317 | |||
2318 | rc = -ENOIOCTLCMD; | ||
2319 | break; | ||
2320 | } | ||
2321 | |||
2322 | ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 ); | ||
2323 | |||
2324 | return rc; | ||
2325 | } | ||
2326 | |||
2327 | static int ip2_get_icount(struct tty_struct *tty, | ||
2328 | struct serial_icounter_struct *icount) | ||
2329 | { | ||
2330 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2331 | i2eBordStrPtr pB; | ||
2332 | struct async_icount cnow; /* kernel counter temp */ | ||
2333 | unsigned long flags; | ||
2334 | |||
2335 | if ( pCh == NULL ) | ||
2336 | return -ENODEV; | ||
2337 | |||
2338 | pB = pCh->pMyBord; | ||
2339 | |||
2340 | /* | ||
2341 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
2342 | * Return: write counters to the user passed counter struct | ||
2343 | * NB: both 1->0 and 0->1 transitions are counted except for RI where | ||
2344 | * only 0->1 is counted. The controller is quite capable of counting | ||
2345 | * both, but this done to preserve compatibility with the standard | ||
2346 | * serial driver. | ||
2347 | */ | ||
2348 | |||
2349 | write_lock_irqsave(&pB->read_fifo_spinlock, flags); | ||
2350 | cnow = pCh->icount; | ||
2351 | write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); | ||
2352 | |||
2353 | icount->cts = cnow.cts; | ||
2354 | icount->dsr = cnow.dsr; | ||
2355 | icount->rng = cnow.rng; | ||
2356 | icount->dcd = cnow.dcd; | ||
2357 | icount->rx = cnow.rx; | ||
2358 | icount->tx = cnow.tx; | ||
2359 | icount->frame = cnow.frame; | ||
2360 | icount->overrun = cnow.overrun; | ||
2361 | icount->parity = cnow.parity; | ||
2362 | icount->brk = cnow.brk; | ||
2363 | icount->buf_overrun = cnow.buf_overrun; | ||
2364 | return 0; | ||
2365 | } | ||
2366 | |||
2367 | /******************************************************************************/ | ||
2368 | /* Function: GetSerialInfo() */ | ||
2369 | /* Parameters: Pointer to channel structure */ | ||
2370 | /* Pointer to old termios structure */ | ||
2371 | /* Returns: Nothing */ | ||
2372 | /* */ | ||
2373 | /* Description: */ | ||
2374 | /* This is to support the setserial command, and requires processing of the */ | ||
2375 | /* standard Linux serial structure. */ | ||
2376 | /******************************************************************************/ | ||
2377 | static int | ||
2378 | get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo ) | ||
2379 | { | ||
2380 | struct serial_struct tmp; | ||
2381 | |||
2382 | memset ( &tmp, 0, sizeof(tmp) ); | ||
2383 | tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16]; | ||
2384 | if (BID_HAS_654(tmp.type)) { | ||
2385 | tmp.type = PORT_16650; | ||
2386 | } else { | ||
2387 | tmp.type = PORT_CIRRUS; | ||
2388 | } | ||
2389 | tmp.line = pCh->port_index; | ||
2390 | tmp.port = pCh->pMyBord->i2eBase; | ||
2391 | tmp.irq = ip2config.irq[pCh->port_index/64]; | ||
2392 | tmp.flags = pCh->flags; | ||
2393 | tmp.baud_base = pCh->BaudBase; | ||
2394 | tmp.close_delay = pCh->ClosingDelay; | ||
2395 | tmp.closing_wait = pCh->ClosingWaitTime; | ||
2396 | tmp.custom_divisor = pCh->BaudDivisor; | ||
2397 | return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); | ||
2398 | } | ||
2399 | |||
2400 | /******************************************************************************/ | ||
2401 | /* Function: SetSerialInfo() */ | ||
2402 | /* Parameters: Pointer to channel structure */ | ||
2403 | /* Pointer to old termios structure */ | ||
2404 | /* Returns: Nothing */ | ||
2405 | /* */ | ||
2406 | /* Description: */ | ||
2407 | /* This function provides support for setserial, which uses the TIOCSSERIAL */ | ||
2408 | /* ioctl. Not all setserial parameters are relevant. If the user attempts to */ | ||
2409 | /* change the IRQ, address or type of the port the ioctl fails. */ | ||
2410 | /******************************************************************************/ | ||
2411 | static int | ||
2412 | set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) | ||
2413 | { | ||
2414 | struct serial_struct ns; | ||
2415 | int old_flags, old_baud_divisor; | ||
2416 | |||
2417 | if (copy_from_user(&ns, new_info, sizeof (ns))) | ||
2418 | return -EFAULT; | ||
2419 | |||
2420 | /* | ||
2421 | * We don't allow setserial to change IRQ, board address, type or baud | ||
2422 | * base. Also line nunber as such is meaningless but we use it for our | ||
2423 | * array index so it is fixed also. | ||
2424 | */ | ||
2425 | if ( (ns.irq != ip2config.irq[pCh->port_index]) | ||
2426 | || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase))) | ||
2427 | || (ns.baud_base != pCh->BaudBase) | ||
2428 | || (ns.line != pCh->port_index) ) { | ||
2429 | return -EINVAL; | ||
2430 | } | ||
2431 | |||
2432 | old_flags = pCh->flags; | ||
2433 | old_baud_divisor = pCh->BaudDivisor; | ||
2434 | |||
2435 | if ( !capable(CAP_SYS_ADMIN) ) { | ||
2436 | if ( ( ns.close_delay != pCh->ClosingDelay ) || | ||
2437 | ( (ns.flags & ~ASYNC_USR_MASK) != | ||
2438 | (pCh->flags & ~ASYNC_USR_MASK) ) ) { | ||
2439 | return -EPERM; | ||
2440 | } | ||
2441 | |||
2442 | pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) | | ||
2443 | (ns.flags & ASYNC_USR_MASK); | ||
2444 | pCh->BaudDivisor = ns.custom_divisor; | ||
2445 | } else { | ||
2446 | pCh->flags = (pCh->flags & ~ASYNC_FLAGS) | | ||
2447 | (ns.flags & ASYNC_FLAGS); | ||
2448 | pCh->BaudDivisor = ns.custom_divisor; | ||
2449 | pCh->ClosingDelay = ns.close_delay * HZ/100; | ||
2450 | pCh->ClosingWaitTime = ns.closing_wait * HZ/100; | ||
2451 | } | ||
2452 | |||
2453 | if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) ) | ||
2454 | || (old_baud_divisor != pCh->BaudDivisor) ) { | ||
2455 | // Invalidate speed and reset parameters | ||
2456 | set_params( pCh, NULL ); | ||
2457 | } | ||
2458 | |||
2459 | return 0; | ||
2460 | } | ||
2461 | |||
2462 | /******************************************************************************/ | ||
2463 | /* Function: ip2_set_termios() */ | ||
2464 | /* Parameters: Pointer to tty structure */ | ||
2465 | /* Pointer to old termios structure */ | ||
2466 | /* Returns: Nothing */ | ||
2467 | /* */ | ||
2468 | /* Description: */ | ||
2469 | /* */ | ||
2470 | /* */ | ||
2471 | /******************************************************************************/ | ||
2472 | static void | ||
2473 | ip2_set_termios( PTTY tty, struct ktermios *old_termios ) | ||
2474 | { | ||
2475 | i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; | ||
2476 | |||
2477 | #ifdef IP2DEBUG_IOCTL | ||
2478 | printk (KERN_DEBUG "IP2: set termios %p\n", old_termios ); | ||
2479 | #endif | ||
2480 | |||
2481 | set_params( pCh, old_termios ); | ||
2482 | } | ||
2483 | |||
2484 | /******************************************************************************/ | ||
2485 | /* Function: ip2_set_line_discipline() */ | ||
2486 | /* Parameters: Pointer to tty structure */ | ||
2487 | /* Returns: Nothing */ | ||
2488 | /* */ | ||
2489 | /* Description: Does nothing */ | ||
2490 | /* */ | ||
2491 | /* */ | ||
2492 | /******************************************************************************/ | ||
2493 | static void | ||
2494 | ip2_set_line_discipline ( PTTY tty ) | ||
2495 | { | ||
2496 | #ifdef IP2DEBUG_IOCTL | ||
2497 | printk (KERN_DEBUG "IP2: set line discipline\n" ); | ||
2498 | #endif | ||
2499 | |||
2500 | ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 ); | ||
2501 | |||
2502 | } | ||
2503 | |||
2504 | /******************************************************************************/ | ||
2505 | /* Function: SetLine Characteristics() */ | ||
2506 | /* Parameters: Pointer to channel structure */ | ||
2507 | /* Returns: Nothing */ | ||
2508 | /* */ | ||
2509 | /* Description: */ | ||
2510 | /* This routine is called to update the channel structure with the new line */ | ||
2511 | /* characteristics, and send the appropriate commands to the board when they */ | ||
2512 | /* change. */ | ||
2513 | /******************************************************************************/ | ||
2514 | static void | ||
2515 | set_params( i2ChanStrPtr pCh, struct ktermios *o_tios ) | ||
2516 | { | ||
2517 | tcflag_t cflag, iflag, lflag; | ||
2518 | char stop_char, start_char; | ||
2519 | struct ktermios dummy; | ||
2520 | |||
2521 | lflag = pCh->pTTY->termios->c_lflag; | ||
2522 | cflag = pCh->pTTY->termios->c_cflag; | ||
2523 | iflag = pCh->pTTY->termios->c_iflag; | ||
2524 | |||
2525 | if (o_tios == NULL) { | ||
2526 | dummy.c_lflag = ~lflag; | ||
2527 | dummy.c_cflag = ~cflag; | ||
2528 | dummy.c_iflag = ~iflag; | ||
2529 | o_tios = &dummy; | ||
2530 | } | ||
2531 | |||
2532 | { | ||
2533 | switch ( cflag & CBAUD ) { | ||
2534 | case B0: | ||
2535 | i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); | ||
2536 | pCh->dataSetOut &= ~(I2_DTR | I2_RTS); | ||
2537 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); | ||
2538 | pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag); | ||
2539 | goto service_it; | ||
2540 | break; | ||
2541 | case B38400: | ||
2542 | /* | ||
2543 | * This is the speed that is overloaded with all the other high | ||
2544 | * speeds, depending upon the flag settings. | ||
2545 | */ | ||
2546 | if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) { | ||
2547 | pCh->speed = CBR_57600; | ||
2548 | } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) { | ||
2549 | pCh->speed = CBR_115200; | ||
2550 | } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) { | ||
2551 | pCh->speed = CBR_C1; | ||
2552 | } else { | ||
2553 | pCh->speed = CBR_38400; | ||
2554 | } | ||
2555 | break; | ||
2556 | case B50: pCh->speed = CBR_50; break; | ||
2557 | case B75: pCh->speed = CBR_75; break; | ||
2558 | case B110: pCh->speed = CBR_110; break; | ||
2559 | case B134: pCh->speed = CBR_134; break; | ||
2560 | case B150: pCh->speed = CBR_150; break; | ||
2561 | case B200: pCh->speed = CBR_200; break; | ||
2562 | case B300: pCh->speed = CBR_300; break; | ||
2563 | case B600: pCh->speed = CBR_600; break; | ||
2564 | case B1200: pCh->speed = CBR_1200; break; | ||
2565 | case B1800: pCh->speed = CBR_1800; break; | ||
2566 | case B2400: pCh->speed = CBR_2400; break; | ||
2567 | case B4800: pCh->speed = CBR_4800; break; | ||
2568 | case B9600: pCh->speed = CBR_9600; break; | ||
2569 | case B19200: pCh->speed = CBR_19200; break; | ||
2570 | case B57600: pCh->speed = CBR_57600; break; | ||
2571 | case B115200: pCh->speed = CBR_115200; break; | ||
2572 | case B153600: pCh->speed = CBR_153600; break; | ||
2573 | case B230400: pCh->speed = CBR_230400; break; | ||
2574 | case B307200: pCh->speed = CBR_307200; break; | ||
2575 | case B460800: pCh->speed = CBR_460800; break; | ||
2576 | case B921600: pCh->speed = CBR_921600; break; | ||
2577 | default: pCh->speed = CBR_9600; break; | ||
2578 | } | ||
2579 | if ( pCh->speed == CBR_C1 ) { | ||
2580 | // Process the custom speed parameters. | ||
2581 | int bps = pCh->BaudBase / pCh->BaudDivisor; | ||
2582 | if ( bps == 921600 ) { | ||
2583 | pCh->speed = CBR_921600; | ||
2584 | } else { | ||
2585 | bps = bps/10; | ||
2586 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) ); | ||
2587 | } | ||
2588 | } | ||
2589 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed)); | ||
2590 | |||
2591 | i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); | ||
2592 | pCh->dataSetOut |= (I2_DTR | I2_RTS); | ||
2593 | } | ||
2594 | if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) | ||
2595 | { | ||
2596 | i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, | ||
2597 | CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1)); | ||
2598 | } | ||
2599 | if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) | ||
2600 | { | ||
2601 | i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, | ||
2602 | CMD_SETPAR( | ||
2603 | (cflag & PARENB ? (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP) | ||
2604 | ) | ||
2605 | ); | ||
2606 | } | ||
2607 | /* byte size and parity */ | ||
2608 | if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) | ||
2609 | { | ||
2610 | int datasize; | ||
2611 | switch ( cflag & CSIZE ) { | ||
2612 | case CS5: datasize = CSZ_5; break; | ||
2613 | case CS6: datasize = CSZ_6; break; | ||
2614 | case CS7: datasize = CSZ_7; break; | ||
2615 | case CS8: datasize = CSZ_8; break; | ||
2616 | default: datasize = CSZ_5; break; /* as per serial.c */ | ||
2617 | } | ||
2618 | i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) ); | ||
2619 | } | ||
2620 | /* Process CTS flow control flag setting */ | ||
2621 | if ( (cflag & CRTSCTS) ) { | ||
2622 | i2QueueCommands(PTYPE_INLINE, pCh, 100, | ||
2623 | 2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB); | ||
2624 | } else { | ||
2625 | i2QueueCommands(PTYPE_INLINE, pCh, 100, | ||
2626 | 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); | ||
2627 | } | ||
2628 | // | ||
2629 | // Process XON/XOFF flow control flags settings | ||
2630 | // | ||
2631 | stop_char = STOP_CHAR(pCh->pTTY); | ||
2632 | start_char = START_CHAR(pCh->pTTY); | ||
2633 | |||
2634 | //////////// can't be \000 | ||
2635 | if (stop_char == __DISABLED_CHAR ) | ||
2636 | { | ||
2637 | stop_char = ~__DISABLED_CHAR; | ||
2638 | } | ||
2639 | if (start_char == __DISABLED_CHAR ) | ||
2640 | { | ||
2641 | start_char = ~__DISABLED_CHAR; | ||
2642 | } | ||
2643 | ///////////////////////////////// | ||
2644 | |||
2645 | if ( o_tios->c_cc[VSTART] != start_char ) | ||
2646 | { | ||
2647 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char)); | ||
2648 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char)); | ||
2649 | } | ||
2650 | if ( o_tios->c_cc[VSTOP] != stop_char ) | ||
2651 | { | ||
2652 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char)); | ||
2653 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char)); | ||
2654 | } | ||
2655 | if (stop_char == __DISABLED_CHAR ) | ||
2656 | { | ||
2657 | stop_char = ~__DISABLED_CHAR; //TEST123 | ||
2658 | goto no_xoff; | ||
2659 | } | ||
2660 | if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) | ||
2661 | { | ||
2662 | if ( iflag & IXOFF ) { // Enable XOFF output flow control | ||
2663 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON)); | ||
2664 | } else { // Disable XOFF output flow control | ||
2665 | no_xoff: | ||
2666 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE)); | ||
2667 | } | ||
2668 | } | ||
2669 | if (start_char == __DISABLED_CHAR ) | ||
2670 | { | ||
2671 | goto no_xon; | ||
2672 | } | ||
2673 | if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) | ||
2674 | { | ||
2675 | if ( iflag & IXON ) { | ||
2676 | if ( iflag & IXANY ) { // Enable XON/XANY output flow control | ||
2677 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY)); | ||
2678 | } else { // Enable XON output flow control | ||
2679 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON)); | ||
2680 | } | ||
2681 | } else { // Disable XON output flow control | ||
2682 | no_xon: | ||
2683 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE)); | ||
2684 | } | ||
2685 | } | ||
2686 | if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) | ||
2687 | { | ||
2688 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, | ||
2689 | CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0))); | ||
2690 | } | ||
2691 | if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) | ||
2692 | { | ||
2693 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, | ||
2694 | CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB)); | ||
2695 | } | ||
2696 | |||
2697 | if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) | ||
2698 | ^ ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) | ||
2699 | { | ||
2700 | char brkrpt = 0; | ||
2701 | char parrpt = 0; | ||
2702 | |||
2703 | if ( iflag & IGNBRK ) { /* Ignore breaks altogether */ | ||
2704 | /* Ignore breaks altogether */ | ||
2705 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP); | ||
2706 | } else { | ||
2707 | if ( iflag & BRKINT ) { | ||
2708 | if ( iflag & PARMRK ) { | ||
2709 | brkrpt = 0x0a; // exception an inline triple | ||
2710 | } else { | ||
2711 | brkrpt = 0x1a; // exception and NULL | ||
2712 | } | ||
2713 | brkrpt |= 0x04; // flush input | ||
2714 | } else { | ||
2715 | if ( iflag & PARMRK ) { | ||
2716 | brkrpt = 0x0b; //POSIX triple \0377 \0 \0 | ||
2717 | } else { | ||
2718 | brkrpt = 0x01; // Null only | ||
2719 | } | ||
2720 | } | ||
2721 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt)); | ||
2722 | } | ||
2723 | |||
2724 | if (iflag & IGNPAR) { | ||
2725 | parrpt = 0x20; | ||
2726 | /* would be 2 for not cirrus bug */ | ||
2727 | /* would be 0x20 cept for cirrus bug */ | ||
2728 | } else { | ||
2729 | if ( iflag & PARMRK ) { | ||
2730 | /* | ||
2731 | * Replace error characters with 3-byte sequence (\0377,\0,char) | ||
2732 | */ | ||
2733 | parrpt = 0x04 ; | ||
2734 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0)); | ||
2735 | } else { | ||
2736 | parrpt = 0x03; | ||
2737 | } | ||
2738 | } | ||
2739 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt)); | ||
2740 | } | ||
2741 | if (cflag & CLOCAL) { | ||
2742 | // Status reporting fails for DCD if this is off | ||
2743 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP); | ||
2744 | pCh->flags &= ~ASYNC_CHECK_CD; | ||
2745 | } else { | ||
2746 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP); | ||
2747 | pCh->flags |= ASYNC_CHECK_CD; | ||
2748 | } | ||
2749 | |||
2750 | service_it: | ||
2751 | i2DrainOutput( pCh, 100 ); | ||
2752 | } | ||
2753 | |||
2754 | /******************************************************************************/ | ||
2755 | /* IPL Device Section */ | ||
2756 | /******************************************************************************/ | ||
2757 | |||
2758 | /******************************************************************************/ | ||
2759 | /* Function: ip2_ipl_read() */ | ||
2760 | /* Parameters: Pointer to device inode */ | ||
2761 | /* Pointer to file structure */ | ||
2762 | /* Pointer to data */ | ||
2763 | /* Number of bytes to read */ | ||
2764 | /* Returns: Success or failure */ | ||
2765 | /* */ | ||
2766 | /* Description: Ugly */ | ||
2767 | /* */ | ||
2768 | /* */ | ||
2769 | /******************************************************************************/ | ||
2770 | |||
2771 | static | ||
2772 | ssize_t | ||
2773 | ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off ) | ||
2774 | { | ||
2775 | unsigned int minor = iminor(pFile->f_path.dentry->d_inode); | ||
2776 | int rc = 0; | ||
2777 | |||
2778 | #ifdef IP2DEBUG_IPL | ||
2779 | printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count ); | ||
2780 | #endif | ||
2781 | |||
2782 | switch( minor ) { | ||
2783 | case 0: // IPL device | ||
2784 | rc = -EINVAL; | ||
2785 | break; | ||
2786 | case 1: // Status dump | ||
2787 | rc = -EINVAL; | ||
2788 | break; | ||
2789 | case 2: // Ping device | ||
2790 | rc = -EINVAL; | ||
2791 | break; | ||
2792 | case 3: // Trace device | ||
2793 | rc = DumpTraceBuffer ( pData, count ); | ||
2794 | break; | ||
2795 | case 4: // Trace device | ||
2796 | rc = DumpFifoBuffer ( pData, count ); | ||
2797 | break; | ||
2798 | default: | ||
2799 | rc = -ENODEV; | ||
2800 | break; | ||
2801 | } | ||
2802 | return rc; | ||
2803 | } | ||
2804 | |||
2805 | static int | ||
2806 | DumpFifoBuffer ( char __user *pData, int count ) | ||
2807 | { | ||
2808 | #ifdef DEBUG_FIFO | ||
2809 | int rc; | ||
2810 | rc = copy_to_user(pData, DBGBuf, count); | ||
2811 | |||
2812 | printk(KERN_DEBUG "Last index %d\n", I ); | ||
2813 | |||
2814 | return count; | ||
2815 | #endif /* DEBUG_FIFO */ | ||
2816 | return 0; | ||
2817 | } | ||
2818 | |||
2819 | static int | ||
2820 | DumpTraceBuffer ( char __user *pData, int count ) | ||
2821 | { | ||
2822 | #ifdef IP2DEBUG_TRACE | ||
2823 | int rc; | ||
2824 | int dumpcount; | ||
2825 | int chunk; | ||
2826 | int *pIndex = (int __user *)pData; | ||
2827 | |||
2828 | if ( count < (sizeof(int) * 6) ) { | ||
2829 | return -EIO; | ||
2830 | } | ||
2831 | rc = put_user(tracewrap, pIndex ); | ||
2832 | rc = put_user(TRACEMAX, ++pIndex ); | ||
2833 | rc = put_user(tracestrip, ++pIndex ); | ||
2834 | rc = put_user(tracestuff, ++pIndex ); | ||
2835 | pData += sizeof(int) * 6; | ||
2836 | count -= sizeof(int) * 6; | ||
2837 | |||
2838 | dumpcount = tracestuff - tracestrip; | ||
2839 | if ( dumpcount < 0 ) { | ||
2840 | dumpcount += TRACEMAX; | ||
2841 | } | ||
2842 | if ( dumpcount > count ) { | ||
2843 | dumpcount = count; | ||
2844 | } | ||
2845 | chunk = TRACEMAX - tracestrip; | ||
2846 | if ( dumpcount > chunk ) { | ||
2847 | rc = copy_to_user(pData, &tracebuf[tracestrip], | ||
2848 | chunk * sizeof(tracebuf[0]) ); | ||
2849 | pData += chunk * sizeof(tracebuf[0]); | ||
2850 | tracestrip = 0; | ||
2851 | chunk = dumpcount - chunk; | ||
2852 | } else { | ||
2853 | chunk = dumpcount; | ||
2854 | } | ||
2855 | rc = copy_to_user(pData, &tracebuf[tracestrip], | ||
2856 | chunk * sizeof(tracebuf[0]) ); | ||
2857 | tracestrip += chunk; | ||
2858 | tracewrap = 0; | ||
2859 | |||
2860 | rc = put_user(tracestrip, ++pIndex ); | ||
2861 | rc = put_user(tracestuff, ++pIndex ); | ||
2862 | |||
2863 | return dumpcount; | ||
2864 | #else | ||
2865 | return 0; | ||
2866 | #endif | ||
2867 | } | ||
2868 | |||
2869 | /******************************************************************************/ | ||
2870 | /* Function: ip2_ipl_write() */ | ||
2871 | /* Parameters: */ | ||
2872 | /* Pointer to file structure */ | ||
2873 | /* Pointer to data */ | ||
2874 | /* Number of bytes to write */ | ||
2875 | /* Returns: Success or failure */ | ||
2876 | /* */ | ||
2877 | /* Description: */ | ||
2878 | /* */ | ||
2879 | /* */ | ||
2880 | /******************************************************************************/ | ||
2881 | static ssize_t | ||
2882 | ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off) | ||
2883 | { | ||
2884 | #ifdef IP2DEBUG_IPL | ||
2885 | printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count ); | ||
2886 | #endif | ||
2887 | return 0; | ||
2888 | } | ||
2889 | |||
2890 | /******************************************************************************/ | ||
2891 | /* Function: ip2_ipl_ioctl() */ | ||
2892 | /* Parameters: Pointer to device inode */ | ||
2893 | /* Pointer to file structure */ | ||
2894 | /* Command */ | ||
2895 | /* Argument */ | ||
2896 | /* Returns: Success or failure */ | ||
2897 | /* */ | ||
2898 | /* Description: */ | ||
2899 | /* */ | ||
2900 | /* */ | ||
2901 | /******************************************************************************/ | ||
2902 | static long | ||
2903 | ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) | ||
2904 | { | ||
2905 | unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode); | ||
2906 | int rc = 0; | ||
2907 | void __user *argp = (void __user *)arg; | ||
2908 | ULONG __user *pIndex = argp; | ||
2909 | i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4]; | ||
2910 | i2ChanStrPtr pCh; | ||
2911 | |||
2912 | #ifdef IP2DEBUG_IPL | ||
2913 | printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); | ||
2914 | #endif | ||
2915 | |||
2916 | mutex_lock(&ip2_mutex); | ||
2917 | |||
2918 | switch ( iplminor ) { | ||
2919 | case 0: // IPL device | ||
2920 | rc = -EINVAL; | ||
2921 | break; | ||
2922 | case 1: // Status dump | ||
2923 | case 5: | ||
2924 | case 9: | ||
2925 | case 13: | ||
2926 | switch ( cmd ) { | ||
2927 | case 64: /* Driver - ip2stat */ | ||
2928 | rc = put_user(-1, pIndex++ ); | ||
2929 | rc = put_user(irq_counter, pIndex++ ); | ||
2930 | rc = put_user(bh_counter, pIndex++ ); | ||
2931 | break; | ||
2932 | |||
2933 | case 65: /* Board - ip2stat */ | ||
2934 | if ( pB ) { | ||
2935 | rc = copy_to_user(argp, pB, sizeof(i2eBordStr)); | ||
2936 | rc = put_user(inb(pB->i2eStatus), | ||
2937 | (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) ); | ||
2938 | } else { | ||
2939 | rc = -ENODEV; | ||
2940 | } | ||
2941 | break; | ||
2942 | |||
2943 | default: | ||
2944 | if (cmd < IP2_MAX_PORTS) { | ||
2945 | pCh = DevTable[cmd]; | ||
2946 | if ( pCh ) | ||
2947 | { | ||
2948 | rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); | ||
2949 | if (rc) | ||
2950 | rc = -EFAULT; | ||
2951 | } else { | ||
2952 | rc = -ENODEV; | ||
2953 | } | ||
2954 | } else { | ||
2955 | rc = -EINVAL; | ||
2956 | } | ||
2957 | } | ||
2958 | break; | ||
2959 | |||
2960 | case 2: // Ping device | ||
2961 | rc = -EINVAL; | ||
2962 | break; | ||
2963 | case 3: // Trace device | ||
2964 | /* | ||
2965 | * akpm: This used to write a whole bunch of function addresses | ||
2966 | * to userspace, which generated lots of put_user() warnings. | ||
2967 | * I killed it all. Just return "success" and don't do | ||
2968 | * anything. | ||
2969 | */ | ||
2970 | if (cmd == 1) | ||
2971 | rc = 0; | ||
2972 | else | ||
2973 | rc = -EINVAL; | ||
2974 | break; | ||
2975 | |||
2976 | default: | ||
2977 | rc = -ENODEV; | ||
2978 | break; | ||
2979 | } | ||
2980 | mutex_unlock(&ip2_mutex); | ||
2981 | return rc; | ||
2982 | } | ||
2983 | |||
2984 | /******************************************************************************/ | ||
2985 | /* Function: ip2_ipl_open() */ | ||
2986 | /* Parameters: Pointer to device inode */ | ||
2987 | /* Pointer to file structure */ | ||
2988 | /* Returns: Success or failure */ | ||
2989 | /* */ | ||
2990 | /* Description: */ | ||
2991 | /* */ | ||
2992 | /* */ | ||
2993 | /******************************************************************************/ | ||
2994 | static int | ||
2995 | ip2_ipl_open( struct inode *pInode, struct file *pFile ) | ||
2996 | { | ||
2997 | |||
2998 | #ifdef IP2DEBUG_IPL | ||
2999 | printk (KERN_DEBUG "IP2IPL: open\n" ); | ||
3000 | #endif | ||
3001 | return 0; | ||
3002 | } | ||
3003 | |||
3004 | static int | ||
3005 | proc_ip2mem_show(struct seq_file *m, void *v) | ||
3006 | { | ||
3007 | i2eBordStrPtr pB; | ||
3008 | i2ChanStrPtr pCh; | ||
3009 | PTTY tty; | ||
3010 | int i; | ||
3011 | |||
3012 | #define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n" | ||
3013 | #define FMTLIN2 " 0x%04x 0x%04x tx flow 0x%x\n" | ||
3014 | #define FMTLIN3 " 0x%04x 0x%04x rc flow\n" | ||
3015 | |||
3016 | seq_printf(m,"\n"); | ||
3017 | |||
3018 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | ||
3019 | pB = i2BoardPtrTable[i]; | ||
3020 | if ( pB ) { | ||
3021 | seq_printf(m,"board %d:\n",i); | ||
3022 | seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n", | ||
3023 | pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting); | ||
3024 | } | ||
3025 | } | ||
3026 | |||
3027 | seq_printf(m,"#: tty flags, port flags, cflags, iflags\n"); | ||
3028 | for (i=0; i < IP2_MAX_PORTS; i++) { | ||
3029 | pCh = DevTable[i]; | ||
3030 | if (pCh) { | ||
3031 | tty = pCh->pTTY; | ||
3032 | if (tty && tty->count) { | ||
3033 | seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags, | ||
3034 | tty->termios->c_cflag,tty->termios->c_iflag); | ||
3035 | |||
3036 | seq_printf(m,FMTLIN2, | ||
3037 | pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds); | ||
3038 | seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room); | ||
3039 | } | ||
3040 | } | ||
3041 | } | ||
3042 | return 0; | ||
3043 | } | ||
3044 | |||
3045 | static int proc_ip2mem_open(struct inode *inode, struct file *file) | ||
3046 | { | ||
3047 | return single_open(file, proc_ip2mem_show, NULL); | ||
3048 | } | ||
3049 | |||
3050 | static const struct file_operations ip2mem_proc_fops = { | ||
3051 | .owner = THIS_MODULE, | ||
3052 | .open = proc_ip2mem_open, | ||
3053 | .read = seq_read, | ||
3054 | .llseek = seq_lseek, | ||
3055 | .release = single_release, | ||
3056 | }; | ||
3057 | |||
3058 | /* | ||
3059 | * This is the handler for /proc/tty/driver/ip2 | ||
3060 | * | ||
3061 | * This stretch of code has been largely plagerized from at least three | ||
3062 | * different sources including ip2mkdev.c and a couple of other drivers. | ||
3063 | * The bugs are all mine. :-) =mhw= | ||
3064 | */ | ||
3065 | static int ip2_proc_show(struct seq_file *m, void *v) | ||
3066 | { | ||
3067 | int i, j, box; | ||
3068 | int boxes = 0; | ||
3069 | int ports = 0; | ||
3070 | int tports = 0; | ||
3071 | i2eBordStrPtr pB; | ||
3072 | char *sep; | ||
3073 | |||
3074 | seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion); | ||
3075 | seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", | ||
3076 | IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, | ||
3077 | IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); | ||
3078 | |||
3079 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | ||
3080 | /* This need to be reset for a board by board count... */ | ||
3081 | boxes = 0; | ||
3082 | pB = i2BoardPtrTable[i]; | ||
3083 | if( pB ) { | ||
3084 | switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) | ||
3085 | { | ||
3086 | case POR_ID_FIIEX: | ||
3087 | seq_printf(m, "Board %d: EX ports=", i); | ||
3088 | sep = ""; | ||
3089 | for( box = 0; box < ABS_MAX_BOXES; ++box ) | ||
3090 | { | ||
3091 | ports = 0; | ||
3092 | |||
3093 | if( pB->i2eChannelMap[box] != 0 ) ++boxes; | ||
3094 | for( j = 0; j < ABS_BIGGEST_BOX; ++j ) | ||
3095 | { | ||
3096 | if( pB->i2eChannelMap[box] & 1<< j ) { | ||
3097 | ++ports; | ||
3098 | } | ||
3099 | } | ||
3100 | seq_printf(m, "%s%d", sep, ports); | ||
3101 | sep = ","; | ||
3102 | tports += ports; | ||
3103 | } | ||
3104 | seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8); | ||
3105 | break; | ||
3106 | |||
3107 | case POR_ID_II_4: | ||
3108 | seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i); | ||
3109 | tports = ports = 4; | ||
3110 | break; | ||
3111 | |||
3112 | case POR_ID_II_8: | ||
3113 | seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i); | ||
3114 | tports = ports = 8; | ||
3115 | break; | ||
3116 | |||
3117 | case POR_ID_II_8R: | ||
3118 | seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i); | ||
3119 | tports = ports = 8; | ||
3120 | break; | ||
3121 | |||
3122 | default: | ||
3123 | seq_printf(m, "Board %d: unknown", i); | ||
3124 | /* Don't try and probe for minor numbers */ | ||
3125 | tports = ports = 0; | ||
3126 | } | ||
3127 | |||
3128 | } else { | ||
3129 | /* Don't try and probe for minor numbers */ | ||
3130 | seq_printf(m, "Board %d: vacant", i); | ||
3131 | tports = ports = 0; | ||
3132 | } | ||
3133 | |||
3134 | if( tports ) { | ||
3135 | seq_puts(m, " minors="); | ||
3136 | sep = ""; | ||
3137 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | ||
3138 | { | ||
3139 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) | ||
3140 | { | ||
3141 | if ( pB->i2eChannelMap[box] & (1 << j) ) | ||
3142 | { | ||
3143 | seq_printf(m, "%s%d", sep, | ||
3144 | j + ABS_BIGGEST_BOX * | ||
3145 | (box+i*ABS_MAX_BOXES)); | ||
3146 | sep = ","; | ||
3147 | } | ||
3148 | } | ||
3149 | } | ||
3150 | } | ||
3151 | seq_putc(m, '\n'); | ||
3152 | } | ||
3153 | return 0; | ||
3154 | } | ||
3155 | |||
3156 | static int ip2_proc_open(struct inode *inode, struct file *file) | ||
3157 | { | ||
3158 | return single_open(file, ip2_proc_show, NULL); | ||
3159 | } | ||
3160 | |||
3161 | static const struct file_operations ip2_proc_fops = { | ||
3162 | .owner = THIS_MODULE, | ||
3163 | .open = ip2_proc_open, | ||
3164 | .read = seq_read, | ||
3165 | .llseek = seq_lseek, | ||
3166 | .release = single_release, | ||
3167 | }; | ||
3168 | |||
3169 | /******************************************************************************/ | ||
3170 | /* Function: ip2trace() */ | ||
3171 | /* Parameters: Value to add to trace buffer */ | ||
3172 | /* Returns: Nothing */ | ||
3173 | /* */ | ||
3174 | /* Description: */ | ||
3175 | /* */ | ||
3176 | /* */ | ||
3177 | /******************************************************************************/ | ||
3178 | #ifdef IP2DEBUG_TRACE | ||
3179 | void | ||
3180 | ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...) | ||
3181 | { | ||
3182 | long flags; | ||
3183 | unsigned long *pCode = &codes; | ||
3184 | union ip2breadcrumb bc; | ||
3185 | i2ChanStrPtr pCh; | ||
3186 | |||
3187 | |||
3188 | tracebuf[tracestuff++] = jiffies; | ||
3189 | if ( tracestuff == TRACEMAX ) { | ||
3190 | tracestuff = 0; | ||
3191 | } | ||
3192 | if ( tracestuff == tracestrip ) { | ||
3193 | if ( ++tracestrip == TRACEMAX ) { | ||
3194 | tracestrip = 0; | ||
3195 | } | ||
3196 | ++tracewrap; | ||
3197 | } | ||
3198 | |||
3199 | bc.hdr.port = 0xff & pn; | ||
3200 | bc.hdr.cat = cat; | ||
3201 | bc.hdr.codes = (unsigned char)( codes & 0xff ); | ||
3202 | bc.hdr.label = label; | ||
3203 | tracebuf[tracestuff++] = bc.value; | ||
3204 | |||
3205 | for (;;) { | ||
3206 | if ( tracestuff == TRACEMAX ) { | ||
3207 | tracestuff = 0; | ||
3208 | } | ||
3209 | if ( tracestuff == tracestrip ) { | ||
3210 | if ( ++tracestrip == TRACEMAX ) { | ||
3211 | tracestrip = 0; | ||
3212 | } | ||
3213 | ++tracewrap; | ||
3214 | } | ||
3215 | |||
3216 | if ( !codes-- ) | ||
3217 | break; | ||
3218 | |||
3219 | tracebuf[tracestuff++] = *++pCode; | ||
3220 | } | ||
3221 | } | ||
3222 | #endif | ||
3223 | |||
3224 | |||
3225 | MODULE_LICENSE("GPL"); | ||
3226 | |||
3227 | static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = { | ||
3228 | { PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) }, | ||
3229 | { } | ||
3230 | }; | ||
3231 | |||
3232 | MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); | ||
3233 | |||
3234 | MODULE_FIRMWARE("intelliport2.bin"); | ||
diff --git a/drivers/char/ip2/ip2trace.h b/drivers/char/ip2/ip2trace.h deleted file mode 100644 index da20435dc8a6..000000000000 --- a/drivers/char/ip2/ip2trace.h +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | |||
2 | // | ||
3 | union ip2breadcrumb | ||
4 | { | ||
5 | struct { | ||
6 | unsigned char port, cat, codes, label; | ||
7 | } __attribute__ ((packed)) hdr; | ||
8 | unsigned long value; | ||
9 | }; | ||
10 | |||
11 | #define ITRC_NO_PORT 0xFF | ||
12 | #define CHANN (pCh->port_index) | ||
13 | |||
14 | #define ITRC_ERROR '!' | ||
15 | #define ITRC_INIT 'A' | ||
16 | #define ITRC_OPEN 'B' | ||
17 | #define ITRC_CLOSE 'C' | ||
18 | #define ITRC_DRAIN 'D' | ||
19 | #define ITRC_IOCTL 'E' | ||
20 | #define ITRC_FLUSH 'F' | ||
21 | #define ITRC_STATUS 'G' | ||
22 | #define ITRC_HANGUP 'H' | ||
23 | #define ITRC_INTR 'I' | ||
24 | #define ITRC_SFLOW 'J' | ||
25 | #define ITRC_SBCMD 'K' | ||
26 | #define ITRC_SICMD 'L' | ||
27 | #define ITRC_MODEM 'M' | ||
28 | #define ITRC_INPUT 'N' | ||
29 | #define ITRC_OUTPUT 'O' | ||
30 | #define ITRC_PUTC 'P' | ||
31 | #define ITRC_QUEUE 'Q' | ||
32 | #define ITRC_STFLW 'R' | ||
33 | #define ITRC_SFIFO 'S' | ||
34 | #define ITRC_VERIFY 'V' | ||
35 | #define ITRC_WRITE 'W' | ||
36 | |||
37 | #define ITRC_ENTER 0x00 | ||
38 | #define ITRC_RETURN 0xFF | ||
39 | |||
40 | #define ITRC_QUEUE_ROOM 2 | ||
41 | #define ITRC_QUEUE_CMD 6 | ||
42 | |||
diff --git a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h deleted file mode 100644 index 9d67b260b2f6..000000000000 --- a/drivers/char/ip2/ip2types.h +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Driver constants and type definitions. | ||
12 | * | ||
13 | * NOTES: | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | #ifndef IP2TYPES_H | ||
17 | #define IP2TYPES_H | ||
18 | |||
19 | //************* | ||
20 | //* Constants * | ||
21 | //************* | ||
22 | |||
23 | // Define some limits for this driver. Ports per board is a hardware limitation | ||
24 | // that will not change. Current hardware limits this to 64 ports per board. | ||
25 | // Boards per driver is a self-imposed limit. | ||
26 | // | ||
27 | #define IP2_MAX_BOARDS 4 | ||
28 | #define IP2_PORTS_PER_BOARD ABS_MOST_PORTS | ||
29 | #define IP2_MAX_PORTS (IP2_MAX_BOARDS*IP2_PORTS_PER_BOARD) | ||
30 | |||
31 | #define ISA 0 | ||
32 | #define PCI 1 | ||
33 | #define EISA 2 | ||
34 | |||
35 | //******************** | ||
36 | //* Type Definitions * | ||
37 | //******************** | ||
38 | |||
39 | typedef struct tty_struct * PTTY; | ||
40 | typedef wait_queue_head_t PWAITQ; | ||
41 | |||
42 | typedef unsigned char UCHAR; | ||
43 | typedef unsigned int UINT; | ||
44 | typedef unsigned short USHORT; | ||
45 | typedef unsigned long ULONG; | ||
46 | |||
47 | typedef struct | ||
48 | { | ||
49 | short irq[IP2_MAX_BOARDS]; | ||
50 | unsigned short addr[IP2_MAX_BOARDS]; | ||
51 | int type[IP2_MAX_BOARDS]; | ||
52 | #ifdef CONFIG_PCI | ||
53 | struct pci_dev *pci_dev[IP2_MAX_BOARDS]; | ||
54 | #endif | ||
55 | } ip2config_t; | ||
56 | |||
57 | #endif | ||
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c deleted file mode 100644 index 0b266272cccd..000000000000 --- a/drivers/char/istallion.c +++ /dev/null | |||
@@ -1,4507 +0,0 @@ | |||
1 | /*****************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * istallion.c -- stallion intelligent multiport serial driver. | ||
5 | * | ||
6 | * Copyright (C) 1996-1999 Stallion Technologies | ||
7 | * Copyright (C) 1994-1996 Greg Ungerer. | ||
8 | * | ||
9 | * This code is loosely based on the Linux serial driver, written by | ||
10 | * Linus Torvalds, Theodore T'so and others. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | /*****************************************************************************/ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/tty.h> | ||
26 | #include <linux/tty_flip.h> | ||
27 | #include <linux/serial.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/cdk.h> | ||
30 | #include <linux/comstats.h> | ||
31 | #include <linux/istallion.h> | ||
32 | #include <linux/ioport.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/device.h> | ||
36 | #include <linux/wait.h> | ||
37 | #include <linux/eisa.h> | ||
38 | #include <linux/ctype.h> | ||
39 | |||
40 | #include <asm/io.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | |||
43 | #include <linux/pci.h> | ||
44 | |||
45 | /*****************************************************************************/ | ||
46 | |||
47 | /* | ||
48 | * Define different board types. Not all of the following board types | ||
49 | * are supported by this driver. But I will use the standard "assigned" | ||
50 | * board numbers. Currently supported boards are abbreviated as: | ||
51 | * ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and | ||
52 | * STAL = Stallion. | ||
53 | */ | ||
54 | #define BRD_UNKNOWN 0 | ||
55 | #define BRD_STALLION 1 | ||
56 | #define BRD_BRUMBY4 2 | ||
57 | #define BRD_ONBOARD2 3 | ||
58 | #define BRD_ONBOARD 4 | ||
59 | #define BRD_ONBOARDE 7 | ||
60 | #define BRD_ECP 23 | ||
61 | #define BRD_ECPE 24 | ||
62 | #define BRD_ECPMC 25 | ||
63 | #define BRD_ECPPCI 29 | ||
64 | |||
65 | #define BRD_BRUMBY BRD_BRUMBY4 | ||
66 | |||
67 | /* | ||
68 | * Define a configuration structure to hold the board configuration. | ||
69 | * Need to set this up in the code (for now) with the boards that are | ||
70 | * to be configured into the system. This is what needs to be modified | ||
71 | * when adding/removing/modifying boards. Each line entry in the | ||
72 | * stli_brdconf[] array is a board. Each line contains io/irq/memory | ||
73 | * ranges for that board (as well as what type of board it is). | ||
74 | * Some examples: | ||
75 | * { BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 }, | ||
76 | * This line will configure an EasyConnection 8/64 at io address 2a0, | ||
77 | * and shared memory address of cc000. Multiple EasyConnection 8/64 | ||
78 | * boards can share the same shared memory address space. No interrupt | ||
79 | * is required for this board type. | ||
80 | * Another example: | ||
81 | * { BRD_ECPE, 0x5000, 0, 0x80000000, 0, 0 }, | ||
82 | * This line will configure an EasyConnection 8/64 EISA in slot 5 and | ||
83 | * shared memory address of 0x80000000 (2 GByte). Multiple | ||
84 | * EasyConnection 8/64 EISA boards can share the same shared memory | ||
85 | * address space. No interrupt is required for this board type. | ||
86 | * Another example: | ||
87 | * { BRD_ONBOARD, 0x240, 0, 0xd0000, 0, 0 }, | ||
88 | * This line will configure an ONboard (ISA type) at io address 240, | ||
89 | * and shared memory address of d0000. Multiple ONboards can share | ||
90 | * the same shared memory address space. No interrupt required. | ||
91 | * Another example: | ||
92 | * { BRD_BRUMBY4, 0x360, 0, 0xc8000, 0, 0 }, | ||
93 | * This line will configure a Brumby board (any number of ports!) at | ||
94 | * io address 360 and shared memory address of c8000. All Brumby boards | ||
95 | * configured into a system must have their own separate io and memory | ||
96 | * addresses. No interrupt is required. | ||
97 | * Another example: | ||
98 | * { BRD_STALLION, 0x330, 0, 0xd0000, 0, 0 }, | ||
99 | * This line will configure an original Stallion board at io address 330 | ||
100 | * and shared memory address d0000 (this would only be valid for a "V4.0" | ||
101 | * or Rev.O Stallion board). All Stallion boards configured into the | ||
102 | * system must have their own separate io and memory addresses. No | ||
103 | * interrupt is required. | ||
104 | */ | ||
105 | |||
106 | struct stlconf { | ||
107 | int brdtype; | ||
108 | int ioaddr1; | ||
109 | int ioaddr2; | ||
110 | unsigned long memaddr; | ||
111 | int irq; | ||
112 | int irqtype; | ||
113 | }; | ||
114 | |||
115 | static unsigned int stli_nrbrds; | ||
116 | |||
117 | /* stli_lock must NOT be taken holding brd_lock */ | ||
118 | static spinlock_t stli_lock; /* TTY logic lock */ | ||
119 | static spinlock_t brd_lock; /* Board logic lock */ | ||
120 | |||
121 | /* | ||
122 | * There is some experimental EISA board detection code in this driver. | ||
123 | * By default it is disabled, but for those that want to try it out, | ||
124 | * then set the define below to be 1. | ||
125 | */ | ||
126 | #define STLI_EISAPROBE 0 | ||
127 | |||
128 | /*****************************************************************************/ | ||
129 | |||
130 | /* | ||
131 | * Define some important driver characteristics. Device major numbers | ||
132 | * allocated as per Linux Device Registry. | ||
133 | */ | ||
134 | #ifndef STL_SIOMEMMAJOR | ||
135 | #define STL_SIOMEMMAJOR 28 | ||
136 | #endif | ||
137 | #ifndef STL_SERIALMAJOR | ||
138 | #define STL_SERIALMAJOR 24 | ||
139 | #endif | ||
140 | #ifndef STL_CALLOUTMAJOR | ||
141 | #define STL_CALLOUTMAJOR 25 | ||
142 | #endif | ||
143 | |||
144 | /*****************************************************************************/ | ||
145 | |||
146 | /* | ||
147 | * Define our local driver identity first. Set up stuff to deal with | ||
148 | * all the local structures required by a serial tty driver. | ||
149 | */ | ||
150 | static char *stli_drvtitle = "Stallion Intelligent Multiport Serial Driver"; | ||
151 | static char *stli_drvname = "istallion"; | ||
152 | static char *stli_drvversion = "5.6.0"; | ||
153 | static char *stli_serialname = "ttyE"; | ||
154 | |||
155 | static struct tty_driver *stli_serial; | ||
156 | static const struct tty_port_operations stli_port_ops; | ||
157 | |||
158 | #define STLI_TXBUFSIZE 4096 | ||
159 | |||
160 | /* | ||
161 | * Use a fast local buffer for cooked characters. Typically a whole | ||
162 | * bunch of cooked characters come in for a port, 1 at a time. So we | ||
163 | * save those up into a local buffer, then write out the whole lot | ||
164 | * with a large memcpy. Just use 1 buffer for all ports, since its | ||
165 | * use it is only need for short periods of time by each port. | ||
166 | */ | ||
167 | static char *stli_txcookbuf; | ||
168 | static int stli_txcooksize; | ||
169 | static int stli_txcookrealsize; | ||
170 | static struct tty_struct *stli_txcooktty; | ||
171 | |||
172 | /* | ||
173 | * Define a local default termios struct. All ports will be created | ||
174 | * with this termios initially. Basically all it defines is a raw port | ||
175 | * at 9600 baud, 8 data bits, no parity, 1 stop bit. | ||
176 | */ | ||
177 | static struct ktermios stli_deftermios = { | ||
178 | .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), | ||
179 | .c_cc = INIT_C_CC, | ||
180 | .c_ispeed = 9600, | ||
181 | .c_ospeed = 9600, | ||
182 | }; | ||
183 | |||
184 | /* | ||
185 | * Define global stats structures. Not used often, and can be | ||
186 | * re-used for each stats call. | ||
187 | */ | ||
188 | static comstats_t stli_comstats; | ||
189 | static combrd_t stli_brdstats; | ||
190 | static struct asystats stli_cdkstats; | ||
191 | |||
192 | /*****************************************************************************/ | ||
193 | |||
194 | static DEFINE_MUTEX(stli_brdslock); | ||
195 | static struct stlibrd *stli_brds[STL_MAXBRDS]; | ||
196 | |||
197 | static int stli_shared; | ||
198 | |||
199 | /* | ||
200 | * Per board state flags. Used with the state field of the board struct. | ||
201 | * Not really much here... All we need to do is keep track of whether | ||
202 | * the board has been detected, and whether it is actually running a slave | ||
203 | * or not. | ||
204 | */ | ||
205 | #define BST_FOUND 0 | ||
206 | #define BST_STARTED 1 | ||
207 | #define BST_PROBED 2 | ||
208 | |||
209 | /* | ||
210 | * Define the set of port state flags. These are marked for internal | ||
211 | * state purposes only, usually to do with the state of communications | ||
212 | * with the slave. Most of them need to be updated atomically, so always | ||
213 | * use the bit setting operations (unless protected by cli/sti). | ||
214 | */ | ||
215 | #define ST_OPENING 2 | ||
216 | #define ST_CLOSING 3 | ||
217 | #define ST_CMDING 4 | ||
218 | #define ST_TXBUSY 5 | ||
219 | #define ST_RXING 6 | ||
220 | #define ST_DOFLUSHRX 7 | ||
221 | #define ST_DOFLUSHTX 8 | ||
222 | #define ST_DOSIGS 9 | ||
223 | #define ST_RXSTOP 10 | ||
224 | #define ST_GETSIGS 11 | ||
225 | |||
226 | /* | ||
227 | * Define an array of board names as printable strings. Handy for | ||
228 | * referencing boards when printing trace and stuff. | ||
229 | */ | ||
230 | static char *stli_brdnames[] = { | ||
231 | "Unknown", | ||
232 | "Stallion", | ||
233 | "Brumby", | ||
234 | "ONboard-MC", | ||
235 | "ONboard", | ||
236 | "Brumby", | ||
237 | "Brumby", | ||
238 | "ONboard-EI", | ||
239 | NULL, | ||
240 | "ONboard", | ||
241 | "ONboard-MC", | ||
242 | "ONboard-MC", | ||
243 | NULL, | ||
244 | NULL, | ||
245 | NULL, | ||
246 | NULL, | ||
247 | NULL, | ||
248 | NULL, | ||
249 | NULL, | ||
250 | NULL, | ||
251 | "EasyIO", | ||
252 | "EC8/32-AT", | ||
253 | "EC8/32-MC", | ||
254 | "EC8/64-AT", | ||
255 | "EC8/64-EI", | ||
256 | "EC8/64-MC", | ||
257 | "EC8/32-PCI", | ||
258 | "EC8/64-PCI", | ||
259 | "EasyIO-PCI", | ||
260 | "EC/RA-PCI", | ||
261 | }; | ||
262 | |||
263 | /*****************************************************************************/ | ||
264 | |||
265 | /* | ||
266 | * Define some string labels for arguments passed from the module | ||
267 | * load line. These allow for easy board definitions, and easy | ||
268 | * modification of the io, memory and irq resoucres. | ||
269 | */ | ||
270 | |||
271 | static char *board0[8]; | ||
272 | static char *board1[8]; | ||
273 | static char *board2[8]; | ||
274 | static char *board3[8]; | ||
275 | |||
276 | static char **stli_brdsp[] = { | ||
277 | (char **) &board0, | ||
278 | (char **) &board1, | ||
279 | (char **) &board2, | ||
280 | (char **) &board3 | ||
281 | }; | ||
282 | |||
283 | /* | ||
284 | * Define a set of common board names, and types. This is used to | ||
285 | * parse any module arguments. | ||
286 | */ | ||
287 | |||
288 | static struct stlibrdtype { | ||
289 | char *name; | ||
290 | int type; | ||
291 | } stli_brdstr[] = { | ||
292 | { "stallion", BRD_STALLION }, | ||
293 | { "1", BRD_STALLION }, | ||
294 | { "brumby", BRD_BRUMBY }, | ||
295 | { "brumby4", BRD_BRUMBY }, | ||
296 | { "brumby/4", BRD_BRUMBY }, | ||
297 | { "brumby-4", BRD_BRUMBY }, | ||
298 | { "brumby8", BRD_BRUMBY }, | ||
299 | { "brumby/8", BRD_BRUMBY }, | ||
300 | { "brumby-8", BRD_BRUMBY }, | ||
301 | { "brumby16", BRD_BRUMBY }, | ||
302 | { "brumby/16", BRD_BRUMBY }, | ||
303 | { "brumby-16", BRD_BRUMBY }, | ||
304 | { "2", BRD_BRUMBY }, | ||
305 | { "onboard2", BRD_ONBOARD2 }, | ||
306 | { "onboard-2", BRD_ONBOARD2 }, | ||
307 | { "onboard/2", BRD_ONBOARD2 }, | ||
308 | { "onboard-mc", BRD_ONBOARD2 }, | ||
309 | { "onboard/mc", BRD_ONBOARD2 }, | ||
310 | { "onboard-mca", BRD_ONBOARD2 }, | ||
311 | { "onboard/mca", BRD_ONBOARD2 }, | ||
312 | { "3", BRD_ONBOARD2 }, | ||
313 | { "onboard", BRD_ONBOARD }, | ||
314 | { "onboardat", BRD_ONBOARD }, | ||
315 | { "4", BRD_ONBOARD }, | ||
316 | { "onboarde", BRD_ONBOARDE }, | ||
317 | { "onboard-e", BRD_ONBOARDE }, | ||
318 | { "onboard/e", BRD_ONBOARDE }, | ||
319 | { "onboard-ei", BRD_ONBOARDE }, | ||
320 | { "onboard/ei", BRD_ONBOARDE }, | ||
321 | { "7", BRD_ONBOARDE }, | ||
322 | { "ecp", BRD_ECP }, | ||
323 | { "ecpat", BRD_ECP }, | ||
324 | { "ec8/64", BRD_ECP }, | ||
325 | { "ec8/64-at", BRD_ECP }, | ||
326 | { "ec8/64-isa", BRD_ECP }, | ||
327 | { "23", BRD_ECP }, | ||
328 | { "ecpe", BRD_ECPE }, | ||
329 | { "ecpei", BRD_ECPE }, | ||
330 | { "ec8/64-e", BRD_ECPE }, | ||
331 | { "ec8/64-ei", BRD_ECPE }, | ||
332 | { "24", BRD_ECPE }, | ||
333 | { "ecpmc", BRD_ECPMC }, | ||
334 | { "ec8/64-mc", BRD_ECPMC }, | ||
335 | { "ec8/64-mca", BRD_ECPMC }, | ||
336 | { "25", BRD_ECPMC }, | ||
337 | { "ecppci", BRD_ECPPCI }, | ||
338 | { "ec/ra", BRD_ECPPCI }, | ||
339 | { "ec/ra-pc", BRD_ECPPCI }, | ||
340 | { "ec/ra-pci", BRD_ECPPCI }, | ||
341 | { "29", BRD_ECPPCI }, | ||
342 | }; | ||
343 | |||
344 | /* | ||
345 | * Define the module agruments. | ||
346 | */ | ||
347 | MODULE_AUTHOR("Greg Ungerer"); | ||
348 | MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver"); | ||
349 | MODULE_LICENSE("GPL"); | ||
350 | |||
351 | |||
352 | module_param_array(board0, charp, NULL, 0); | ||
353 | MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]"); | ||
354 | module_param_array(board1, charp, NULL, 0); | ||
355 | MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]"); | ||
356 | module_param_array(board2, charp, NULL, 0); | ||
357 | MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]"); | ||
358 | module_param_array(board3, charp, NULL, 0); | ||
359 | MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]"); | ||
360 | |||
361 | #if STLI_EISAPROBE != 0 | ||
362 | /* | ||
363 | * Set up a default memory address table for EISA board probing. | ||
364 | * The default addresses are all bellow 1Mbyte, which has to be the | ||
365 | * case anyway. They should be safe, since we only read values from | ||
366 | * them, and interrupts are disabled while we do it. If the higher | ||
367 | * memory support is compiled in then we also try probing around | ||
368 | * the 1Gb, 2Gb and 3Gb areas as well... | ||
369 | */ | ||
370 | static unsigned long stli_eisamemprobeaddrs[] = { | ||
371 | 0xc0000, 0xd0000, 0xe0000, 0xf0000, | ||
372 | 0x80000000, 0x80010000, 0x80020000, 0x80030000, | ||
373 | 0x40000000, 0x40010000, 0x40020000, 0x40030000, | ||
374 | 0xc0000000, 0xc0010000, 0xc0020000, 0xc0030000, | ||
375 | 0xff000000, 0xff010000, 0xff020000, 0xff030000, | ||
376 | }; | ||
377 | |||
378 | static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs); | ||
379 | #endif | ||
380 | |||
381 | /* | ||
382 | * Define the Stallion PCI vendor and device IDs. | ||
383 | */ | ||
384 | #ifndef PCI_DEVICE_ID_ECRA | ||
385 | #define PCI_DEVICE_ID_ECRA 0x0004 | ||
386 | #endif | ||
387 | |||
388 | static struct pci_device_id istallion_pci_tbl[] = { | ||
389 | { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), }, | ||
390 | { 0 } | ||
391 | }; | ||
392 | MODULE_DEVICE_TABLE(pci, istallion_pci_tbl); | ||
393 | |||
394 | static struct pci_driver stli_pcidriver; | ||
395 | |||
396 | /*****************************************************************************/ | ||
397 | |||
398 | /* | ||
399 | * Hardware configuration info for ECP boards. These defines apply | ||
400 | * to the directly accessible io ports of the ECP. There is a set of | ||
401 | * defines for each ECP board type, ISA, EISA, MCA and PCI. | ||
402 | */ | ||
403 | #define ECP_IOSIZE 4 | ||
404 | |||
405 | #define ECP_MEMSIZE (128 * 1024) | ||
406 | #define ECP_PCIMEMSIZE (256 * 1024) | ||
407 | |||
408 | #define ECP_ATPAGESIZE (4 * 1024) | ||
409 | #define ECP_MCPAGESIZE (4 * 1024) | ||
410 | #define ECP_EIPAGESIZE (64 * 1024) | ||
411 | #define ECP_PCIPAGESIZE (64 * 1024) | ||
412 | |||
413 | #define STL_EISAID 0x8c4e | ||
414 | |||
415 | /* | ||
416 | * Important defines for the ISA class of ECP board. | ||
417 | */ | ||
418 | #define ECP_ATIREG 0 | ||
419 | #define ECP_ATCONFR 1 | ||
420 | #define ECP_ATMEMAR 2 | ||
421 | #define ECP_ATMEMPR 3 | ||
422 | #define ECP_ATSTOP 0x1 | ||
423 | #define ECP_ATINTENAB 0x10 | ||
424 | #define ECP_ATENABLE 0x20 | ||
425 | #define ECP_ATDISABLE 0x00 | ||
426 | #define ECP_ATADDRMASK 0x3f000 | ||
427 | #define ECP_ATADDRSHFT 12 | ||
428 | |||
429 | /* | ||
430 | * Important defines for the EISA class of ECP board. | ||
431 | */ | ||
432 | #define ECP_EIIREG 0 | ||
433 | #define ECP_EIMEMARL 1 | ||
434 | #define ECP_EICONFR 2 | ||
435 | #define ECP_EIMEMARH 3 | ||
436 | #define ECP_EIENABLE 0x1 | ||
437 | #define ECP_EIDISABLE 0x0 | ||
438 | #define ECP_EISTOP 0x4 | ||
439 | #define ECP_EIEDGE 0x00 | ||
440 | #define ECP_EILEVEL 0x80 | ||
441 | #define ECP_EIADDRMASKL 0x00ff0000 | ||
442 | #define ECP_EIADDRSHFTL 16 | ||
443 | #define ECP_EIADDRMASKH 0xff000000 | ||
444 | #define ECP_EIADDRSHFTH 24 | ||
445 | #define ECP_EIBRDENAB 0xc84 | ||
446 | |||
447 | #define ECP_EISAID 0x4 | ||
448 | |||
449 | /* | ||
450 | * Important defines for the Micro-channel class of ECP board. | ||
451 | * (It has a lot in common with the ISA boards.) | ||
452 | */ | ||
453 | #define ECP_MCIREG 0 | ||
454 | #define ECP_MCCONFR 1 | ||
455 | #define ECP_MCSTOP 0x20 | ||
456 | #define ECP_MCENABLE 0x80 | ||
457 | #define ECP_MCDISABLE 0x00 | ||
458 | |||
459 | /* | ||
460 | * Important defines for the PCI class of ECP board. | ||
461 | * (It has a lot in common with the other ECP boards.) | ||
462 | */ | ||
463 | #define ECP_PCIIREG 0 | ||
464 | #define ECP_PCICONFR 1 | ||
465 | #define ECP_PCISTOP 0x01 | ||
466 | |||
467 | /* | ||
468 | * Hardware configuration info for ONboard and Brumby boards. These | ||
469 | * defines apply to the directly accessible io ports of these boards. | ||
470 | */ | ||
471 | #define ONB_IOSIZE 16 | ||
472 | #define ONB_MEMSIZE (64 * 1024) | ||
473 | #define ONB_ATPAGESIZE (64 * 1024) | ||
474 | #define ONB_MCPAGESIZE (64 * 1024) | ||
475 | #define ONB_EIMEMSIZE (128 * 1024) | ||
476 | #define ONB_EIPAGESIZE (64 * 1024) | ||
477 | |||
478 | /* | ||
479 | * Important defines for the ISA class of ONboard board. | ||
480 | */ | ||
481 | #define ONB_ATIREG 0 | ||
482 | #define ONB_ATMEMAR 1 | ||
483 | #define ONB_ATCONFR 2 | ||
484 | #define ONB_ATSTOP 0x4 | ||
485 | #define ONB_ATENABLE 0x01 | ||
486 | #define ONB_ATDISABLE 0x00 | ||
487 | #define ONB_ATADDRMASK 0xff0000 | ||
488 | #define ONB_ATADDRSHFT 16 | ||
489 | |||
490 | #define ONB_MEMENABLO 0 | ||
491 | #define ONB_MEMENABHI 0x02 | ||
492 | |||
493 | /* | ||
494 | * Important defines for the EISA class of ONboard board. | ||
495 | */ | ||
496 | #define ONB_EIIREG 0 | ||
497 | #define ONB_EIMEMARL 1 | ||
498 | #define ONB_EICONFR 2 | ||
499 | #define ONB_EIMEMARH 3 | ||
500 | #define ONB_EIENABLE 0x1 | ||
501 | #define ONB_EIDISABLE 0x0 | ||
502 | #define ONB_EISTOP 0x4 | ||
503 | #define ONB_EIEDGE 0x00 | ||
504 | #define ONB_EILEVEL 0x80 | ||
505 | #define ONB_EIADDRMASKL 0x00ff0000 | ||
506 | #define ONB_EIADDRSHFTL 16 | ||
507 | #define ONB_EIADDRMASKH 0xff000000 | ||
508 | #define ONB_EIADDRSHFTH 24 | ||
509 | #define ONB_EIBRDENAB 0xc84 | ||
510 | |||
511 | #define ONB_EISAID 0x1 | ||
512 | |||
513 | /* | ||
514 | * Important defines for the Brumby boards. They are pretty simple, | ||
515 | * there is not much that is programmably configurable. | ||
516 | */ | ||
517 | #define BBY_IOSIZE 16 | ||
518 | #define BBY_MEMSIZE (64 * 1024) | ||
519 | #define BBY_PAGESIZE (16 * 1024) | ||
520 | |||
521 | #define BBY_ATIREG 0 | ||
522 | #define BBY_ATCONFR 1 | ||
523 | #define BBY_ATSTOP 0x4 | ||
524 | |||
525 | /* | ||
526 | * Important defines for the Stallion boards. They are pretty simple, | ||
527 | * there is not much that is programmably configurable. | ||
528 | */ | ||
529 | #define STAL_IOSIZE 16 | ||
530 | #define STAL_MEMSIZE (64 * 1024) | ||
531 | #define STAL_PAGESIZE (64 * 1024) | ||
532 | |||
533 | /* | ||
534 | * Define the set of status register values for EasyConnection panels. | ||
535 | * The signature will return with the status value for each panel. From | ||
536 | * this we can determine what is attached to the board - before we have | ||
537 | * actually down loaded any code to it. | ||
538 | */ | ||
539 | #define ECH_PNLSTATUS 2 | ||
540 | #define ECH_PNL16PORT 0x20 | ||
541 | #define ECH_PNLIDMASK 0x07 | ||
542 | #define ECH_PNLXPID 0x40 | ||
543 | #define ECH_PNLINTRPEND 0x80 | ||
544 | |||
545 | /* | ||
546 | * Define some macros to do things to the board. Even those these boards | ||
547 | * are somewhat related there is often significantly different ways of | ||
548 | * doing some operation on it (like enable, paging, reset, etc). So each | ||
549 | * board class has a set of functions which do the commonly required | ||
550 | * operations. The macros below basically just call these functions, | ||
551 | * generally checking for a NULL function - which means that the board | ||
552 | * needs nothing done to it to achieve this operation! | ||
553 | */ | ||
554 | #define EBRDINIT(brdp) \ | ||
555 | if (brdp->init != NULL) \ | ||
556 | (* brdp->init)(brdp) | ||
557 | |||
558 | #define EBRDENABLE(brdp) \ | ||
559 | if (brdp->enable != NULL) \ | ||
560 | (* brdp->enable)(brdp); | ||
561 | |||
562 | #define EBRDDISABLE(brdp) \ | ||
563 | if (brdp->disable != NULL) \ | ||
564 | (* brdp->disable)(brdp); | ||
565 | |||
566 | #define EBRDINTR(brdp) \ | ||
567 | if (brdp->intr != NULL) \ | ||
568 | (* brdp->intr)(brdp); | ||
569 | |||
570 | #define EBRDRESET(brdp) \ | ||
571 | if (brdp->reset != NULL) \ | ||
572 | (* brdp->reset)(brdp); | ||
573 | |||
574 | #define EBRDGETMEMPTR(brdp,offset) \ | ||
575 | (* brdp->getmemptr)(brdp, offset, __LINE__) | ||
576 | |||
577 | /* | ||
578 | * Define the maximal baud rate, and the default baud base for ports. | ||
579 | */ | ||
580 | #define STL_MAXBAUD 460800 | ||
581 | #define STL_BAUDBASE 115200 | ||
582 | #define STL_CLOSEDELAY (5 * HZ / 10) | ||
583 | |||
584 | /*****************************************************************************/ | ||
585 | |||
586 | /* | ||
587 | * Define macros to extract a brd or port number from a minor number. | ||
588 | */ | ||
589 | #define MINOR2BRD(min) (((min) & 0xc0) >> 6) | ||
590 | #define MINOR2PORT(min) ((min) & 0x3f) | ||
591 | |||
592 | /*****************************************************************************/ | ||
593 | |||
594 | /* | ||
595 | * Prototype all functions in this driver! | ||
596 | */ | ||
597 | |||
598 | static int stli_parsebrd(struct stlconf *confp, char **argp); | ||
599 | static int stli_open(struct tty_struct *tty, struct file *filp); | ||
600 | static void stli_close(struct tty_struct *tty, struct file *filp); | ||
601 | static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); | ||
602 | static int stli_putchar(struct tty_struct *tty, unsigned char ch); | ||
603 | static void stli_flushchars(struct tty_struct *tty); | ||
604 | static int stli_writeroom(struct tty_struct *tty); | ||
605 | static int stli_charsinbuffer(struct tty_struct *tty); | ||
606 | static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); | ||
607 | static void stli_settermios(struct tty_struct *tty, struct ktermios *old); | ||
608 | static void stli_throttle(struct tty_struct *tty); | ||
609 | static void stli_unthrottle(struct tty_struct *tty); | ||
610 | static void stli_stop(struct tty_struct *tty); | ||
611 | static void stli_start(struct tty_struct *tty); | ||
612 | static void stli_flushbuffer(struct tty_struct *tty); | ||
613 | static int stli_breakctl(struct tty_struct *tty, int state); | ||
614 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); | ||
615 | static void stli_sendxchar(struct tty_struct *tty, char ch); | ||
616 | static void stli_hangup(struct tty_struct *tty); | ||
617 | |||
618 | static int stli_brdinit(struct stlibrd *brdp); | ||
619 | static int stli_startbrd(struct stlibrd *brdp); | ||
620 | static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); | ||
621 | static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); | ||
622 | static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); | ||
623 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); | ||
624 | static void stli_poll(unsigned long arg); | ||
625 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); | ||
626 | static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); | ||
627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | ||
628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | ||
629 | static int stli_setport(struct tty_struct *tty); | ||
630 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | ||
631 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | ||
632 | static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | ||
633 | static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp); | ||
634 | static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp); | ||
635 | static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts); | ||
636 | static long stli_mktiocm(unsigned long sigvalue); | ||
637 | static void stli_read(struct stlibrd *brdp, struct stliport *portp); | ||
638 | static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp); | ||
639 | static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp); | ||
640 | static int stli_getbrdstats(combrd_t __user *bp); | ||
641 | static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp); | ||
642 | static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp); | ||
643 | static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp); | ||
644 | static int stli_getportstruct(struct stliport __user *arg); | ||
645 | static int stli_getbrdstruct(struct stlibrd __user *arg); | ||
646 | static struct stlibrd *stli_allocbrd(void); | ||
647 | |||
648 | static void stli_ecpinit(struct stlibrd *brdp); | ||
649 | static void stli_ecpenable(struct stlibrd *brdp); | ||
650 | static void stli_ecpdisable(struct stlibrd *brdp); | ||
651 | static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); | ||
652 | static void stli_ecpreset(struct stlibrd *brdp); | ||
653 | static void stli_ecpintr(struct stlibrd *brdp); | ||
654 | static void stli_ecpeiinit(struct stlibrd *brdp); | ||
655 | static void stli_ecpeienable(struct stlibrd *brdp); | ||
656 | static void stli_ecpeidisable(struct stlibrd *brdp); | ||
657 | static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); | ||
658 | static void stli_ecpeireset(struct stlibrd *brdp); | ||
659 | static void stli_ecpmcenable(struct stlibrd *brdp); | ||
660 | static void stli_ecpmcdisable(struct stlibrd *brdp); | ||
661 | static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); | ||
662 | static void stli_ecpmcreset(struct stlibrd *brdp); | ||
663 | static void stli_ecppciinit(struct stlibrd *brdp); | ||
664 | static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); | ||
665 | static void stli_ecppcireset(struct stlibrd *brdp); | ||
666 | |||
667 | static void stli_onbinit(struct stlibrd *brdp); | ||
668 | static void stli_onbenable(struct stlibrd *brdp); | ||
669 | static void stli_onbdisable(struct stlibrd *brdp); | ||
670 | static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); | ||
671 | static void stli_onbreset(struct stlibrd *brdp); | ||
672 | static void stli_onbeinit(struct stlibrd *brdp); | ||
673 | static void stli_onbeenable(struct stlibrd *brdp); | ||
674 | static void stli_onbedisable(struct stlibrd *brdp); | ||
675 | static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line); | ||
676 | static void stli_onbereset(struct stlibrd *brdp); | ||
677 | static void stli_bbyinit(struct stlibrd *brdp); | ||
678 | static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line); | ||
679 | static void stli_bbyreset(struct stlibrd *brdp); | ||
680 | static void stli_stalinit(struct stlibrd *brdp); | ||
681 | static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); | ||
682 | static void stli_stalreset(struct stlibrd *brdp); | ||
683 | |||
684 | static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr); | ||
685 | |||
686 | static int stli_initecp(struct stlibrd *brdp); | ||
687 | static int stli_initonb(struct stlibrd *brdp); | ||
688 | #if STLI_EISAPROBE != 0 | ||
689 | static int stli_eisamemprobe(struct stlibrd *brdp); | ||
690 | #endif | ||
691 | static int stli_initports(struct stlibrd *brdp); | ||
692 | |||
693 | /*****************************************************************************/ | ||
694 | |||
695 | /* | ||
696 | * Define the driver info for a user level shared memory device. This | ||
697 | * device will work sort of like the /dev/kmem device - except that it | ||
698 | * will give access to the shared memory on the Stallion intelligent | ||
699 | * board. This is also a very useful debugging tool. | ||
700 | */ | ||
701 | static const struct file_operations stli_fsiomem = { | ||
702 | .owner = THIS_MODULE, | ||
703 | .read = stli_memread, | ||
704 | .write = stli_memwrite, | ||
705 | .unlocked_ioctl = stli_memioctl, | ||
706 | .llseek = default_llseek, | ||
707 | }; | ||
708 | |||
709 | /*****************************************************************************/ | ||
710 | |||
711 | /* | ||
712 | * Define a timer_list entry for our poll routine. The slave board | ||
713 | * is polled every so often to see if anything needs doing. This is | ||
714 | * much cheaper on host cpu than using interrupts. It turns out to | ||
715 | * not increase character latency by much either... | ||
716 | */ | ||
717 | static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0); | ||
718 | |||
719 | static int stli_timeron; | ||
720 | |||
721 | /* | ||
722 | * Define the calculation for the timeout routine. | ||
723 | */ | ||
724 | #define STLI_TIMEOUT (jiffies + 1) | ||
725 | |||
726 | /*****************************************************************************/ | ||
727 | |||
728 | static struct class *istallion_class; | ||
729 | |||
730 | static void stli_cleanup_ports(struct stlibrd *brdp) | ||
731 | { | ||
732 | struct stliport *portp; | ||
733 | unsigned int j; | ||
734 | struct tty_struct *tty; | ||
735 | |||
736 | for (j = 0; j < STL_MAXPORTS; j++) { | ||
737 | portp = brdp->ports[j]; | ||
738 | if (portp != NULL) { | ||
739 | tty = tty_port_tty_get(&portp->port); | ||
740 | if (tty != NULL) { | ||
741 | tty_hangup(tty); | ||
742 | tty_kref_put(tty); | ||
743 | } | ||
744 | kfree(portp); | ||
745 | } | ||
746 | } | ||
747 | } | ||
748 | |||
749 | /*****************************************************************************/ | ||
750 | |||
751 | /* | ||
752 | * Parse the supplied argument string, into the board conf struct. | ||
753 | */ | ||
754 | |||
755 | static int stli_parsebrd(struct stlconf *confp, char **argp) | ||
756 | { | ||
757 | unsigned int i; | ||
758 | char *sp; | ||
759 | |||
760 | if (argp[0] == NULL || *argp[0] == 0) | ||
761 | return 0; | ||
762 | |||
763 | for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) | ||
764 | *sp = tolower(*sp); | ||
765 | |||
766 | for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) { | ||
767 | if (strcmp(stli_brdstr[i].name, argp[0]) == 0) | ||
768 | break; | ||
769 | } | ||
770 | if (i == ARRAY_SIZE(stli_brdstr)) { | ||
771 | printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]); | ||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | confp->brdtype = stli_brdstr[i].type; | ||
776 | if (argp[1] != NULL && *argp[1] != 0) | ||
777 | confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0); | ||
778 | if (argp[2] != NULL && *argp[2] != 0) | ||
779 | confp->memaddr = simple_strtoul(argp[2], NULL, 0); | ||
780 | return(1); | ||
781 | } | ||
782 | |||
783 | /*****************************************************************************/ | ||
784 | |||
785 | /* | ||
786 | * On the first open of the device setup the port hardware, and | ||
787 | * initialize the per port data structure. Since initializing the port | ||
788 | * requires several commands to the board we will need to wait for any | ||
789 | * other open that is already initializing the port. | ||
790 | * | ||
791 | * Locking: protected by the port mutex. | ||
792 | */ | ||
793 | |||
794 | static int stli_activate(struct tty_port *port, struct tty_struct *tty) | ||
795 | { | ||
796 | struct stliport *portp = container_of(port, struct stliport, port); | ||
797 | struct stlibrd *brdp = stli_brds[portp->brdnr]; | ||
798 | int rc; | ||
799 | |||
800 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) | ||
801 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
802 | wake_up_interruptible(&portp->raw_wait); | ||
803 | return rc; | ||
804 | } | ||
805 | |||
806 | static int stli_open(struct tty_struct *tty, struct file *filp) | ||
807 | { | ||
808 | struct stlibrd *brdp; | ||
809 | struct stliport *portp; | ||
810 | unsigned int minordev, brdnr, portnr; | ||
811 | |||
812 | minordev = tty->index; | ||
813 | brdnr = MINOR2BRD(minordev); | ||
814 | if (brdnr >= stli_nrbrds) | ||
815 | return -ENODEV; | ||
816 | brdp = stli_brds[brdnr]; | ||
817 | if (brdp == NULL) | ||
818 | return -ENODEV; | ||
819 | if (!test_bit(BST_STARTED, &brdp->state)) | ||
820 | return -ENODEV; | ||
821 | portnr = MINOR2PORT(minordev); | ||
822 | if (portnr > brdp->nrports) | ||
823 | return -ENODEV; | ||
824 | |||
825 | portp = brdp->ports[portnr]; | ||
826 | if (portp == NULL) | ||
827 | return -ENODEV; | ||
828 | if (portp->devnr < 1) | ||
829 | return -ENODEV; | ||
830 | |||
831 | tty->driver_data = portp; | ||
832 | return tty_port_open(&portp->port, tty, filp); | ||
833 | } | ||
834 | |||
835 | |||
836 | /*****************************************************************************/ | ||
837 | |||
838 | static void stli_shutdown(struct tty_port *port) | ||
839 | { | ||
840 | struct stlibrd *brdp; | ||
841 | unsigned long ftype; | ||
842 | unsigned long flags; | ||
843 | struct stliport *portp = container_of(port, struct stliport, port); | ||
844 | |||
845 | if (portp->brdnr >= stli_nrbrds) | ||
846 | return; | ||
847 | brdp = stli_brds[portp->brdnr]; | ||
848 | if (brdp == NULL) | ||
849 | return; | ||
850 | |||
851 | /* | ||
852 | * May want to wait for data to drain before closing. The BUSY | ||
853 | * flag keeps track of whether we are still transmitting or not. | ||
854 | * It is updated by messages from the slave - indicating when all | ||
855 | * chars really have drained. | ||
856 | */ | ||
857 | |||
858 | if (!test_bit(ST_CLOSING, &portp->state)) | ||
859 | stli_rawclose(brdp, portp, 0, 0); | ||
860 | |||
861 | spin_lock_irqsave(&stli_lock, flags); | ||
862 | clear_bit(ST_TXBUSY, &portp->state); | ||
863 | clear_bit(ST_RXSTOP, &portp->state); | ||
864 | spin_unlock_irqrestore(&stli_lock, flags); | ||
865 | |||
866 | ftype = FLUSHTX | FLUSHRX; | ||
867 | stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); | ||
868 | } | ||
869 | |||
870 | static void stli_close(struct tty_struct *tty, struct file *filp) | ||
871 | { | ||
872 | struct stliport *portp = tty->driver_data; | ||
873 | unsigned long flags; | ||
874 | if (portp == NULL) | ||
875 | return; | ||
876 | spin_lock_irqsave(&stli_lock, flags); | ||
877 | /* Flush any internal buffering out first */ | ||
878 | if (tty == stli_txcooktty) | ||
879 | stli_flushchars(tty); | ||
880 | spin_unlock_irqrestore(&stli_lock, flags); | ||
881 | tty_port_close(&portp->port, tty, filp); | ||
882 | } | ||
883 | |||
884 | /*****************************************************************************/ | ||
885 | |||
886 | /* | ||
887 | * Carry out first open operations on a port. This involves a number of | ||
888 | * commands to be sent to the slave. We need to open the port, set the | ||
889 | * notification events, set the initial port settings, get and set the | ||
890 | * initial signal values. We sleep and wait in between each one. But | ||
891 | * this still all happens pretty quickly. | ||
892 | */ | ||
893 | |||
894 | static int stli_initopen(struct tty_struct *tty, | ||
895 | struct stlibrd *brdp, struct stliport *portp) | ||
896 | { | ||
897 | asynotify_t nt; | ||
898 | asyport_t aport; | ||
899 | int rc; | ||
900 | |||
901 | if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0) | ||
902 | return rc; | ||
903 | |||
904 | memset(&nt, 0, sizeof(asynotify_t)); | ||
905 | nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK); | ||
906 | nt.signal = SG_DCD; | ||
907 | if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt, | ||
908 | sizeof(asynotify_t), 0)) < 0) | ||
909 | return rc; | ||
910 | |||
911 | stli_mkasyport(tty, portp, &aport, tty->termios); | ||
912 | if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport, | ||
913 | sizeof(asyport_t), 0)) < 0) | ||
914 | return rc; | ||
915 | |||
916 | set_bit(ST_GETSIGS, &portp->state); | ||
917 | if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig, | ||
918 | sizeof(asysigs_t), 1)) < 0) | ||
919 | return rc; | ||
920 | if (test_and_clear_bit(ST_GETSIGS, &portp->state)) | ||
921 | portp->sigs = stli_mktiocm(portp->asig.sigvalue); | ||
922 | stli_mkasysigs(&portp->asig, 1, 1); | ||
923 | if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | ||
924 | sizeof(asysigs_t), 0)) < 0) | ||
925 | return rc; | ||
926 | |||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | /*****************************************************************************/ | ||
931 | |||
932 | /* | ||
933 | * Send an open message to the slave. This will sleep waiting for the | ||
934 | * acknowledgement, so must have user context. We need to co-ordinate | ||
935 | * with close events here, since we don't want open and close events | ||
936 | * to overlap. | ||
937 | */ | ||
938 | |||
939 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) | ||
940 | { | ||
941 | cdkhdr_t __iomem *hdrp; | ||
942 | cdkctrl_t __iomem *cp; | ||
943 | unsigned char __iomem *bits; | ||
944 | unsigned long flags; | ||
945 | int rc; | ||
946 | |||
947 | /* | ||
948 | * Send a message to the slave to open this port. | ||
949 | */ | ||
950 | |||
951 | /* | ||
952 | * Slave is already closing this port. This can happen if a hangup | ||
953 | * occurs on this port. So we must wait until it is complete. The | ||
954 | * order of opens and closes may not be preserved across shared | ||
955 | * memory, so we must wait until it is complete. | ||
956 | */ | ||
957 | wait_event_interruptible_tty(portp->raw_wait, | ||
958 | !test_bit(ST_CLOSING, &portp->state)); | ||
959 | if (signal_pending(current)) { | ||
960 | return -ERESTARTSYS; | ||
961 | } | ||
962 | |||
963 | /* | ||
964 | * Everything is ready now, so write the open message into shared | ||
965 | * memory. Once the message is in set the service bits to say that | ||
966 | * this port wants service. | ||
967 | */ | ||
968 | spin_lock_irqsave(&brd_lock, flags); | ||
969 | EBRDENABLE(brdp); | ||
970 | cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; | ||
971 | writel(arg, &cp->openarg); | ||
972 | writeb(1, &cp->open); | ||
973 | hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); | ||
974 | bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + | ||
975 | portp->portidx; | ||
976 | writeb(readb(bits) | portp->portbit, bits); | ||
977 | EBRDDISABLE(brdp); | ||
978 | |||
979 | if (wait == 0) { | ||
980 | spin_unlock_irqrestore(&brd_lock, flags); | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | /* | ||
985 | * Slave is in action, so now we must wait for the open acknowledgment | ||
986 | * to come back. | ||
987 | */ | ||
988 | rc = 0; | ||
989 | set_bit(ST_OPENING, &portp->state); | ||
990 | spin_unlock_irqrestore(&brd_lock, flags); | ||
991 | |||
992 | wait_event_interruptible_tty(portp->raw_wait, | ||
993 | !test_bit(ST_OPENING, &portp->state)); | ||
994 | if (signal_pending(current)) | ||
995 | rc = -ERESTARTSYS; | ||
996 | |||
997 | if ((rc == 0) && (portp->rc != 0)) | ||
998 | rc = -EIO; | ||
999 | return rc; | ||
1000 | } | ||
1001 | |||
1002 | /*****************************************************************************/ | ||
1003 | |||
1004 | /* | ||
1005 | * Send a close message to the slave. Normally this will sleep waiting | ||
1006 | * for the acknowledgement, but if wait parameter is 0 it will not. If | ||
1007 | * wait is true then must have user context (to sleep). | ||
1008 | */ | ||
1009 | |||
1010 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) | ||
1011 | { | ||
1012 | cdkhdr_t __iomem *hdrp; | ||
1013 | cdkctrl_t __iomem *cp; | ||
1014 | unsigned char __iomem *bits; | ||
1015 | unsigned long flags; | ||
1016 | int rc; | ||
1017 | |||
1018 | /* | ||
1019 | * Slave is already closing this port. This can happen if a hangup | ||
1020 | * occurs on this port. | ||
1021 | */ | ||
1022 | if (wait) { | ||
1023 | wait_event_interruptible_tty(portp->raw_wait, | ||
1024 | !test_bit(ST_CLOSING, &portp->state)); | ||
1025 | if (signal_pending(current)) { | ||
1026 | return -ERESTARTSYS; | ||
1027 | } | ||
1028 | } | ||
1029 | |||
1030 | /* | ||
1031 | * Write the close command into shared memory. | ||
1032 | */ | ||
1033 | spin_lock_irqsave(&brd_lock, flags); | ||
1034 | EBRDENABLE(brdp); | ||
1035 | cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; | ||
1036 | writel(arg, &cp->closearg); | ||
1037 | writeb(1, &cp->close); | ||
1038 | hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); | ||
1039 | bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + | ||
1040 | portp->portidx; | ||
1041 | writeb(readb(bits) |portp->portbit, bits); | ||
1042 | EBRDDISABLE(brdp); | ||
1043 | |||
1044 | set_bit(ST_CLOSING, &portp->state); | ||
1045 | spin_unlock_irqrestore(&brd_lock, flags); | ||
1046 | |||
1047 | if (wait == 0) | ||
1048 | return 0; | ||
1049 | |||
1050 | /* | ||
1051 | * Slave is in action, so now we must wait for the open acknowledgment | ||
1052 | * to come back. | ||
1053 | */ | ||
1054 | rc = 0; | ||
1055 | wait_event_interruptible_tty(portp->raw_wait, | ||
1056 | !test_bit(ST_CLOSING, &portp->state)); | ||
1057 | if (signal_pending(current)) | ||
1058 | rc = -ERESTARTSYS; | ||
1059 | |||
1060 | if ((rc == 0) && (portp->rc != 0)) | ||
1061 | rc = -EIO; | ||
1062 | return rc; | ||
1063 | } | ||
1064 | |||
1065 | /*****************************************************************************/ | ||
1066 | |||
1067 | /* | ||
1068 | * Send a command to the slave and wait for the response. This must | ||
1069 | * have user context (it sleeps). This routine is generic in that it | ||
1070 | * can send any type of command. Its purpose is to wait for that command | ||
1071 | * to complete (as opposed to initiating the command then returning). | ||
1072 | */ | ||
1073 | |||
1074 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) | ||
1075 | { | ||
1076 | /* | ||
1077 | * no need for wait_event_tty because clearing ST_CMDING cannot block | ||
1078 | * on BTM | ||
1079 | */ | ||
1080 | wait_event_interruptible(portp->raw_wait, | ||
1081 | !test_bit(ST_CMDING, &portp->state)); | ||
1082 | if (signal_pending(current)) | ||
1083 | return -ERESTARTSYS; | ||
1084 | |||
1085 | stli_sendcmd(brdp, portp, cmd, arg, size, copyback); | ||
1086 | |||
1087 | wait_event_interruptible(portp->raw_wait, | ||
1088 | !test_bit(ST_CMDING, &portp->state)); | ||
1089 | if (signal_pending(current)) | ||
1090 | return -ERESTARTSYS; | ||
1091 | |||
1092 | if (portp->rc != 0) | ||
1093 | return -EIO; | ||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | /*****************************************************************************/ | ||
1098 | |||
1099 | /* | ||
1100 | * Send the termios settings for this port to the slave. This sleeps | ||
1101 | * waiting for the command to complete - so must have user context. | ||
1102 | */ | ||
1103 | |||
1104 | static int stli_setport(struct tty_struct *tty) | ||
1105 | { | ||
1106 | struct stliport *portp = tty->driver_data; | ||
1107 | struct stlibrd *brdp; | ||
1108 | asyport_t aport; | ||
1109 | |||
1110 | if (portp == NULL) | ||
1111 | return -ENODEV; | ||
1112 | if (portp->brdnr >= stli_nrbrds) | ||
1113 | return -ENODEV; | ||
1114 | brdp = stli_brds[portp->brdnr]; | ||
1115 | if (brdp == NULL) | ||
1116 | return -ENODEV; | ||
1117 | |||
1118 | stli_mkasyport(tty, portp, &aport, tty->termios); | ||
1119 | return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0)); | ||
1120 | } | ||
1121 | |||
1122 | /*****************************************************************************/ | ||
1123 | |||
1124 | static int stli_carrier_raised(struct tty_port *port) | ||
1125 | { | ||
1126 | struct stliport *portp = container_of(port, struct stliport, port); | ||
1127 | return (portp->sigs & TIOCM_CD) ? 1 : 0; | ||
1128 | } | ||
1129 | |||
1130 | static void stli_dtr_rts(struct tty_port *port, int on) | ||
1131 | { | ||
1132 | struct stliport *portp = container_of(port, struct stliport, port); | ||
1133 | struct stlibrd *brdp = stli_brds[portp->brdnr]; | ||
1134 | stli_mkasysigs(&portp->asig, on, on); | ||
1135 | if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | ||
1136 | sizeof(asysigs_t), 0) < 0) | ||
1137 | printk(KERN_WARNING "istallion: dtr set failed.\n"); | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | /*****************************************************************************/ | ||
1142 | |||
1143 | /* | ||
1144 | * Write routine. Take the data and put it in the shared memory ring | ||
1145 | * queue. If port is not already sending chars then need to mark the | ||
1146 | * service bits for this port. | ||
1147 | */ | ||
1148 | |||
1149 | static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count) | ||
1150 | { | ||
1151 | cdkasy_t __iomem *ap; | ||
1152 | cdkhdr_t __iomem *hdrp; | ||
1153 | unsigned char __iomem *bits; | ||
1154 | unsigned char __iomem *shbuf; | ||
1155 | unsigned char *chbuf; | ||
1156 | struct stliport *portp; | ||
1157 | struct stlibrd *brdp; | ||
1158 | unsigned int len, stlen, head, tail, size; | ||
1159 | unsigned long flags; | ||
1160 | |||
1161 | if (tty == stli_txcooktty) | ||
1162 | stli_flushchars(tty); | ||
1163 | portp = tty->driver_data; | ||
1164 | if (portp == NULL) | ||
1165 | return 0; | ||
1166 | if (portp->brdnr >= stli_nrbrds) | ||
1167 | return 0; | ||
1168 | brdp = stli_brds[portp->brdnr]; | ||
1169 | if (brdp == NULL) | ||
1170 | return 0; | ||
1171 | chbuf = (unsigned char *) buf; | ||
1172 | |||
1173 | /* | ||
1174 | * All data is now local, shove as much as possible into shared memory. | ||
1175 | */ | ||
1176 | spin_lock_irqsave(&brd_lock, flags); | ||
1177 | EBRDENABLE(brdp); | ||
1178 | ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); | ||
1179 | head = (unsigned int) readw(&ap->txq.head); | ||
1180 | tail = (unsigned int) readw(&ap->txq.tail); | ||
1181 | if (tail != ((unsigned int) readw(&ap->txq.tail))) | ||
1182 | tail = (unsigned int) readw(&ap->txq.tail); | ||
1183 | size = portp->txsize; | ||
1184 | if (head >= tail) { | ||
1185 | len = size - (head - tail) - 1; | ||
1186 | stlen = size - head; | ||
1187 | } else { | ||
1188 | len = tail - head - 1; | ||
1189 | stlen = len; | ||
1190 | } | ||
1191 | |||
1192 | len = min(len, (unsigned int)count); | ||
1193 | count = 0; | ||
1194 | shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset); | ||
1195 | |||
1196 | while (len > 0) { | ||
1197 | stlen = min(len, stlen); | ||
1198 | memcpy_toio(shbuf + head, chbuf, stlen); | ||
1199 | chbuf += stlen; | ||
1200 | len -= stlen; | ||
1201 | count += stlen; | ||
1202 | head += stlen; | ||
1203 | if (head >= size) { | ||
1204 | head = 0; | ||
1205 | stlen = tail; | ||
1206 | } | ||
1207 | } | ||
1208 | |||
1209 | ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); | ||
1210 | writew(head, &ap->txq.head); | ||
1211 | if (test_bit(ST_TXBUSY, &portp->state)) { | ||
1212 | if (readl(&ap->changed.data) & DT_TXEMPTY) | ||
1213 | writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data); | ||
1214 | } | ||
1215 | hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); | ||
1216 | bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + | ||
1217 | portp->portidx; | ||
1218 | writeb(readb(bits) | portp->portbit, bits); | ||
1219 | set_bit(ST_TXBUSY, &portp->state); | ||
1220 | EBRDDISABLE(brdp); | ||
1221 | spin_unlock_irqrestore(&brd_lock, flags); | ||
1222 | |||
1223 | return(count); | ||
1224 | } | ||
1225 | |||
1226 | /*****************************************************************************/ | ||
1227 | |||
1228 | /* | ||
1229 | * Output a single character. We put it into a temporary local buffer | ||
1230 | * (for speed) then write out that buffer when the flushchars routine | ||
1231 | * is called. There is a safety catch here so that if some other port | ||
1232 | * writes chars before the current buffer has been, then we write them | ||
1233 | * first them do the new ports. | ||
1234 | */ | ||
1235 | |||
1236 | static int stli_putchar(struct tty_struct *tty, unsigned char ch) | ||
1237 | { | ||
1238 | if (tty != stli_txcooktty) { | ||
1239 | if (stli_txcooktty != NULL) | ||
1240 | stli_flushchars(stli_txcooktty); | ||
1241 | stli_txcooktty = tty; | ||
1242 | } | ||
1243 | |||
1244 | stli_txcookbuf[stli_txcooksize++] = ch; | ||
1245 | return 0; | ||
1246 | } | ||
1247 | |||
1248 | /*****************************************************************************/ | ||
1249 | |||
1250 | /* | ||
1251 | * Transfer characters from the local TX cooking buffer to the board. | ||
1252 | * We sort of ignore the tty that gets passed in here. We rely on the | ||
1253 | * info stored with the TX cook buffer to tell us which port to flush | ||
1254 | * the data on. In any case we clean out the TX cook buffer, for re-use | ||
1255 | * by someone else. | ||
1256 | */ | ||
1257 | |||
1258 | static void stli_flushchars(struct tty_struct *tty) | ||
1259 | { | ||
1260 | cdkhdr_t __iomem *hdrp; | ||
1261 | unsigned char __iomem *bits; | ||
1262 | cdkasy_t __iomem *ap; | ||
1263 | struct tty_struct *cooktty; | ||
1264 | struct stliport *portp; | ||
1265 | struct stlibrd *brdp; | ||
1266 | unsigned int len, stlen, head, tail, size, count, cooksize; | ||
1267 | unsigned char *buf; | ||
1268 | unsigned char __iomem *shbuf; | ||
1269 | unsigned long flags; | ||
1270 | |||
1271 | cooksize = stli_txcooksize; | ||
1272 | cooktty = stli_txcooktty; | ||
1273 | stli_txcooksize = 0; | ||
1274 | stli_txcookrealsize = 0; | ||
1275 | stli_txcooktty = NULL; | ||
1276 | |||
1277 | if (cooktty == NULL) | ||
1278 | return; | ||
1279 | if (tty != cooktty) | ||
1280 | tty = cooktty; | ||
1281 | if (cooksize == 0) | ||
1282 | return; | ||
1283 | |||
1284 | portp = tty->driver_data; | ||
1285 | if (portp == NULL) | ||
1286 | return; | ||
1287 | if (portp->brdnr >= stli_nrbrds) | ||
1288 | return; | ||
1289 | brdp = stli_brds[portp->brdnr]; | ||
1290 | if (brdp == NULL) | ||
1291 | return; | ||
1292 | |||
1293 | spin_lock_irqsave(&brd_lock, flags); | ||
1294 | EBRDENABLE(brdp); | ||
1295 | |||
1296 | ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); | ||
1297 | head = (unsigned int) readw(&ap->txq.head); | ||
1298 | tail = (unsigned int) readw(&ap->txq.tail); | ||
1299 | if (tail != ((unsigned int) readw(&ap->txq.tail))) | ||
1300 | tail = (unsigned int) readw(&ap->txq.tail); | ||
1301 | size = portp->txsize; | ||
1302 | if (head >= tail) { | ||
1303 | len = size - (head - tail) - 1; | ||
1304 | stlen = size - head; | ||
1305 | } else { | ||
1306 | len = tail - head - 1; | ||
1307 | stlen = len; | ||
1308 | } | ||
1309 | |||
1310 | len = min(len, cooksize); | ||
1311 | count = 0; | ||
1312 | shbuf = EBRDGETMEMPTR(brdp, portp->txoffset); | ||
1313 | buf = stli_txcookbuf; | ||
1314 | |||
1315 | while (len > 0) { | ||
1316 | stlen = min(len, stlen); | ||
1317 | memcpy_toio(shbuf + head, buf, stlen); | ||
1318 | buf += stlen; | ||
1319 | len -= stlen; | ||
1320 | count += stlen; | ||
1321 | head += stlen; | ||
1322 | if (head >= size) { | ||
1323 | head = 0; | ||
1324 | stlen = tail; | ||
1325 | } | ||
1326 | } | ||
1327 | |||
1328 | ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); | ||
1329 | writew(head, &ap->txq.head); | ||
1330 | |||
1331 | if (test_bit(ST_TXBUSY, &portp->state)) { | ||
1332 | if (readl(&ap->changed.data) & DT_TXEMPTY) | ||
1333 | writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data); | ||
1334 | } | ||
1335 | hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); | ||
1336 | bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + | ||
1337 | portp->portidx; | ||
1338 | writeb(readb(bits) | portp->portbit, bits); | ||
1339 | set_bit(ST_TXBUSY, &portp->state); | ||
1340 | |||
1341 | EBRDDISABLE(brdp); | ||
1342 | spin_unlock_irqrestore(&brd_lock, flags); | ||
1343 | } | ||
1344 | |||
1345 | /*****************************************************************************/ | ||
1346 | |||
1347 | static int stli_writeroom(struct tty_struct *tty) | ||
1348 | { | ||
1349 | cdkasyrq_t __iomem *rp; | ||
1350 | struct stliport *portp; | ||
1351 | struct stlibrd *brdp; | ||
1352 | unsigned int head, tail, len; | ||
1353 | unsigned long flags; | ||
1354 | |||
1355 | if (tty == stli_txcooktty) { | ||
1356 | if (stli_txcookrealsize != 0) { | ||
1357 | len = stli_txcookrealsize - stli_txcooksize; | ||
1358 | return len; | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | portp = tty->driver_data; | ||
1363 | if (portp == NULL) | ||
1364 | return 0; | ||
1365 | if (portp->brdnr >= stli_nrbrds) | ||
1366 | return 0; | ||
1367 | brdp = stli_brds[portp->brdnr]; | ||
1368 | if (brdp == NULL) | ||
1369 | return 0; | ||
1370 | |||
1371 | spin_lock_irqsave(&brd_lock, flags); | ||
1372 | EBRDENABLE(brdp); | ||
1373 | rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq; | ||
1374 | head = (unsigned int) readw(&rp->head); | ||
1375 | tail = (unsigned int) readw(&rp->tail); | ||
1376 | if (tail != ((unsigned int) readw(&rp->tail))) | ||
1377 | tail = (unsigned int) readw(&rp->tail); | ||
1378 | len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head); | ||
1379 | len--; | ||
1380 | EBRDDISABLE(brdp); | ||
1381 | spin_unlock_irqrestore(&brd_lock, flags); | ||
1382 | |||
1383 | if (tty == stli_txcooktty) { | ||
1384 | stli_txcookrealsize = len; | ||
1385 | len -= stli_txcooksize; | ||
1386 | } | ||
1387 | return len; | ||
1388 | } | ||
1389 | |||
1390 | /*****************************************************************************/ | ||
1391 | |||
1392 | /* | ||
1393 | * Return the number of characters in the transmit buffer. Normally we | ||
1394 | * will return the number of chars in the shared memory ring queue. | ||
1395 | * We need to kludge around the case where the shared memory buffer is | ||
1396 | * empty but not all characters have drained yet, for this case just | ||
1397 | * return that there is 1 character in the buffer! | ||
1398 | */ | ||
1399 | |||
1400 | static int stli_charsinbuffer(struct tty_struct *tty) | ||
1401 | { | ||
1402 | cdkasyrq_t __iomem *rp; | ||
1403 | struct stliport *portp; | ||
1404 | struct stlibrd *brdp; | ||
1405 | unsigned int head, tail, len; | ||
1406 | unsigned long flags; | ||
1407 | |||
1408 | if (tty == stli_txcooktty) | ||
1409 | stli_flushchars(tty); | ||
1410 | portp = tty->driver_data; | ||
1411 | if (portp == NULL) | ||
1412 | return 0; | ||
1413 | if (portp->brdnr >= stli_nrbrds) | ||
1414 | return 0; | ||
1415 | brdp = stli_brds[portp->brdnr]; | ||
1416 | if (brdp == NULL) | ||
1417 | return 0; | ||
1418 | |||
1419 | spin_lock_irqsave(&brd_lock, flags); | ||
1420 | EBRDENABLE(brdp); | ||
1421 | rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq; | ||
1422 | head = (unsigned int) readw(&rp->head); | ||
1423 | tail = (unsigned int) readw(&rp->tail); | ||
1424 | if (tail != ((unsigned int) readw(&rp->tail))) | ||
1425 | tail = (unsigned int) readw(&rp->tail); | ||
1426 | len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head)); | ||
1427 | if ((len == 0) && test_bit(ST_TXBUSY, &portp->state)) | ||
1428 | len = 1; | ||
1429 | EBRDDISABLE(brdp); | ||
1430 | spin_unlock_irqrestore(&brd_lock, flags); | ||
1431 | |||
1432 | return len; | ||
1433 | } | ||
1434 | |||
1435 | /*****************************************************************************/ | ||
1436 | |||
1437 | /* | ||
1438 | * Generate the serial struct info. | ||
1439 | */ | ||
1440 | |||
1441 | static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp) | ||
1442 | { | ||
1443 | struct serial_struct sio; | ||
1444 | struct stlibrd *brdp; | ||
1445 | |||
1446 | memset(&sio, 0, sizeof(struct serial_struct)); | ||
1447 | sio.type = PORT_UNKNOWN; | ||
1448 | sio.line = portp->portnr; | ||
1449 | sio.irq = 0; | ||
1450 | sio.flags = portp->port.flags; | ||
1451 | sio.baud_base = portp->baud_base; | ||
1452 | sio.close_delay = portp->port.close_delay; | ||
1453 | sio.closing_wait = portp->closing_wait; | ||
1454 | sio.custom_divisor = portp->custom_divisor; | ||
1455 | sio.xmit_fifo_size = 0; | ||
1456 | sio.hub6 = 0; | ||
1457 | |||
1458 | brdp = stli_brds[portp->brdnr]; | ||
1459 | if (brdp != NULL) | ||
1460 | sio.port = brdp->iobase; | ||
1461 | |||
1462 | return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? | ||
1463 | -EFAULT : 0; | ||
1464 | } | ||
1465 | |||
1466 | /*****************************************************************************/ | ||
1467 | |||
1468 | /* | ||
1469 | * Set port according to the serial struct info. | ||
1470 | * At this point we do not do any auto-configure stuff, so we will | ||
1471 | * just quietly ignore any requests to change irq, etc. | ||
1472 | */ | ||
1473 | |||
1474 | static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp) | ||
1475 | { | ||
1476 | struct serial_struct sio; | ||
1477 | int rc; | ||
1478 | struct stliport *portp = tty->driver_data; | ||
1479 | |||
1480 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) | ||
1481 | return -EFAULT; | ||
1482 | if (!capable(CAP_SYS_ADMIN)) { | ||
1483 | if ((sio.baud_base != portp->baud_base) || | ||
1484 | (sio.close_delay != portp->port.close_delay) || | ||
1485 | ((sio.flags & ~ASYNC_USR_MASK) != | ||
1486 | (portp->port.flags & ~ASYNC_USR_MASK))) | ||
1487 | return -EPERM; | ||
1488 | } | ||
1489 | |||
1490 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | | ||
1491 | (sio.flags & ASYNC_USR_MASK); | ||
1492 | portp->baud_base = sio.baud_base; | ||
1493 | portp->port.close_delay = sio.close_delay; | ||
1494 | portp->closing_wait = sio.closing_wait; | ||
1495 | portp->custom_divisor = sio.custom_divisor; | ||
1496 | |||
1497 | if ((rc = stli_setport(tty)) < 0) | ||
1498 | return rc; | ||
1499 | return 0; | ||
1500 | } | ||
1501 | |||
1502 | /*****************************************************************************/ | ||
1503 | |||
1504 | static int stli_tiocmget(struct tty_struct *tty) | ||
1505 | { | ||
1506 | struct stliport *portp = tty->driver_data; | ||
1507 | struct stlibrd *brdp; | ||
1508 | int rc; | ||
1509 | |||
1510 | if (portp == NULL) | ||
1511 | return -ENODEV; | ||
1512 | if (portp->brdnr >= stli_nrbrds) | ||
1513 | return 0; | ||
1514 | brdp = stli_brds[portp->brdnr]; | ||
1515 | if (brdp == NULL) | ||
1516 | return 0; | ||
1517 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1518 | return -EIO; | ||
1519 | |||
1520 | if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, | ||
1521 | &portp->asig, sizeof(asysigs_t), 1)) < 0) | ||
1522 | return rc; | ||
1523 | |||
1524 | return stli_mktiocm(portp->asig.sigvalue); | ||
1525 | } | ||
1526 | |||
1527 | static int stli_tiocmset(struct tty_struct *tty, | ||
1528 | unsigned int set, unsigned int clear) | ||
1529 | { | ||
1530 | struct stliport *portp = tty->driver_data; | ||
1531 | struct stlibrd *brdp; | ||
1532 | int rts = -1, dtr = -1; | ||
1533 | |||
1534 | if (portp == NULL) | ||
1535 | return -ENODEV; | ||
1536 | if (portp->brdnr >= stli_nrbrds) | ||
1537 | return 0; | ||
1538 | brdp = stli_brds[portp->brdnr]; | ||
1539 | if (brdp == NULL) | ||
1540 | return 0; | ||
1541 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1542 | return -EIO; | ||
1543 | |||
1544 | if (set & TIOCM_RTS) | ||
1545 | rts = 1; | ||
1546 | if (set & TIOCM_DTR) | ||
1547 | dtr = 1; | ||
1548 | if (clear & TIOCM_RTS) | ||
1549 | rts = 0; | ||
1550 | if (clear & TIOCM_DTR) | ||
1551 | dtr = 0; | ||
1552 | |||
1553 | stli_mkasysigs(&portp->asig, dtr, rts); | ||
1554 | |||
1555 | return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | ||
1556 | sizeof(asysigs_t), 0); | ||
1557 | } | ||
1558 | |||
1559 | static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) | ||
1560 | { | ||
1561 | struct stliport *portp; | ||
1562 | struct stlibrd *brdp; | ||
1563 | int rc; | ||
1564 | void __user *argp = (void __user *)arg; | ||
1565 | |||
1566 | portp = tty->driver_data; | ||
1567 | if (portp == NULL) | ||
1568 | return -ENODEV; | ||
1569 | if (portp->brdnr >= stli_nrbrds) | ||
1570 | return 0; | ||
1571 | brdp = stli_brds[portp->brdnr]; | ||
1572 | if (brdp == NULL) | ||
1573 | return 0; | ||
1574 | |||
1575 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | ||
1576 | (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) { | ||
1577 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1578 | return -EIO; | ||
1579 | } | ||
1580 | |||
1581 | rc = 0; | ||
1582 | |||
1583 | switch (cmd) { | ||
1584 | case TIOCGSERIAL: | ||
1585 | rc = stli_getserial(portp, argp); | ||
1586 | break; | ||
1587 | case TIOCSSERIAL: | ||
1588 | rc = stli_setserial(tty, argp); | ||
1589 | break; | ||
1590 | case STL_GETPFLAG: | ||
1591 | rc = put_user(portp->pflag, (unsigned __user *)argp); | ||
1592 | break; | ||
1593 | case STL_SETPFLAG: | ||
1594 | if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0) | ||
1595 | stli_setport(tty); | ||
1596 | break; | ||
1597 | case COM_GETPORTSTATS: | ||
1598 | rc = stli_getportstats(tty, portp, argp); | ||
1599 | break; | ||
1600 | case COM_CLRPORTSTATS: | ||
1601 | rc = stli_clrportstats(portp, argp); | ||
1602 | break; | ||
1603 | case TIOCSERCONFIG: | ||
1604 | case TIOCSERGWILD: | ||
1605 | case TIOCSERSWILD: | ||
1606 | case TIOCSERGETLSR: | ||
1607 | case TIOCSERGSTRUCT: | ||
1608 | case TIOCSERGETMULTI: | ||
1609 | case TIOCSERSETMULTI: | ||
1610 | default: | ||
1611 | rc = -ENOIOCTLCMD; | ||
1612 | break; | ||
1613 | } | ||
1614 | |||
1615 | return rc; | ||
1616 | } | ||
1617 | |||
1618 | /*****************************************************************************/ | ||
1619 | |||
1620 | /* | ||
1621 | * This routine assumes that we have user context and can sleep. | ||
1622 | * Looks like it is true for the current ttys implementation..!! | ||
1623 | */ | ||
1624 | |||
1625 | static void stli_settermios(struct tty_struct *tty, struct ktermios *old) | ||
1626 | { | ||
1627 | struct stliport *portp; | ||
1628 | struct stlibrd *brdp; | ||
1629 | struct ktermios *tiosp; | ||
1630 | asyport_t aport; | ||
1631 | |||
1632 | portp = tty->driver_data; | ||
1633 | if (portp == NULL) | ||
1634 | return; | ||
1635 | if (portp->brdnr >= stli_nrbrds) | ||
1636 | return; | ||
1637 | brdp = stli_brds[portp->brdnr]; | ||
1638 | if (brdp == NULL) | ||
1639 | return; | ||
1640 | |||
1641 | tiosp = tty->termios; | ||
1642 | |||
1643 | stli_mkasyport(tty, portp, &aport, tiosp); | ||
1644 | stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0); | ||
1645 | stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1); | ||
1646 | stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | ||
1647 | sizeof(asysigs_t), 0); | ||
1648 | if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) | ||
1649 | tty->hw_stopped = 0; | ||
1650 | if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL)) | ||
1651 | wake_up_interruptible(&portp->port.open_wait); | ||
1652 | } | ||
1653 | |||
1654 | /*****************************************************************************/ | ||
1655 | |||
1656 | /* | ||
1657 | * Attempt to flow control who ever is sending us data. We won't really | ||
1658 | * do any flow control action here. We can't directly, and even if we | ||
1659 | * wanted to we would have to send a command to the slave. The slave | ||
1660 | * knows how to flow control, and will do so when its buffers reach its | ||
1661 | * internal high water marks. So what we will do is set a local state | ||
1662 | * bit that will stop us sending any RX data up from the poll routine | ||
1663 | * (which is the place where RX data from the slave is handled). | ||
1664 | */ | ||
1665 | |||
1666 | static void stli_throttle(struct tty_struct *tty) | ||
1667 | { | ||
1668 | struct stliport *portp = tty->driver_data; | ||
1669 | if (portp == NULL) | ||
1670 | return; | ||
1671 | set_bit(ST_RXSTOP, &portp->state); | ||
1672 | } | ||
1673 | |||
1674 | /*****************************************************************************/ | ||
1675 | |||
1676 | /* | ||
1677 | * Unflow control the device sending us data... That means that all | ||
1678 | * we have to do is clear the RXSTOP state bit. The next poll call | ||
1679 | * will then be able to pass the RX data back up. | ||
1680 | */ | ||
1681 | |||
1682 | static void stli_unthrottle(struct tty_struct *tty) | ||
1683 | { | ||
1684 | struct stliport *portp = tty->driver_data; | ||
1685 | if (portp == NULL) | ||
1686 | return; | ||
1687 | clear_bit(ST_RXSTOP, &portp->state); | ||
1688 | } | ||
1689 | |||
1690 | /*****************************************************************************/ | ||
1691 | |||
1692 | /* | ||
1693 | * Stop the transmitter. | ||
1694 | */ | ||
1695 | |||
1696 | static void stli_stop(struct tty_struct *tty) | ||
1697 | { | ||
1698 | } | ||
1699 | |||
1700 | /*****************************************************************************/ | ||
1701 | |||
1702 | /* | ||
1703 | * Start the transmitter again. | ||
1704 | */ | ||
1705 | |||
1706 | static void stli_start(struct tty_struct *tty) | ||
1707 | { | ||
1708 | } | ||
1709 | |||
1710 | /*****************************************************************************/ | ||
1711 | |||
1712 | |||
1713 | /* | ||
1714 | * Hangup this port. This is pretty much like closing the port, only | ||
1715 | * a little more brutal. No waiting for data to drain. Shutdown the | ||
1716 | * port and maybe drop signals. This is rather tricky really. We want | ||
1717 | * to close the port as well. | ||
1718 | */ | ||
1719 | |||
1720 | static void stli_hangup(struct tty_struct *tty) | ||
1721 | { | ||
1722 | struct stliport *portp = tty->driver_data; | ||
1723 | tty_port_hangup(&portp->port); | ||
1724 | } | ||
1725 | |||
1726 | /*****************************************************************************/ | ||
1727 | |||
1728 | /* | ||
1729 | * Flush characters from the lower buffer. We may not have user context | ||
1730 | * so we cannot sleep waiting for it to complete. Also we need to check | ||
1731 | * if there is chars for this port in the TX cook buffer, and flush them | ||
1732 | * as well. | ||
1733 | */ | ||
1734 | |||
1735 | static void stli_flushbuffer(struct tty_struct *tty) | ||
1736 | { | ||
1737 | struct stliport *portp; | ||
1738 | struct stlibrd *brdp; | ||
1739 | unsigned long ftype, flags; | ||
1740 | |||
1741 | portp = tty->driver_data; | ||
1742 | if (portp == NULL) | ||
1743 | return; | ||
1744 | if (portp->brdnr >= stli_nrbrds) | ||
1745 | return; | ||
1746 | brdp = stli_brds[portp->brdnr]; | ||
1747 | if (brdp == NULL) | ||
1748 | return; | ||
1749 | |||
1750 | spin_lock_irqsave(&brd_lock, flags); | ||
1751 | if (tty == stli_txcooktty) { | ||
1752 | stli_txcooktty = NULL; | ||
1753 | stli_txcooksize = 0; | ||
1754 | stli_txcookrealsize = 0; | ||
1755 | } | ||
1756 | if (test_bit(ST_CMDING, &portp->state)) { | ||
1757 | set_bit(ST_DOFLUSHTX, &portp->state); | ||
1758 | } else { | ||
1759 | ftype = FLUSHTX; | ||
1760 | if (test_bit(ST_DOFLUSHRX, &portp->state)) { | ||
1761 | ftype |= FLUSHRX; | ||
1762 | clear_bit(ST_DOFLUSHRX, &portp->state); | ||
1763 | } | ||
1764 | __stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); | ||
1765 | } | ||
1766 | spin_unlock_irqrestore(&brd_lock, flags); | ||
1767 | tty_wakeup(tty); | ||
1768 | } | ||
1769 | |||
1770 | /*****************************************************************************/ | ||
1771 | |||
1772 | static int stli_breakctl(struct tty_struct *tty, int state) | ||
1773 | { | ||
1774 | struct stlibrd *brdp; | ||
1775 | struct stliport *portp; | ||
1776 | long arg; | ||
1777 | |||
1778 | portp = tty->driver_data; | ||
1779 | if (portp == NULL) | ||
1780 | return -EINVAL; | ||
1781 | if (portp->brdnr >= stli_nrbrds) | ||
1782 | return -EINVAL; | ||
1783 | brdp = stli_brds[portp->brdnr]; | ||
1784 | if (brdp == NULL) | ||
1785 | return -EINVAL; | ||
1786 | |||
1787 | arg = (state == -1) ? BREAKON : BREAKOFF; | ||
1788 | stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0); | ||
1789 | return 0; | ||
1790 | } | ||
1791 | |||
1792 | /*****************************************************************************/ | ||
1793 | |||
1794 | static void stli_waituntilsent(struct tty_struct *tty, int timeout) | ||
1795 | { | ||
1796 | struct stliport *portp; | ||
1797 | unsigned long tend; | ||
1798 | |||
1799 | portp = tty->driver_data; | ||
1800 | if (portp == NULL) | ||
1801 | return; | ||
1802 | |||
1803 | if (timeout == 0) | ||
1804 | timeout = HZ; | ||
1805 | tend = jiffies + timeout; | ||
1806 | |||
1807 | while (test_bit(ST_TXBUSY, &portp->state)) { | ||
1808 | if (signal_pending(current)) | ||
1809 | break; | ||
1810 | msleep_interruptible(20); | ||
1811 | if (time_after_eq(jiffies, tend)) | ||
1812 | break; | ||
1813 | } | ||
1814 | } | ||
1815 | |||
1816 | /*****************************************************************************/ | ||
1817 | |||
1818 | static void stli_sendxchar(struct tty_struct *tty, char ch) | ||
1819 | { | ||
1820 | struct stlibrd *brdp; | ||
1821 | struct stliport *portp; | ||
1822 | asyctrl_t actrl; | ||
1823 | |||
1824 | portp = tty->driver_data; | ||
1825 | if (portp == NULL) | ||
1826 | return; | ||
1827 | if (portp->brdnr >= stli_nrbrds) | ||
1828 | return; | ||
1829 | brdp = stli_brds[portp->brdnr]; | ||
1830 | if (brdp == NULL) | ||
1831 | return; | ||
1832 | |||
1833 | memset(&actrl, 0, sizeof(asyctrl_t)); | ||
1834 | if (ch == STOP_CHAR(tty)) { | ||
1835 | actrl.rxctrl = CT_STOPFLOW; | ||
1836 | } else if (ch == START_CHAR(tty)) { | ||
1837 | actrl.rxctrl = CT_STARTFLOW; | ||
1838 | } else { | ||
1839 | actrl.txctrl = CT_SENDCHR; | ||
1840 | actrl.tximdch = ch; | ||
1841 | } | ||
1842 | stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); | ||
1843 | } | ||
1844 | |||
1845 | static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr) | ||
1846 | { | ||
1847 | char *uart; | ||
1848 | int rc; | ||
1849 | |||
1850 | rc = stli_portcmdstats(NULL, portp); | ||
1851 | |||
1852 | uart = "UNKNOWN"; | ||
1853 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
1854 | switch (stli_comstats.hwid) { | ||
1855 | case 0: uart = "2681"; break; | ||
1856 | case 1: uart = "SC26198"; break; | ||
1857 | default:uart = "CD1400"; break; | ||
1858 | } | ||
1859 | } | ||
1860 | seq_printf(m, "%d: uart:%s ", portnr, uart); | ||
1861 | |||
1862 | if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) { | ||
1863 | char sep; | ||
1864 | |||
1865 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, | ||
1866 | (int) stli_comstats.rxtotal); | ||
1867 | |||
1868 | if (stli_comstats.rxframing) | ||
1869 | seq_printf(m, " fe:%d", | ||
1870 | (int) stli_comstats.rxframing); | ||
1871 | if (stli_comstats.rxparity) | ||
1872 | seq_printf(m, " pe:%d", | ||
1873 | (int) stli_comstats.rxparity); | ||
1874 | if (stli_comstats.rxbreaks) | ||
1875 | seq_printf(m, " brk:%d", | ||
1876 | (int) stli_comstats.rxbreaks); | ||
1877 | if (stli_comstats.rxoverrun) | ||
1878 | seq_printf(m, " oe:%d", | ||
1879 | (int) stli_comstats.rxoverrun); | ||
1880 | |||
1881 | sep = ' '; | ||
1882 | if (stli_comstats.signals & TIOCM_RTS) { | ||
1883 | seq_printf(m, "%c%s", sep, "RTS"); | ||
1884 | sep = '|'; | ||
1885 | } | ||
1886 | if (stli_comstats.signals & TIOCM_CTS) { | ||
1887 | seq_printf(m, "%c%s", sep, "CTS"); | ||
1888 | sep = '|'; | ||
1889 | } | ||
1890 | if (stli_comstats.signals & TIOCM_DTR) { | ||
1891 | seq_printf(m, "%c%s", sep, "DTR"); | ||
1892 | sep = '|'; | ||
1893 | } | ||
1894 | if (stli_comstats.signals & TIOCM_CD) { | ||
1895 | seq_printf(m, "%c%s", sep, "DCD"); | ||
1896 | sep = '|'; | ||
1897 | } | ||
1898 | if (stli_comstats.signals & TIOCM_DSR) { | ||
1899 | seq_printf(m, "%c%s", sep, "DSR"); | ||
1900 | sep = '|'; | ||
1901 | } | ||
1902 | } | ||
1903 | seq_putc(m, '\n'); | ||
1904 | } | ||
1905 | |||
1906 | /*****************************************************************************/ | ||
1907 | |||
1908 | /* | ||
1909 | * Port info, read from the /proc file system. | ||
1910 | */ | ||
1911 | |||
1912 | static int stli_proc_show(struct seq_file *m, void *v) | ||
1913 | { | ||
1914 | struct stlibrd *brdp; | ||
1915 | struct stliport *portp; | ||
1916 | unsigned int brdnr, portnr, totalport; | ||
1917 | |||
1918 | totalport = 0; | ||
1919 | |||
1920 | seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion); | ||
1921 | |||
1922 | /* | ||
1923 | * We scan through for each board, panel and port. The offset is | ||
1924 | * calculated on the fly, and irrelevant ports are skipped. | ||
1925 | */ | ||
1926 | for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) { | ||
1927 | brdp = stli_brds[brdnr]; | ||
1928 | if (brdp == NULL) | ||
1929 | continue; | ||
1930 | if (brdp->state == 0) | ||
1931 | continue; | ||
1932 | |||
1933 | totalport = brdnr * STL_MAXPORTS; | ||
1934 | for (portnr = 0; (portnr < brdp->nrports); portnr++, | ||
1935 | totalport++) { | ||
1936 | portp = brdp->ports[portnr]; | ||
1937 | if (portp == NULL) | ||
1938 | continue; | ||
1939 | stli_portinfo(m, brdp, portp, totalport); | ||
1940 | } | ||
1941 | } | ||
1942 | return 0; | ||
1943 | } | ||
1944 | |||
1945 | static int stli_proc_open(struct inode *inode, struct file *file) | ||
1946 | { | ||
1947 | return single_open(file, stli_proc_show, NULL); | ||
1948 | } | ||
1949 | |||
1950 | static const struct file_operations stli_proc_fops = { | ||
1951 | .owner = THIS_MODULE, | ||
1952 | .open = stli_proc_open, | ||
1953 | .read = seq_read, | ||
1954 | .llseek = seq_lseek, | ||
1955 | .release = single_release, | ||
1956 | }; | ||
1957 | |||
1958 | /*****************************************************************************/ | ||
1959 | |||
1960 | /* | ||
1961 | * Generic send command routine. This will send a message to the slave, | ||
1962 | * of the specified type with the specified argument. Must be very | ||
1963 | * careful of data that will be copied out from shared memory - | ||
1964 | * containing command results. The command completion is all done from | ||
1965 | * a poll routine that does not have user context. Therefore you cannot | ||
1966 | * copy back directly into user space, or to the kernel stack of a | ||
1967 | * process. This routine does not sleep, so can be called from anywhere. | ||
1968 | * | ||
1969 | * The caller must hold the brd_lock (see also stli_sendcmd the usual | ||
1970 | * entry point) | ||
1971 | */ | ||
1972 | |||
1973 | static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) | ||
1974 | { | ||
1975 | cdkhdr_t __iomem *hdrp; | ||
1976 | cdkctrl_t __iomem *cp; | ||
1977 | unsigned char __iomem *bits; | ||
1978 | |||
1979 | if (test_bit(ST_CMDING, &portp->state)) { | ||
1980 | printk(KERN_ERR "istallion: command already busy, cmd=%x!\n", | ||
1981 | (int) cmd); | ||
1982 | return; | ||
1983 | } | ||
1984 | |||
1985 | EBRDENABLE(brdp); | ||
1986 | cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; | ||
1987 | if (size > 0) { | ||
1988 | memcpy_toio((void __iomem *) &(cp->args[0]), arg, size); | ||
1989 | if (copyback) { | ||
1990 | portp->argp = arg; | ||
1991 | portp->argsize = size; | ||
1992 | } | ||
1993 | } | ||
1994 | writel(0, &cp->status); | ||
1995 | writel(cmd, &cp->cmd); | ||
1996 | hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); | ||
1997 | bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + | ||
1998 | portp->portidx; | ||
1999 | writeb(readb(bits) | portp->portbit, bits); | ||
2000 | set_bit(ST_CMDING, &portp->state); | ||
2001 | EBRDDISABLE(brdp); | ||
2002 | } | ||
2003 | |||
2004 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) | ||
2005 | { | ||
2006 | unsigned long flags; | ||
2007 | |||
2008 | spin_lock_irqsave(&brd_lock, flags); | ||
2009 | __stli_sendcmd(brdp, portp, cmd, arg, size, copyback); | ||
2010 | spin_unlock_irqrestore(&brd_lock, flags); | ||
2011 | } | ||
2012 | |||
2013 | /*****************************************************************************/ | ||
2014 | |||
2015 | /* | ||
2016 | * Read data from shared memory. This assumes that the shared memory | ||
2017 | * is enabled and that interrupts are off. Basically we just empty out | ||
2018 | * the shared memory buffer into the tty buffer. Must be careful to | ||
2019 | * handle the case where we fill up the tty buffer, but still have | ||
2020 | * more chars to unload. | ||
2021 | */ | ||
2022 | |||
2023 | static void stli_read(struct stlibrd *brdp, struct stliport *portp) | ||
2024 | { | ||
2025 | cdkasyrq_t __iomem *rp; | ||
2026 | char __iomem *shbuf; | ||
2027 | struct tty_struct *tty; | ||
2028 | unsigned int head, tail, size; | ||
2029 | unsigned int len, stlen; | ||
2030 | |||
2031 | if (test_bit(ST_RXSTOP, &portp->state)) | ||
2032 | return; | ||
2033 | tty = tty_port_tty_get(&portp->port); | ||
2034 | if (tty == NULL) | ||
2035 | return; | ||
2036 | |||
2037 | rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq; | ||
2038 | head = (unsigned int) readw(&rp->head); | ||
2039 | if (head != ((unsigned int) readw(&rp->head))) | ||
2040 | head = (unsigned int) readw(&rp->head); | ||
2041 | tail = (unsigned int) readw(&rp->tail); | ||
2042 | size = portp->rxsize; | ||
2043 | if (head >= tail) { | ||
2044 | len = head - tail; | ||
2045 | stlen = len; | ||
2046 | } else { | ||
2047 | len = size - (tail - head); | ||
2048 | stlen = size - tail; | ||
2049 | } | ||
2050 | |||
2051 | len = tty_buffer_request_room(tty, len); | ||
2052 | |||
2053 | shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset); | ||
2054 | |||
2055 | while (len > 0) { | ||
2056 | unsigned char *cptr; | ||
2057 | |||
2058 | stlen = min(len, stlen); | ||
2059 | tty_prepare_flip_string(tty, &cptr, stlen); | ||
2060 | memcpy_fromio(cptr, shbuf + tail, stlen); | ||
2061 | len -= stlen; | ||
2062 | tail += stlen; | ||
2063 | if (tail >= size) { | ||
2064 | tail = 0; | ||
2065 | stlen = head; | ||
2066 | } | ||
2067 | } | ||
2068 | rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq; | ||
2069 | writew(tail, &rp->tail); | ||
2070 | |||
2071 | if (head != tail) | ||
2072 | set_bit(ST_RXING, &portp->state); | ||
2073 | |||
2074 | tty_schedule_flip(tty); | ||
2075 | tty_kref_put(tty); | ||
2076 | } | ||
2077 | |||
2078 | /*****************************************************************************/ | ||
2079 | |||
2080 | /* | ||
2081 | * Set up and carry out any delayed commands. There is only a small set | ||
2082 | * of slave commands that can be done "off-level". So it is not too | ||
2083 | * difficult to deal with them here. | ||
2084 | */ | ||
2085 | |||
2086 | static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp) | ||
2087 | { | ||
2088 | int cmd; | ||
2089 | |||
2090 | if (test_bit(ST_DOSIGS, &portp->state)) { | ||
2091 | if (test_bit(ST_DOFLUSHTX, &portp->state) && | ||
2092 | test_bit(ST_DOFLUSHRX, &portp->state)) | ||
2093 | cmd = A_SETSIGNALSF; | ||
2094 | else if (test_bit(ST_DOFLUSHTX, &portp->state)) | ||
2095 | cmd = A_SETSIGNALSFTX; | ||
2096 | else if (test_bit(ST_DOFLUSHRX, &portp->state)) | ||
2097 | cmd = A_SETSIGNALSFRX; | ||
2098 | else | ||
2099 | cmd = A_SETSIGNALS; | ||
2100 | clear_bit(ST_DOFLUSHTX, &portp->state); | ||
2101 | clear_bit(ST_DOFLUSHRX, &portp->state); | ||
2102 | clear_bit(ST_DOSIGS, &portp->state); | ||
2103 | memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig, | ||
2104 | sizeof(asysigs_t)); | ||
2105 | writel(0, &cp->status); | ||
2106 | writel(cmd, &cp->cmd); | ||
2107 | set_bit(ST_CMDING, &portp->state); | ||
2108 | } else if (test_bit(ST_DOFLUSHTX, &portp->state) || | ||
2109 | test_bit(ST_DOFLUSHRX, &portp->state)) { | ||
2110 | cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0); | ||
2111 | cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0); | ||
2112 | clear_bit(ST_DOFLUSHTX, &portp->state); | ||
2113 | clear_bit(ST_DOFLUSHRX, &portp->state); | ||
2114 | memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int)); | ||
2115 | writel(0, &cp->status); | ||
2116 | writel(A_FLUSH, &cp->cmd); | ||
2117 | set_bit(ST_CMDING, &portp->state); | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | /*****************************************************************************/ | ||
2122 | |||
2123 | /* | ||
2124 | * Host command service checking. This handles commands or messages | ||
2125 | * coming from the slave to the host. Must have board shared memory | ||
2126 | * enabled and interrupts off when called. Notice that by servicing the | ||
2127 | * read data last we don't need to change the shared memory pointer | ||
2128 | * during processing (which is a slow IO operation). | ||
2129 | * Return value indicates if this port is still awaiting actions from | ||
2130 | * the slave (like open, command, or even TX data being sent). If 0 | ||
2131 | * then port is still busy, otherwise no longer busy. | ||
2132 | */ | ||
2133 | |||
2134 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) | ||
2135 | { | ||
2136 | cdkasy_t __iomem *ap; | ||
2137 | cdkctrl_t __iomem *cp; | ||
2138 | struct tty_struct *tty; | ||
2139 | asynotify_t nt; | ||
2140 | unsigned long oldsigs; | ||
2141 | int rc, donerx; | ||
2142 | |||
2143 | ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); | ||
2144 | cp = &ap->ctrl; | ||
2145 | |||
2146 | /* | ||
2147 | * Check if we are waiting for an open completion message. | ||
2148 | */ | ||
2149 | if (test_bit(ST_OPENING, &portp->state)) { | ||
2150 | rc = readl(&cp->openarg); | ||
2151 | if (readb(&cp->open) == 0 && rc != 0) { | ||
2152 | if (rc > 0) | ||
2153 | rc--; | ||
2154 | writel(0, &cp->openarg); | ||
2155 | portp->rc = rc; | ||
2156 | clear_bit(ST_OPENING, &portp->state); | ||
2157 | wake_up_interruptible(&portp->raw_wait); | ||
2158 | } | ||
2159 | } | ||
2160 | |||
2161 | /* | ||
2162 | * Check if we are waiting for a close completion message. | ||
2163 | */ | ||
2164 | if (test_bit(ST_CLOSING, &portp->state)) { | ||
2165 | rc = (int) readl(&cp->closearg); | ||
2166 | if (readb(&cp->close) == 0 && rc != 0) { | ||
2167 | if (rc > 0) | ||
2168 | rc--; | ||
2169 | writel(0, &cp->closearg); | ||
2170 | portp->rc = rc; | ||
2171 | clear_bit(ST_CLOSING, &portp->state); | ||
2172 | wake_up_interruptible(&portp->raw_wait); | ||
2173 | } | ||
2174 | } | ||
2175 | |||
2176 | /* | ||
2177 | * Check if we are waiting for a command completion message. We may | ||
2178 | * need to copy out the command results associated with this command. | ||
2179 | */ | ||
2180 | if (test_bit(ST_CMDING, &portp->state)) { | ||
2181 | rc = readl(&cp->status); | ||
2182 | if (readl(&cp->cmd) == 0 && rc != 0) { | ||
2183 | if (rc > 0) | ||
2184 | rc--; | ||
2185 | if (portp->argp != NULL) { | ||
2186 | memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]), | ||
2187 | portp->argsize); | ||
2188 | portp->argp = NULL; | ||
2189 | } | ||
2190 | writel(0, &cp->status); | ||
2191 | portp->rc = rc; | ||
2192 | clear_bit(ST_CMDING, &portp->state); | ||
2193 | stli_dodelaycmd(portp, cp); | ||
2194 | wake_up_interruptible(&portp->raw_wait); | ||
2195 | } | ||
2196 | } | ||
2197 | |||
2198 | /* | ||
2199 | * Check for any notification messages ready. This includes lots of | ||
2200 | * different types of events - RX chars ready, RX break received, | ||
2201 | * TX data low or empty in the slave, modem signals changed state. | ||
2202 | */ | ||
2203 | donerx = 0; | ||
2204 | |||
2205 | if (ap->notify) { | ||
2206 | nt = ap->changed; | ||
2207 | ap->notify = 0; | ||
2208 | tty = tty_port_tty_get(&portp->port); | ||
2209 | |||
2210 | if (nt.signal & SG_DCD) { | ||
2211 | oldsigs = portp->sigs; | ||
2212 | portp->sigs = stli_mktiocm(nt.sigvalue); | ||
2213 | clear_bit(ST_GETSIGS, &portp->state); | ||
2214 | if ((portp->sigs & TIOCM_CD) && | ||
2215 | ((oldsigs & TIOCM_CD) == 0)) | ||
2216 | wake_up_interruptible(&portp->port.open_wait); | ||
2217 | if ((oldsigs & TIOCM_CD) && | ||
2218 | ((portp->sigs & TIOCM_CD) == 0)) { | ||
2219 | if (portp->port.flags & ASYNC_CHECK_CD) { | ||
2220 | if (tty) | ||
2221 | tty_hangup(tty); | ||
2222 | } | ||
2223 | } | ||
2224 | } | ||
2225 | |||
2226 | if (nt.data & DT_TXEMPTY) | ||
2227 | clear_bit(ST_TXBUSY, &portp->state); | ||
2228 | if (nt.data & (DT_TXEMPTY | DT_TXLOW)) { | ||
2229 | if (tty != NULL) { | ||
2230 | tty_wakeup(tty); | ||
2231 | EBRDENABLE(brdp); | ||
2232 | } | ||
2233 | } | ||
2234 | |||
2235 | if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) { | ||
2236 | if (tty != NULL) { | ||
2237 | tty_insert_flip_char(tty, 0, TTY_BREAK); | ||
2238 | if (portp->port.flags & ASYNC_SAK) { | ||
2239 | do_SAK(tty); | ||
2240 | EBRDENABLE(brdp); | ||
2241 | } | ||
2242 | tty_schedule_flip(tty); | ||
2243 | } | ||
2244 | } | ||
2245 | tty_kref_put(tty); | ||
2246 | |||
2247 | if (nt.data & DT_RXBUSY) { | ||
2248 | donerx++; | ||
2249 | stli_read(brdp, portp); | ||
2250 | } | ||
2251 | } | ||
2252 | |||
2253 | /* | ||
2254 | * It might seem odd that we are checking for more RX chars here. | ||
2255 | * But, we need to handle the case where the tty buffer was previously | ||
2256 | * filled, but we had more characters to pass up. The slave will not | ||
2257 | * send any more RX notify messages until the RX buffer has been emptied. | ||
2258 | * But it will leave the service bits on (since the buffer is not empty). | ||
2259 | * So from here we can try to process more RX chars. | ||
2260 | */ | ||
2261 | if ((!donerx) && test_bit(ST_RXING, &portp->state)) { | ||
2262 | clear_bit(ST_RXING, &portp->state); | ||
2263 | stli_read(brdp, portp); | ||
2264 | } | ||
2265 | |||
2266 | return((test_bit(ST_OPENING, &portp->state) || | ||
2267 | test_bit(ST_CLOSING, &portp->state) || | ||
2268 | test_bit(ST_CMDING, &portp->state) || | ||
2269 | test_bit(ST_TXBUSY, &portp->state) || | ||
2270 | test_bit(ST_RXING, &portp->state)) ? 0 : 1); | ||
2271 | } | ||
2272 | |||
2273 | /*****************************************************************************/ | ||
2274 | |||
2275 | /* | ||
2276 | * Service all ports on a particular board. Assumes that the boards | ||
2277 | * shared memory is enabled, and that the page pointer is pointed | ||
2278 | * at the cdk header structure. | ||
2279 | */ | ||
2280 | |||
2281 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp) | ||
2282 | { | ||
2283 | struct stliport *portp; | ||
2284 | unsigned char hostbits[(STL_MAXCHANS / 8) + 1]; | ||
2285 | unsigned char slavebits[(STL_MAXCHANS / 8) + 1]; | ||
2286 | unsigned char __iomem *slavep; | ||
2287 | int bitpos, bitat, bitsize; | ||
2288 | int channr, nrdevs, slavebitchange; | ||
2289 | |||
2290 | bitsize = brdp->bitsize; | ||
2291 | nrdevs = brdp->nrdevs; | ||
2292 | |||
2293 | /* | ||
2294 | * Check if slave wants any service. Basically we try to do as | ||
2295 | * little work as possible here. There are 2 levels of service | ||
2296 | * bits. So if there is nothing to do we bail early. We check | ||
2297 | * 8 service bits at a time in the inner loop, so we can bypass | ||
2298 | * the lot if none of them want service. | ||
2299 | */ | ||
2300 | memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset), | ||
2301 | bitsize); | ||
2302 | |||
2303 | memset(&slavebits[0], 0, bitsize); | ||
2304 | slavebitchange = 0; | ||
2305 | |||
2306 | for (bitpos = 0; (bitpos < bitsize); bitpos++) { | ||
2307 | if (hostbits[bitpos] == 0) | ||
2308 | continue; | ||
2309 | channr = bitpos * 8; | ||
2310 | for (bitat = 0x1; (channr < nrdevs); channr++, bitat <<= 1) { | ||
2311 | if (hostbits[bitpos] & bitat) { | ||
2312 | portp = brdp->ports[(channr - 1)]; | ||
2313 | if (stli_hostcmd(brdp, portp)) { | ||
2314 | slavebitchange++; | ||
2315 | slavebits[bitpos] |= bitat; | ||
2316 | } | ||
2317 | } | ||
2318 | } | ||
2319 | } | ||
2320 | |||
2321 | /* | ||
2322 | * If any of the ports are no longer busy then update them in the | ||
2323 | * slave request bits. We need to do this after, since a host port | ||
2324 | * service may initiate more slave requests. | ||
2325 | */ | ||
2326 | if (slavebitchange) { | ||
2327 | hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); | ||
2328 | slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset; | ||
2329 | for (bitpos = 0; (bitpos < bitsize); bitpos++) { | ||
2330 | if (readb(slavebits + bitpos)) | ||
2331 | writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos); | ||
2332 | } | ||
2333 | } | ||
2334 | } | ||
2335 | |||
2336 | /*****************************************************************************/ | ||
2337 | |||
2338 | /* | ||
2339 | * Driver poll routine. This routine polls the boards in use and passes | ||
2340 | * messages back up to host when necessary. This is actually very | ||
2341 | * CPU efficient, since we will always have the kernel poll clock, it | ||
2342 | * adds only a few cycles when idle (since board service can be | ||
2343 | * determined very easily), but when loaded generates no interrupts | ||
2344 | * (with their expensive associated context change). | ||
2345 | */ | ||
2346 | |||
2347 | static void stli_poll(unsigned long arg) | ||
2348 | { | ||
2349 | cdkhdr_t __iomem *hdrp; | ||
2350 | struct stlibrd *brdp; | ||
2351 | unsigned int brdnr; | ||
2352 | |||
2353 | mod_timer(&stli_timerlist, STLI_TIMEOUT); | ||
2354 | |||
2355 | /* | ||
2356 | * Check each board and do any servicing required. | ||
2357 | */ | ||
2358 | for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) { | ||
2359 | brdp = stli_brds[brdnr]; | ||
2360 | if (brdp == NULL) | ||
2361 | continue; | ||
2362 | if (!test_bit(BST_STARTED, &brdp->state)) | ||
2363 | continue; | ||
2364 | |||
2365 | spin_lock(&brd_lock); | ||
2366 | EBRDENABLE(brdp); | ||
2367 | hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); | ||
2368 | if (readb(&hdrp->hostreq)) | ||
2369 | stli_brdpoll(brdp, hdrp); | ||
2370 | EBRDDISABLE(brdp); | ||
2371 | spin_unlock(&brd_lock); | ||
2372 | } | ||
2373 | } | ||
2374 | |||
2375 | /*****************************************************************************/ | ||
2376 | |||
2377 | /* | ||
2378 | * Translate the termios settings into the port setting structure of | ||
2379 | * the slave. | ||
2380 | */ | ||
2381 | |||
2382 | static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, | ||
2383 | asyport_t *pp, struct ktermios *tiosp) | ||
2384 | { | ||
2385 | memset(pp, 0, sizeof(asyport_t)); | ||
2386 | |||
2387 | /* | ||
2388 | * Start of by setting the baud, char size, parity and stop bit info. | ||
2389 | */ | ||
2390 | pp->baudout = tty_get_baud_rate(tty); | ||
2391 | if ((tiosp->c_cflag & CBAUD) == B38400) { | ||
2392 | if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
2393 | pp->baudout = 57600; | ||
2394 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
2395 | pp->baudout = 115200; | ||
2396 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
2397 | pp->baudout = 230400; | ||
2398 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
2399 | pp->baudout = 460800; | ||
2400 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) | ||
2401 | pp->baudout = (portp->baud_base / portp->custom_divisor); | ||
2402 | } | ||
2403 | if (pp->baudout > STL_MAXBAUD) | ||
2404 | pp->baudout = STL_MAXBAUD; | ||
2405 | pp->baudin = pp->baudout; | ||
2406 | |||
2407 | switch (tiosp->c_cflag & CSIZE) { | ||
2408 | case CS5: | ||
2409 | pp->csize = 5; | ||
2410 | break; | ||
2411 | case CS6: | ||
2412 | pp->csize = 6; | ||
2413 | break; | ||
2414 | case CS7: | ||
2415 | pp->csize = 7; | ||
2416 | break; | ||
2417 | default: | ||
2418 | pp->csize = 8; | ||
2419 | break; | ||
2420 | } | ||
2421 | |||
2422 | if (tiosp->c_cflag & CSTOPB) | ||
2423 | pp->stopbs = PT_STOP2; | ||
2424 | else | ||
2425 | pp->stopbs = PT_STOP1; | ||
2426 | |||
2427 | if (tiosp->c_cflag & PARENB) { | ||
2428 | if (tiosp->c_cflag & PARODD) | ||
2429 | pp->parity = PT_ODDPARITY; | ||
2430 | else | ||
2431 | pp->parity = PT_EVENPARITY; | ||
2432 | } else { | ||
2433 | pp->parity = PT_NOPARITY; | ||
2434 | } | ||
2435 | |||
2436 | /* | ||
2437 | * Set up any flow control options enabled. | ||
2438 | */ | ||
2439 | if (tiosp->c_iflag & IXON) { | ||
2440 | pp->flow |= F_IXON; | ||
2441 | if (tiosp->c_iflag & IXANY) | ||
2442 | pp->flow |= F_IXANY; | ||
2443 | } | ||
2444 | if (tiosp->c_cflag & CRTSCTS) | ||
2445 | pp->flow |= (F_RTSFLOW | F_CTSFLOW); | ||
2446 | |||
2447 | pp->startin = tiosp->c_cc[VSTART]; | ||
2448 | pp->stopin = tiosp->c_cc[VSTOP]; | ||
2449 | pp->startout = tiosp->c_cc[VSTART]; | ||
2450 | pp->stopout = tiosp->c_cc[VSTOP]; | ||
2451 | |||
2452 | /* | ||
2453 | * Set up the RX char marking mask with those RX error types we must | ||
2454 | * catch. We can get the slave to help us out a little here, it will | ||
2455 | * ignore parity errors and breaks for us, and mark parity errors in | ||
2456 | * the data stream. | ||
2457 | */ | ||
2458 | if (tiosp->c_iflag & IGNPAR) | ||
2459 | pp->iflag |= FI_IGNRXERRS; | ||
2460 | if (tiosp->c_iflag & IGNBRK) | ||
2461 | pp->iflag |= FI_IGNBREAK; | ||
2462 | |||
2463 | portp->rxmarkmsk = 0; | ||
2464 | if (tiosp->c_iflag & (INPCK | PARMRK)) | ||
2465 | pp->iflag |= FI_1MARKRXERRS; | ||
2466 | if (tiosp->c_iflag & BRKINT) | ||
2467 | portp->rxmarkmsk |= BRKINT; | ||
2468 | |||
2469 | /* | ||
2470 | * Set up clocal processing as required. | ||
2471 | */ | ||
2472 | if (tiosp->c_cflag & CLOCAL) | ||
2473 | portp->port.flags &= ~ASYNC_CHECK_CD; | ||
2474 | else | ||
2475 | portp->port.flags |= ASYNC_CHECK_CD; | ||
2476 | |||
2477 | /* | ||
2478 | * Transfer any persistent flags into the asyport structure. | ||
2479 | */ | ||
2480 | pp->pflag = (portp->pflag & 0xffff); | ||
2481 | pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0; | ||
2482 | pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0; | ||
2483 | pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0; | ||
2484 | } | ||
2485 | |||
2486 | /*****************************************************************************/ | ||
2487 | |||
2488 | /* | ||
2489 | * Construct a slave signals structure for setting the DTR and RTS | ||
2490 | * signals as specified. | ||
2491 | */ | ||
2492 | |||
2493 | static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts) | ||
2494 | { | ||
2495 | memset(sp, 0, sizeof(asysigs_t)); | ||
2496 | if (dtr >= 0) { | ||
2497 | sp->signal |= SG_DTR; | ||
2498 | sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0); | ||
2499 | } | ||
2500 | if (rts >= 0) { | ||
2501 | sp->signal |= SG_RTS; | ||
2502 | sp->sigvalue |= ((rts > 0) ? SG_RTS : 0); | ||
2503 | } | ||
2504 | } | ||
2505 | |||
2506 | /*****************************************************************************/ | ||
2507 | |||
2508 | /* | ||
2509 | * Convert the signals returned from the slave into a local TIOCM type | ||
2510 | * signals value. We keep them locally in TIOCM format. | ||
2511 | */ | ||
2512 | |||
2513 | static long stli_mktiocm(unsigned long sigvalue) | ||
2514 | { | ||
2515 | long tiocm = 0; | ||
2516 | tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0); | ||
2517 | tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0); | ||
2518 | tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0); | ||
2519 | tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0); | ||
2520 | tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0); | ||
2521 | tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0); | ||
2522 | return(tiocm); | ||
2523 | } | ||
2524 | |||
2525 | /*****************************************************************************/ | ||
2526 | |||
2527 | /* | ||
2528 | * All panels and ports actually attached have been worked out. All | ||
2529 | * we need to do here is set up the appropriate per port data structures. | ||
2530 | */ | ||
2531 | |||
2532 | static int stli_initports(struct stlibrd *brdp) | ||
2533 | { | ||
2534 | struct stliport *portp; | ||
2535 | unsigned int i, panelnr, panelport; | ||
2536 | |||
2537 | for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { | ||
2538 | portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); | ||
2539 | if (!portp) { | ||
2540 | printk(KERN_WARNING "istallion: failed to allocate port structure\n"); | ||
2541 | continue; | ||
2542 | } | ||
2543 | tty_port_init(&portp->port); | ||
2544 | portp->port.ops = &stli_port_ops; | ||
2545 | portp->magic = STLI_PORTMAGIC; | ||
2546 | portp->portnr = i; | ||
2547 | portp->brdnr = brdp->brdnr; | ||
2548 | portp->panelnr = panelnr; | ||
2549 | portp->baud_base = STL_BAUDBASE; | ||
2550 | portp->port.close_delay = STL_CLOSEDELAY; | ||
2551 | portp->closing_wait = 30 * HZ; | ||
2552 | init_waitqueue_head(&portp->port.open_wait); | ||
2553 | init_waitqueue_head(&portp->port.close_wait); | ||
2554 | init_waitqueue_head(&portp->raw_wait); | ||
2555 | panelport++; | ||
2556 | if (panelport >= brdp->panels[panelnr]) { | ||
2557 | panelport = 0; | ||
2558 | panelnr++; | ||
2559 | } | ||
2560 | brdp->ports[i] = portp; | ||
2561 | } | ||
2562 | |||
2563 | return 0; | ||
2564 | } | ||
2565 | |||
2566 | /*****************************************************************************/ | ||
2567 | |||
2568 | /* | ||
2569 | * All the following routines are board specific hardware operations. | ||
2570 | */ | ||
2571 | |||
2572 | static void stli_ecpinit(struct stlibrd *brdp) | ||
2573 | { | ||
2574 | unsigned long memconf; | ||
2575 | |||
2576 | outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR)); | ||
2577 | udelay(10); | ||
2578 | outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); | ||
2579 | udelay(100); | ||
2580 | |||
2581 | memconf = (brdp->memaddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT; | ||
2582 | outb(memconf, (brdp->iobase + ECP_ATMEMAR)); | ||
2583 | } | ||
2584 | |||
2585 | /*****************************************************************************/ | ||
2586 | |||
2587 | static void stli_ecpenable(struct stlibrd *brdp) | ||
2588 | { | ||
2589 | outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR)); | ||
2590 | } | ||
2591 | |||
2592 | /*****************************************************************************/ | ||
2593 | |||
2594 | static void stli_ecpdisable(struct stlibrd *brdp) | ||
2595 | { | ||
2596 | outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); | ||
2597 | } | ||
2598 | |||
2599 | /*****************************************************************************/ | ||
2600 | |||
2601 | static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) | ||
2602 | { | ||
2603 | void __iomem *ptr; | ||
2604 | unsigned char val; | ||
2605 | |||
2606 | if (offset > brdp->memsize) { | ||
2607 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " | ||
2608 | "range at line=%d(%d), brd=%d\n", | ||
2609 | (int) offset, line, __LINE__, brdp->brdnr); | ||
2610 | ptr = NULL; | ||
2611 | val = 0; | ||
2612 | } else { | ||
2613 | ptr = brdp->membase + (offset % ECP_ATPAGESIZE); | ||
2614 | val = (unsigned char) (offset / ECP_ATPAGESIZE); | ||
2615 | } | ||
2616 | outb(val, (brdp->iobase + ECP_ATMEMPR)); | ||
2617 | return(ptr); | ||
2618 | } | ||
2619 | |||
2620 | /*****************************************************************************/ | ||
2621 | |||
2622 | static void stli_ecpreset(struct stlibrd *brdp) | ||
2623 | { | ||
2624 | outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR)); | ||
2625 | udelay(10); | ||
2626 | outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); | ||
2627 | udelay(500); | ||
2628 | } | ||
2629 | |||
2630 | /*****************************************************************************/ | ||
2631 | |||
2632 | static void stli_ecpintr(struct stlibrd *brdp) | ||
2633 | { | ||
2634 | outb(0x1, brdp->iobase); | ||
2635 | } | ||
2636 | |||
2637 | /*****************************************************************************/ | ||
2638 | |||
2639 | /* | ||
2640 | * The following set of functions act on ECP EISA boards. | ||
2641 | */ | ||
2642 | |||
2643 | static void stli_ecpeiinit(struct stlibrd *brdp) | ||
2644 | { | ||
2645 | unsigned long memconf; | ||
2646 | |||
2647 | outb(0x1, (brdp->iobase + ECP_EIBRDENAB)); | ||
2648 | outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); | ||
2649 | udelay(10); | ||
2650 | outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); | ||
2651 | udelay(500); | ||
2652 | |||
2653 | memconf = (brdp->memaddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL; | ||
2654 | outb(memconf, (brdp->iobase + ECP_EIMEMARL)); | ||
2655 | memconf = (brdp->memaddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH; | ||
2656 | outb(memconf, (brdp->iobase + ECP_EIMEMARH)); | ||
2657 | } | ||
2658 | |||
2659 | /*****************************************************************************/ | ||
2660 | |||
2661 | static void stli_ecpeienable(struct stlibrd *brdp) | ||
2662 | { | ||
2663 | outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR)); | ||
2664 | } | ||
2665 | |||
2666 | /*****************************************************************************/ | ||
2667 | |||
2668 | static void stli_ecpeidisable(struct stlibrd *brdp) | ||
2669 | { | ||
2670 | outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); | ||
2671 | } | ||
2672 | |||
2673 | /*****************************************************************************/ | ||
2674 | |||
2675 | static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) | ||
2676 | { | ||
2677 | void __iomem *ptr; | ||
2678 | unsigned char val; | ||
2679 | |||
2680 | if (offset > brdp->memsize) { | ||
2681 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " | ||
2682 | "range at line=%d(%d), brd=%d\n", | ||
2683 | (int) offset, line, __LINE__, brdp->brdnr); | ||
2684 | ptr = NULL; | ||
2685 | val = 0; | ||
2686 | } else { | ||
2687 | ptr = brdp->membase + (offset % ECP_EIPAGESIZE); | ||
2688 | if (offset < ECP_EIPAGESIZE) | ||
2689 | val = ECP_EIENABLE; | ||
2690 | else | ||
2691 | val = ECP_EIENABLE | 0x40; | ||
2692 | } | ||
2693 | outb(val, (brdp->iobase + ECP_EICONFR)); | ||
2694 | return(ptr); | ||
2695 | } | ||
2696 | |||
2697 | /*****************************************************************************/ | ||
2698 | |||
2699 | static void stli_ecpeireset(struct stlibrd *brdp) | ||
2700 | { | ||
2701 | outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); | ||
2702 | udelay(10); | ||
2703 | outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); | ||
2704 | udelay(500); | ||
2705 | } | ||
2706 | |||
2707 | /*****************************************************************************/ | ||
2708 | |||
2709 | /* | ||
2710 | * The following set of functions act on ECP MCA boards. | ||
2711 | */ | ||
2712 | |||
2713 | static void stli_ecpmcenable(struct stlibrd *brdp) | ||
2714 | { | ||
2715 | outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR)); | ||
2716 | } | ||
2717 | |||
2718 | /*****************************************************************************/ | ||
2719 | |||
2720 | static void stli_ecpmcdisable(struct stlibrd *brdp) | ||
2721 | { | ||
2722 | outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR)); | ||
2723 | } | ||
2724 | |||
2725 | /*****************************************************************************/ | ||
2726 | |||
2727 | static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) | ||
2728 | { | ||
2729 | void __iomem *ptr; | ||
2730 | unsigned char val; | ||
2731 | |||
2732 | if (offset > brdp->memsize) { | ||
2733 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " | ||
2734 | "range at line=%d(%d), brd=%d\n", | ||
2735 | (int) offset, line, __LINE__, brdp->brdnr); | ||
2736 | ptr = NULL; | ||
2737 | val = 0; | ||
2738 | } else { | ||
2739 | ptr = brdp->membase + (offset % ECP_MCPAGESIZE); | ||
2740 | val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE; | ||
2741 | } | ||
2742 | outb(val, (brdp->iobase + ECP_MCCONFR)); | ||
2743 | return(ptr); | ||
2744 | } | ||
2745 | |||
2746 | /*****************************************************************************/ | ||
2747 | |||
2748 | static void stli_ecpmcreset(struct stlibrd *brdp) | ||
2749 | { | ||
2750 | outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR)); | ||
2751 | udelay(10); | ||
2752 | outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR)); | ||
2753 | udelay(500); | ||
2754 | } | ||
2755 | |||
2756 | /*****************************************************************************/ | ||
2757 | |||
2758 | /* | ||
2759 | * The following set of functions act on ECP PCI boards. | ||
2760 | */ | ||
2761 | |||
2762 | static void stli_ecppciinit(struct stlibrd *brdp) | ||
2763 | { | ||
2764 | outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); | ||
2765 | udelay(10); | ||
2766 | outb(0, (brdp->iobase + ECP_PCICONFR)); | ||
2767 | udelay(500); | ||
2768 | } | ||
2769 | |||
2770 | /*****************************************************************************/ | ||
2771 | |||
2772 | static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) | ||
2773 | { | ||
2774 | void __iomem *ptr; | ||
2775 | unsigned char val; | ||
2776 | |||
2777 | if (offset > brdp->memsize) { | ||
2778 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " | ||
2779 | "range at line=%d(%d), board=%d\n", | ||
2780 | (int) offset, line, __LINE__, brdp->brdnr); | ||
2781 | ptr = NULL; | ||
2782 | val = 0; | ||
2783 | } else { | ||
2784 | ptr = brdp->membase + (offset % ECP_PCIPAGESIZE); | ||
2785 | val = (offset / ECP_PCIPAGESIZE) << 1; | ||
2786 | } | ||
2787 | outb(val, (brdp->iobase + ECP_PCICONFR)); | ||
2788 | return(ptr); | ||
2789 | } | ||
2790 | |||
2791 | /*****************************************************************************/ | ||
2792 | |||
2793 | static void stli_ecppcireset(struct stlibrd *brdp) | ||
2794 | { | ||
2795 | outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); | ||
2796 | udelay(10); | ||
2797 | outb(0, (brdp->iobase + ECP_PCICONFR)); | ||
2798 | udelay(500); | ||
2799 | } | ||
2800 | |||
2801 | /*****************************************************************************/ | ||
2802 | |||
2803 | /* | ||
2804 | * The following routines act on ONboards. | ||
2805 | */ | ||
2806 | |||
2807 | static void stli_onbinit(struct stlibrd *brdp) | ||
2808 | { | ||
2809 | unsigned long memconf; | ||
2810 | |||
2811 | outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR)); | ||
2812 | udelay(10); | ||
2813 | outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR)); | ||
2814 | mdelay(1000); | ||
2815 | |||
2816 | memconf = (brdp->memaddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT; | ||
2817 | outb(memconf, (brdp->iobase + ONB_ATMEMAR)); | ||
2818 | outb(0x1, brdp->iobase); | ||
2819 | mdelay(1); | ||
2820 | } | ||
2821 | |||
2822 | /*****************************************************************************/ | ||
2823 | |||
2824 | static void stli_onbenable(struct stlibrd *brdp) | ||
2825 | { | ||
2826 | outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR)); | ||
2827 | } | ||
2828 | |||
2829 | /*****************************************************************************/ | ||
2830 | |||
2831 | static void stli_onbdisable(struct stlibrd *brdp) | ||
2832 | { | ||
2833 | outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR)); | ||
2834 | } | ||
2835 | |||
2836 | /*****************************************************************************/ | ||
2837 | |||
2838 | static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) | ||
2839 | { | ||
2840 | void __iomem *ptr; | ||
2841 | |||
2842 | if (offset > brdp->memsize) { | ||
2843 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " | ||
2844 | "range at line=%d(%d), brd=%d\n", | ||
2845 | (int) offset, line, __LINE__, brdp->brdnr); | ||
2846 | ptr = NULL; | ||
2847 | } else { | ||
2848 | ptr = brdp->membase + (offset % ONB_ATPAGESIZE); | ||
2849 | } | ||
2850 | return(ptr); | ||
2851 | } | ||
2852 | |||
2853 | /*****************************************************************************/ | ||
2854 | |||
2855 | static void stli_onbreset(struct stlibrd *brdp) | ||
2856 | { | ||
2857 | outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR)); | ||
2858 | udelay(10); | ||
2859 | outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR)); | ||
2860 | mdelay(1000); | ||
2861 | } | ||
2862 | |||
2863 | /*****************************************************************************/ | ||
2864 | |||
2865 | /* | ||
2866 | * The following routines act on ONboard EISA. | ||
2867 | */ | ||
2868 | |||
2869 | static void stli_onbeinit(struct stlibrd *brdp) | ||
2870 | { | ||
2871 | unsigned long memconf; | ||
2872 | |||
2873 | outb(0x1, (brdp->iobase + ONB_EIBRDENAB)); | ||
2874 | outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); | ||
2875 | udelay(10); | ||
2876 | outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); | ||
2877 | mdelay(1000); | ||
2878 | |||
2879 | memconf = (brdp->memaddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL; | ||
2880 | outb(memconf, (brdp->iobase + ONB_EIMEMARL)); | ||
2881 | memconf = (brdp->memaddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH; | ||
2882 | outb(memconf, (brdp->iobase + ONB_EIMEMARH)); | ||
2883 | outb(0x1, brdp->iobase); | ||
2884 | mdelay(1); | ||
2885 | } | ||
2886 | |||
2887 | /*****************************************************************************/ | ||
2888 | |||
2889 | static void stli_onbeenable(struct stlibrd *brdp) | ||
2890 | { | ||
2891 | outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR)); | ||
2892 | } | ||
2893 | |||
2894 | /*****************************************************************************/ | ||
2895 | |||
2896 | static void stli_onbedisable(struct stlibrd *brdp) | ||
2897 | { | ||
2898 | outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); | ||
2899 | } | ||
2900 | |||
2901 | /*****************************************************************************/ | ||
2902 | |||
2903 | static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line) | ||
2904 | { | ||
2905 | void __iomem *ptr; | ||
2906 | unsigned char val; | ||
2907 | |||
2908 | if (offset > brdp->memsize) { | ||
2909 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " | ||
2910 | "range at line=%d(%d), brd=%d\n", | ||
2911 | (int) offset, line, __LINE__, brdp->brdnr); | ||
2912 | ptr = NULL; | ||
2913 | val = 0; | ||
2914 | } else { | ||
2915 | ptr = brdp->membase + (offset % ONB_EIPAGESIZE); | ||
2916 | if (offset < ONB_EIPAGESIZE) | ||
2917 | val = ONB_EIENABLE; | ||
2918 | else | ||
2919 | val = ONB_EIENABLE | 0x40; | ||
2920 | } | ||
2921 | outb(val, (brdp->iobase + ONB_EICONFR)); | ||
2922 | return(ptr); | ||
2923 | } | ||
2924 | |||
2925 | /*****************************************************************************/ | ||
2926 | |||
2927 | static void stli_onbereset(struct stlibrd *brdp) | ||
2928 | { | ||
2929 | outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); | ||
2930 | udelay(10); | ||
2931 | outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); | ||
2932 | mdelay(1000); | ||
2933 | } | ||
2934 | |||
2935 | /*****************************************************************************/ | ||
2936 | |||
2937 | /* | ||
2938 | * The following routines act on Brumby boards. | ||
2939 | */ | ||
2940 | |||
2941 | static void stli_bbyinit(struct stlibrd *brdp) | ||
2942 | { | ||
2943 | outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); | ||
2944 | udelay(10); | ||
2945 | outb(0, (brdp->iobase + BBY_ATCONFR)); | ||
2946 | mdelay(1000); | ||
2947 | outb(0x1, brdp->iobase); | ||
2948 | mdelay(1); | ||
2949 | } | ||
2950 | |||
2951 | /*****************************************************************************/ | ||
2952 | |||
2953 | static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line) | ||
2954 | { | ||
2955 | void __iomem *ptr; | ||
2956 | unsigned char val; | ||
2957 | |||
2958 | BUG_ON(offset > brdp->memsize); | ||
2959 | |||
2960 | ptr = brdp->membase + (offset % BBY_PAGESIZE); | ||
2961 | val = (unsigned char) (offset / BBY_PAGESIZE); | ||
2962 | outb(val, (brdp->iobase + BBY_ATCONFR)); | ||
2963 | return(ptr); | ||
2964 | } | ||
2965 | |||
2966 | /*****************************************************************************/ | ||
2967 | |||
2968 | static void stli_bbyreset(struct stlibrd *brdp) | ||
2969 | { | ||
2970 | outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); | ||
2971 | udelay(10); | ||
2972 | outb(0, (brdp->iobase + BBY_ATCONFR)); | ||
2973 | mdelay(1000); | ||
2974 | } | ||
2975 | |||
2976 | /*****************************************************************************/ | ||
2977 | |||
2978 | /* | ||
2979 | * The following routines act on original old Stallion boards. | ||
2980 | */ | ||
2981 | |||
2982 | static void stli_stalinit(struct stlibrd *brdp) | ||
2983 | { | ||
2984 | outb(0x1, brdp->iobase); | ||
2985 | mdelay(1000); | ||
2986 | } | ||
2987 | |||
2988 | /*****************************************************************************/ | ||
2989 | |||
2990 | static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) | ||
2991 | { | ||
2992 | BUG_ON(offset > brdp->memsize); | ||
2993 | return brdp->membase + (offset % STAL_PAGESIZE); | ||
2994 | } | ||
2995 | |||
2996 | /*****************************************************************************/ | ||
2997 | |||
2998 | static void stli_stalreset(struct stlibrd *brdp) | ||
2999 | { | ||
3000 | u32 __iomem *vecp; | ||
3001 | |||
3002 | vecp = (u32 __iomem *) (brdp->membase + 0x30); | ||
3003 | writel(0xffff0000, vecp); | ||
3004 | outb(0, brdp->iobase); | ||
3005 | mdelay(1000); | ||
3006 | } | ||
3007 | |||
3008 | /*****************************************************************************/ | ||
3009 | |||
3010 | /* | ||
3011 | * Try to find an ECP board and initialize it. This handles only ECP | ||
3012 | * board types. | ||
3013 | */ | ||
3014 | |||
3015 | static int stli_initecp(struct stlibrd *brdp) | ||
3016 | { | ||
3017 | cdkecpsig_t sig; | ||
3018 | cdkecpsig_t __iomem *sigsp; | ||
3019 | unsigned int status, nxtid; | ||
3020 | char *name; | ||
3021 | int retval, panelnr, nrports; | ||
3022 | |||
3023 | if ((brdp->iobase == 0) || (brdp->memaddr == 0)) { | ||
3024 | retval = -ENODEV; | ||
3025 | goto err; | ||
3026 | } | ||
3027 | |||
3028 | brdp->iosize = ECP_IOSIZE; | ||
3029 | |||
3030 | if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { | ||
3031 | retval = -EIO; | ||
3032 | goto err; | ||
3033 | } | ||
3034 | |||
3035 | /* | ||
3036 | * Based on the specific board type setup the common vars to access | ||
3037 | * and enable shared memory. Set all board specific information now | ||
3038 | * as well. | ||
3039 | */ | ||
3040 | switch (brdp->brdtype) { | ||
3041 | case BRD_ECP: | ||
3042 | brdp->memsize = ECP_MEMSIZE; | ||
3043 | brdp->pagesize = ECP_ATPAGESIZE; | ||
3044 | brdp->init = stli_ecpinit; | ||
3045 | brdp->enable = stli_ecpenable; | ||
3046 | brdp->reenable = stli_ecpenable; | ||
3047 | brdp->disable = stli_ecpdisable; | ||
3048 | brdp->getmemptr = stli_ecpgetmemptr; | ||
3049 | brdp->intr = stli_ecpintr; | ||
3050 | brdp->reset = stli_ecpreset; | ||
3051 | name = "serial(EC8/64)"; | ||
3052 | break; | ||
3053 | |||
3054 | case BRD_ECPE: | ||
3055 | brdp->memsize = ECP_MEMSIZE; | ||
3056 | brdp->pagesize = ECP_EIPAGESIZE; | ||
3057 | brdp->init = stli_ecpeiinit; | ||
3058 | brdp->enable = stli_ecpeienable; | ||
3059 | brdp->reenable = stli_ecpeienable; | ||
3060 | brdp->disable = stli_ecpeidisable; | ||
3061 | brdp->getmemptr = stli_ecpeigetmemptr; | ||
3062 | brdp->intr = stli_ecpintr; | ||
3063 | brdp->reset = stli_ecpeireset; | ||
3064 | name = "serial(EC8/64-EI)"; | ||
3065 | break; | ||
3066 | |||
3067 | case BRD_ECPMC: | ||
3068 | brdp->memsize = ECP_MEMSIZE; | ||
3069 | brdp->pagesize = ECP_MCPAGESIZE; | ||
3070 | brdp->init = NULL; | ||
3071 | brdp->enable = stli_ecpmcenable; | ||
3072 | brdp->reenable = stli_ecpmcenable; | ||
3073 | brdp->disable = stli_ecpmcdisable; | ||
3074 | brdp->getmemptr = stli_ecpmcgetmemptr; | ||
3075 | brdp->intr = stli_ecpintr; | ||
3076 | brdp->reset = stli_ecpmcreset; | ||
3077 | name = "serial(EC8/64-MCA)"; | ||
3078 | break; | ||
3079 | |||
3080 | case BRD_ECPPCI: | ||
3081 | brdp->memsize = ECP_PCIMEMSIZE; | ||
3082 | brdp->pagesize = ECP_PCIPAGESIZE; | ||
3083 | brdp->init = stli_ecppciinit; | ||
3084 | brdp->enable = NULL; | ||
3085 | brdp->reenable = NULL; | ||
3086 | brdp->disable = NULL; | ||
3087 | brdp->getmemptr = stli_ecppcigetmemptr; | ||
3088 | brdp->intr = stli_ecpintr; | ||
3089 | brdp->reset = stli_ecppcireset; | ||
3090 | name = "serial(EC/RA-PCI)"; | ||
3091 | break; | ||
3092 | |||
3093 | default: | ||
3094 | retval = -EINVAL; | ||
3095 | goto err_reg; | ||
3096 | } | ||
3097 | |||
3098 | /* | ||
3099 | * The per-board operations structure is all set up, so now let's go | ||
3100 | * and get the board operational. Firstly initialize board configuration | ||
3101 | * registers. Set the memory mapping info so we can get at the boards | ||
3102 | * shared memory. | ||
3103 | */ | ||
3104 | EBRDINIT(brdp); | ||
3105 | |||
3106 | brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); | ||
3107 | if (brdp->membase == NULL) { | ||
3108 | retval = -ENOMEM; | ||
3109 | goto err_reg; | ||
3110 | } | ||
3111 | |||
3112 | /* | ||
3113 | * Now that all specific code is set up, enable the shared memory and | ||
3114 | * look for the a signature area that will tell us exactly what board | ||
3115 | * this is, and what it is connected to it. | ||
3116 | */ | ||
3117 | EBRDENABLE(brdp); | ||
3118 | sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR); | ||
3119 | memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t)); | ||
3120 | EBRDDISABLE(brdp); | ||
3121 | |||
3122 | if (sig.magic != cpu_to_le32(ECP_MAGIC)) { | ||
3123 | retval = -ENODEV; | ||
3124 | goto err_unmap; | ||
3125 | } | ||
3126 | |||
3127 | /* | ||
3128 | * Scan through the signature looking at the panels connected to the | ||
3129 | * board. Calculate the total number of ports as we go. | ||
3130 | */ | ||
3131 | for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) { | ||
3132 | status = sig.panelid[nxtid]; | ||
3133 | if ((status & ECH_PNLIDMASK) != nxtid) | ||
3134 | break; | ||
3135 | |||
3136 | brdp->panelids[panelnr] = status; | ||
3137 | nrports = (status & ECH_PNL16PORT) ? 16 : 8; | ||
3138 | if ((nrports == 16) && ((status & ECH_PNLXPID) == 0)) | ||
3139 | nxtid++; | ||
3140 | brdp->panels[panelnr] = nrports; | ||
3141 | brdp->nrports += nrports; | ||
3142 | nxtid++; | ||
3143 | brdp->nrpanels++; | ||
3144 | } | ||
3145 | |||
3146 | |||
3147 | set_bit(BST_FOUND, &brdp->state); | ||
3148 | return 0; | ||
3149 | err_unmap: | ||
3150 | iounmap(brdp->membase); | ||
3151 | brdp->membase = NULL; | ||
3152 | err_reg: | ||
3153 | release_region(brdp->iobase, brdp->iosize); | ||
3154 | err: | ||
3155 | return retval; | ||
3156 | } | ||
3157 | |||
3158 | /*****************************************************************************/ | ||
3159 | |||
3160 | /* | ||
3161 | * Try to find an ONboard, Brumby or Stallion board and initialize it. | ||
3162 | * This handles only these board types. | ||
3163 | */ | ||
3164 | |||
3165 | static int stli_initonb(struct stlibrd *brdp) | ||
3166 | { | ||
3167 | cdkonbsig_t sig; | ||
3168 | cdkonbsig_t __iomem *sigsp; | ||
3169 | char *name; | ||
3170 | int i, retval; | ||
3171 | |||
3172 | /* | ||
3173 | * Do a basic sanity check on the IO and memory addresses. | ||
3174 | */ | ||
3175 | if (brdp->iobase == 0 || brdp->memaddr == 0) { | ||
3176 | retval = -ENODEV; | ||
3177 | goto err; | ||
3178 | } | ||
3179 | |||
3180 | brdp->iosize = ONB_IOSIZE; | ||
3181 | |||
3182 | if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { | ||
3183 | retval = -EIO; | ||
3184 | goto err; | ||
3185 | } | ||
3186 | |||
3187 | /* | ||
3188 | * Based on the specific board type setup the common vars to access | ||
3189 | * and enable shared memory. Set all board specific information now | ||
3190 | * as well. | ||
3191 | */ | ||
3192 | switch (brdp->brdtype) { | ||
3193 | case BRD_ONBOARD: | ||
3194 | case BRD_ONBOARD2: | ||
3195 | brdp->memsize = ONB_MEMSIZE; | ||
3196 | brdp->pagesize = ONB_ATPAGESIZE; | ||
3197 | brdp->init = stli_onbinit; | ||
3198 | brdp->enable = stli_onbenable; | ||
3199 | brdp->reenable = stli_onbenable; | ||
3200 | brdp->disable = stli_onbdisable; | ||
3201 | brdp->getmemptr = stli_onbgetmemptr; | ||
3202 | brdp->intr = stli_ecpintr; | ||
3203 | brdp->reset = stli_onbreset; | ||
3204 | if (brdp->memaddr > 0x100000) | ||
3205 | brdp->enabval = ONB_MEMENABHI; | ||
3206 | else | ||
3207 | brdp->enabval = ONB_MEMENABLO; | ||
3208 | name = "serial(ONBoard)"; | ||
3209 | break; | ||
3210 | |||
3211 | case BRD_ONBOARDE: | ||
3212 | brdp->memsize = ONB_EIMEMSIZE; | ||
3213 | brdp->pagesize = ONB_EIPAGESIZE; | ||
3214 | brdp->init = stli_onbeinit; | ||
3215 | brdp->enable = stli_onbeenable; | ||
3216 | brdp->reenable = stli_onbeenable; | ||
3217 | brdp->disable = stli_onbedisable; | ||
3218 | brdp->getmemptr = stli_onbegetmemptr; | ||
3219 | brdp->intr = stli_ecpintr; | ||
3220 | brdp->reset = stli_onbereset; | ||
3221 | name = "serial(ONBoard/E)"; | ||
3222 | break; | ||
3223 | |||
3224 | case BRD_BRUMBY4: | ||
3225 | brdp->memsize = BBY_MEMSIZE; | ||
3226 | brdp->pagesize = BBY_PAGESIZE; | ||
3227 | brdp->init = stli_bbyinit; | ||
3228 | brdp->enable = NULL; | ||
3229 | brdp->reenable = NULL; | ||
3230 | brdp->disable = NULL; | ||
3231 | brdp->getmemptr = stli_bbygetmemptr; | ||
3232 | brdp->intr = stli_ecpintr; | ||
3233 | brdp->reset = stli_bbyreset; | ||
3234 | name = "serial(Brumby)"; | ||
3235 | break; | ||
3236 | |||
3237 | case BRD_STALLION: | ||
3238 | brdp->memsize = STAL_MEMSIZE; | ||
3239 | brdp->pagesize = STAL_PAGESIZE; | ||
3240 | brdp->init = stli_stalinit; | ||
3241 | brdp->enable = NULL; | ||
3242 | brdp->reenable = NULL; | ||
3243 | brdp->disable = NULL; | ||
3244 | brdp->getmemptr = stli_stalgetmemptr; | ||
3245 | brdp->intr = stli_ecpintr; | ||
3246 | brdp->reset = stli_stalreset; | ||
3247 | name = "serial(Stallion)"; | ||
3248 | break; | ||
3249 | |||
3250 | default: | ||
3251 | retval = -EINVAL; | ||
3252 | goto err_reg; | ||
3253 | } | ||
3254 | |||
3255 | /* | ||
3256 | * The per-board operations structure is all set up, so now let's go | ||
3257 | * and get the board operational. Firstly initialize board configuration | ||
3258 | * registers. Set the memory mapping info so we can get at the boards | ||
3259 | * shared memory. | ||
3260 | */ | ||
3261 | EBRDINIT(brdp); | ||
3262 | |||
3263 | brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); | ||
3264 | if (brdp->membase == NULL) { | ||
3265 | retval = -ENOMEM; | ||
3266 | goto err_reg; | ||
3267 | } | ||
3268 | |||
3269 | /* | ||
3270 | * Now that all specific code is set up, enable the shared memory and | ||
3271 | * look for the a signature area that will tell us exactly what board | ||
3272 | * this is, and how many ports. | ||
3273 | */ | ||
3274 | EBRDENABLE(brdp); | ||
3275 | sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR); | ||
3276 | memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t)); | ||
3277 | EBRDDISABLE(brdp); | ||
3278 | |||
3279 | if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) || | ||
3280 | sig.magic1 != cpu_to_le16(ONB_MAGIC1) || | ||
3281 | sig.magic2 != cpu_to_le16(ONB_MAGIC2) || | ||
3282 | sig.magic3 != cpu_to_le16(ONB_MAGIC3)) { | ||
3283 | retval = -ENODEV; | ||
3284 | goto err_unmap; | ||
3285 | } | ||
3286 | |||
3287 | /* | ||
3288 | * Scan through the signature alive mask and calculate how many ports | ||
3289 | * there are on this board. | ||
3290 | */ | ||
3291 | brdp->nrpanels = 1; | ||
3292 | if (sig.amask1) { | ||
3293 | brdp->nrports = 32; | ||
3294 | } else { | ||
3295 | for (i = 0; (i < 16); i++) { | ||
3296 | if (((sig.amask0 << i) & 0x8000) == 0) | ||
3297 | break; | ||
3298 | } | ||
3299 | brdp->nrports = i; | ||
3300 | } | ||
3301 | brdp->panels[0] = brdp->nrports; | ||
3302 | |||
3303 | |||
3304 | set_bit(BST_FOUND, &brdp->state); | ||
3305 | return 0; | ||
3306 | err_unmap: | ||
3307 | iounmap(brdp->membase); | ||
3308 | brdp->membase = NULL; | ||
3309 | err_reg: | ||
3310 | release_region(brdp->iobase, brdp->iosize); | ||
3311 | err: | ||
3312 | return retval; | ||
3313 | } | ||
3314 | |||
3315 | /*****************************************************************************/ | ||
3316 | |||
3317 | /* | ||
3318 | * Start up a running board. This routine is only called after the | ||
3319 | * code has been down loaded to the board and is operational. It will | ||
3320 | * read in the memory map, and get the show on the road... | ||
3321 | */ | ||
3322 | |||
3323 | static int stli_startbrd(struct stlibrd *brdp) | ||
3324 | { | ||
3325 | cdkhdr_t __iomem *hdrp; | ||
3326 | cdkmem_t __iomem *memp; | ||
3327 | cdkasy_t __iomem *ap; | ||
3328 | unsigned long flags; | ||
3329 | unsigned int portnr, nrdevs, i; | ||
3330 | struct stliport *portp; | ||
3331 | int rc = 0; | ||
3332 | u32 memoff; | ||
3333 | |||
3334 | spin_lock_irqsave(&brd_lock, flags); | ||
3335 | EBRDENABLE(brdp); | ||
3336 | hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); | ||
3337 | nrdevs = hdrp->nrdevs; | ||
3338 | |||
3339 | #if 0 | ||
3340 | printk("%s(%d): CDK version %d.%d.%d --> " | ||
3341 | "nrdevs=%d memp=%x hostp=%x slavep=%x\n", | ||
3342 | __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification), | ||
3343 | readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp), | ||
3344 | readl(&hdrp->slavep)); | ||
3345 | #endif | ||
3346 | |||
3347 | if (nrdevs < (brdp->nrports + 1)) { | ||
3348 | printk(KERN_ERR "istallion: slave failed to allocate memory for " | ||
3349 | "all devices, devices=%d\n", nrdevs); | ||
3350 | brdp->nrports = nrdevs - 1; | ||
3351 | } | ||
3352 | brdp->nrdevs = nrdevs; | ||
3353 | brdp->hostoffset = hdrp->hostp - CDK_CDKADDR; | ||
3354 | brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR; | ||
3355 | brdp->bitsize = (nrdevs + 7) / 8; | ||
3356 | memoff = readl(&hdrp->memp); | ||
3357 | if (memoff > brdp->memsize) { | ||
3358 | printk(KERN_ERR "istallion: corrupted shared memory region?\n"); | ||
3359 | rc = -EIO; | ||
3360 | goto stli_donestartup; | ||
3361 | } | ||
3362 | memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); | ||
3363 | if (readw(&memp->dtype) != TYP_ASYNCTRL) { | ||
3364 | printk(KERN_ERR "istallion: no slave control device found\n"); | ||
3365 | goto stli_donestartup; | ||
3366 | } | ||
3367 | memp++; | ||
3368 | |||
3369 | /* | ||
3370 | * Cycle through memory allocation of each port. We are guaranteed to | ||
3371 | * have all ports inside the first page of slave window, so no need to | ||
3372 | * change pages while reading memory map. | ||
3373 | */ | ||
3374 | for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) { | ||
3375 | if (readw(&memp->dtype) != TYP_ASYNC) | ||
3376 | break; | ||
3377 | portp = brdp->ports[portnr]; | ||
3378 | if (portp == NULL) | ||
3379 | break; | ||
3380 | portp->devnr = i; | ||
3381 | portp->addr = readl(&memp->offset); | ||
3382 | portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs)); | ||
3383 | portp->portidx = (unsigned char) (i / 8); | ||
3384 | portp->portbit = (unsigned char) (0x1 << (i % 8)); | ||
3385 | } | ||
3386 | |||
3387 | writeb(0xff, &hdrp->slavereq); | ||
3388 | |||
3389 | /* | ||
3390 | * For each port setup a local copy of the RX and TX buffer offsets | ||
3391 | * and sizes. We do this separate from the above, because we need to | ||
3392 | * move the shared memory page... | ||
3393 | */ | ||
3394 | for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) { | ||
3395 | portp = brdp->ports[portnr]; | ||
3396 | if (portp == NULL) | ||
3397 | break; | ||
3398 | if (portp->addr == 0) | ||
3399 | break; | ||
3400 | ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); | ||
3401 | if (ap != NULL) { | ||
3402 | portp->rxsize = readw(&ap->rxq.size); | ||
3403 | portp->txsize = readw(&ap->txq.size); | ||
3404 | portp->rxoffset = readl(&ap->rxq.offset); | ||
3405 | portp->txoffset = readl(&ap->txq.offset); | ||
3406 | } | ||
3407 | } | ||
3408 | |||
3409 | stli_donestartup: | ||
3410 | EBRDDISABLE(brdp); | ||
3411 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3412 | |||
3413 | if (rc == 0) | ||
3414 | set_bit(BST_STARTED, &brdp->state); | ||
3415 | |||
3416 | if (! stli_timeron) { | ||
3417 | stli_timeron++; | ||
3418 | mod_timer(&stli_timerlist, STLI_TIMEOUT); | ||
3419 | } | ||
3420 | |||
3421 | return rc; | ||
3422 | } | ||
3423 | |||
3424 | /*****************************************************************************/ | ||
3425 | |||
3426 | /* | ||
3427 | * Probe and initialize the specified board. | ||
3428 | */ | ||
3429 | |||
3430 | static int __devinit stli_brdinit(struct stlibrd *brdp) | ||
3431 | { | ||
3432 | int retval; | ||
3433 | |||
3434 | switch (brdp->brdtype) { | ||
3435 | case BRD_ECP: | ||
3436 | case BRD_ECPE: | ||
3437 | case BRD_ECPMC: | ||
3438 | case BRD_ECPPCI: | ||
3439 | retval = stli_initecp(brdp); | ||
3440 | break; | ||
3441 | case BRD_ONBOARD: | ||
3442 | case BRD_ONBOARDE: | ||
3443 | case BRD_ONBOARD2: | ||
3444 | case BRD_BRUMBY4: | ||
3445 | case BRD_STALLION: | ||
3446 | retval = stli_initonb(brdp); | ||
3447 | break; | ||
3448 | default: | ||
3449 | printk(KERN_ERR "istallion: board=%d is unknown board " | ||
3450 | "type=%d\n", brdp->brdnr, brdp->brdtype); | ||
3451 | retval = -ENODEV; | ||
3452 | } | ||
3453 | |||
3454 | if (retval) | ||
3455 | return retval; | ||
3456 | |||
3457 | stli_initports(brdp); | ||
3458 | printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x " | ||
3459 | "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], | ||
3460 | brdp->brdnr, brdp->iobase, (int) brdp->memaddr, | ||
3461 | brdp->nrpanels, brdp->nrports); | ||
3462 | return 0; | ||
3463 | } | ||
3464 | |||
3465 | #if STLI_EISAPROBE != 0 | ||
3466 | /*****************************************************************************/ | ||
3467 | |||
3468 | /* | ||
3469 | * Probe around trying to find where the EISA boards shared memory | ||
3470 | * might be. This is a bit if hack, but it is the best we can do. | ||
3471 | */ | ||
3472 | |||
3473 | static int stli_eisamemprobe(struct stlibrd *brdp) | ||
3474 | { | ||
3475 | cdkecpsig_t ecpsig, __iomem *ecpsigp; | ||
3476 | cdkonbsig_t onbsig, __iomem *onbsigp; | ||
3477 | int i, foundit; | ||
3478 | |||
3479 | /* | ||
3480 | * First up we reset the board, to get it into a known state. There | ||
3481 | * is only 2 board types here we need to worry about. Don;t use the | ||
3482 | * standard board init routine here, it programs up the shared | ||
3483 | * memory address, and we don't know it yet... | ||
3484 | */ | ||
3485 | if (brdp->brdtype == BRD_ECPE) { | ||
3486 | outb(0x1, (brdp->iobase + ECP_EIBRDENAB)); | ||
3487 | outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); | ||
3488 | udelay(10); | ||
3489 | outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); | ||
3490 | udelay(500); | ||
3491 | stli_ecpeienable(brdp); | ||
3492 | } else if (brdp->brdtype == BRD_ONBOARDE) { | ||
3493 | outb(0x1, (brdp->iobase + ONB_EIBRDENAB)); | ||
3494 | outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); | ||
3495 | udelay(10); | ||
3496 | outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); | ||
3497 | mdelay(100); | ||
3498 | outb(0x1, brdp->iobase); | ||
3499 | mdelay(1); | ||
3500 | stli_onbeenable(brdp); | ||
3501 | } else { | ||
3502 | return -ENODEV; | ||
3503 | } | ||
3504 | |||
3505 | foundit = 0; | ||
3506 | brdp->memsize = ECP_MEMSIZE; | ||
3507 | |||
3508 | /* | ||
3509 | * Board shared memory is enabled, so now we have a poke around and | ||
3510 | * see if we can find it. | ||
3511 | */ | ||
3512 | for (i = 0; (i < stli_eisamempsize); i++) { | ||
3513 | brdp->memaddr = stli_eisamemprobeaddrs[i]; | ||
3514 | brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); | ||
3515 | if (brdp->membase == NULL) | ||
3516 | continue; | ||
3517 | |||
3518 | if (brdp->brdtype == BRD_ECPE) { | ||
3519 | ecpsigp = stli_ecpeigetmemptr(brdp, | ||
3520 | CDK_SIGADDR, __LINE__); | ||
3521 | memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t)); | ||
3522 | if (ecpsig.magic == cpu_to_le32(ECP_MAGIC)) | ||
3523 | foundit = 1; | ||
3524 | } else { | ||
3525 | onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp, | ||
3526 | CDK_SIGADDR, __LINE__); | ||
3527 | memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t)); | ||
3528 | if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) && | ||
3529 | (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) && | ||
3530 | (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) && | ||
3531 | (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3))) | ||
3532 | foundit = 1; | ||
3533 | } | ||
3534 | |||
3535 | iounmap(brdp->membase); | ||
3536 | if (foundit) | ||
3537 | break; | ||
3538 | } | ||
3539 | |||
3540 | /* | ||
3541 | * Regardless of whether we found the shared memory or not we must | ||
3542 | * disable the region. After that return success or failure. | ||
3543 | */ | ||
3544 | if (brdp->brdtype == BRD_ECPE) | ||
3545 | stli_ecpeidisable(brdp); | ||
3546 | else | ||
3547 | stli_onbedisable(brdp); | ||
3548 | |||
3549 | if (! foundit) { | ||
3550 | brdp->memaddr = 0; | ||
3551 | brdp->membase = NULL; | ||
3552 | printk(KERN_ERR "istallion: failed to probe shared memory " | ||
3553 | "region for %s in EISA slot=%d\n", | ||
3554 | stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); | ||
3555 | return -ENODEV; | ||
3556 | } | ||
3557 | return 0; | ||
3558 | } | ||
3559 | #endif | ||
3560 | |||
3561 | static int stli_getbrdnr(void) | ||
3562 | { | ||
3563 | unsigned int i; | ||
3564 | |||
3565 | for (i = 0; i < STL_MAXBRDS; i++) { | ||
3566 | if (!stli_brds[i]) { | ||
3567 | if (i >= stli_nrbrds) | ||
3568 | stli_nrbrds = i + 1; | ||
3569 | return i; | ||
3570 | } | ||
3571 | } | ||
3572 | return -1; | ||
3573 | } | ||
3574 | |||
3575 | #if STLI_EISAPROBE != 0 | ||
3576 | /*****************************************************************************/ | ||
3577 | |||
3578 | /* | ||
3579 | * Probe around and try to find any EISA boards in system. The biggest | ||
3580 | * problem here is finding out what memory address is associated with | ||
3581 | * an EISA board after it is found. The registers of the ECPE and | ||
3582 | * ONboardE are not readable - so we can't read them from there. We | ||
3583 | * don't have access to the EISA CMOS (or EISA BIOS) so we don't | ||
3584 | * actually have any way to find out the real value. The best we can | ||
3585 | * do is go probing around in the usual places hoping we can find it. | ||
3586 | */ | ||
3587 | |||
3588 | static int __init stli_findeisabrds(void) | ||
3589 | { | ||
3590 | struct stlibrd *brdp; | ||
3591 | unsigned int iobase, eid, i; | ||
3592 | int brdnr, found = 0; | ||
3593 | |||
3594 | /* | ||
3595 | * Firstly check if this is an EISA system. If this is not an EISA system then | ||
3596 | * don't bother going any further! | ||
3597 | */ | ||
3598 | if (EISA_bus) | ||
3599 | return 0; | ||
3600 | |||
3601 | /* | ||
3602 | * Looks like an EISA system, so go searching for EISA boards. | ||
3603 | */ | ||
3604 | for (iobase = 0x1000; (iobase <= 0xc000); iobase += 0x1000) { | ||
3605 | outb(0xff, (iobase + 0xc80)); | ||
3606 | eid = inb(iobase + 0xc80); | ||
3607 | eid |= inb(iobase + 0xc81) << 8; | ||
3608 | if (eid != STL_EISAID) | ||
3609 | continue; | ||
3610 | |||
3611 | /* | ||
3612 | * We have found a board. Need to check if this board was | ||
3613 | * statically configured already (just in case!). | ||
3614 | */ | ||
3615 | for (i = 0; (i < STL_MAXBRDS); i++) { | ||
3616 | brdp = stli_brds[i]; | ||
3617 | if (brdp == NULL) | ||
3618 | continue; | ||
3619 | if (brdp->iobase == iobase) | ||
3620 | break; | ||
3621 | } | ||
3622 | if (i < STL_MAXBRDS) | ||
3623 | continue; | ||
3624 | |||
3625 | /* | ||
3626 | * We have found a Stallion board and it is not configured already. | ||
3627 | * Allocate a board structure and initialize it. | ||
3628 | */ | ||
3629 | if ((brdp = stli_allocbrd()) == NULL) | ||
3630 | return found ? : -ENOMEM; | ||
3631 | brdnr = stli_getbrdnr(); | ||
3632 | if (brdnr < 0) | ||
3633 | return found ? : -ENOMEM; | ||
3634 | brdp->brdnr = (unsigned int)brdnr; | ||
3635 | eid = inb(iobase + 0xc82); | ||
3636 | if (eid == ECP_EISAID) | ||
3637 | brdp->brdtype = BRD_ECPE; | ||
3638 | else if (eid == ONB_EISAID) | ||
3639 | brdp->brdtype = BRD_ONBOARDE; | ||
3640 | else | ||
3641 | brdp->brdtype = BRD_UNKNOWN; | ||
3642 | brdp->iobase = iobase; | ||
3643 | outb(0x1, (iobase + 0xc84)); | ||
3644 | if (stli_eisamemprobe(brdp)) | ||
3645 | outb(0, (iobase + 0xc84)); | ||
3646 | if (stli_brdinit(brdp) < 0) { | ||
3647 | kfree(brdp); | ||
3648 | continue; | ||
3649 | } | ||
3650 | |||
3651 | stli_brds[brdp->brdnr] = brdp; | ||
3652 | found++; | ||
3653 | |||
3654 | for (i = 0; i < brdp->nrports; i++) | ||
3655 | tty_register_device(stli_serial, | ||
3656 | brdp->brdnr * STL_MAXPORTS + i, NULL); | ||
3657 | } | ||
3658 | |||
3659 | return found; | ||
3660 | } | ||
3661 | #else | ||
3662 | static inline int stli_findeisabrds(void) { return 0; } | ||
3663 | #endif | ||
3664 | |||
3665 | /*****************************************************************************/ | ||
3666 | |||
3667 | /* | ||
3668 | * Find the next available board number that is free. | ||
3669 | */ | ||
3670 | |||
3671 | /*****************************************************************************/ | ||
3672 | |||
3673 | /* | ||
3674 | * We have a Stallion board. Allocate a board structure and | ||
3675 | * initialize it. Read its IO and MEMORY resources from PCI | ||
3676 | * configuration space. | ||
3677 | */ | ||
3678 | |||
3679 | static int __devinit stli_pciprobe(struct pci_dev *pdev, | ||
3680 | const struct pci_device_id *ent) | ||
3681 | { | ||
3682 | struct stlibrd *brdp; | ||
3683 | unsigned int i; | ||
3684 | int brdnr, retval = -EIO; | ||
3685 | |||
3686 | retval = pci_enable_device(pdev); | ||
3687 | if (retval) | ||
3688 | goto err; | ||
3689 | brdp = stli_allocbrd(); | ||
3690 | if (brdp == NULL) { | ||
3691 | retval = -ENOMEM; | ||
3692 | goto err; | ||
3693 | } | ||
3694 | mutex_lock(&stli_brdslock); | ||
3695 | brdnr = stli_getbrdnr(); | ||
3696 | if (brdnr < 0) { | ||
3697 | printk(KERN_INFO "istallion: too many boards found, " | ||
3698 | "maximum supported %d\n", STL_MAXBRDS); | ||
3699 | mutex_unlock(&stli_brdslock); | ||
3700 | retval = -EIO; | ||
3701 | goto err_fr; | ||
3702 | } | ||
3703 | brdp->brdnr = (unsigned int)brdnr; | ||
3704 | stli_brds[brdp->brdnr] = brdp; | ||
3705 | mutex_unlock(&stli_brdslock); | ||
3706 | brdp->brdtype = BRD_ECPPCI; | ||
3707 | /* | ||
3708 | * We have all resources from the board, so lets setup the actual | ||
3709 | * board structure now. | ||
3710 | */ | ||
3711 | brdp->iobase = pci_resource_start(pdev, 3); | ||
3712 | brdp->memaddr = pci_resource_start(pdev, 2); | ||
3713 | retval = stli_brdinit(brdp); | ||
3714 | if (retval) | ||
3715 | goto err_null; | ||
3716 | |||
3717 | set_bit(BST_PROBED, &brdp->state); | ||
3718 | pci_set_drvdata(pdev, brdp); | ||
3719 | |||
3720 | EBRDENABLE(brdp); | ||
3721 | brdp->enable = NULL; | ||
3722 | brdp->disable = NULL; | ||
3723 | |||
3724 | for (i = 0; i < brdp->nrports; i++) | ||
3725 | tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i, | ||
3726 | &pdev->dev); | ||
3727 | |||
3728 | return 0; | ||
3729 | err_null: | ||
3730 | stli_brds[brdp->brdnr] = NULL; | ||
3731 | err_fr: | ||
3732 | kfree(brdp); | ||
3733 | err: | ||
3734 | return retval; | ||
3735 | } | ||
3736 | |||
3737 | static void __devexit stli_pciremove(struct pci_dev *pdev) | ||
3738 | { | ||
3739 | struct stlibrd *brdp = pci_get_drvdata(pdev); | ||
3740 | |||
3741 | stli_cleanup_ports(brdp); | ||
3742 | |||
3743 | iounmap(brdp->membase); | ||
3744 | if (brdp->iosize > 0) | ||
3745 | release_region(brdp->iobase, brdp->iosize); | ||
3746 | |||
3747 | stli_brds[brdp->brdnr] = NULL; | ||
3748 | kfree(brdp); | ||
3749 | } | ||
3750 | |||
3751 | static struct pci_driver stli_pcidriver = { | ||
3752 | .name = "istallion", | ||
3753 | .id_table = istallion_pci_tbl, | ||
3754 | .probe = stli_pciprobe, | ||
3755 | .remove = __devexit_p(stli_pciremove) | ||
3756 | }; | ||
3757 | /*****************************************************************************/ | ||
3758 | |||
3759 | /* | ||
3760 | * Allocate a new board structure. Fill out the basic info in it. | ||
3761 | */ | ||
3762 | |||
3763 | static struct stlibrd *stli_allocbrd(void) | ||
3764 | { | ||
3765 | struct stlibrd *brdp; | ||
3766 | |||
3767 | brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); | ||
3768 | if (!brdp) { | ||
3769 | printk(KERN_ERR "istallion: failed to allocate memory " | ||
3770 | "(size=%Zd)\n", sizeof(struct stlibrd)); | ||
3771 | return NULL; | ||
3772 | } | ||
3773 | brdp->magic = STLI_BOARDMAGIC; | ||
3774 | return brdp; | ||
3775 | } | ||
3776 | |||
3777 | /*****************************************************************************/ | ||
3778 | |||
3779 | /* | ||
3780 | * Scan through all the boards in the configuration and see what we | ||
3781 | * can find. | ||
3782 | */ | ||
3783 | |||
3784 | static int __init stli_initbrds(void) | ||
3785 | { | ||
3786 | struct stlibrd *brdp, *nxtbrdp; | ||
3787 | struct stlconf conf; | ||
3788 | unsigned int i, j, found = 0; | ||
3789 | int retval; | ||
3790 | |||
3791 | for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp); | ||
3792 | stli_nrbrds++) { | ||
3793 | memset(&conf, 0, sizeof(conf)); | ||
3794 | if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0) | ||
3795 | continue; | ||
3796 | if ((brdp = stli_allocbrd()) == NULL) | ||
3797 | continue; | ||
3798 | brdp->brdnr = stli_nrbrds; | ||
3799 | brdp->brdtype = conf.brdtype; | ||
3800 | brdp->iobase = conf.ioaddr1; | ||
3801 | brdp->memaddr = conf.memaddr; | ||
3802 | if (stli_brdinit(brdp) < 0) { | ||
3803 | kfree(brdp); | ||
3804 | continue; | ||
3805 | } | ||
3806 | stli_brds[brdp->brdnr] = brdp; | ||
3807 | found++; | ||
3808 | |||
3809 | for (i = 0; i < brdp->nrports; i++) | ||
3810 | tty_register_device(stli_serial, | ||
3811 | brdp->brdnr * STL_MAXPORTS + i, NULL); | ||
3812 | } | ||
3813 | |||
3814 | retval = stli_findeisabrds(); | ||
3815 | if (retval > 0) | ||
3816 | found += retval; | ||
3817 | |||
3818 | /* | ||
3819 | * All found boards are initialized. Now for a little optimization, if | ||
3820 | * no boards are sharing the "shared memory" regions then we can just | ||
3821 | * leave them all enabled. This is in fact the usual case. | ||
3822 | */ | ||
3823 | stli_shared = 0; | ||
3824 | if (stli_nrbrds > 1) { | ||
3825 | for (i = 0; (i < stli_nrbrds); i++) { | ||
3826 | brdp = stli_brds[i]; | ||
3827 | if (brdp == NULL) | ||
3828 | continue; | ||
3829 | for (j = i + 1; (j < stli_nrbrds); j++) { | ||
3830 | nxtbrdp = stli_brds[j]; | ||
3831 | if (nxtbrdp == NULL) | ||
3832 | continue; | ||
3833 | if ((brdp->membase >= nxtbrdp->membase) && | ||
3834 | (brdp->membase <= (nxtbrdp->membase + | ||
3835 | nxtbrdp->memsize - 1))) { | ||
3836 | stli_shared++; | ||
3837 | break; | ||
3838 | } | ||
3839 | } | ||
3840 | } | ||
3841 | } | ||
3842 | |||
3843 | if (stli_shared == 0) { | ||
3844 | for (i = 0; (i < stli_nrbrds); i++) { | ||
3845 | brdp = stli_brds[i]; | ||
3846 | if (brdp == NULL) | ||
3847 | continue; | ||
3848 | if (test_bit(BST_FOUND, &brdp->state)) { | ||
3849 | EBRDENABLE(brdp); | ||
3850 | brdp->enable = NULL; | ||
3851 | brdp->disable = NULL; | ||
3852 | } | ||
3853 | } | ||
3854 | } | ||
3855 | |||
3856 | retval = pci_register_driver(&stli_pcidriver); | ||
3857 | if (retval && found == 0) { | ||
3858 | printk(KERN_ERR "Neither isa nor eisa cards found nor pci " | ||
3859 | "driver can be registered!\n"); | ||
3860 | goto err; | ||
3861 | } | ||
3862 | |||
3863 | return 0; | ||
3864 | err: | ||
3865 | return retval; | ||
3866 | } | ||
3867 | |||
3868 | /*****************************************************************************/ | ||
3869 | |||
3870 | /* | ||
3871 | * Code to handle an "staliomem" read operation. This device is the | ||
3872 | * contents of the board shared memory. It is used for down loading | ||
3873 | * the slave image (and debugging :-) | ||
3874 | */ | ||
3875 | |||
3876 | static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp) | ||
3877 | { | ||
3878 | unsigned long flags; | ||
3879 | void __iomem *memptr; | ||
3880 | struct stlibrd *brdp; | ||
3881 | unsigned int brdnr; | ||
3882 | int size, n; | ||
3883 | void *p; | ||
3884 | loff_t off = *offp; | ||
3885 | |||
3886 | brdnr = iminor(fp->f_path.dentry->d_inode); | ||
3887 | if (brdnr >= stli_nrbrds) | ||
3888 | return -ENODEV; | ||
3889 | brdp = stli_brds[brdnr]; | ||
3890 | if (brdp == NULL) | ||
3891 | return -ENODEV; | ||
3892 | if (brdp->state == 0) | ||
3893 | return -ENODEV; | ||
3894 | if (off >= brdp->memsize || off + count < off) | ||
3895 | return 0; | ||
3896 | |||
3897 | size = min(count, (size_t)(brdp->memsize - off)); | ||
3898 | |||
3899 | /* | ||
3900 | * Copy the data a page at a time | ||
3901 | */ | ||
3902 | |||
3903 | p = (void *)__get_free_page(GFP_KERNEL); | ||
3904 | if(p == NULL) | ||
3905 | return -ENOMEM; | ||
3906 | |||
3907 | while (size > 0) { | ||
3908 | spin_lock_irqsave(&brd_lock, flags); | ||
3909 | EBRDENABLE(brdp); | ||
3910 | memptr = EBRDGETMEMPTR(brdp, off); | ||
3911 | n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); | ||
3912 | n = min(n, (int)PAGE_SIZE); | ||
3913 | memcpy_fromio(p, memptr, n); | ||
3914 | EBRDDISABLE(brdp); | ||
3915 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3916 | if (copy_to_user(buf, p, n)) { | ||
3917 | count = -EFAULT; | ||
3918 | goto out; | ||
3919 | } | ||
3920 | off += n; | ||
3921 | buf += n; | ||
3922 | size -= n; | ||
3923 | } | ||
3924 | out: | ||
3925 | *offp = off; | ||
3926 | free_page((unsigned long)p); | ||
3927 | return count; | ||
3928 | } | ||
3929 | |||
3930 | /*****************************************************************************/ | ||
3931 | |||
3932 | /* | ||
3933 | * Code to handle an "staliomem" write operation. This device is the | ||
3934 | * contents of the board shared memory. It is used for down loading | ||
3935 | * the slave image (and debugging :-) | ||
3936 | * | ||
3937 | * FIXME: copy under lock | ||
3938 | */ | ||
3939 | |||
3940 | static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp) | ||
3941 | { | ||
3942 | unsigned long flags; | ||
3943 | void __iomem *memptr; | ||
3944 | struct stlibrd *brdp; | ||
3945 | char __user *chbuf; | ||
3946 | unsigned int brdnr; | ||
3947 | int size, n; | ||
3948 | void *p; | ||
3949 | loff_t off = *offp; | ||
3950 | |||
3951 | brdnr = iminor(fp->f_path.dentry->d_inode); | ||
3952 | |||
3953 | if (brdnr >= stli_nrbrds) | ||
3954 | return -ENODEV; | ||
3955 | brdp = stli_brds[brdnr]; | ||
3956 | if (brdp == NULL) | ||
3957 | return -ENODEV; | ||
3958 | if (brdp->state == 0) | ||
3959 | return -ENODEV; | ||
3960 | if (off >= brdp->memsize || off + count < off) | ||
3961 | return 0; | ||
3962 | |||
3963 | chbuf = (char __user *) buf; | ||
3964 | size = min(count, (size_t)(brdp->memsize - off)); | ||
3965 | |||
3966 | /* | ||
3967 | * Copy the data a page at a time | ||
3968 | */ | ||
3969 | |||
3970 | p = (void *)__get_free_page(GFP_KERNEL); | ||
3971 | if(p == NULL) | ||
3972 | return -ENOMEM; | ||
3973 | |||
3974 | while (size > 0) { | ||
3975 | n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); | ||
3976 | n = min(n, (int)PAGE_SIZE); | ||
3977 | if (copy_from_user(p, chbuf, n)) { | ||
3978 | if (count == 0) | ||
3979 | count = -EFAULT; | ||
3980 | goto out; | ||
3981 | } | ||
3982 | spin_lock_irqsave(&brd_lock, flags); | ||
3983 | EBRDENABLE(brdp); | ||
3984 | memptr = EBRDGETMEMPTR(brdp, off); | ||
3985 | memcpy_toio(memptr, p, n); | ||
3986 | EBRDDISABLE(brdp); | ||
3987 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3988 | off += n; | ||
3989 | chbuf += n; | ||
3990 | size -= n; | ||
3991 | } | ||
3992 | out: | ||
3993 | free_page((unsigned long) p); | ||
3994 | *offp = off; | ||
3995 | return count; | ||
3996 | } | ||
3997 | |||
3998 | /*****************************************************************************/ | ||
3999 | |||
4000 | /* | ||
4001 | * Return the board stats structure to user app. | ||
4002 | */ | ||
4003 | |||
4004 | static int stli_getbrdstats(combrd_t __user *bp) | ||
4005 | { | ||
4006 | struct stlibrd *brdp; | ||
4007 | unsigned int i; | ||
4008 | |||
4009 | if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t))) | ||
4010 | return -EFAULT; | ||
4011 | if (stli_brdstats.brd >= STL_MAXBRDS) | ||
4012 | return -ENODEV; | ||
4013 | brdp = stli_brds[stli_brdstats.brd]; | ||
4014 | if (brdp == NULL) | ||
4015 | return -ENODEV; | ||
4016 | |||
4017 | memset(&stli_brdstats, 0, sizeof(combrd_t)); | ||
4018 | |||
4019 | stli_brdstats.brd = brdp->brdnr; | ||
4020 | stli_brdstats.type = brdp->brdtype; | ||
4021 | stli_brdstats.hwid = 0; | ||
4022 | stli_brdstats.state = brdp->state; | ||
4023 | stli_brdstats.ioaddr = brdp->iobase; | ||
4024 | stli_brdstats.memaddr = brdp->memaddr; | ||
4025 | stli_brdstats.nrpanels = brdp->nrpanels; | ||
4026 | stli_brdstats.nrports = brdp->nrports; | ||
4027 | for (i = 0; (i < brdp->nrpanels); i++) { | ||
4028 | stli_brdstats.panels[i].panel = i; | ||
4029 | stli_brdstats.panels[i].hwid = brdp->panelids[i]; | ||
4030 | stli_brdstats.panels[i].nrports = brdp->panels[i]; | ||
4031 | } | ||
4032 | |||
4033 | if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t))) | ||
4034 | return -EFAULT; | ||
4035 | return 0; | ||
4036 | } | ||
4037 | |||
4038 | /*****************************************************************************/ | ||
4039 | |||
4040 | /* | ||
4041 | * Resolve the referenced port number into a port struct pointer. | ||
4042 | */ | ||
4043 | |||
4044 | static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, | ||
4045 | unsigned int portnr) | ||
4046 | { | ||
4047 | struct stlibrd *brdp; | ||
4048 | unsigned int i; | ||
4049 | |||
4050 | if (brdnr >= STL_MAXBRDS) | ||
4051 | return NULL; | ||
4052 | brdp = stli_brds[brdnr]; | ||
4053 | if (brdp == NULL) | ||
4054 | return NULL; | ||
4055 | for (i = 0; (i < panelnr); i++) | ||
4056 | portnr += brdp->panels[i]; | ||
4057 | if (portnr >= brdp->nrports) | ||
4058 | return NULL; | ||
4059 | return brdp->ports[portnr]; | ||
4060 | } | ||
4061 | |||
4062 | /*****************************************************************************/ | ||
4063 | |||
4064 | /* | ||
4065 | * Return the port stats structure to user app. A NULL port struct | ||
4066 | * pointer passed in means that we need to find out from the app | ||
4067 | * what port to get stats for (used through board control device). | ||
4068 | */ | ||
4069 | |||
4070 | static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) | ||
4071 | { | ||
4072 | unsigned long flags; | ||
4073 | struct stlibrd *brdp; | ||
4074 | int rc; | ||
4075 | |||
4076 | memset(&stli_comstats, 0, sizeof(comstats_t)); | ||
4077 | |||
4078 | if (portp == NULL) | ||
4079 | return -ENODEV; | ||
4080 | brdp = stli_brds[portp->brdnr]; | ||
4081 | if (brdp == NULL) | ||
4082 | return -ENODEV; | ||
4083 | |||
4084 | mutex_lock(&portp->port.mutex); | ||
4085 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
4086 | if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, | ||
4087 | &stli_cdkstats, sizeof(asystats_t), 1)) < 0) { | ||
4088 | mutex_unlock(&portp->port.mutex); | ||
4089 | return rc; | ||
4090 | } | ||
4091 | } else { | ||
4092 | memset(&stli_cdkstats, 0, sizeof(asystats_t)); | ||
4093 | } | ||
4094 | |||
4095 | stli_comstats.brd = portp->brdnr; | ||
4096 | stli_comstats.panel = portp->panelnr; | ||
4097 | stli_comstats.port = portp->portnr; | ||
4098 | stli_comstats.state = portp->state; | ||
4099 | stli_comstats.flags = portp->port.flags; | ||
4100 | |||
4101 | spin_lock_irqsave(&brd_lock, flags); | ||
4102 | if (tty != NULL) { | ||
4103 | if (portp->port.tty == tty) { | ||
4104 | stli_comstats.ttystate = tty->flags; | ||
4105 | stli_comstats.rxbuffered = -1; | ||
4106 | if (tty->termios != NULL) { | ||
4107 | stli_comstats.cflags = tty->termios->c_cflag; | ||
4108 | stli_comstats.iflags = tty->termios->c_iflag; | ||
4109 | stli_comstats.oflags = tty->termios->c_oflag; | ||
4110 | stli_comstats.lflags = tty->termios->c_lflag; | ||
4111 | } | ||
4112 | } | ||
4113 | } | ||
4114 | spin_unlock_irqrestore(&brd_lock, flags); | ||
4115 | |||
4116 | stli_comstats.txtotal = stli_cdkstats.txchars; | ||
4117 | stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover; | ||
4118 | stli_comstats.txbuffered = stli_cdkstats.txringq; | ||
4119 | stli_comstats.rxbuffered += stli_cdkstats.rxringq; | ||
4120 | stli_comstats.rxoverrun = stli_cdkstats.overruns; | ||
4121 | stli_comstats.rxparity = stli_cdkstats.parity; | ||
4122 | stli_comstats.rxframing = stli_cdkstats.framing; | ||
4123 | stli_comstats.rxlost = stli_cdkstats.ringover; | ||
4124 | stli_comstats.rxbreaks = stli_cdkstats.rxbreaks; | ||
4125 | stli_comstats.txbreaks = stli_cdkstats.txbreaks; | ||
4126 | stli_comstats.txxon = stli_cdkstats.txstart; | ||
4127 | stli_comstats.txxoff = stli_cdkstats.txstop; | ||
4128 | stli_comstats.rxxon = stli_cdkstats.rxstart; | ||
4129 | stli_comstats.rxxoff = stli_cdkstats.rxstop; | ||
4130 | stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2; | ||
4131 | stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff; | ||
4132 | stli_comstats.modem = stli_cdkstats.dcdcnt; | ||
4133 | stli_comstats.hwid = stli_cdkstats.hwid; | ||
4134 | stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); | ||
4135 | mutex_unlock(&portp->port.mutex); | ||
4136 | |||
4137 | return 0; | ||
4138 | } | ||
4139 | |||
4140 | /*****************************************************************************/ | ||
4141 | |||
4142 | /* | ||
4143 | * Return the port stats structure to user app. A NULL port struct | ||
4144 | * pointer passed in means that we need to find out from the app | ||
4145 | * what port to get stats for (used through board control device). | ||
4146 | */ | ||
4147 | |||
4148 | static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, | ||
4149 | comstats_t __user *cp) | ||
4150 | { | ||
4151 | struct stlibrd *brdp; | ||
4152 | int rc; | ||
4153 | |||
4154 | if (!portp) { | ||
4155 | if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t))) | ||
4156 | return -EFAULT; | ||
4157 | portp = stli_getport(stli_comstats.brd, stli_comstats.panel, | ||
4158 | stli_comstats.port); | ||
4159 | if (!portp) | ||
4160 | return -ENODEV; | ||
4161 | } | ||
4162 | |||
4163 | brdp = stli_brds[portp->brdnr]; | ||
4164 | if (!brdp) | ||
4165 | return -ENODEV; | ||
4166 | |||
4167 | if ((rc = stli_portcmdstats(tty, portp)) < 0) | ||
4168 | return rc; | ||
4169 | |||
4170 | return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ? | ||
4171 | -EFAULT : 0; | ||
4172 | } | ||
4173 | |||
4174 | /*****************************************************************************/ | ||
4175 | |||
4176 | /* | ||
4177 | * Clear the port stats structure. We also return it zeroed out... | ||
4178 | */ | ||
4179 | |||
4180 | static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp) | ||
4181 | { | ||
4182 | struct stlibrd *brdp; | ||
4183 | int rc; | ||
4184 | |||
4185 | if (!portp) { | ||
4186 | if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t))) | ||
4187 | return -EFAULT; | ||
4188 | portp = stli_getport(stli_comstats.brd, stli_comstats.panel, | ||
4189 | stli_comstats.port); | ||
4190 | if (!portp) | ||
4191 | return -ENODEV; | ||
4192 | } | ||
4193 | |||
4194 | brdp = stli_brds[portp->brdnr]; | ||
4195 | if (!brdp) | ||
4196 | return -ENODEV; | ||
4197 | |||
4198 | mutex_lock(&portp->port.mutex); | ||
4199 | |||
4200 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
4201 | if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) { | ||
4202 | mutex_unlock(&portp->port.mutex); | ||
4203 | return rc; | ||
4204 | } | ||
4205 | } | ||
4206 | |||
4207 | memset(&stli_comstats, 0, sizeof(comstats_t)); | ||
4208 | stli_comstats.brd = portp->brdnr; | ||
4209 | stli_comstats.panel = portp->panelnr; | ||
4210 | stli_comstats.port = portp->portnr; | ||
4211 | mutex_unlock(&portp->port.mutex); | ||
4212 | |||
4213 | if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) | ||
4214 | return -EFAULT; | ||
4215 | return 0; | ||
4216 | } | ||
4217 | |||
4218 | /*****************************************************************************/ | ||
4219 | |||
4220 | /* | ||
4221 | * Return the entire driver ports structure to a user app. | ||
4222 | */ | ||
4223 | |||
4224 | static int stli_getportstruct(struct stliport __user *arg) | ||
4225 | { | ||
4226 | struct stliport stli_dummyport; | ||
4227 | struct stliport *portp; | ||
4228 | |||
4229 | if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport))) | ||
4230 | return -EFAULT; | ||
4231 | portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr, | ||
4232 | stli_dummyport.portnr); | ||
4233 | if (!portp) | ||
4234 | return -ENODEV; | ||
4235 | if (copy_to_user(arg, portp, sizeof(struct stliport))) | ||
4236 | return -EFAULT; | ||
4237 | return 0; | ||
4238 | } | ||
4239 | |||
4240 | /*****************************************************************************/ | ||
4241 | |||
4242 | /* | ||
4243 | * Return the entire driver board structure to a user app. | ||
4244 | */ | ||
4245 | |||
4246 | static int stli_getbrdstruct(struct stlibrd __user *arg) | ||
4247 | { | ||
4248 | struct stlibrd stli_dummybrd; | ||
4249 | struct stlibrd *brdp; | ||
4250 | |||
4251 | if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd))) | ||
4252 | return -EFAULT; | ||
4253 | if (stli_dummybrd.brdnr >= STL_MAXBRDS) | ||
4254 | return -ENODEV; | ||
4255 | brdp = stli_brds[stli_dummybrd.brdnr]; | ||
4256 | if (!brdp) | ||
4257 | return -ENODEV; | ||
4258 | if (copy_to_user(arg, brdp, sizeof(struct stlibrd))) | ||
4259 | return -EFAULT; | ||
4260 | return 0; | ||
4261 | } | ||
4262 | |||
4263 | /*****************************************************************************/ | ||
4264 | |||
4265 | /* | ||
4266 | * The "staliomem" device is also required to do some special operations on | ||
4267 | * the board. We need to be able to send an interrupt to the board, | ||
4268 | * reset it, and start/stop it. | ||
4269 | */ | ||
4270 | |||
4271 | static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | ||
4272 | { | ||
4273 | struct stlibrd *brdp; | ||
4274 | int brdnr, rc, done; | ||
4275 | void __user *argp = (void __user *)arg; | ||
4276 | |||
4277 | /* | ||
4278 | * First up handle the board independent ioctls. | ||
4279 | */ | ||
4280 | done = 0; | ||
4281 | rc = 0; | ||
4282 | |||
4283 | switch (cmd) { | ||
4284 | case COM_GETPORTSTATS: | ||
4285 | rc = stli_getportstats(NULL, NULL, argp); | ||
4286 | done++; | ||
4287 | break; | ||
4288 | case COM_CLRPORTSTATS: | ||
4289 | rc = stli_clrportstats(NULL, argp); | ||
4290 | done++; | ||
4291 | break; | ||
4292 | case COM_GETBRDSTATS: | ||
4293 | rc = stli_getbrdstats(argp); | ||
4294 | done++; | ||
4295 | break; | ||
4296 | case COM_READPORT: | ||
4297 | rc = stli_getportstruct(argp); | ||
4298 | done++; | ||
4299 | break; | ||
4300 | case COM_READBOARD: | ||
4301 | rc = stli_getbrdstruct(argp); | ||
4302 | done++; | ||
4303 | break; | ||
4304 | } | ||
4305 | if (done) | ||
4306 | return rc; | ||
4307 | |||
4308 | /* | ||
4309 | * Now handle the board specific ioctls. These all depend on the | ||
4310 | * minor number of the device they were called from. | ||
4311 | */ | ||
4312 | brdnr = iminor(fp->f_dentry->d_inode); | ||
4313 | if (brdnr >= STL_MAXBRDS) | ||
4314 | return -ENODEV; | ||
4315 | brdp = stli_brds[brdnr]; | ||
4316 | if (!brdp) | ||
4317 | return -ENODEV; | ||
4318 | if (brdp->state == 0) | ||
4319 | return -ENODEV; | ||
4320 | |||
4321 | switch (cmd) { | ||
4322 | case STL_BINTR: | ||
4323 | EBRDINTR(brdp); | ||
4324 | break; | ||
4325 | case STL_BSTART: | ||
4326 | rc = stli_startbrd(brdp); | ||
4327 | break; | ||
4328 | case STL_BSTOP: | ||
4329 | clear_bit(BST_STARTED, &brdp->state); | ||
4330 | break; | ||
4331 | case STL_BRESET: | ||
4332 | clear_bit(BST_STARTED, &brdp->state); | ||
4333 | EBRDRESET(brdp); | ||
4334 | if (stli_shared == 0) { | ||
4335 | if (brdp->reenable != NULL) | ||
4336 | (* brdp->reenable)(brdp); | ||
4337 | } | ||
4338 | break; | ||
4339 | default: | ||
4340 | rc = -ENOIOCTLCMD; | ||
4341 | break; | ||
4342 | } | ||
4343 | return rc; | ||
4344 | } | ||
4345 | |||
4346 | static const struct tty_operations stli_ops = { | ||
4347 | .open = stli_open, | ||
4348 | .close = stli_close, | ||
4349 | .write = stli_write, | ||
4350 | .put_char = stli_putchar, | ||
4351 | .flush_chars = stli_flushchars, | ||
4352 | .write_room = stli_writeroom, | ||
4353 | .chars_in_buffer = stli_charsinbuffer, | ||
4354 | .ioctl = stli_ioctl, | ||
4355 | .set_termios = stli_settermios, | ||
4356 | .throttle = stli_throttle, | ||
4357 | .unthrottle = stli_unthrottle, | ||
4358 | .stop = stli_stop, | ||
4359 | .start = stli_start, | ||
4360 | .hangup = stli_hangup, | ||
4361 | .flush_buffer = stli_flushbuffer, | ||
4362 | .break_ctl = stli_breakctl, | ||
4363 | .wait_until_sent = stli_waituntilsent, | ||
4364 | .send_xchar = stli_sendxchar, | ||
4365 | .tiocmget = stli_tiocmget, | ||
4366 | .tiocmset = stli_tiocmset, | ||
4367 | .proc_fops = &stli_proc_fops, | ||
4368 | }; | ||
4369 | |||
4370 | static const struct tty_port_operations stli_port_ops = { | ||
4371 | .carrier_raised = stli_carrier_raised, | ||
4372 | .dtr_rts = stli_dtr_rts, | ||
4373 | .activate = stli_activate, | ||
4374 | .shutdown = stli_shutdown, | ||
4375 | }; | ||
4376 | |||
4377 | /*****************************************************************************/ | ||
4378 | /* | ||
4379 | * Loadable module initialization stuff. | ||
4380 | */ | ||
4381 | |||
4382 | static void istallion_cleanup_isa(void) | ||
4383 | { | ||
4384 | struct stlibrd *brdp; | ||
4385 | unsigned int j; | ||
4386 | |||
4387 | for (j = 0; (j < stli_nrbrds); j++) { | ||
4388 | if ((brdp = stli_brds[j]) == NULL || | ||
4389 | test_bit(BST_PROBED, &brdp->state)) | ||
4390 | continue; | ||
4391 | |||
4392 | stli_cleanup_ports(brdp); | ||
4393 | |||
4394 | iounmap(brdp->membase); | ||
4395 | if (brdp->iosize > 0) | ||
4396 | release_region(brdp->iobase, brdp->iosize); | ||
4397 | kfree(brdp); | ||
4398 | stli_brds[j] = NULL; | ||
4399 | } | ||
4400 | } | ||
4401 | |||
4402 | static int __init istallion_module_init(void) | ||
4403 | { | ||
4404 | unsigned int i; | ||
4405 | int retval; | ||
4406 | |||
4407 | printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion); | ||
4408 | |||
4409 | spin_lock_init(&stli_lock); | ||
4410 | spin_lock_init(&brd_lock); | ||
4411 | |||
4412 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); | ||
4413 | if (!stli_txcookbuf) { | ||
4414 | printk(KERN_ERR "istallion: failed to allocate memory " | ||
4415 | "(size=%d)\n", STLI_TXBUFSIZE); | ||
4416 | retval = -ENOMEM; | ||
4417 | goto err; | ||
4418 | } | ||
4419 | |||
4420 | stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); | ||
4421 | if (!stli_serial) { | ||
4422 | retval = -ENOMEM; | ||
4423 | goto err_free; | ||
4424 | } | ||
4425 | |||
4426 | stli_serial->owner = THIS_MODULE; | ||
4427 | stli_serial->driver_name = stli_drvname; | ||
4428 | stli_serial->name = stli_serialname; | ||
4429 | stli_serial->major = STL_SERIALMAJOR; | ||
4430 | stli_serial->minor_start = 0; | ||
4431 | stli_serial->type = TTY_DRIVER_TYPE_SERIAL; | ||
4432 | stli_serial->subtype = SERIAL_TYPE_NORMAL; | ||
4433 | stli_serial->init_termios = stli_deftermios; | ||
4434 | stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
4435 | tty_set_operations(stli_serial, &stli_ops); | ||
4436 | |||
4437 | retval = tty_register_driver(stli_serial); | ||
4438 | if (retval) { | ||
4439 | printk(KERN_ERR "istallion: failed to register serial driver\n"); | ||
4440 | goto err_ttyput; | ||
4441 | } | ||
4442 | |||
4443 | retval = stli_initbrds(); | ||
4444 | if (retval) | ||
4445 | goto err_ttyunr; | ||
4446 | |||
4447 | /* | ||
4448 | * Set up a character driver for the shared memory region. We need this | ||
4449 | * to down load the slave code image. Also it is a useful debugging tool. | ||
4450 | */ | ||
4451 | retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); | ||
4452 | if (retval) { | ||
4453 | printk(KERN_ERR "istallion: failed to register serial memory " | ||
4454 | "device\n"); | ||
4455 | goto err_deinit; | ||
4456 | } | ||
4457 | |||
4458 | istallion_class = class_create(THIS_MODULE, "staliomem"); | ||
4459 | for (i = 0; i < 4; i++) | ||
4460 | device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), | ||
4461 | NULL, "staliomem%d", i); | ||
4462 | |||
4463 | return 0; | ||
4464 | err_deinit: | ||
4465 | pci_unregister_driver(&stli_pcidriver); | ||
4466 | istallion_cleanup_isa(); | ||
4467 | err_ttyunr: | ||
4468 | tty_unregister_driver(stli_serial); | ||
4469 | err_ttyput: | ||
4470 | put_tty_driver(stli_serial); | ||
4471 | err_free: | ||
4472 | kfree(stli_txcookbuf); | ||
4473 | err: | ||
4474 | return retval; | ||
4475 | } | ||
4476 | |||
4477 | /*****************************************************************************/ | ||
4478 | |||
4479 | static void __exit istallion_module_exit(void) | ||
4480 | { | ||
4481 | unsigned int j; | ||
4482 | |||
4483 | printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, | ||
4484 | stli_drvversion); | ||
4485 | |||
4486 | if (stli_timeron) { | ||
4487 | stli_timeron = 0; | ||
4488 | del_timer_sync(&stli_timerlist); | ||
4489 | } | ||
4490 | |||
4491 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); | ||
4492 | |||
4493 | for (j = 0; j < 4; j++) | ||
4494 | device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j)); | ||
4495 | class_destroy(istallion_class); | ||
4496 | |||
4497 | pci_unregister_driver(&stli_pcidriver); | ||
4498 | istallion_cleanup_isa(); | ||
4499 | |||
4500 | tty_unregister_driver(stli_serial); | ||
4501 | put_tty_driver(stli_serial); | ||
4502 | |||
4503 | kfree(stli_txcookbuf); | ||
4504 | } | ||
4505 | |||
4506 | module_init(istallion_module_init); | ||
4507 | module_exit(istallion_module_exit); | ||
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c deleted file mode 100644 index 602643a40b4b..000000000000 --- a/drivers/char/riscom8.c +++ /dev/null | |||
@@ -1,1560 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/char/riscom.c -- RISCom/8 multiport serial driver. | ||
3 | * | ||
4 | * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) | ||
5 | * | ||
6 | * This code is loosely based on the Linux serial driver, written by | ||
7 | * Linus Torvalds, Theodore T'so and others. The RISCom/8 card | ||
8 | * programming info was obtained from various drivers for other OSes | ||
9 | * (FreeBSD, ISC, etc), but no source code from those drivers were | ||
10 | * directly included in this driver. | ||
11 | * | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | * | ||
27 | * Revision 1.1 | ||
28 | * | ||
29 | * ChangeLog: | ||
30 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 27-Jun-2001 | ||
31 | * - get rid of check_region and several cleanups | ||
32 | */ | ||
33 | |||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/io.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/ioport.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/tty.h> | ||
43 | #include <linux/mm.h> | ||
44 | #include <linux/serial.h> | ||
45 | #include <linux/fcntl.h> | ||
46 | #include <linux/major.h> | ||
47 | #include <linux/init.h> | ||
48 | #include <linux/delay.h> | ||
49 | #include <linux/tty_flip.h> | ||
50 | #include <linux/spinlock.h> | ||
51 | #include <linux/device.h> | ||
52 | |||
53 | #include <linux/uaccess.h> | ||
54 | |||
55 | #include "riscom8.h" | ||
56 | #include "riscom8_reg.h" | ||
57 | |||
58 | /* Am I paranoid or not ? ;-) */ | ||
59 | #define RISCOM_PARANOIA_CHECK | ||
60 | |||
61 | /* | ||
62 | * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals. | ||
63 | * You can slightly speed up things by #undefing the following option, | ||
64 | * if you are REALLY sure that your board is correct one. | ||
65 | */ | ||
66 | |||
67 | #define RISCOM_BRAIN_DAMAGED_CTS | ||
68 | |||
69 | /* | ||
70 | * The following defines are mostly for testing purposes. But if you need | ||
71 | * some nice reporting in your syslog, you can define them also. | ||
72 | */ | ||
73 | #undef RC_REPORT_FIFO | ||
74 | #undef RC_REPORT_OVERRUN | ||
75 | |||
76 | |||
77 | #define RISCOM_LEGAL_FLAGS \ | ||
78 | (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ | ||
79 | ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ | ||
80 | ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) | ||
81 | |||
82 | static struct tty_driver *riscom_driver; | ||
83 | |||
84 | static DEFINE_SPINLOCK(riscom_lock); | ||
85 | |||
86 | static struct riscom_board rc_board[RC_NBOARD] = { | ||
87 | { | ||
88 | .base = RC_IOBASE1, | ||
89 | }, | ||
90 | { | ||
91 | .base = RC_IOBASE2, | ||
92 | }, | ||
93 | { | ||
94 | .base = RC_IOBASE3, | ||
95 | }, | ||
96 | { | ||
97 | .base = RC_IOBASE4, | ||
98 | }, | ||
99 | }; | ||
100 | |||
101 | static struct riscom_port rc_port[RC_NBOARD * RC_NPORT]; | ||
102 | |||
103 | /* RISCom/8 I/O ports addresses (without address translation) */ | ||
104 | static unsigned short rc_ioport[] = { | ||
105 | #if 1 | ||
106 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, | ||
107 | #else | ||
108 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10, | ||
109 | 0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62, | ||
110 | 0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101 | ||
111 | #endif | ||
112 | }; | ||
113 | #define RC_NIOPORT ARRAY_SIZE(rc_ioport) | ||
114 | |||
115 | |||
116 | static int rc_paranoia_check(struct riscom_port const *port, | ||
117 | char *name, const char *routine) | ||
118 | { | ||
119 | #ifdef RISCOM_PARANOIA_CHECK | ||
120 | static const char badmagic[] = KERN_INFO | ||
121 | "rc: Warning: bad riscom port magic number for device %s in %s\n"; | ||
122 | static const char badinfo[] = KERN_INFO | ||
123 | "rc: Warning: null riscom port for device %s in %s\n"; | ||
124 | |||
125 | if (!port) { | ||
126 | printk(badinfo, name, routine); | ||
127 | return 1; | ||
128 | } | ||
129 | if (port->magic != RISCOM8_MAGIC) { | ||
130 | printk(badmagic, name, routine); | ||
131 | return 1; | ||
132 | } | ||
133 | #endif | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * | ||
139 | * Service functions for RISCom/8 driver. | ||
140 | * | ||
141 | */ | ||
142 | |||
143 | /* Get board number from pointer */ | ||
144 | static inline int board_No(struct riscom_board const *bp) | ||
145 | { | ||
146 | return bp - rc_board; | ||
147 | } | ||
148 | |||
149 | /* Get port number from pointer */ | ||
150 | static inline int port_No(struct riscom_port const *port) | ||
151 | { | ||
152 | return RC_PORT(port - rc_port); | ||
153 | } | ||
154 | |||
155 | /* Get pointer to board from pointer to port */ | ||
156 | static inline struct riscom_board *port_Board(struct riscom_port const *port) | ||
157 | { | ||
158 | return &rc_board[RC_BOARD(port - rc_port)]; | ||
159 | } | ||
160 | |||
161 | /* Input Byte from CL CD180 register */ | ||
162 | static inline unsigned char rc_in(struct riscom_board const *bp, | ||
163 | unsigned short reg) | ||
164 | { | ||
165 | return inb(bp->base + RC_TO_ISA(reg)); | ||
166 | } | ||
167 | |||
168 | /* Output Byte to CL CD180 register */ | ||
169 | static inline void rc_out(struct riscom_board const *bp, unsigned short reg, | ||
170 | unsigned char val) | ||
171 | { | ||
172 | outb(val, bp->base + RC_TO_ISA(reg)); | ||
173 | } | ||
174 | |||
175 | /* Wait for Channel Command Register ready */ | ||
176 | static void rc_wait_CCR(struct riscom_board const *bp) | ||
177 | { | ||
178 | unsigned long delay; | ||
179 | |||
180 | /* FIXME: need something more descriptive then 100000 :) */ | ||
181 | for (delay = 100000; delay; delay--) | ||
182 | if (!rc_in(bp, CD180_CCR)) | ||
183 | return; | ||
184 | |||
185 | printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp)); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * RISCom/8 probe functions. | ||
190 | */ | ||
191 | |||
192 | static int rc_request_io_range(struct riscom_board * const bp) | ||
193 | { | ||
194 | int i; | ||
195 | |||
196 | for (i = 0; i < RC_NIOPORT; i++) | ||
197 | if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1, | ||
198 | "RISCom/8")) { | ||
199 | goto out_release; | ||
200 | } | ||
201 | return 0; | ||
202 | out_release: | ||
203 | printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n", | ||
204 | board_No(bp), bp->base); | ||
205 | while (--i >= 0) | ||
206 | release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1); | ||
207 | return 1; | ||
208 | } | ||
209 | |||
210 | static void rc_release_io_range(struct riscom_board * const bp) | ||
211 | { | ||
212 | int i; | ||
213 | |||
214 | for (i = 0; i < RC_NIOPORT; i++) | ||
215 | release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1); | ||
216 | } | ||
217 | |||
218 | /* Reset and setup CD180 chip */ | ||
219 | static void __init rc_init_CD180(struct riscom_board const *bp) | ||
220 | { | ||
221 | unsigned long flags; | ||
222 | |||
223 | spin_lock_irqsave(&riscom_lock, flags); | ||
224 | |||
225 | rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ | ||
226 | rc_wait_CCR(bp); /* Wait for CCR ready */ | ||
227 | rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ | ||
228 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
229 | msleep(50); /* Delay 0.05 sec */ | ||
230 | spin_lock_irqsave(&riscom_lock, flags); | ||
231 | rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ | ||
232 | rc_out(bp, CD180_GICR, 0); /* Clear all bits */ | ||
233 | rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ | ||
234 | rc_out(bp, CD180_PILR2, RC_ACK_TINT); /* Prio for tx intr */ | ||
235 | rc_out(bp, CD180_PILR3, RC_ACK_RINT); /* Prio for rx intr */ | ||
236 | |||
237 | /* Setting up prescaler. We need 4 ticks per 1 ms */ | ||
238 | rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); | ||
239 | rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); | ||
240 | |||
241 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
242 | } | ||
243 | |||
244 | /* Main probing routine, also sets irq. */ | ||
245 | static int __init rc_probe(struct riscom_board *bp) | ||
246 | { | ||
247 | unsigned char val1, val2; | ||
248 | int irqs = 0; | ||
249 | int retries; | ||
250 | |||
251 | bp->irq = 0; | ||
252 | |||
253 | if (rc_request_io_range(bp)) | ||
254 | return 1; | ||
255 | |||
256 | /* Are the I/O ports here ? */ | ||
257 | rc_out(bp, CD180_PPRL, 0x5a); | ||
258 | outb(0xff, 0x80); | ||
259 | val1 = rc_in(bp, CD180_PPRL); | ||
260 | rc_out(bp, CD180_PPRL, 0xa5); | ||
261 | outb(0x00, 0x80); | ||
262 | val2 = rc_in(bp, CD180_PPRL); | ||
263 | |||
264 | if ((val1 != 0x5a) || (val2 != 0xa5)) { | ||
265 | printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n", | ||
266 | board_No(bp), bp->base); | ||
267 | goto out_release; | ||
268 | } | ||
269 | |||
270 | /* It's time to find IRQ for this board */ | ||
271 | for (retries = 0; retries < 5 && irqs <= 0; retries++) { | ||
272 | irqs = probe_irq_on(); | ||
273 | rc_init_CD180(bp); /* Reset CD180 chip */ | ||
274 | rc_out(bp, CD180_CAR, 2); /* Select port 2 */ | ||
275 | rc_wait_CCR(bp); | ||
276 | rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter */ | ||
277 | rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr */ | ||
278 | msleep(50); | ||
279 | irqs = probe_irq_off(irqs); | ||
280 | val1 = rc_in(bp, RC_BSR); /* Get Board Status reg */ | ||
281 | val2 = rc_in(bp, RC_ACK_TINT); /* ACK interrupt */ | ||
282 | rc_init_CD180(bp); /* Reset CD180 again */ | ||
283 | |||
284 | if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX))) { | ||
285 | printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not " | ||
286 | "found.\n", board_No(bp), bp->base); | ||
287 | goto out_release; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | if (irqs <= 0) { | ||
292 | printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board " | ||
293 | "at 0x%03x.\n", board_No(bp), bp->base); | ||
294 | goto out_release; | ||
295 | } | ||
296 | bp->irq = irqs; | ||
297 | bp->flags |= RC_BOARD_PRESENT; | ||
298 | |||
299 | printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at " | ||
300 | "0x%03x, IRQ %d.\n", | ||
301 | board_No(bp), | ||
302 | (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A', /* Board revision */ | ||
303 | bp->base, bp->irq); | ||
304 | |||
305 | return 0; | ||
306 | out_release: | ||
307 | rc_release_io_range(bp); | ||
308 | return 1; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * | ||
313 | * Interrupt processing routines. | ||
314 | * | ||
315 | */ | ||
316 | |||
317 | static struct riscom_port *rc_get_port(struct riscom_board const *bp, | ||
318 | unsigned char const *what) | ||
319 | { | ||
320 | unsigned char channel; | ||
321 | struct riscom_port *port; | ||
322 | |||
323 | channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF; | ||
324 | if (channel < CD180_NCH) { | ||
325 | port = &rc_port[board_No(bp) * RC_NPORT + channel]; | ||
326 | if (port->port.flags & ASYNC_INITIALIZED) | ||
327 | return port; | ||
328 | } | ||
329 | printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n", | ||
330 | board_No(bp), what, channel); | ||
331 | return NULL; | ||
332 | } | ||
333 | |||
334 | static void rc_receive_exc(struct riscom_board const *bp) | ||
335 | { | ||
336 | struct riscom_port *port; | ||
337 | struct tty_struct *tty; | ||
338 | unsigned char status; | ||
339 | unsigned char ch, flag; | ||
340 | |||
341 | port = rc_get_port(bp, "Receive"); | ||
342 | if (port == NULL) | ||
343 | return; | ||
344 | |||
345 | tty = tty_port_tty_get(&port->port); | ||
346 | |||
347 | #ifdef RC_REPORT_OVERRUN | ||
348 | status = rc_in(bp, CD180_RCSR); | ||
349 | if (status & RCSR_OE) | ||
350 | port->overrun++; | ||
351 | status &= port->mark_mask; | ||
352 | #else | ||
353 | status = rc_in(bp, CD180_RCSR) & port->mark_mask; | ||
354 | #endif | ||
355 | ch = rc_in(bp, CD180_RDR); | ||
356 | if (!status) | ||
357 | goto out; | ||
358 | if (status & RCSR_TOUT) { | ||
359 | printk(KERN_WARNING "rc%d: port %d: Receiver timeout. " | ||
360 | "Hardware problems ?\n", | ||
361 | board_No(bp), port_No(port)); | ||
362 | goto out; | ||
363 | |||
364 | } else if (status & RCSR_BREAK) { | ||
365 | printk(KERN_INFO "rc%d: port %d: Handling break...\n", | ||
366 | board_No(bp), port_No(port)); | ||
367 | flag = TTY_BREAK; | ||
368 | if (tty && (port->port.flags & ASYNC_SAK)) | ||
369 | do_SAK(tty); | ||
370 | |||
371 | } else if (status & RCSR_PE) | ||
372 | flag = TTY_PARITY; | ||
373 | |||
374 | else if (status & RCSR_FE) | ||
375 | flag = TTY_FRAME; | ||
376 | |||
377 | else if (status & RCSR_OE) | ||
378 | flag = TTY_OVERRUN; | ||
379 | else | ||
380 | flag = TTY_NORMAL; | ||
381 | |||
382 | if (tty) { | ||
383 | tty_insert_flip_char(tty, ch, flag); | ||
384 | tty_flip_buffer_push(tty); | ||
385 | } | ||
386 | out: | ||
387 | tty_kref_put(tty); | ||
388 | } | ||
389 | |||
390 | static void rc_receive(struct riscom_board const *bp) | ||
391 | { | ||
392 | struct riscom_port *port; | ||
393 | struct tty_struct *tty; | ||
394 | unsigned char count; | ||
395 | |||
396 | port = rc_get_port(bp, "Receive"); | ||
397 | if (port == NULL) | ||
398 | return; | ||
399 | |||
400 | tty = tty_port_tty_get(&port->port); | ||
401 | |||
402 | count = rc_in(bp, CD180_RDCR); | ||
403 | |||
404 | #ifdef RC_REPORT_FIFO | ||
405 | port->hits[count > 8 ? 9 : count]++; | ||
406 | #endif | ||
407 | |||
408 | while (count--) { | ||
409 | u8 ch = rc_in(bp, CD180_RDR); | ||
410 | if (tty) | ||
411 | tty_insert_flip_char(tty, ch, TTY_NORMAL); | ||
412 | } | ||
413 | if (tty) { | ||
414 | tty_flip_buffer_push(tty); | ||
415 | tty_kref_put(tty); | ||
416 | } | ||
417 | } | ||
418 | |||
419 | static void rc_transmit(struct riscom_board const *bp) | ||
420 | { | ||
421 | struct riscom_port *port; | ||
422 | struct tty_struct *tty; | ||
423 | unsigned char count; | ||
424 | |||
425 | port = rc_get_port(bp, "Transmit"); | ||
426 | if (port == NULL) | ||
427 | return; | ||
428 | |||
429 | tty = tty_port_tty_get(&port->port); | ||
430 | |||
431 | if (port->IER & IER_TXEMPTY) { | ||
432 | /* FIFO drained */ | ||
433 | rc_out(bp, CD180_CAR, port_No(port)); | ||
434 | port->IER &= ~IER_TXEMPTY; | ||
435 | rc_out(bp, CD180_IER, port->IER); | ||
436 | goto out; | ||
437 | } | ||
438 | |||
439 | if ((port->xmit_cnt <= 0 && !port->break_length) | ||
440 | || (tty && (tty->stopped || tty->hw_stopped))) { | ||
441 | rc_out(bp, CD180_CAR, port_No(port)); | ||
442 | port->IER &= ~IER_TXRDY; | ||
443 | rc_out(bp, CD180_IER, port->IER); | ||
444 | goto out; | ||
445 | } | ||
446 | |||
447 | if (port->break_length) { | ||
448 | if (port->break_length > 0) { | ||
449 | if (port->COR2 & COR2_ETC) { | ||
450 | rc_out(bp, CD180_TDR, CD180_C_ESC); | ||
451 | rc_out(bp, CD180_TDR, CD180_C_SBRK); | ||
452 | port->COR2 &= ~COR2_ETC; | ||
453 | } | ||
454 | count = min_t(int, port->break_length, 0xff); | ||
455 | rc_out(bp, CD180_TDR, CD180_C_ESC); | ||
456 | rc_out(bp, CD180_TDR, CD180_C_DELAY); | ||
457 | rc_out(bp, CD180_TDR, count); | ||
458 | port->break_length -= count; | ||
459 | if (port->break_length == 0) | ||
460 | port->break_length--; | ||
461 | } else { | ||
462 | rc_out(bp, CD180_TDR, CD180_C_ESC); | ||
463 | rc_out(bp, CD180_TDR, CD180_C_EBRK); | ||
464 | rc_out(bp, CD180_COR2, port->COR2); | ||
465 | rc_wait_CCR(bp); | ||
466 | rc_out(bp, CD180_CCR, CCR_CORCHG2); | ||
467 | port->break_length = 0; | ||
468 | } | ||
469 | goto out; | ||
470 | } | ||
471 | |||
472 | count = CD180_NFIFO; | ||
473 | do { | ||
474 | rc_out(bp, CD180_TDR, port->port.xmit_buf[port->xmit_tail++]); | ||
475 | port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); | ||
476 | if (--port->xmit_cnt <= 0) | ||
477 | break; | ||
478 | } while (--count > 0); | ||
479 | |||
480 | if (port->xmit_cnt <= 0) { | ||
481 | rc_out(bp, CD180_CAR, port_No(port)); | ||
482 | port->IER &= ~IER_TXRDY; | ||
483 | rc_out(bp, CD180_IER, port->IER); | ||
484 | } | ||
485 | if (tty && port->xmit_cnt <= port->wakeup_chars) | ||
486 | tty_wakeup(tty); | ||
487 | out: | ||
488 | tty_kref_put(tty); | ||
489 | } | ||
490 | |||
491 | static void rc_check_modem(struct riscom_board const *bp) | ||
492 | { | ||
493 | struct riscom_port *port; | ||
494 | struct tty_struct *tty; | ||
495 | unsigned char mcr; | ||
496 | |||
497 | port = rc_get_port(bp, "Modem"); | ||
498 | if (port == NULL) | ||
499 | return; | ||
500 | |||
501 | tty = tty_port_tty_get(&port->port); | ||
502 | |||
503 | mcr = rc_in(bp, CD180_MCR); | ||
504 | if (mcr & MCR_CDCHG) { | ||
505 | if (rc_in(bp, CD180_MSVR) & MSVR_CD) | ||
506 | wake_up_interruptible(&port->port.open_wait); | ||
507 | else if (tty) | ||
508 | tty_hangup(tty); | ||
509 | } | ||
510 | |||
511 | #ifdef RISCOM_BRAIN_DAMAGED_CTS | ||
512 | if (mcr & MCR_CTSCHG) { | ||
513 | if (rc_in(bp, CD180_MSVR) & MSVR_CTS) { | ||
514 | port->IER |= IER_TXRDY; | ||
515 | if (tty) { | ||
516 | tty->hw_stopped = 0; | ||
517 | if (port->xmit_cnt <= port->wakeup_chars) | ||
518 | tty_wakeup(tty); | ||
519 | } | ||
520 | } else { | ||
521 | if (tty) | ||
522 | tty->hw_stopped = 1; | ||
523 | port->IER &= ~IER_TXRDY; | ||
524 | } | ||
525 | rc_out(bp, CD180_IER, port->IER); | ||
526 | } | ||
527 | if (mcr & MCR_DSRCHG) { | ||
528 | if (rc_in(bp, CD180_MSVR) & MSVR_DSR) { | ||
529 | port->IER |= IER_TXRDY; | ||
530 | if (tty) { | ||
531 | tty->hw_stopped = 0; | ||
532 | if (port->xmit_cnt <= port->wakeup_chars) | ||
533 | tty_wakeup(tty); | ||
534 | } | ||
535 | } else { | ||
536 | if (tty) | ||
537 | tty->hw_stopped = 1; | ||
538 | port->IER &= ~IER_TXRDY; | ||
539 | } | ||
540 | rc_out(bp, CD180_IER, port->IER); | ||
541 | } | ||
542 | #endif /* RISCOM_BRAIN_DAMAGED_CTS */ | ||
543 | |||
544 | /* Clear change bits */ | ||
545 | rc_out(bp, CD180_MCR, 0); | ||
546 | tty_kref_put(tty); | ||
547 | } | ||
548 | |||
549 | /* The main interrupt processing routine */ | ||
550 | static irqreturn_t rc_interrupt(int dummy, void *dev_id) | ||
551 | { | ||
552 | unsigned char status; | ||
553 | unsigned char ack; | ||
554 | struct riscom_board *bp = dev_id; | ||
555 | unsigned long loop = 0; | ||
556 | int handled = 0; | ||
557 | |||
558 | if (!(bp->flags & RC_BOARD_ACTIVE)) | ||
559 | return IRQ_NONE; | ||
560 | |||
561 | while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) & | ||
562 | (RC_BSR_TOUT | RC_BSR_TINT | | ||
563 | RC_BSR_MINT | RC_BSR_RINT))) { | ||
564 | handled = 1; | ||
565 | if (status & RC_BSR_TOUT) | ||
566 | printk(KERN_WARNING "rc%d: Got timeout. Hardware " | ||
567 | "error?\n", board_No(bp)); | ||
568 | else if (status & RC_BSR_RINT) { | ||
569 | ack = rc_in(bp, RC_ACK_RINT); | ||
570 | if (ack == (RC_ID | GIVR_IT_RCV)) | ||
571 | rc_receive(bp); | ||
572 | else if (ack == (RC_ID | GIVR_IT_REXC)) | ||
573 | rc_receive_exc(bp); | ||
574 | else | ||
575 | printk(KERN_WARNING "rc%d: Bad receive ack " | ||
576 | "0x%02x.\n", | ||
577 | board_No(bp), ack); | ||
578 | } else if (status & RC_BSR_TINT) { | ||
579 | ack = rc_in(bp, RC_ACK_TINT); | ||
580 | if (ack == (RC_ID | GIVR_IT_TX)) | ||
581 | rc_transmit(bp); | ||
582 | else | ||
583 | printk(KERN_WARNING "rc%d: Bad transmit ack " | ||
584 | "0x%02x.\n", | ||
585 | board_No(bp), ack); | ||
586 | } else /* if (status & RC_BSR_MINT) */ { | ||
587 | ack = rc_in(bp, RC_ACK_MINT); | ||
588 | if (ack == (RC_ID | GIVR_IT_MODEM)) | ||
589 | rc_check_modem(bp); | ||
590 | else | ||
591 | printk(KERN_WARNING "rc%d: Bad modem ack " | ||
592 | "0x%02x.\n", | ||
593 | board_No(bp), ack); | ||
594 | } | ||
595 | rc_out(bp, CD180_EOIR, 0); /* Mark end of interrupt */ | ||
596 | rc_out(bp, RC_CTOUT, 0); /* Clear timeout flag */ | ||
597 | } | ||
598 | return IRQ_RETVAL(handled); | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * Routines for open & close processing. | ||
603 | */ | ||
604 | |||
605 | /* Called with disabled interrupts */ | ||
606 | static int rc_setup_board(struct riscom_board *bp) | ||
607 | { | ||
608 | int error; | ||
609 | |||
610 | if (bp->flags & RC_BOARD_ACTIVE) | ||
611 | return 0; | ||
612 | |||
613 | error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED, | ||
614 | "RISCom/8", bp); | ||
615 | if (error) | ||
616 | return error; | ||
617 | |||
618 | rc_out(bp, RC_CTOUT, 0); /* Just in case */ | ||
619 | bp->DTR = ~0; | ||
620 | rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */ | ||
621 | |||
622 | bp->flags |= RC_BOARD_ACTIVE; | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | /* Called with disabled interrupts */ | ||
628 | static void rc_shutdown_board(struct riscom_board *bp) | ||
629 | { | ||
630 | if (!(bp->flags & RC_BOARD_ACTIVE)) | ||
631 | return; | ||
632 | |||
633 | bp->flags &= ~RC_BOARD_ACTIVE; | ||
634 | |||
635 | free_irq(bp->irq, NULL); | ||
636 | |||
637 | bp->DTR = ~0; | ||
638 | rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */ | ||
639 | |||
640 | } | ||
641 | |||
642 | /* | ||
643 | * Setting up port characteristics. | ||
644 | * Must be called with disabled interrupts | ||
645 | */ | ||
646 | static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp, | ||
647 | struct riscom_port *port) | ||
648 | { | ||
649 | unsigned long baud; | ||
650 | long tmp; | ||
651 | unsigned char cor1 = 0, cor3 = 0; | ||
652 | unsigned char mcor1 = 0, mcor2 = 0; | ||
653 | |||
654 | port->IER = 0; | ||
655 | port->COR2 = 0; | ||
656 | port->MSVR = MSVR_RTS; | ||
657 | |||
658 | baud = tty_get_baud_rate(tty); | ||
659 | |||
660 | /* Select port on the board */ | ||
661 | rc_out(bp, CD180_CAR, port_No(port)); | ||
662 | |||
663 | if (!baud) { | ||
664 | /* Drop DTR & exit */ | ||
665 | bp->DTR |= (1u << port_No(port)); | ||
666 | rc_out(bp, RC_DTR, bp->DTR); | ||
667 | return; | ||
668 | } else { | ||
669 | /* Set DTR on */ | ||
670 | bp->DTR &= ~(1u << port_No(port)); | ||
671 | rc_out(bp, RC_DTR, bp->DTR); | ||
672 | } | ||
673 | |||
674 | /* | ||
675 | * Now we must calculate some speed depended things | ||
676 | */ | ||
677 | |||
678 | /* Set baud rate for port */ | ||
679 | tmp = (((RC_OSCFREQ + baud/2) / baud + | ||
680 | CD180_TPC/2) / CD180_TPC); | ||
681 | |||
682 | rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff); | ||
683 | rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff); | ||
684 | rc_out(bp, CD180_RBPRL, tmp & 0xff); | ||
685 | rc_out(bp, CD180_TBPRL, tmp & 0xff); | ||
686 | |||
687 | baud = (baud + 5) / 10; /* Estimated CPS */ | ||
688 | |||
689 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ | ||
690 | tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO; | ||
691 | port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? | ||
692 | SERIAL_XMIT_SIZE - 1 : tmp); | ||
693 | |||
694 | /* Receiver timeout will be transmission time for 1.5 chars */ | ||
695 | tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud; | ||
696 | tmp = (tmp > 0xff) ? 0xff : tmp; | ||
697 | rc_out(bp, CD180_RTPR, tmp); | ||
698 | |||
699 | switch (C_CSIZE(tty)) { | ||
700 | case CS5: | ||
701 | cor1 |= COR1_5BITS; | ||
702 | break; | ||
703 | case CS6: | ||
704 | cor1 |= COR1_6BITS; | ||
705 | break; | ||
706 | case CS7: | ||
707 | cor1 |= COR1_7BITS; | ||
708 | break; | ||
709 | case CS8: | ||
710 | cor1 |= COR1_8BITS; | ||
711 | break; | ||
712 | } | ||
713 | if (C_CSTOPB(tty)) | ||
714 | cor1 |= COR1_2SB; | ||
715 | |||
716 | cor1 |= COR1_IGNORE; | ||
717 | if (C_PARENB(tty)) { | ||
718 | cor1 |= COR1_NORMPAR; | ||
719 | if (C_PARODD(tty)) | ||
720 | cor1 |= COR1_ODDP; | ||
721 | if (I_INPCK(tty)) | ||
722 | cor1 &= ~COR1_IGNORE; | ||
723 | } | ||
724 | /* Set marking of some errors */ | ||
725 | port->mark_mask = RCSR_OE | RCSR_TOUT; | ||
726 | if (I_INPCK(tty)) | ||
727 | port->mark_mask |= RCSR_FE | RCSR_PE; | ||
728 | if (I_BRKINT(tty) || I_PARMRK(tty)) | ||
729 | port->mark_mask |= RCSR_BREAK; | ||
730 | if (I_IGNPAR(tty)) | ||
731 | port->mark_mask &= ~(RCSR_FE | RCSR_PE); | ||
732 | if (I_IGNBRK(tty)) { | ||
733 | port->mark_mask &= ~RCSR_BREAK; | ||
734 | if (I_IGNPAR(tty)) | ||
735 | /* Real raw mode. Ignore all */ | ||
736 | port->mark_mask &= ~RCSR_OE; | ||
737 | } | ||
738 | /* Enable Hardware Flow Control */ | ||
739 | if (C_CRTSCTS(tty)) { | ||
740 | #ifdef RISCOM_BRAIN_DAMAGED_CTS | ||
741 | port->IER |= IER_DSR | IER_CTS; | ||
742 | mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; | ||
743 | mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; | ||
744 | tty->hw_stopped = !(rc_in(bp, CD180_MSVR) & | ||
745 | (MSVR_CTS|MSVR_DSR)); | ||
746 | #else | ||
747 | port->COR2 |= COR2_CTSAE; | ||
748 | #endif | ||
749 | } | ||
750 | /* Enable Software Flow Control. FIXME: I'm not sure about this */ | ||
751 | /* Some people reported that it works, but I still doubt */ | ||
752 | if (I_IXON(tty)) { | ||
753 | port->COR2 |= COR2_TXIBE; | ||
754 | cor3 |= (COR3_FCT | COR3_SCDE); | ||
755 | if (I_IXANY(tty)) | ||
756 | port->COR2 |= COR2_IXM; | ||
757 | rc_out(bp, CD180_SCHR1, START_CHAR(tty)); | ||
758 | rc_out(bp, CD180_SCHR2, STOP_CHAR(tty)); | ||
759 | rc_out(bp, CD180_SCHR3, START_CHAR(tty)); | ||
760 | rc_out(bp, CD180_SCHR4, STOP_CHAR(tty)); | ||
761 | } | ||
762 | if (!C_CLOCAL(tty)) { | ||
763 | /* Enable CD check */ | ||
764 | port->IER |= IER_CD; | ||
765 | mcor1 |= MCOR1_CDZD; | ||
766 | mcor2 |= MCOR2_CDOD; | ||
767 | } | ||
768 | |||
769 | if (C_CREAD(tty)) | ||
770 | /* Enable receiver */ | ||
771 | port->IER |= IER_RXD; | ||
772 | |||
773 | /* Set input FIFO size (1-8 bytes) */ | ||
774 | cor3 |= RISCOM_RXFIFO; | ||
775 | /* Setting up CD180 channel registers */ | ||
776 | rc_out(bp, CD180_COR1, cor1); | ||
777 | rc_out(bp, CD180_COR2, port->COR2); | ||
778 | rc_out(bp, CD180_COR3, cor3); | ||
779 | /* Make CD180 know about registers change */ | ||
780 | rc_wait_CCR(bp); | ||
781 | rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); | ||
782 | /* Setting up modem option registers */ | ||
783 | rc_out(bp, CD180_MCOR1, mcor1); | ||
784 | rc_out(bp, CD180_MCOR2, mcor2); | ||
785 | /* Enable CD180 transmitter & receiver */ | ||
786 | rc_wait_CCR(bp); | ||
787 | rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN); | ||
788 | /* Enable interrupts */ | ||
789 | rc_out(bp, CD180_IER, port->IER); | ||
790 | /* And finally set RTS on */ | ||
791 | rc_out(bp, CD180_MSVR, port->MSVR); | ||
792 | } | ||
793 | |||
794 | /* Must be called with interrupts enabled */ | ||
795 | static int rc_activate_port(struct tty_port *port, struct tty_struct *tty) | ||
796 | { | ||
797 | struct riscom_port *rp = container_of(port, struct riscom_port, port); | ||
798 | struct riscom_board *bp = port_Board(rp); | ||
799 | unsigned long flags; | ||
800 | |||
801 | if (tty_port_alloc_xmit_buf(port) < 0) | ||
802 | return -ENOMEM; | ||
803 | |||
804 | spin_lock_irqsave(&riscom_lock, flags); | ||
805 | |||
806 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
807 | bp->count++; | ||
808 | rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0; | ||
809 | rc_change_speed(tty, bp, rp); | ||
810 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | /* Must be called with interrupts disabled */ | ||
815 | static void rc_shutdown_port(struct tty_struct *tty, | ||
816 | struct riscom_board *bp, struct riscom_port *port) | ||
817 | { | ||
818 | #ifdef RC_REPORT_OVERRUN | ||
819 | printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n", | ||
820 | board_No(bp), port_No(port), port->overrun); | ||
821 | #endif | ||
822 | #ifdef RC_REPORT_FIFO | ||
823 | { | ||
824 | int i; | ||
825 | |||
826 | printk(KERN_INFO "rc%d: port %d: FIFO hits [ ", | ||
827 | board_No(bp), port_No(port)); | ||
828 | for (i = 0; i < 10; i++) | ||
829 | printk("%ld ", port->hits[i]); | ||
830 | printk("].\n"); | ||
831 | } | ||
832 | #endif | ||
833 | tty_port_free_xmit_buf(&port->port); | ||
834 | |||
835 | /* Select port */ | ||
836 | rc_out(bp, CD180_CAR, port_No(port)); | ||
837 | /* Reset port */ | ||
838 | rc_wait_CCR(bp); | ||
839 | rc_out(bp, CD180_CCR, CCR_SOFTRESET); | ||
840 | /* Disable all interrupts from this port */ | ||
841 | port->IER = 0; | ||
842 | rc_out(bp, CD180_IER, port->IER); | ||
843 | |||
844 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
845 | |||
846 | if (--bp->count < 0) { | ||
847 | printk(KERN_INFO "rc%d: rc_shutdown_port: " | ||
848 | "bad board count: %d\n", | ||
849 | board_No(bp), bp->count); | ||
850 | bp->count = 0; | ||
851 | } | ||
852 | /* | ||
853 | * If this is the last opened port on the board | ||
854 | * shutdown whole board | ||
855 | */ | ||
856 | if (!bp->count) | ||
857 | rc_shutdown_board(bp); | ||
858 | } | ||
859 | |||
860 | static int carrier_raised(struct tty_port *port) | ||
861 | { | ||
862 | struct riscom_port *p = container_of(port, struct riscom_port, port); | ||
863 | struct riscom_board *bp = port_Board(p); | ||
864 | unsigned long flags; | ||
865 | int CD; | ||
866 | |||
867 | spin_lock_irqsave(&riscom_lock, flags); | ||
868 | rc_out(bp, CD180_CAR, port_No(p)); | ||
869 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; | ||
870 | rc_out(bp, CD180_MSVR, MSVR_RTS); | ||
871 | bp->DTR &= ~(1u << port_No(p)); | ||
872 | rc_out(bp, RC_DTR, bp->DTR); | ||
873 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
874 | return CD; | ||
875 | } | ||
876 | |||
877 | static void dtr_rts(struct tty_port *port, int onoff) | ||
878 | { | ||
879 | struct riscom_port *p = container_of(port, struct riscom_port, port); | ||
880 | struct riscom_board *bp = port_Board(p); | ||
881 | unsigned long flags; | ||
882 | |||
883 | spin_lock_irqsave(&riscom_lock, flags); | ||
884 | bp->DTR &= ~(1u << port_No(p)); | ||
885 | if (onoff == 0) | ||
886 | bp->DTR |= (1u << port_No(p)); | ||
887 | rc_out(bp, RC_DTR, bp->DTR); | ||
888 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
889 | } | ||
890 | |||
891 | static int rc_open(struct tty_struct *tty, struct file *filp) | ||
892 | { | ||
893 | int board; | ||
894 | int error; | ||
895 | struct riscom_port *port; | ||
896 | struct riscom_board *bp; | ||
897 | |||
898 | board = RC_BOARD(tty->index); | ||
899 | if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT)) | ||
900 | return -ENODEV; | ||
901 | |||
902 | bp = &rc_board[board]; | ||
903 | port = rc_port + board * RC_NPORT + RC_PORT(tty->index); | ||
904 | if (rc_paranoia_check(port, tty->name, "rc_open")) | ||
905 | return -ENODEV; | ||
906 | |||
907 | error = rc_setup_board(bp); | ||
908 | if (error) | ||
909 | return error; | ||
910 | |||
911 | tty->driver_data = port; | ||
912 | return tty_port_open(&port->port, tty, filp); | ||
913 | } | ||
914 | |||
915 | static void rc_flush_buffer(struct tty_struct *tty) | ||
916 | { | ||
917 | struct riscom_port *port = tty->driver_data; | ||
918 | unsigned long flags; | ||
919 | |||
920 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) | ||
921 | return; | ||
922 | |||
923 | spin_lock_irqsave(&riscom_lock, flags); | ||
924 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | ||
925 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
926 | |||
927 | tty_wakeup(tty); | ||
928 | } | ||
929 | |||
930 | static void rc_close_port(struct tty_port *port) | ||
931 | { | ||
932 | unsigned long flags; | ||
933 | struct riscom_port *rp = container_of(port, struct riscom_port, port); | ||
934 | struct riscom_board *bp = port_Board(rp); | ||
935 | unsigned long timeout; | ||
936 | |||
937 | /* | ||
938 | * At this point we stop accepting input. To do this, we | ||
939 | * disable the receive line status interrupts, and tell the | ||
940 | * interrupt driver to stop checking the data ready bit in the | ||
941 | * line status register. | ||
942 | */ | ||
943 | |||
944 | spin_lock_irqsave(&riscom_lock, flags); | ||
945 | rp->IER &= ~IER_RXD; | ||
946 | |||
947 | rp->IER &= ~IER_TXRDY; | ||
948 | rp->IER |= IER_TXEMPTY; | ||
949 | rc_out(bp, CD180_CAR, port_No(rp)); | ||
950 | rc_out(bp, CD180_IER, rp->IER); | ||
951 | /* | ||
952 | * Before we drop DTR, make sure the UART transmitter | ||
953 | * has completely drained; this is especially | ||
954 | * important if there is a transmit FIFO! | ||
955 | */ | ||
956 | timeout = jiffies + HZ; | ||
957 | while (rp->IER & IER_TXEMPTY) { | ||
958 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
959 | msleep_interruptible(jiffies_to_msecs(rp->timeout)); | ||
960 | spin_lock_irqsave(&riscom_lock, flags); | ||
961 | if (time_after(jiffies, timeout)) | ||
962 | break; | ||
963 | } | ||
964 | rc_shutdown_port(port->tty, bp, rp); | ||
965 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
966 | } | ||
967 | |||
968 | static void rc_close(struct tty_struct *tty, struct file *filp) | ||
969 | { | ||
970 | struct riscom_port *port = tty->driver_data; | ||
971 | |||
972 | if (!port || rc_paranoia_check(port, tty->name, "close")) | ||
973 | return; | ||
974 | tty_port_close(&port->port, tty, filp); | ||
975 | } | ||
976 | |||
977 | static int rc_write(struct tty_struct *tty, | ||
978 | const unsigned char *buf, int count) | ||
979 | { | ||
980 | struct riscom_port *port = tty->driver_data; | ||
981 | struct riscom_board *bp; | ||
982 | int c, total = 0; | ||
983 | unsigned long flags; | ||
984 | |||
985 | if (rc_paranoia_check(port, tty->name, "rc_write")) | ||
986 | return 0; | ||
987 | |||
988 | bp = port_Board(port); | ||
989 | |||
990 | while (1) { | ||
991 | spin_lock_irqsave(&riscom_lock, flags); | ||
992 | |||
993 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, | ||
994 | SERIAL_XMIT_SIZE - port->xmit_head)); | ||
995 | if (c <= 0) | ||
996 | break; /* lock continues to be held */ | ||
997 | |||
998 | memcpy(port->port.xmit_buf + port->xmit_head, buf, c); | ||
999 | port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | ||
1000 | port->xmit_cnt += c; | ||
1001 | |||
1002 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1003 | |||
1004 | buf += c; | ||
1005 | count -= c; | ||
1006 | total += c; | ||
1007 | } | ||
1008 | |||
1009 | if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && | ||
1010 | !(port->IER & IER_TXRDY)) { | ||
1011 | port->IER |= IER_TXRDY; | ||
1012 | rc_out(bp, CD180_CAR, port_No(port)); | ||
1013 | rc_out(bp, CD180_IER, port->IER); | ||
1014 | } | ||
1015 | |||
1016 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1017 | |||
1018 | return total; | ||
1019 | } | ||
1020 | |||
1021 | static int rc_put_char(struct tty_struct *tty, unsigned char ch) | ||
1022 | { | ||
1023 | struct riscom_port *port = tty->driver_data; | ||
1024 | unsigned long flags; | ||
1025 | int ret = 0; | ||
1026 | |||
1027 | if (rc_paranoia_check(port, tty->name, "rc_put_char")) | ||
1028 | return 0; | ||
1029 | |||
1030 | spin_lock_irqsave(&riscom_lock, flags); | ||
1031 | |||
1032 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) | ||
1033 | goto out; | ||
1034 | |||
1035 | port->port.xmit_buf[port->xmit_head++] = ch; | ||
1036 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | ||
1037 | port->xmit_cnt++; | ||
1038 | ret = 1; | ||
1039 | |||
1040 | out: | ||
1041 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1042 | return ret; | ||
1043 | } | ||
1044 | |||
1045 | static void rc_flush_chars(struct tty_struct *tty) | ||
1046 | { | ||
1047 | struct riscom_port *port = tty->driver_data; | ||
1048 | unsigned long flags; | ||
1049 | |||
1050 | if (rc_paranoia_check(port, tty->name, "rc_flush_chars")) | ||
1051 | return; | ||
1052 | |||
1053 | if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped) | ||
1054 | return; | ||
1055 | |||
1056 | spin_lock_irqsave(&riscom_lock, flags); | ||
1057 | |||
1058 | port->IER |= IER_TXRDY; | ||
1059 | rc_out(port_Board(port), CD180_CAR, port_No(port)); | ||
1060 | rc_out(port_Board(port), CD180_IER, port->IER); | ||
1061 | |||
1062 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1063 | } | ||
1064 | |||
1065 | static int rc_write_room(struct tty_struct *tty) | ||
1066 | { | ||
1067 | struct riscom_port *port = tty->driver_data; | ||
1068 | int ret; | ||
1069 | |||
1070 | if (rc_paranoia_check(port, tty->name, "rc_write_room")) | ||
1071 | return 0; | ||
1072 | |||
1073 | ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; | ||
1074 | if (ret < 0) | ||
1075 | ret = 0; | ||
1076 | return ret; | ||
1077 | } | ||
1078 | |||
1079 | static int rc_chars_in_buffer(struct tty_struct *tty) | ||
1080 | { | ||
1081 | struct riscom_port *port = tty->driver_data; | ||
1082 | |||
1083 | if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer")) | ||
1084 | return 0; | ||
1085 | |||
1086 | return port->xmit_cnt; | ||
1087 | } | ||
1088 | |||
1089 | static int rc_tiocmget(struct tty_struct *tty) | ||
1090 | { | ||
1091 | struct riscom_port *port = tty->driver_data; | ||
1092 | struct riscom_board *bp; | ||
1093 | unsigned char status; | ||
1094 | unsigned int result; | ||
1095 | unsigned long flags; | ||
1096 | |||
1097 | if (rc_paranoia_check(port, tty->name, __func__)) | ||
1098 | return -ENODEV; | ||
1099 | |||
1100 | bp = port_Board(port); | ||
1101 | |||
1102 | spin_lock_irqsave(&riscom_lock, flags); | ||
1103 | |||
1104 | rc_out(bp, CD180_CAR, port_No(port)); | ||
1105 | status = rc_in(bp, CD180_MSVR); | ||
1106 | result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; | ||
1107 | |||
1108 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1109 | |||
1110 | result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) | ||
1111 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | ||
1112 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | ||
1113 | | ((status & MSVR_DSR) ? TIOCM_DSR : 0) | ||
1114 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); | ||
1115 | return result; | ||
1116 | } | ||
1117 | |||
1118 | static int rc_tiocmset(struct tty_struct *tty, | ||
1119 | unsigned int set, unsigned int clear) | ||
1120 | { | ||
1121 | struct riscom_port *port = tty->driver_data; | ||
1122 | unsigned long flags; | ||
1123 | struct riscom_board *bp; | ||
1124 | |||
1125 | if (rc_paranoia_check(port, tty->name, __func__)) | ||
1126 | return -ENODEV; | ||
1127 | |||
1128 | bp = port_Board(port); | ||
1129 | |||
1130 | spin_lock_irqsave(&riscom_lock, flags); | ||
1131 | |||
1132 | if (set & TIOCM_RTS) | ||
1133 | port->MSVR |= MSVR_RTS; | ||
1134 | if (set & TIOCM_DTR) | ||
1135 | bp->DTR &= ~(1u << port_No(port)); | ||
1136 | |||
1137 | if (clear & TIOCM_RTS) | ||
1138 | port->MSVR &= ~MSVR_RTS; | ||
1139 | if (clear & TIOCM_DTR) | ||
1140 | bp->DTR |= (1u << port_No(port)); | ||
1141 | |||
1142 | rc_out(bp, CD180_CAR, port_No(port)); | ||
1143 | rc_out(bp, CD180_MSVR, port->MSVR); | ||
1144 | rc_out(bp, RC_DTR, bp->DTR); | ||
1145 | |||
1146 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1147 | |||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static int rc_send_break(struct tty_struct *tty, int length) | ||
1152 | { | ||
1153 | struct riscom_port *port = tty->driver_data; | ||
1154 | struct riscom_board *bp = port_Board(port); | ||
1155 | unsigned long flags; | ||
1156 | |||
1157 | if (length == 0 || length == -1) | ||
1158 | return -EOPNOTSUPP; | ||
1159 | |||
1160 | spin_lock_irqsave(&riscom_lock, flags); | ||
1161 | |||
1162 | port->break_length = RISCOM_TPS / HZ * length; | ||
1163 | port->COR2 |= COR2_ETC; | ||
1164 | port->IER |= IER_TXRDY; | ||
1165 | rc_out(bp, CD180_CAR, port_No(port)); | ||
1166 | rc_out(bp, CD180_COR2, port->COR2); | ||
1167 | rc_out(bp, CD180_IER, port->IER); | ||
1168 | rc_wait_CCR(bp); | ||
1169 | rc_out(bp, CD180_CCR, CCR_CORCHG2); | ||
1170 | rc_wait_CCR(bp); | ||
1171 | |||
1172 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1173 | return 0; | ||
1174 | } | ||
1175 | |||
1176 | static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | ||
1177 | struct serial_struct __user *newinfo) | ||
1178 | { | ||
1179 | struct serial_struct tmp; | ||
1180 | struct riscom_board *bp = port_Board(port); | ||
1181 | int change_speed; | ||
1182 | |||
1183 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) | ||
1184 | return -EFAULT; | ||
1185 | |||
1186 | mutex_lock(&port->port.mutex); | ||
1187 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != | ||
1188 | (tmp.flags & ASYNC_SPD_MASK)); | ||
1189 | |||
1190 | if (!capable(CAP_SYS_ADMIN)) { | ||
1191 | if ((tmp.close_delay != port->port.close_delay) || | ||
1192 | (tmp.closing_wait != port->port.closing_wait) || | ||
1193 | ((tmp.flags & ~ASYNC_USR_MASK) != | ||
1194 | (port->port.flags & ~ASYNC_USR_MASK))) { | ||
1195 | mutex_unlock(&port->port.mutex); | ||
1196 | return -EPERM; | ||
1197 | } | ||
1198 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | ||
1199 | (tmp.flags & ASYNC_USR_MASK)); | ||
1200 | } else { | ||
1201 | port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | | ||
1202 | (tmp.flags & ASYNC_FLAGS)); | ||
1203 | port->port.close_delay = tmp.close_delay; | ||
1204 | port->port.closing_wait = tmp.closing_wait; | ||
1205 | } | ||
1206 | if (change_speed) { | ||
1207 | unsigned long flags; | ||
1208 | |||
1209 | spin_lock_irqsave(&riscom_lock, flags); | ||
1210 | rc_change_speed(tty, bp, port); | ||
1211 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1212 | } | ||
1213 | mutex_unlock(&port->port.mutex); | ||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | static int rc_get_serial_info(struct riscom_port *port, | ||
1218 | struct serial_struct __user *retinfo) | ||
1219 | { | ||
1220 | struct serial_struct tmp; | ||
1221 | struct riscom_board *bp = port_Board(port); | ||
1222 | |||
1223 | memset(&tmp, 0, sizeof(tmp)); | ||
1224 | tmp.type = PORT_CIRRUS; | ||
1225 | tmp.line = port - rc_port; | ||
1226 | |||
1227 | mutex_lock(&port->port.mutex); | ||
1228 | tmp.port = bp->base; | ||
1229 | tmp.irq = bp->irq; | ||
1230 | tmp.flags = port->port.flags; | ||
1231 | tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; | ||
1232 | tmp.close_delay = port->port.close_delay * HZ/100; | ||
1233 | tmp.closing_wait = port->port.closing_wait * HZ/100; | ||
1234 | mutex_unlock(&port->port.mutex); | ||
1235 | tmp.xmit_fifo_size = CD180_NFIFO; | ||
1236 | return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; | ||
1237 | } | ||
1238 | |||
1239 | static int rc_ioctl(struct tty_struct *tty, | ||
1240 | unsigned int cmd, unsigned long arg) | ||
1241 | { | ||
1242 | struct riscom_port *port = tty->driver_data; | ||
1243 | void __user *argp = (void __user *)arg; | ||
1244 | int retval; | ||
1245 | |||
1246 | if (rc_paranoia_check(port, tty->name, "rc_ioctl")) | ||
1247 | return -ENODEV; | ||
1248 | |||
1249 | switch (cmd) { | ||
1250 | case TIOCGSERIAL: | ||
1251 | retval = rc_get_serial_info(port, argp); | ||
1252 | break; | ||
1253 | case TIOCSSERIAL: | ||
1254 | retval = rc_set_serial_info(tty, port, argp); | ||
1255 | break; | ||
1256 | default: | ||
1257 | retval = -ENOIOCTLCMD; | ||
1258 | } | ||
1259 | return retval; | ||
1260 | } | ||
1261 | |||
1262 | static void rc_throttle(struct tty_struct *tty) | ||
1263 | { | ||
1264 | struct riscom_port *port = tty->driver_data; | ||
1265 | struct riscom_board *bp; | ||
1266 | unsigned long flags; | ||
1267 | |||
1268 | if (rc_paranoia_check(port, tty->name, "rc_throttle")) | ||
1269 | return; | ||
1270 | bp = port_Board(port); | ||
1271 | |||
1272 | spin_lock_irqsave(&riscom_lock, flags); | ||
1273 | port->MSVR &= ~MSVR_RTS; | ||
1274 | rc_out(bp, CD180_CAR, port_No(port)); | ||
1275 | if (I_IXOFF(tty)) { | ||
1276 | rc_wait_CCR(bp); | ||
1277 | rc_out(bp, CD180_CCR, CCR_SSCH2); | ||
1278 | rc_wait_CCR(bp); | ||
1279 | } | ||
1280 | rc_out(bp, CD180_MSVR, port->MSVR); | ||
1281 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1282 | } | ||
1283 | |||
1284 | static void rc_unthrottle(struct tty_struct *tty) | ||
1285 | { | ||
1286 | struct riscom_port *port = tty->driver_data; | ||
1287 | struct riscom_board *bp; | ||
1288 | unsigned long flags; | ||
1289 | |||
1290 | if (rc_paranoia_check(port, tty->name, "rc_unthrottle")) | ||
1291 | return; | ||
1292 | bp = port_Board(port); | ||
1293 | |||
1294 | spin_lock_irqsave(&riscom_lock, flags); | ||
1295 | port->MSVR |= MSVR_RTS; | ||
1296 | rc_out(bp, CD180_CAR, port_No(port)); | ||
1297 | if (I_IXOFF(tty)) { | ||
1298 | rc_wait_CCR(bp); | ||
1299 | rc_out(bp, CD180_CCR, CCR_SSCH1); | ||
1300 | rc_wait_CCR(bp); | ||
1301 | } | ||
1302 | rc_out(bp, CD180_MSVR, port->MSVR); | ||
1303 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1304 | } | ||
1305 | |||
1306 | static void rc_stop(struct tty_struct *tty) | ||
1307 | { | ||
1308 | struct riscom_port *port = tty->driver_data; | ||
1309 | struct riscom_board *bp; | ||
1310 | unsigned long flags; | ||
1311 | |||
1312 | if (rc_paranoia_check(port, tty->name, "rc_stop")) | ||
1313 | return; | ||
1314 | |||
1315 | bp = port_Board(port); | ||
1316 | |||
1317 | spin_lock_irqsave(&riscom_lock, flags); | ||
1318 | port->IER &= ~IER_TXRDY; | ||
1319 | rc_out(bp, CD180_CAR, port_No(port)); | ||
1320 | rc_out(bp, CD180_IER, port->IER); | ||
1321 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1322 | } | ||
1323 | |||
1324 | static void rc_start(struct tty_struct *tty) | ||
1325 | { | ||
1326 | struct riscom_port *port = tty->driver_data; | ||
1327 | struct riscom_board *bp; | ||
1328 | unsigned long flags; | ||
1329 | |||
1330 | if (rc_paranoia_check(port, tty->name, "rc_start")) | ||
1331 | return; | ||
1332 | |||
1333 | bp = port_Board(port); | ||
1334 | |||
1335 | spin_lock_irqsave(&riscom_lock, flags); | ||
1336 | |||
1337 | if (port->xmit_cnt && port->port.xmit_buf && !(port->IER & IER_TXRDY)) { | ||
1338 | port->IER |= IER_TXRDY; | ||
1339 | rc_out(bp, CD180_CAR, port_No(port)); | ||
1340 | rc_out(bp, CD180_IER, port->IER); | ||
1341 | } | ||
1342 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1343 | } | ||
1344 | |||
1345 | static void rc_hangup(struct tty_struct *tty) | ||
1346 | { | ||
1347 | struct riscom_port *port = tty->driver_data; | ||
1348 | |||
1349 | if (rc_paranoia_check(port, tty->name, "rc_hangup")) | ||
1350 | return; | ||
1351 | |||
1352 | tty_port_hangup(&port->port); | ||
1353 | } | ||
1354 | |||
1355 | static void rc_set_termios(struct tty_struct *tty, | ||
1356 | struct ktermios *old_termios) | ||
1357 | { | ||
1358 | struct riscom_port *port = tty->driver_data; | ||
1359 | unsigned long flags; | ||
1360 | |||
1361 | if (rc_paranoia_check(port, tty->name, "rc_set_termios")) | ||
1362 | return; | ||
1363 | |||
1364 | spin_lock_irqsave(&riscom_lock, flags); | ||
1365 | rc_change_speed(tty, port_Board(port), port); | ||
1366 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1367 | |||
1368 | if ((old_termios->c_cflag & CRTSCTS) && | ||
1369 | !(tty->termios->c_cflag & CRTSCTS)) { | ||
1370 | tty->hw_stopped = 0; | ||
1371 | rc_start(tty); | ||
1372 | } | ||
1373 | } | ||
1374 | |||
1375 | static const struct tty_operations riscom_ops = { | ||
1376 | .open = rc_open, | ||
1377 | .close = rc_close, | ||
1378 | .write = rc_write, | ||
1379 | .put_char = rc_put_char, | ||
1380 | .flush_chars = rc_flush_chars, | ||
1381 | .write_room = rc_write_room, | ||
1382 | .chars_in_buffer = rc_chars_in_buffer, | ||
1383 | .flush_buffer = rc_flush_buffer, | ||
1384 | .ioctl = rc_ioctl, | ||
1385 | .throttle = rc_throttle, | ||
1386 | .unthrottle = rc_unthrottle, | ||
1387 | .set_termios = rc_set_termios, | ||
1388 | .stop = rc_stop, | ||
1389 | .start = rc_start, | ||
1390 | .hangup = rc_hangup, | ||
1391 | .tiocmget = rc_tiocmget, | ||
1392 | .tiocmset = rc_tiocmset, | ||
1393 | .break_ctl = rc_send_break, | ||
1394 | }; | ||
1395 | |||
1396 | static const struct tty_port_operations riscom_port_ops = { | ||
1397 | .carrier_raised = carrier_raised, | ||
1398 | .dtr_rts = dtr_rts, | ||
1399 | .shutdown = rc_close_port, | ||
1400 | .activate = rc_activate_port, | ||
1401 | }; | ||
1402 | |||
1403 | |||
1404 | static int __init rc_init_drivers(void) | ||
1405 | { | ||
1406 | int error; | ||
1407 | int i; | ||
1408 | |||
1409 | riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT); | ||
1410 | if (!riscom_driver) | ||
1411 | return -ENOMEM; | ||
1412 | |||
1413 | riscom_driver->owner = THIS_MODULE; | ||
1414 | riscom_driver->name = "ttyL"; | ||
1415 | riscom_driver->major = RISCOM8_NORMAL_MAJOR; | ||
1416 | riscom_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
1417 | riscom_driver->subtype = SERIAL_TYPE_NORMAL; | ||
1418 | riscom_driver->init_termios = tty_std_termios; | ||
1419 | riscom_driver->init_termios.c_cflag = | ||
1420 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
1421 | riscom_driver->init_termios.c_ispeed = 9600; | ||
1422 | riscom_driver->init_termios.c_ospeed = 9600; | ||
1423 | riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; | ||
1424 | tty_set_operations(riscom_driver, &riscom_ops); | ||
1425 | error = tty_register_driver(riscom_driver); | ||
1426 | if (error != 0) { | ||
1427 | put_tty_driver(riscom_driver); | ||
1428 | printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, " | ||
1429 | "error = %d\n", error); | ||
1430 | return 1; | ||
1431 | } | ||
1432 | memset(rc_port, 0, sizeof(rc_port)); | ||
1433 | for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { | ||
1434 | tty_port_init(&rc_port[i].port); | ||
1435 | rc_port[i].port.ops = &riscom_port_ops; | ||
1436 | rc_port[i].magic = RISCOM8_MAGIC; | ||
1437 | } | ||
1438 | return 0; | ||
1439 | } | ||
1440 | |||
1441 | static void rc_release_drivers(void) | ||
1442 | { | ||
1443 | tty_unregister_driver(riscom_driver); | ||
1444 | put_tty_driver(riscom_driver); | ||
1445 | } | ||
1446 | |||
1447 | #ifndef MODULE | ||
1448 | /* | ||
1449 | * Called at boot time. | ||
1450 | * | ||
1451 | * You can specify IO base for up to RC_NBOARD cards, | ||
1452 | * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt. | ||
1453 | * Note that there will be no probing at default | ||
1454 | * addresses in this case. | ||
1455 | * | ||
1456 | */ | ||
1457 | static int __init riscom8_setup(char *str) | ||
1458 | { | ||
1459 | int ints[RC_NBOARD]; | ||
1460 | int i; | ||
1461 | |||
1462 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
1463 | |||
1464 | for (i = 0; i < RC_NBOARD; i++) { | ||
1465 | if (i < ints[0]) | ||
1466 | rc_board[i].base = ints[i+1]; | ||
1467 | else | ||
1468 | rc_board[i].base = 0; | ||
1469 | } | ||
1470 | return 1; | ||
1471 | } | ||
1472 | |||
1473 | __setup("riscom8=", riscom8_setup); | ||
1474 | #endif | ||
1475 | |||
1476 | static char banner[] __initdata = | ||
1477 | KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin " | ||
1478 | "1994-1996.\n"; | ||
1479 | static char no_boards_msg[] __initdata = | ||
1480 | KERN_INFO "rc: No RISCom/8 boards detected.\n"; | ||
1481 | |||
1482 | /* | ||
1483 | * This routine must be called by kernel at boot time | ||
1484 | */ | ||
1485 | static int __init riscom8_init(void) | ||
1486 | { | ||
1487 | int i; | ||
1488 | int found = 0; | ||
1489 | |||
1490 | printk(banner); | ||
1491 | |||
1492 | if (rc_init_drivers()) | ||
1493 | return -EIO; | ||
1494 | |||
1495 | for (i = 0; i < RC_NBOARD; i++) | ||
1496 | if (rc_board[i].base && !rc_probe(&rc_board[i])) | ||
1497 | found++; | ||
1498 | if (!found) { | ||
1499 | rc_release_drivers(); | ||
1500 | printk(no_boards_msg); | ||
1501 | return -EIO; | ||
1502 | } | ||
1503 | return 0; | ||
1504 | } | ||
1505 | |||
1506 | #ifdef MODULE | ||
1507 | static int iobase; | ||
1508 | static int iobase1; | ||
1509 | static int iobase2; | ||
1510 | static int iobase3; | ||
1511 | module_param(iobase, int, 0); | ||
1512 | module_param(iobase1, int, 0); | ||
1513 | module_param(iobase2, int, 0); | ||
1514 | module_param(iobase3, int, 0); | ||
1515 | |||
1516 | MODULE_LICENSE("GPL"); | ||
1517 | MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR); | ||
1518 | #endif /* MODULE */ | ||
1519 | |||
1520 | /* | ||
1521 | * You can setup up to 4 boards (current value of RC_NBOARD) | ||
1522 | * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter. | ||
1523 | * | ||
1524 | */ | ||
1525 | static int __init riscom8_init_module(void) | ||
1526 | { | ||
1527 | #ifdef MODULE | ||
1528 | int i; | ||
1529 | |||
1530 | if (iobase || iobase1 || iobase2 || iobase3) { | ||
1531 | for (i = 0; i < RC_NBOARD; i++) | ||
1532 | rc_board[i].base = 0; | ||
1533 | } | ||
1534 | |||
1535 | if (iobase) | ||
1536 | rc_board[0].base = iobase; | ||
1537 | if (iobase1) | ||
1538 | rc_board[1].base = iobase1; | ||
1539 | if (iobase2) | ||
1540 | rc_board[2].base = iobase2; | ||
1541 | if (iobase3) | ||
1542 | rc_board[3].base = iobase3; | ||
1543 | #endif /* MODULE */ | ||
1544 | |||
1545 | return riscom8_init(); | ||
1546 | } | ||
1547 | |||
1548 | static void __exit riscom8_exit_module(void) | ||
1549 | { | ||
1550 | int i; | ||
1551 | |||
1552 | rc_release_drivers(); | ||
1553 | for (i = 0; i < RC_NBOARD; i++) | ||
1554 | if (rc_board[i].flags & RC_BOARD_PRESENT) | ||
1555 | rc_release_io_range(&rc_board[i]); | ||
1556 | |||
1557 | } | ||
1558 | |||
1559 | module_init(riscom8_init_module); | ||
1560 | module_exit(riscom8_exit_module); | ||
diff --git a/drivers/char/riscom8.h b/drivers/char/riscom8.h deleted file mode 100644 index c9876b3f9714..000000000000 --- a/drivers/char/riscom8.h +++ /dev/null | |||
@@ -1,91 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/char/riscom8.h -- RISCom/8 multiport serial driver. | ||
3 | * | ||
4 | * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) | ||
5 | * | ||
6 | * This code is loosely based on the Linux serial driver, written by | ||
7 | * Linus Torvalds, Theodore T'so and others. The RISCom/8 card | ||
8 | * programming info was obtained from various drivers for other OSes | ||
9 | * (FreeBSD, ISC, etc), but no source code from those drivers were | ||
10 | * directly included in this driver. | ||
11 | * | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __LINUX_RISCOM8_H | ||
29 | #define __LINUX_RISCOM8_H | ||
30 | |||
31 | #include <linux/serial.h> | ||
32 | |||
33 | #ifdef __KERNEL__ | ||
34 | |||
35 | #define RC_NBOARD 4 | ||
36 | /* NOTE: RISCom decoder recognizes 16 addresses... */ | ||
37 | #define RC_NPORT 8 | ||
38 | #define RC_BOARD(line) (((line) >> 3) & 0x07) | ||
39 | #define RC_PORT(line) ((line) & (RC_NPORT - 1)) | ||
40 | |||
41 | /* Ticks per sec. Used for setting receiver timeout and break length */ | ||
42 | #define RISCOM_TPS 4000 | ||
43 | |||
44 | /* Yeah, after heavy testing I decided it must be 6. | ||
45 | * Sure, You can change it if needed. | ||
46 | */ | ||
47 | #define RISCOM_RXFIFO 6 /* Max. receiver FIFO size (1-8) */ | ||
48 | |||
49 | #define RISCOM8_MAGIC 0x0907 | ||
50 | |||
51 | #define RC_IOBASE1 0x220 | ||
52 | #define RC_IOBASE2 0x240 | ||
53 | #define RC_IOBASE3 0x250 | ||
54 | #define RC_IOBASE4 0x260 | ||
55 | |||
56 | struct riscom_board { | ||
57 | unsigned long flags; | ||
58 | unsigned short base; | ||
59 | unsigned char irq; | ||
60 | signed char count; | ||
61 | unsigned char DTR; | ||
62 | }; | ||
63 | |||
64 | #define RC_BOARD_PRESENT 0x00000001 | ||
65 | #define RC_BOARD_ACTIVE 0x00000002 | ||
66 | |||
67 | struct riscom_port { | ||
68 | int magic; | ||
69 | struct tty_port port; | ||
70 | int baud_base; | ||
71 | int timeout; | ||
72 | int custom_divisor; | ||
73 | int xmit_head; | ||
74 | int xmit_tail; | ||
75 | int xmit_cnt; | ||
76 | short wakeup_chars; | ||
77 | short break_length; | ||
78 | unsigned char mark_mask; | ||
79 | unsigned char IER; | ||
80 | unsigned char MSVR; | ||
81 | unsigned char COR2; | ||
82 | #ifdef RC_REPORT_OVERRUN | ||
83 | unsigned long overrun; | ||
84 | #endif | ||
85 | #ifdef RC_REPORT_FIFO | ||
86 | unsigned long hits[10]; | ||
87 | #endif | ||
88 | }; | ||
89 | |||
90 | #endif /* __KERNEL__ */ | ||
91 | #endif /* __LINUX_RISCOM8_H */ | ||
diff --git a/drivers/char/riscom8_reg.h b/drivers/char/riscom8_reg.h deleted file mode 100644 index a32475ed0d18..000000000000 --- a/drivers/char/riscom8_reg.h +++ /dev/null | |||
@@ -1,254 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/char/riscom8_reg.h -- RISCom/8 multiport serial driver. | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * Definitions for RISCom/8 Async Mux card by SDL Communications, Inc. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Address mapping between Cirrus Logic CD180 chip internal registers | ||
11 | * and ISA port addresses: | ||
12 | * | ||
13 | * CL-CD180 A6 A5 A4 A3 A2 A1 A0 | ||
14 | * ISA A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 | ||
15 | */ | ||
16 | #define RC_TO_ISA(r) ((((r)&0x07)<<1) | (((r)&~0x07)<<7)) | ||
17 | |||
18 | |||
19 | /* RISCom/8 On-Board Registers (assuming address translation) */ | ||
20 | |||
21 | #define RC_RI 0x100 /* Ring Indicator Register (R/O) */ | ||
22 | #define RC_DTR 0x100 /* DTR Register (W/O) */ | ||
23 | #define RC_BSR 0x101 /* Board Status Register (R/O) */ | ||
24 | #define RC_CTOUT 0x101 /* Clear Timeout (W/O) */ | ||
25 | |||
26 | |||
27 | /* Board Status Register */ | ||
28 | |||
29 | #define RC_BSR_TOUT 0x08 /* Hardware Timeout */ | ||
30 | #define RC_BSR_RINT 0x04 /* Receiver Interrupt */ | ||
31 | #define RC_BSR_TINT 0x02 /* Transmitter Interrupt */ | ||
32 | #define RC_BSR_MINT 0x01 /* Modem Ctl Interrupt */ | ||
33 | |||
34 | |||
35 | /* On-board oscillator frequency (in Hz) */ | ||
36 | #define RC_OSCFREQ 9830400 | ||
37 | |||
38 | /* Values of choice for Interrupt ACKs */ | ||
39 | #define RC_ACK_MINT 0x81 /* goes to PILR1 */ | ||
40 | #define RC_ACK_RINT 0x82 /* goes to PILR3 */ | ||
41 | #define RC_ACK_TINT 0x84 /* goes to PILR2 */ | ||
42 | |||
43 | /* Chip ID (sorry, only one chip now) */ | ||
44 | #define RC_ID 0x10 | ||
45 | |||
46 | /* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */ | ||
47 | |||
48 | #define CD180_NCH 8 /* Total number of channels */ | ||
49 | #define CD180_TPC 16 /* Ticks per character */ | ||
50 | #define CD180_NFIFO 8 /* TX FIFO size */ | ||
51 | |||
52 | |||
53 | /* Global registers */ | ||
54 | |||
55 | #define CD180_GIVR 0x40 /* Global Interrupt Vector Register */ | ||
56 | #define CD180_GICR 0x41 /* Global Interrupting Channel Register */ | ||
57 | #define CD180_PILR1 0x61 /* Priority Interrupt Level Register 1 */ | ||
58 | #define CD180_PILR2 0x62 /* Priority Interrupt Level Register 2 */ | ||
59 | #define CD180_PILR3 0x63 /* Priority Interrupt Level Register 3 */ | ||
60 | #define CD180_CAR 0x64 /* Channel Access Register */ | ||
61 | #define CD180_GFRCR 0x6b /* Global Firmware Revision Code Register */ | ||
62 | #define CD180_PPRH 0x70 /* Prescaler Period Register High */ | ||
63 | #define CD180_PPRL 0x71 /* Prescaler Period Register Low */ | ||
64 | #define CD180_RDR 0x78 /* Receiver Data Register */ | ||
65 | #define CD180_RCSR 0x7a /* Receiver Character Status Register */ | ||
66 | #define CD180_TDR 0x7b /* Transmit Data Register */ | ||
67 | #define CD180_EOIR 0x7f /* End of Interrupt Register */ | ||
68 | |||
69 | |||
70 | /* Channel Registers */ | ||
71 | |||
72 | #define CD180_CCR 0x01 /* Channel Command Register */ | ||
73 | #define CD180_IER 0x02 /* Interrupt Enable Register */ | ||
74 | #define CD180_COR1 0x03 /* Channel Option Register 1 */ | ||
75 | #define CD180_COR2 0x04 /* Channel Option Register 2 */ | ||
76 | #define CD180_COR3 0x05 /* Channel Option Register 3 */ | ||
77 | #define CD180_CCSR 0x06 /* Channel Control Status Register */ | ||
78 | #define CD180_RDCR 0x07 /* Receive Data Count Register */ | ||
79 | #define CD180_SCHR1 0x09 /* Special Character Register 1 */ | ||
80 | #define CD180_SCHR2 0x0a /* Special Character Register 2 */ | ||
81 | #define CD180_SCHR3 0x0b /* Special Character Register 3 */ | ||
82 | #define CD180_SCHR4 0x0c /* Special Character Register 4 */ | ||
83 | #define CD180_MCOR1 0x10 /* Modem Change Option 1 Register */ | ||
84 | #define CD180_MCOR2 0x11 /* Modem Change Option 2 Register */ | ||
85 | #define CD180_MCR 0x12 /* Modem Change Register */ | ||
86 | #define CD180_RTPR 0x18 /* Receive Timeout Period Register */ | ||
87 | #define CD180_MSVR 0x28 /* Modem Signal Value Register */ | ||
88 | #define CD180_RBPRH 0x31 /* Receive Baud Rate Period Register High */ | ||
89 | #define CD180_RBPRL 0x32 /* Receive Baud Rate Period Register Low */ | ||
90 | #define CD180_TBPRH 0x39 /* Transmit Baud Rate Period Register High */ | ||
91 | #define CD180_TBPRL 0x3a /* Transmit Baud Rate Period Register Low */ | ||
92 | |||
93 | |||
94 | /* Global Interrupt Vector Register (R/W) */ | ||
95 | |||
96 | #define GIVR_ITMASK 0x07 /* Interrupt type mask */ | ||
97 | #define GIVR_IT_MODEM 0x01 /* Modem Signal Change Interrupt */ | ||
98 | #define GIVR_IT_TX 0x02 /* Transmit Data Interrupt */ | ||
99 | #define GIVR_IT_RCV 0x03 /* Receive Good Data Interrupt */ | ||
100 | #define GIVR_IT_REXC 0x07 /* Receive Exception Interrupt */ | ||
101 | |||
102 | |||
103 | /* Global Interrupt Channel Register (R/W) */ | ||
104 | |||
105 | #define GICR_CHAN 0x1c /* Channel Number Mask */ | ||
106 | #define GICR_CHAN_OFF 2 /* Channel Number Offset */ | ||
107 | |||
108 | |||
109 | /* Channel Address Register (R/W) */ | ||
110 | |||
111 | #define CAR_CHAN 0x07 /* Channel Number Mask */ | ||
112 | #define CAR_A7 0x08 /* A7 Address Extension (unused) */ | ||
113 | |||
114 | |||
115 | /* Receive Character Status Register (R/O) */ | ||
116 | |||
117 | #define RCSR_TOUT 0x80 /* Rx Timeout */ | ||
118 | #define RCSR_SCDET 0x70 /* Special Character Detected Mask */ | ||
119 | #define RCSR_NO_SC 0x00 /* No Special Characters Detected */ | ||
120 | #define RCSR_SC_1 0x10 /* Special Char 1 (or 1 & 3) Detected */ | ||
121 | #define RCSR_SC_2 0x20 /* Special Char 2 (or 2 & 4) Detected */ | ||
122 | #define RCSR_SC_3 0x30 /* Special Char 3 Detected */ | ||
123 | #define RCSR_SC_4 0x40 /* Special Char 4 Detected */ | ||
124 | #define RCSR_BREAK 0x08 /* Break has been detected */ | ||
125 | #define RCSR_PE 0x04 /* Parity Error */ | ||
126 | #define RCSR_FE 0x02 /* Frame Error */ | ||
127 | #define RCSR_OE 0x01 /* Overrun Error */ | ||
128 | |||
129 | |||
130 | /* Channel Command Register (R/W) (commands in groups can be OR-ed) */ | ||
131 | |||
132 | #define CCR_HARDRESET 0x81 /* Reset the chip */ | ||
133 | |||
134 | #define CCR_SOFTRESET 0x80 /* Soft Channel Reset */ | ||
135 | |||
136 | #define CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed */ | ||
137 | #define CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed */ | ||
138 | #define CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed */ | ||
139 | |||
140 | #define CCR_SSCH1 0x21 /* Send Special Character 1 */ | ||
141 | |||
142 | #define CCR_SSCH2 0x22 /* Send Special Character 2 */ | ||
143 | |||
144 | #define CCR_SSCH3 0x23 /* Send Special Character 3 */ | ||
145 | |||
146 | #define CCR_SSCH4 0x24 /* Send Special Character 4 */ | ||
147 | |||
148 | #define CCR_TXEN 0x18 /* Enable Transmitter */ | ||
149 | #define CCR_RXEN 0x12 /* Enable Receiver */ | ||
150 | |||
151 | #define CCR_TXDIS 0x14 /* Disable Transmitter */ | ||
152 | #define CCR_RXDIS 0x11 /* Disable Receiver */ | ||
153 | |||
154 | |||
155 | /* Interrupt Enable Register (R/W) */ | ||
156 | |||
157 | #define IER_DSR 0x80 /* Enable interrupt on DSR change */ | ||
158 | #define IER_CD 0x40 /* Enable interrupt on CD change */ | ||
159 | #define IER_CTS 0x20 /* Enable interrupt on CTS change */ | ||
160 | #define IER_RXD 0x10 /* Enable interrupt on Receive Data */ | ||
161 | #define IER_RXSC 0x08 /* Enable interrupt on Receive Spec. Char */ | ||
162 | #define IER_TXRDY 0x04 /* Enable interrupt on TX FIFO empty */ | ||
163 | #define IER_TXEMPTY 0x02 /* Enable interrupt on TX completely empty */ | ||
164 | #define IER_RET 0x01 /* Enable interrupt on RX Exc. Timeout */ | ||
165 | |||
166 | |||
167 | /* Channel Option Register 1 (R/W) */ | ||
168 | |||
169 | #define COR1_ODDP 0x80 /* Odd Parity */ | ||
170 | #define COR1_PARMODE 0x60 /* Parity Mode mask */ | ||
171 | #define COR1_NOPAR 0x00 /* No Parity */ | ||
172 | #define COR1_FORCEPAR 0x20 /* Force Parity */ | ||
173 | #define COR1_NORMPAR 0x40 /* Normal Parity */ | ||
174 | #define COR1_IGNORE 0x10 /* Ignore Parity on RX */ | ||
175 | #define COR1_STOPBITS 0x0c /* Number of Stop Bits */ | ||
176 | #define COR1_1SB 0x00 /* 1 Stop Bit */ | ||
177 | #define COR1_15SB 0x04 /* 1.5 Stop Bits */ | ||
178 | #define COR1_2SB 0x08 /* 2 Stop Bits */ | ||
179 | #define COR1_CHARLEN 0x03 /* Character Length */ | ||
180 | #define COR1_5BITS 0x00 /* 5 bits */ | ||
181 | #define COR1_6BITS 0x01 /* 6 bits */ | ||
182 | #define COR1_7BITS 0x02 /* 7 bits */ | ||
183 | #define COR1_8BITS 0x03 /* 8 bits */ | ||
184 | |||
185 | |||
186 | /* Channel Option Register 2 (R/W) */ | ||
187 | |||
188 | #define COR2_IXM 0x80 /* Implied XON mode */ | ||
189 | #define COR2_TXIBE 0x40 /* Enable In-Band (XON/XOFF) Flow Control */ | ||
190 | #define COR2_ETC 0x20 /* Embedded Tx Commands Enable */ | ||
191 | #define COR2_LLM 0x10 /* Local Loopback Mode */ | ||
192 | #define COR2_RLM 0x08 /* Remote Loopback Mode */ | ||
193 | #define COR2_RTSAO 0x04 /* RTS Automatic Output Enable */ | ||
194 | #define COR2_CTSAE 0x02 /* CTS Automatic Enable */ | ||
195 | #define COR2_DSRAE 0x01 /* DSR Automatic Enable */ | ||
196 | |||
197 | |||
198 | /* Channel Option Register 3 (R/W) */ | ||
199 | |||
200 | #define COR3_XONCH 0x80 /* XON is a pair of characters (1 & 3) */ | ||
201 | #define COR3_XOFFCH 0x40 /* XOFF is a pair of characters (2 & 4) */ | ||
202 | #define COR3_FCT 0x20 /* Flow-Control Transparency Mode */ | ||
203 | #define COR3_SCDE 0x10 /* Special Character Detection Enable */ | ||
204 | #define COR3_RXTH 0x0f /* RX FIFO Threshold value (1-8) */ | ||
205 | |||
206 | |||
207 | /* Channel Control Status Register (R/O) */ | ||
208 | |||
209 | #define CCSR_RXEN 0x80 /* Receiver Enabled */ | ||
210 | #define CCSR_RXFLOFF 0x40 /* Receive Flow Off (XOFF was sent) */ | ||
211 | #define CCSR_RXFLON 0x20 /* Receive Flow On (XON was sent) */ | ||
212 | #define CCSR_TXEN 0x08 /* Transmitter Enabled */ | ||
213 | #define CCSR_TXFLOFF 0x04 /* Transmit Flow Off (got XOFF) */ | ||
214 | #define CCSR_TXFLON 0x02 /* Transmit Flow On (got XON) */ | ||
215 | |||
216 | |||
217 | /* Modem Change Option Register 1 (R/W) */ | ||
218 | |||
219 | #define MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR */ | ||
220 | #define MCOR1_CDZD 0x40 /* Detect 0->1 transition of CD */ | ||
221 | #define MCOR1_CTSZD 0x20 /* Detect 0->1 transition of CTS */ | ||
222 | #define MCOR1_DTRTH 0x0f /* Auto DTR flow control Threshold (1-8) */ | ||
223 | #define MCOR1_NODTRFC 0x0 /* Automatic DTR flow control disabled */ | ||
224 | |||
225 | |||
226 | /* Modem Change Option Register 2 (R/W) */ | ||
227 | |||
228 | #define MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR */ | ||
229 | #define MCOR2_CDOD 0x40 /* Detect 1->0 transition of CD */ | ||
230 | #define MCOR2_CTSOD 0x20 /* Detect 1->0 transition of CTS */ | ||
231 | |||
232 | |||
233 | /* Modem Change Register (R/W) */ | ||
234 | |||
235 | #define MCR_DSRCHG 0x80 /* DSR Changed */ | ||
236 | #define MCR_CDCHG 0x40 /* CD Changed */ | ||
237 | #define MCR_CTSCHG 0x20 /* CTS Changed */ | ||
238 | |||
239 | |||
240 | /* Modem Signal Value Register (R/W) */ | ||
241 | |||
242 | #define MSVR_DSR 0x80 /* Current state of DSR input */ | ||
243 | #define MSVR_CD 0x40 /* Current state of CD input */ | ||
244 | #define MSVR_CTS 0x20 /* Current state of CTS input */ | ||
245 | #define MSVR_DTR 0x02 /* Current state of DTR output */ | ||
246 | #define MSVR_RTS 0x01 /* Current state of RTS output */ | ||
247 | |||
248 | |||
249 | /* Escape characters */ | ||
250 | |||
251 | #define CD180_C_ESC 0x00 /* Escape character */ | ||
252 | #define CD180_C_SBRK 0x81 /* Start sending BREAK */ | ||
253 | #define CD180_C_DELAY 0x82 /* Delay output */ | ||
254 | #define CD180_C_EBRK 0x83 /* Stop sending BREAK */ | ||
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c deleted file mode 100644 index 674af6933978..000000000000 --- a/drivers/char/serial167.c +++ /dev/null | |||
@@ -1,2489 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/char/serial167.c | ||
3 | * | ||
4 | * Driver for MVME166/7 board serial ports, which are via a CD2401. | ||
5 | * Based very much on cyclades.c. | ||
6 | * | ||
7 | * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk] | ||
8 | * | ||
9 | * ============================================================== | ||
10 | * | ||
11 | * static char rcsid[] = | ||
12 | * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $"; | ||
13 | * | ||
14 | * linux/kernel/cyclades.c | ||
15 | * | ||
16 | * Maintained by Marcio Saito (cyclades@netcom.com) and | ||
17 | * Randolph Bentson (bentson@grieg.seaslug.org) | ||
18 | * | ||
19 | * Much of the design and some of the code came from serial.c | ||
20 | * which was copyright (C) 1991, 1992 Linus Torvalds. It was | ||
21 | * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, | ||
22 | * and then fixed as suggested by Michael K. Johnson 12/12/92. | ||
23 | * | ||
24 | * This version does not support shared irq's. | ||
25 | * | ||
26 | * $Log: cyclades.c,v $ | ||
27 | * Revision 1.36.1.4 1995/03/29 06:14:14 bentson | ||
28 | * disambiguate between Cyclom-16Y and Cyclom-32Ye; | ||
29 | * | ||
30 | * Changes: | ||
31 | * | ||
32 | * 200 lines of changes record removed - RGH 11-10-95, starting work on | ||
33 | * converting this to drive serial ports on mvme166 (cd2401). | ||
34 | * | ||
35 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25 | ||
36 | * - get rid of verify_area | ||
37 | * - use get_user to access memory from userspace in set_threshold, | ||
38 | * set_default_threshold and set_timeout | ||
39 | * - don't use the panic function in serial167_init | ||
40 | * - do resource release on failure on serial167_init | ||
41 | * - include missing restore_flags in mvme167_serial_console_setup | ||
42 | * | ||
43 | * Kars de Jong <jongk@linux-m68k.org> - 2004/09/06 | ||
44 | * - replace bottom half handler with task queue handler | ||
45 | */ | ||
46 | |||
47 | #include <linux/errno.h> | ||
48 | #include <linux/signal.h> | ||
49 | #include <linux/sched.h> | ||
50 | #include <linux/timer.h> | ||
51 | #include <linux/tty.h> | ||
52 | #include <linux/interrupt.h> | ||
53 | #include <linux/serial.h> | ||
54 | #include <linux/serialP.h> | ||
55 | #include <linux/string.h> | ||
56 | #include <linux/fcntl.h> | ||
57 | #include <linux/ptrace.h> | ||
58 | #include <linux/serial167.h> | ||
59 | #include <linux/delay.h> | ||
60 | #include <linux/major.h> | ||
61 | #include <linux/mm.h> | ||
62 | #include <linux/console.h> | ||
63 | #include <linux/module.h> | ||
64 | #include <linux/bitops.h> | ||
65 | #include <linux/tty_flip.h> | ||
66 | #include <linux/gfp.h> | ||
67 | |||
68 | #include <asm/system.h> | ||
69 | #include <asm/io.h> | ||
70 | #include <asm/mvme16xhw.h> | ||
71 | #include <asm/bootinfo.h> | ||
72 | #include <asm/setup.h> | ||
73 | |||
74 | #include <linux/types.h> | ||
75 | #include <linux/kernel.h> | ||
76 | |||
77 | #include <asm/uaccess.h> | ||
78 | #include <linux/init.h> | ||
79 | |||
80 | #define SERIAL_PARANOIA_CHECK | ||
81 | #undef SERIAL_DEBUG_OPEN | ||
82 | #undef SERIAL_DEBUG_THROTTLE | ||
83 | #undef SERIAL_DEBUG_OTHER | ||
84 | #undef SERIAL_DEBUG_IO | ||
85 | #undef SERIAL_DEBUG_COUNT | ||
86 | #undef SERIAL_DEBUG_DTR | ||
87 | #undef CYCLOM_16Y_HACK | ||
88 | #define CYCLOM_ENABLE_MONITORING | ||
89 | |||
90 | #define WAKEUP_CHARS 256 | ||
91 | |||
92 | #define STD_COM_FLAGS (0) | ||
93 | |||
94 | static struct tty_driver *cy_serial_driver; | ||
95 | extern int serial_console; | ||
96 | static struct cyclades_port *serial_console_info = NULL; | ||
97 | static unsigned int serial_console_cflag = 0; | ||
98 | u_char initial_console_speed; | ||
99 | |||
100 | /* Base address of cd2401 chip on mvme166/7 */ | ||
101 | |||
102 | #define BASE_ADDR (0xfff45000) | ||
103 | #define pcc2chip ((volatile u_char *)0xfff42000) | ||
104 | #define PccSCCMICR 0x1d | ||
105 | #define PccSCCTICR 0x1e | ||
106 | #define PccSCCRICR 0x1f | ||
107 | #define PccTPIACKR 0x25 | ||
108 | #define PccRPIACKR 0x27 | ||
109 | #define PccIMLR 0x3f | ||
110 | |||
111 | /* This is the per-port data structure */ | ||
112 | struct cyclades_port cy_port[] = { | ||
113 | /* CARD# */ | ||
114 | {-1}, /* ttyS0 */ | ||
115 | {-1}, /* ttyS1 */ | ||
116 | {-1}, /* ttyS2 */ | ||
117 | {-1}, /* ttyS3 */ | ||
118 | }; | ||
119 | |||
120 | #define NR_PORTS ARRAY_SIZE(cy_port) | ||
121 | |||
122 | /* | ||
123 | * This is used to look up the divisor speeds and the timeouts | ||
124 | * We're normally limited to 15 distinct baud rates. The extra | ||
125 | * are accessed via settings in info->flags. | ||
126 | * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | ||
127 | * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, | ||
128 | * HI VHI | ||
129 | */ | ||
130 | static int baud_table[] = { | ||
131 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, | ||
132 | 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000, | ||
133 | 0 | ||
134 | }; | ||
135 | |||
136 | #if 0 | ||
137 | static char baud_co[] = { /* 25 MHz clock option table */ | ||
138 | /* value => 00 01 02 03 04 */ | ||
139 | /* divide by 8 32 128 512 2048 */ | ||
140 | 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, | ||
141 | 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
142 | }; | ||
143 | |||
144 | static char baud_bpr[] = { /* 25 MHz baud rate period table */ | ||
145 | 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, | ||
146 | 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15 | ||
147 | }; | ||
148 | #endif | ||
149 | |||
150 | /* I think 166 brd clocks 2401 at 20MHz.... */ | ||
151 | |||
152 | /* These values are written directly to tcor, and >> 5 for writing to rcor */ | ||
153 | static u_char baud_co[] = { /* 20 MHz clock option table */ | ||
154 | 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40, | ||
155 | 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
156 | }; | ||
157 | |||
158 | /* These values written directly to tbpr/rbpr */ | ||
159 | static u_char baud_bpr[] = { /* 20 MHz baud rate period table */ | ||
160 | 0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81, | ||
161 | 0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10 | ||
162 | }; | ||
163 | |||
164 | static u_char baud_cor4[] = { /* receive threshold */ | ||
165 | 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, | ||
166 | 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07 | ||
167 | }; | ||
168 | |||
169 | static void shutdown(struct cyclades_port *); | ||
170 | static int startup(struct cyclades_port *); | ||
171 | static void cy_throttle(struct tty_struct *); | ||
172 | static void cy_unthrottle(struct tty_struct *); | ||
173 | static void config_setup(struct cyclades_port *); | ||
174 | #ifdef CYCLOM_SHOW_STATUS | ||
175 | static void show_status(int); | ||
176 | #endif | ||
177 | |||
178 | /* | ||
179 | * I have my own version of udelay(), as it is needed when initialising | ||
180 | * the chip, before the delay loop has been calibrated. Should probably | ||
181 | * reference one of the vmechip2 or pccchip2 counter for an accurate | ||
182 | * delay, but this wild guess will do for now. | ||
183 | */ | ||
184 | |||
185 | void my_udelay(long us) | ||
186 | { | ||
187 | u_char x; | ||
188 | volatile u_char *p = &x; | ||
189 | int i; | ||
190 | |||
191 | while (us--) | ||
192 | for (i = 100; i; i--) | ||
193 | x |= *p; | ||
194 | } | ||
195 | |||
196 | static inline int serial_paranoia_check(struct cyclades_port *info, char *name, | ||
197 | const char *routine) | ||
198 | { | ||
199 | #ifdef SERIAL_PARANOIA_CHECK | ||
200 | if (!info) { | ||
201 | printk("Warning: null cyclades_port for (%s) in %s\n", name, | ||
202 | routine); | ||
203 | return 1; | ||
204 | } | ||
205 | |||
206 | if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) { | ||
207 | printk("Warning: cyclades_port out of range for (%s) in %s\n", | ||
208 | name, routine); | ||
209 | return 1; | ||
210 | } | ||
211 | |||
212 | if (info->magic != CYCLADES_MAGIC) { | ||
213 | printk("Warning: bad magic number for serial struct (%s) in " | ||
214 | "%s\n", name, routine); | ||
215 | return 1; | ||
216 | } | ||
217 | #endif | ||
218 | return 0; | ||
219 | } /* serial_paranoia_check */ | ||
220 | |||
221 | #if 0 | ||
222 | /* The following diagnostic routines allow the driver to spew | ||
223 | information on the screen, even (especially!) during interrupts. | ||
224 | */ | ||
225 | void SP(char *data) | ||
226 | { | ||
227 | unsigned long flags; | ||
228 | local_irq_save(flags); | ||
229 | printk(KERN_EMERG "%s", data); | ||
230 | local_irq_restore(flags); | ||
231 | } | ||
232 | |||
233 | char scrn[2]; | ||
234 | void CP(char data) | ||
235 | { | ||
236 | unsigned long flags; | ||
237 | local_irq_save(flags); | ||
238 | scrn[0] = data; | ||
239 | printk(KERN_EMERG "%c", scrn); | ||
240 | local_irq_restore(flags); | ||
241 | } /* CP */ | ||
242 | |||
243 | void CP1(int data) | ||
244 | { | ||
245 | (data < 10) ? CP(data + '0') : CP(data + 'A' - 10); | ||
246 | } /* CP1 */ | ||
247 | void CP2(int data) | ||
248 | { | ||
249 | CP1((data >> 4) & 0x0f); | ||
250 | CP1(data & 0x0f); | ||
251 | } /* CP2 */ | ||
252 | void CP4(int data) | ||
253 | { | ||
254 | CP2((data >> 8) & 0xff); | ||
255 | CP2(data & 0xff); | ||
256 | } /* CP4 */ | ||
257 | void CP8(long data) | ||
258 | { | ||
259 | CP4((data >> 16) & 0xffff); | ||
260 | CP4(data & 0xffff); | ||
261 | } /* CP8 */ | ||
262 | #endif | ||
263 | |||
264 | /* This routine waits up to 1000 micro-seconds for the previous | ||
265 | command to the Cirrus chip to complete and then issues the | ||
266 | new command. An error is returned if the previous command | ||
267 | didn't finish within the time limit. | ||
268 | */ | ||
269 | u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd) | ||
270 | { | ||
271 | unsigned long flags; | ||
272 | volatile int i; | ||
273 | |||
274 | local_irq_save(flags); | ||
275 | /* Check to see that the previous command has completed */ | ||
276 | for (i = 0; i < 100; i++) { | ||
277 | if (base_addr[CyCCR] == 0) { | ||
278 | break; | ||
279 | } | ||
280 | my_udelay(10L); | ||
281 | } | ||
282 | /* if the CCR never cleared, the previous command | ||
283 | didn't finish within the "reasonable time" */ | ||
284 | if (i == 10) { | ||
285 | local_irq_restore(flags); | ||
286 | return (-1); | ||
287 | } | ||
288 | |||
289 | /* Issue the new command */ | ||
290 | base_addr[CyCCR] = cmd; | ||
291 | local_irq_restore(flags); | ||
292 | return (0); | ||
293 | } /* write_cy_cmd */ | ||
294 | |||
295 | /* cy_start and cy_stop provide software output flow control as a | ||
296 | function of XON/XOFF, software CTS, and other such stuff. */ | ||
297 | |||
298 | static void cy_stop(struct tty_struct *tty) | ||
299 | { | ||
300 | struct cyclades_port *info = tty->driver_data; | ||
301 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | ||
302 | int channel; | ||
303 | unsigned long flags; | ||
304 | |||
305 | #ifdef SERIAL_DEBUG_OTHER | ||
306 | printk("cy_stop %s\n", tty->name); /* */ | ||
307 | #endif | ||
308 | |||
309 | if (serial_paranoia_check(info, tty->name, "cy_stop")) | ||
310 | return; | ||
311 | |||
312 | channel = info->line; | ||
313 | |||
314 | local_irq_save(flags); | ||
315 | base_addr[CyCAR] = (u_char) (channel); /* index channel */ | ||
316 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
317 | local_irq_restore(flags); | ||
318 | } /* cy_stop */ | ||
319 | |||
320 | static void cy_start(struct tty_struct *tty) | ||
321 | { | ||
322 | struct cyclades_port *info = tty->driver_data; | ||
323 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | ||
324 | int channel; | ||
325 | unsigned long flags; | ||
326 | |||
327 | #ifdef SERIAL_DEBUG_OTHER | ||
328 | printk("cy_start %s\n", tty->name); /* */ | ||
329 | #endif | ||
330 | |||
331 | if (serial_paranoia_check(info, tty->name, "cy_start")) | ||
332 | return; | ||
333 | |||
334 | channel = info->line; | ||
335 | |||
336 | local_irq_save(flags); | ||
337 | base_addr[CyCAR] = (u_char) (channel); | ||
338 | base_addr[CyIER] |= CyTxMpty; | ||
339 | local_irq_restore(flags); | ||
340 | } /* cy_start */ | ||
341 | |||
342 | /* The real interrupt service routines are called | ||
343 | whenever the card wants its hand held--chars | ||
344 | received, out buffer empty, modem change, etc. | ||
345 | */ | ||
346 | static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id) | ||
347 | { | ||
348 | struct tty_struct *tty; | ||
349 | struct cyclades_port *info; | ||
350 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | ||
351 | unsigned char err, rfoc; | ||
352 | int channel; | ||
353 | char data; | ||
354 | |||
355 | /* determine the channel and change to that context */ | ||
356 | channel = (u_short) (base_addr[CyLICR] >> 2); | ||
357 | info = &cy_port[channel]; | ||
358 | info->last_active = jiffies; | ||
359 | |||
360 | if ((err = base_addr[CyRISR]) & CyTIMEOUT) { | ||
361 | /* This is a receive timeout interrupt, ignore it */ | ||
362 | base_addr[CyREOIR] = CyNOTRANS; | ||
363 | return IRQ_HANDLED; | ||
364 | } | ||
365 | |||
366 | /* Read a byte of data if there is any - assume the error | ||
367 | * is associated with this character */ | ||
368 | |||
369 | if ((rfoc = base_addr[CyRFOC]) != 0) | ||
370 | data = base_addr[CyRDR]; | ||
371 | else | ||
372 | data = 0; | ||
373 | |||
374 | /* if there is nowhere to put the data, discard it */ | ||
375 | if (info->tty == 0) { | ||
376 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; | ||
377 | return IRQ_HANDLED; | ||
378 | } else { /* there is an open port for this data */ | ||
379 | tty = info->tty; | ||
380 | if (err & info->ignore_status_mask) { | ||
381 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; | ||
382 | return IRQ_HANDLED; | ||
383 | } | ||
384 | if (tty_buffer_request_room(tty, 1) != 0) { | ||
385 | if (err & info->read_status_mask) { | ||
386 | if (err & CyBREAK) { | ||
387 | tty_insert_flip_char(tty, data, | ||
388 | TTY_BREAK); | ||
389 | if (info->flags & ASYNC_SAK) { | ||
390 | do_SAK(tty); | ||
391 | } | ||
392 | } else if (err & CyFRAME) { | ||
393 | tty_insert_flip_char(tty, data, | ||
394 | TTY_FRAME); | ||
395 | } else if (err & CyPARITY) { | ||
396 | tty_insert_flip_char(tty, data, | ||
397 | TTY_PARITY); | ||
398 | } else if (err & CyOVERRUN) { | ||
399 | tty_insert_flip_char(tty, 0, | ||
400 | TTY_OVERRUN); | ||
401 | /* | ||
402 | If the flip buffer itself is | ||
403 | overflowing, we still lose | ||
404 | the next incoming character. | ||
405 | */ | ||
406 | if (tty_buffer_request_room(tty, 1) != | ||
407 | 0) { | ||
408 | tty_insert_flip_char(tty, data, | ||
409 | TTY_FRAME); | ||
410 | } | ||
411 | /* These two conditions may imply */ | ||
412 | /* a normal read should be done. */ | ||
413 | /* else if(data & CyTIMEOUT) */ | ||
414 | /* else if(data & CySPECHAR) */ | ||
415 | } else { | ||
416 | tty_insert_flip_char(tty, 0, | ||
417 | TTY_NORMAL); | ||
418 | } | ||
419 | } else { | ||
420 | tty_insert_flip_char(tty, data, TTY_NORMAL); | ||
421 | } | ||
422 | } else { | ||
423 | /* there was a software buffer overrun | ||
424 | and nothing could be done about it!!! */ | ||
425 | } | ||
426 | } | ||
427 | tty_schedule_flip(tty); | ||
428 | /* end of service */ | ||
429 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; | ||
430 | return IRQ_HANDLED; | ||
431 | } /* cy_rxerr_interrupt */ | ||
432 | |||
433 | static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id) | ||
434 | { | ||
435 | struct cyclades_port *info; | ||
436 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | ||
437 | int channel; | ||
438 | int mdm_change; | ||
439 | int mdm_status; | ||
440 | |||
441 | /* determine the channel and change to that context */ | ||
442 | channel = (u_short) (base_addr[CyLICR] >> 2); | ||
443 | info = &cy_port[channel]; | ||
444 | info->last_active = jiffies; | ||
445 | |||
446 | mdm_change = base_addr[CyMISR]; | ||
447 | mdm_status = base_addr[CyMSVR1]; | ||
448 | |||
449 | if (info->tty == 0) { /* nowhere to put the data, ignore it */ | ||
450 | ; | ||
451 | } else { | ||
452 | if ((mdm_change & CyDCD) | ||
453 | && (info->flags & ASYNC_CHECK_CD)) { | ||
454 | if (mdm_status & CyDCD) { | ||
455 | /* CP('!'); */ | ||
456 | wake_up_interruptible(&info->open_wait); | ||
457 | } else { | ||
458 | /* CP('@'); */ | ||
459 | tty_hangup(info->tty); | ||
460 | wake_up_interruptible(&info->open_wait); | ||
461 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
462 | } | ||
463 | } | ||
464 | if ((mdm_change & CyCTS) | ||
465 | && (info->flags & ASYNC_CTS_FLOW)) { | ||
466 | if (info->tty->stopped) { | ||
467 | if (mdm_status & CyCTS) { | ||
468 | /* !!! cy_start isn't used because... */ | ||
469 | info->tty->stopped = 0; | ||
470 | base_addr[CyIER] |= CyTxMpty; | ||
471 | tty_wakeup(info->tty); | ||
472 | } | ||
473 | } else { | ||
474 | if (!(mdm_status & CyCTS)) { | ||
475 | /* !!! cy_stop isn't used because... */ | ||
476 | info->tty->stopped = 1; | ||
477 | base_addr[CyIER] &= | ||
478 | ~(CyTxMpty | CyTxRdy); | ||
479 | } | ||
480 | } | ||
481 | } | ||
482 | if (mdm_status & CyDSR) { | ||
483 | } | ||
484 | } | ||
485 | base_addr[CyMEOIR] = 0; | ||
486 | return IRQ_HANDLED; | ||
487 | } /* cy_modem_interrupt */ | ||
488 | |||
489 | static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id) | ||
490 | { | ||
491 | struct cyclades_port *info; | ||
492 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | ||
493 | int channel; | ||
494 | int char_count, saved_cnt; | ||
495 | int outch; | ||
496 | |||
497 | /* determine the channel and change to that context */ | ||
498 | channel = (u_short) (base_addr[CyLICR] >> 2); | ||
499 | |||
500 | /* validate the port number (as configured and open) */ | ||
501 | if ((channel < 0) || (NR_PORTS <= channel)) { | ||
502 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
503 | base_addr[CyTEOIR] = CyNOTRANS; | ||
504 | return IRQ_HANDLED; | ||
505 | } | ||
506 | info = &cy_port[channel]; | ||
507 | info->last_active = jiffies; | ||
508 | if (info->tty == 0) { | ||
509 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
510 | base_addr[CyTEOIR] = CyNOTRANS; | ||
511 | return IRQ_HANDLED; | ||
512 | } | ||
513 | |||
514 | /* load the on-chip space available for outbound data */ | ||
515 | saved_cnt = char_count = base_addr[CyTFTC]; | ||
516 | |||
517 | if (info->x_char) { /* send special char */ | ||
518 | outch = info->x_char; | ||
519 | base_addr[CyTDR] = outch; | ||
520 | char_count--; | ||
521 | info->x_char = 0; | ||
522 | } | ||
523 | |||
524 | if (info->x_break) { | ||
525 | /* The Cirrus chip requires the "Embedded Transmit | ||
526 | Commands" of start break, delay, and end break | ||
527 | sequences to be sent. The duration of the | ||
528 | break is given in TICs, which runs at HZ | ||
529 | (typically 100) and the PPR runs at 200 Hz, | ||
530 | so the delay is duration * 200/HZ, and thus a | ||
531 | break can run from 1/100 sec to about 5/4 sec. | ||
532 | Need to check these values - RGH 141095. | ||
533 | */ | ||
534 | base_addr[CyTDR] = 0; /* start break */ | ||
535 | base_addr[CyTDR] = 0x81; | ||
536 | base_addr[CyTDR] = 0; /* delay a bit */ | ||
537 | base_addr[CyTDR] = 0x82; | ||
538 | base_addr[CyTDR] = info->x_break * 200 / HZ; | ||
539 | base_addr[CyTDR] = 0; /* terminate break */ | ||
540 | base_addr[CyTDR] = 0x83; | ||
541 | char_count -= 7; | ||
542 | info->x_break = 0; | ||
543 | } | ||
544 | |||
545 | while (char_count > 0) { | ||
546 | if (!info->xmit_cnt) { | ||
547 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
548 | break; | ||
549 | } | ||
550 | if (info->xmit_buf == 0) { | ||
551 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
552 | break; | ||
553 | } | ||
554 | if (info->tty->stopped || info->tty->hw_stopped) { | ||
555 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
556 | break; | ||
557 | } | ||
558 | /* Because the Embedded Transmit Commands have been | ||
559 | enabled, we must check to see if the escape | ||
560 | character, NULL, is being sent. If it is, we | ||
561 | must ensure that there is room for it to be | ||
562 | doubled in the output stream. Therefore we | ||
563 | no longer advance the pointer when the character | ||
564 | is fetched, but rather wait until after the check | ||
565 | for a NULL output character. (This is necessary | ||
566 | because there may not be room for the two chars | ||
567 | needed to send a NULL. | ||
568 | */ | ||
569 | outch = info->xmit_buf[info->xmit_tail]; | ||
570 | if (outch) { | ||
571 | info->xmit_cnt--; | ||
572 | info->xmit_tail = (info->xmit_tail + 1) | ||
573 | & (PAGE_SIZE - 1); | ||
574 | base_addr[CyTDR] = outch; | ||
575 | char_count--; | ||
576 | } else { | ||
577 | if (char_count > 1) { | ||
578 | info->xmit_cnt--; | ||
579 | info->xmit_tail = (info->xmit_tail + 1) | ||
580 | & (PAGE_SIZE - 1); | ||
581 | base_addr[CyTDR] = outch; | ||
582 | base_addr[CyTDR] = 0; | ||
583 | char_count--; | ||
584 | char_count--; | ||
585 | } else { | ||
586 | break; | ||
587 | } | ||
588 | } | ||
589 | } | ||
590 | |||
591 | if (info->xmit_cnt < WAKEUP_CHARS) | ||
592 | tty_wakeup(info->tty); | ||
593 | |||
594 | base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; | ||
595 | return IRQ_HANDLED; | ||
596 | } /* cy_tx_interrupt */ | ||
597 | |||
598 | static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) | ||
599 | { | ||
600 | struct tty_struct *tty; | ||
601 | struct cyclades_port *info; | ||
602 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | ||
603 | int channel; | ||
604 | char data; | ||
605 | int char_count; | ||
606 | int save_cnt; | ||
607 | |||
608 | /* determine the channel and change to that context */ | ||
609 | channel = (u_short) (base_addr[CyLICR] >> 2); | ||
610 | info = &cy_port[channel]; | ||
611 | info->last_active = jiffies; | ||
612 | save_cnt = char_count = base_addr[CyRFOC]; | ||
613 | |||
614 | /* if there is nowhere to put the data, discard it */ | ||
615 | if (info->tty == 0) { | ||
616 | while (char_count--) { | ||
617 | data = base_addr[CyRDR]; | ||
618 | } | ||
619 | } else { /* there is an open port for this data */ | ||
620 | tty = info->tty; | ||
621 | /* load # characters available from the chip */ | ||
622 | |||
623 | #ifdef CYCLOM_ENABLE_MONITORING | ||
624 | ++info->mon.int_count; | ||
625 | info->mon.char_count += char_count; | ||
626 | if (char_count > info->mon.char_max) | ||
627 | info->mon.char_max = char_count; | ||
628 | info->mon.char_last = char_count; | ||
629 | #endif | ||
630 | while (char_count--) { | ||
631 | data = base_addr[CyRDR]; | ||
632 | tty_insert_flip_char(tty, data, TTY_NORMAL); | ||
633 | #ifdef CYCLOM_16Y_HACK | ||
634 | udelay(10L); | ||
635 | #endif | ||
636 | } | ||
637 | tty_schedule_flip(tty); | ||
638 | } | ||
639 | /* end of service */ | ||
640 | base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; | ||
641 | return IRQ_HANDLED; | ||
642 | } /* cy_rx_interrupt */ | ||
643 | |||
644 | /* This is called whenever a port becomes active; | ||
645 | interrupts are enabled and DTR & RTS are turned on. | ||
646 | */ | ||
647 | static int startup(struct cyclades_port *info) | ||
648 | { | ||
649 | unsigned long flags; | ||
650 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | ||
651 | int channel; | ||
652 | |||
653 | if (info->flags & ASYNC_INITIALIZED) { | ||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | if (!info->type) { | ||
658 | if (info->tty) { | ||
659 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
660 | } | ||
661 | return 0; | ||
662 | } | ||
663 | if (!info->xmit_buf) { | ||
664 | info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); | ||
665 | if (!info->xmit_buf) { | ||
666 | return -ENOMEM; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | config_setup(info); | ||
671 | |||
672 | channel = info->line; | ||
673 | |||
674 | #ifdef SERIAL_DEBUG_OPEN | ||
675 | printk("startup channel %d\n", channel); | ||
676 | #endif | ||
677 | |||
678 | local_irq_save(flags); | ||
679 | base_addr[CyCAR] = (u_char) channel; | ||
680 | write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR); | ||
681 | |||
682 | base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */ | ||
683 | base_addr[CyMSVR1] = CyRTS; | ||
684 | /* CP('S');CP('1'); */ | ||
685 | base_addr[CyMSVR2] = CyDTR; | ||
686 | |||
687 | #ifdef SERIAL_DEBUG_DTR | ||
688 | printk("cyc: %d: raising DTR\n", __LINE__); | ||
689 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], | ||
690 | base_addr[CyMSVR2]); | ||
691 | #endif | ||
692 | |||
693 | base_addr[CyIER] |= CyRxData; | ||
694 | info->flags |= ASYNC_INITIALIZED; | ||
695 | |||
696 | if (info->tty) { | ||
697 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | ||
698 | } | ||
699 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
700 | |||
701 | local_irq_restore(flags); | ||
702 | |||
703 | #ifdef SERIAL_DEBUG_OPEN | ||
704 | printk(" done\n"); | ||
705 | #endif | ||
706 | return 0; | ||
707 | } /* startup */ | ||
708 | |||
709 | void start_xmit(struct cyclades_port *info) | ||
710 | { | ||
711 | unsigned long flags; | ||
712 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
713 | int channel; | ||
714 | |||
715 | channel = info->line; | ||
716 | local_irq_save(flags); | ||
717 | base_addr[CyCAR] = channel; | ||
718 | base_addr[CyIER] |= CyTxMpty; | ||
719 | local_irq_restore(flags); | ||
720 | } /* start_xmit */ | ||
721 | |||
722 | /* | ||
723 | * This routine shuts down a serial port; interrupts are disabled, | ||
724 | * and DTR is dropped if the hangup on close termio flag is on. | ||
725 | */ | ||
726 | static void shutdown(struct cyclades_port *info) | ||
727 | { | ||
728 | unsigned long flags; | ||
729 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
730 | int channel; | ||
731 | |||
732 | if (!(info->flags & ASYNC_INITIALIZED)) { | ||
733 | /* CP('$'); */ | ||
734 | return; | ||
735 | } | ||
736 | |||
737 | channel = info->line; | ||
738 | |||
739 | #ifdef SERIAL_DEBUG_OPEN | ||
740 | printk("shutdown channel %d\n", channel); | ||
741 | #endif | ||
742 | |||
743 | /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE | ||
744 | SENT BEFORE DROPPING THE LINE !!! (Perhaps | ||
745 | set some flag that is read when XMTY happens.) | ||
746 | Other choices are to delay some fixed interval | ||
747 | or schedule some later processing. | ||
748 | */ | ||
749 | local_irq_save(flags); | ||
750 | if (info->xmit_buf) { | ||
751 | free_page((unsigned long)info->xmit_buf); | ||
752 | info->xmit_buf = NULL; | ||
753 | } | ||
754 | |||
755 | base_addr[CyCAR] = (u_char) channel; | ||
756 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { | ||
757 | base_addr[CyMSVR1] = 0; | ||
758 | /* CP('C');CP('1'); */ | ||
759 | base_addr[CyMSVR2] = 0; | ||
760 | #ifdef SERIAL_DEBUG_DTR | ||
761 | printk("cyc: %d: dropping DTR\n", __LINE__); | ||
762 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], | ||
763 | base_addr[CyMSVR2]); | ||
764 | #endif | ||
765 | } | ||
766 | write_cy_cmd(base_addr, CyDIS_RCVR); | ||
767 | /* it may be appropriate to clear _XMIT at | ||
768 | some later date (after testing)!!! */ | ||
769 | |||
770 | if (info->tty) { | ||
771 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
772 | } | ||
773 | info->flags &= ~ASYNC_INITIALIZED; | ||
774 | local_irq_restore(flags); | ||
775 | |||
776 | #ifdef SERIAL_DEBUG_OPEN | ||
777 | printk(" done\n"); | ||
778 | #endif | ||
779 | } /* shutdown */ | ||
780 | |||
781 | /* | ||
782 | * This routine finds or computes the various line characteristics. | ||
783 | */ | ||
784 | static void config_setup(struct cyclades_port *info) | ||
785 | { | ||
786 | unsigned long flags; | ||
787 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
788 | int channel; | ||
789 | unsigned cflag; | ||
790 | int i; | ||
791 | unsigned char ti, need_init_chan = 0; | ||
792 | |||
793 | if (!info->tty || !info->tty->termios) { | ||
794 | return; | ||
795 | } | ||
796 | if (info->line == -1) { | ||
797 | return; | ||
798 | } | ||
799 | cflag = info->tty->termios->c_cflag; | ||
800 | |||
801 | /* baud rate */ | ||
802 | i = cflag & CBAUD; | ||
803 | #ifdef CBAUDEX | ||
804 | /* Starting with kernel 1.1.65, there is direct support for | ||
805 | higher baud rates. The following code supports those | ||
806 | changes. The conditional aspect allows this driver to be | ||
807 | used for earlier as well as later kernel versions. (The | ||
808 | mapping is slightly different from serial.c because there | ||
809 | is still the possibility of supporting 75 kbit/sec with | ||
810 | the Cyclades board.) | ||
811 | */ | ||
812 | if (i & CBAUDEX) { | ||
813 | if (i == B57600) | ||
814 | i = 16; | ||
815 | else if (i == B115200) | ||
816 | i = 18; | ||
817 | #ifdef B78600 | ||
818 | else if (i == B78600) | ||
819 | i = 17; | ||
820 | #endif | ||
821 | else | ||
822 | info->tty->termios->c_cflag &= ~CBAUDEX; | ||
823 | } | ||
824 | #endif | ||
825 | if (i == 15) { | ||
826 | if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
827 | i += 1; | ||
828 | if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
829 | i += 3; | ||
830 | } | ||
831 | /* Don't ever change the speed of the console port. It will | ||
832 | * run at the speed specified in bootinfo, or at 19.2K */ | ||
833 | /* Actually, it should run at whatever speed 166Bug was using */ | ||
834 | /* Note info->timeout isn't used at present */ | ||
835 | if (info != serial_console_info) { | ||
836 | info->tbpr = baud_bpr[i]; /* Tx BPR */ | ||
837 | info->tco = baud_co[i]; /* Tx CO */ | ||
838 | info->rbpr = baud_bpr[i]; /* Rx BPR */ | ||
839 | info->rco = baud_co[i] >> 5; /* Rx CO */ | ||
840 | if (baud_table[i] == 134) { | ||
841 | info->timeout = | ||
842 | (info->xmit_fifo_size * HZ * 30 / 269) + 2; | ||
843 | /* get it right for 134.5 baud */ | ||
844 | } else if (baud_table[i]) { | ||
845 | info->timeout = | ||
846 | (info->xmit_fifo_size * HZ * 15 / baud_table[i]) + | ||
847 | 2; | ||
848 | /* this needs to be propagated into the card info */ | ||
849 | } else { | ||
850 | info->timeout = 0; | ||
851 | } | ||
852 | } | ||
853 | /* By tradition (is it a standard?) a baud rate of zero | ||
854 | implies the line should be/has been closed. A bit | ||
855 | later in this routine such a test is performed. */ | ||
856 | |||
857 | /* byte size and parity */ | ||
858 | info->cor7 = 0; | ||
859 | info->cor6 = 0; | ||
860 | info->cor5 = 0; | ||
861 | info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]); /* receive threshold */ | ||
862 | /* Following two lines added 101295, RGH. */ | ||
863 | /* It is obviously wrong to access CyCORx, and not info->corx here, | ||
864 | * try and remember to fix it later! */ | ||
865 | channel = info->line; | ||
866 | base_addr[CyCAR] = (u_char) channel; | ||
867 | if (C_CLOCAL(info->tty)) { | ||
868 | if (base_addr[CyIER] & CyMdmCh) | ||
869 | base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */ | ||
870 | /* ignore 1->0 modem transitions */ | ||
871 | if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) | ||
872 | base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD); | ||
873 | /* ignore 0->1 modem transitions */ | ||
874 | if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) | ||
875 | base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD); | ||
876 | } else { | ||
877 | if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh) | ||
878 | base_addr[CyIER] |= CyMdmCh; /* with modem intr */ | ||
879 | /* act on 1->0 modem transitions */ | ||
880 | if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) != | ||
881 | (CyDSR | CyCTS | CyDCD)) | ||
882 | base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD; | ||
883 | /* act on 0->1 modem transitions */ | ||
884 | if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) != | ||
885 | (CyDSR | CyCTS | CyDCD)) | ||
886 | base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD; | ||
887 | } | ||
888 | info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP; | ||
889 | info->cor2 = CyETC; | ||
890 | switch (cflag & CSIZE) { | ||
891 | case CS5: | ||
892 | info->cor1 = Cy_5_BITS; | ||
893 | break; | ||
894 | case CS6: | ||
895 | info->cor1 = Cy_6_BITS; | ||
896 | break; | ||
897 | case CS7: | ||
898 | info->cor1 = Cy_7_BITS; | ||
899 | break; | ||
900 | case CS8: | ||
901 | info->cor1 = Cy_8_BITS; | ||
902 | break; | ||
903 | } | ||
904 | if (cflag & PARENB) { | ||
905 | if (cflag & PARODD) { | ||
906 | info->cor1 |= CyPARITY_O; | ||
907 | } else { | ||
908 | info->cor1 |= CyPARITY_E; | ||
909 | } | ||
910 | } else { | ||
911 | info->cor1 |= CyPARITY_NONE; | ||
912 | } | ||
913 | |||
914 | /* CTS flow control flag */ | ||
915 | #if 0 | ||
916 | /* Don't complcate matters for now! RGH 141095 */ | ||
917 | if (cflag & CRTSCTS) { | ||
918 | info->flags |= ASYNC_CTS_FLOW; | ||
919 | info->cor2 |= CyCtsAE; | ||
920 | } else { | ||
921 | info->flags &= ~ASYNC_CTS_FLOW; | ||
922 | info->cor2 &= ~CyCtsAE; | ||
923 | } | ||
924 | #endif | ||
925 | if (cflag & CLOCAL) | ||
926 | info->flags &= ~ASYNC_CHECK_CD; | ||
927 | else | ||
928 | info->flags |= ASYNC_CHECK_CD; | ||
929 | |||
930 | /*********************************************** | ||
931 | The hardware option, CyRtsAO, presents RTS when | ||
932 | the chip has characters to send. Since most modems | ||
933 | use RTS as reverse (inbound) flow control, this | ||
934 | option is not used. If inbound flow control is | ||
935 | necessary, DTR can be programmed to provide the | ||
936 | appropriate signals for use with a non-standard | ||
937 | cable. Contact Marcio Saito for details. | ||
938 | ***********************************************/ | ||
939 | |||
940 | channel = info->line; | ||
941 | |||
942 | local_irq_save(flags); | ||
943 | base_addr[CyCAR] = (u_char) channel; | ||
944 | |||
945 | /* CyCMR set once only in mvme167_init_serial() */ | ||
946 | if (base_addr[CyLICR] != channel << 2) | ||
947 | base_addr[CyLICR] = channel << 2; | ||
948 | if (base_addr[CyLIVR] != 0x5c) | ||
949 | base_addr[CyLIVR] = 0x5c; | ||
950 | |||
951 | /* tx and rx baud rate */ | ||
952 | |||
953 | if (base_addr[CyCOR1] != info->cor1) | ||
954 | need_init_chan = 1; | ||
955 | if (base_addr[CyTCOR] != info->tco) | ||
956 | base_addr[CyTCOR] = info->tco; | ||
957 | if (base_addr[CyTBPR] != info->tbpr) | ||
958 | base_addr[CyTBPR] = info->tbpr; | ||
959 | if (base_addr[CyRCOR] != info->rco) | ||
960 | base_addr[CyRCOR] = info->rco; | ||
961 | if (base_addr[CyRBPR] != info->rbpr) | ||
962 | base_addr[CyRBPR] = info->rbpr; | ||
963 | |||
964 | /* set line characteristics according configuration */ | ||
965 | |||
966 | if (base_addr[CySCHR1] != START_CHAR(info->tty)) | ||
967 | base_addr[CySCHR1] = START_CHAR(info->tty); | ||
968 | if (base_addr[CySCHR2] != STOP_CHAR(info->tty)) | ||
969 | base_addr[CySCHR2] = STOP_CHAR(info->tty); | ||
970 | if (base_addr[CySCRL] != START_CHAR(info->tty)) | ||
971 | base_addr[CySCRL] = START_CHAR(info->tty); | ||
972 | if (base_addr[CySCRH] != START_CHAR(info->tty)) | ||
973 | base_addr[CySCRH] = START_CHAR(info->tty); | ||
974 | if (base_addr[CyCOR1] != info->cor1) | ||
975 | base_addr[CyCOR1] = info->cor1; | ||
976 | if (base_addr[CyCOR2] != info->cor2) | ||
977 | base_addr[CyCOR2] = info->cor2; | ||
978 | if (base_addr[CyCOR3] != info->cor3) | ||
979 | base_addr[CyCOR3] = info->cor3; | ||
980 | if (base_addr[CyCOR4] != info->cor4) | ||
981 | base_addr[CyCOR4] = info->cor4; | ||
982 | if (base_addr[CyCOR5] != info->cor5) | ||
983 | base_addr[CyCOR5] = info->cor5; | ||
984 | if (base_addr[CyCOR6] != info->cor6) | ||
985 | base_addr[CyCOR6] = info->cor6; | ||
986 | if (base_addr[CyCOR7] != info->cor7) | ||
987 | base_addr[CyCOR7] = info->cor7; | ||
988 | |||
989 | if (need_init_chan) | ||
990 | write_cy_cmd(base_addr, CyINIT_CHAN); | ||
991 | |||
992 | base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */ | ||
993 | |||
994 | /* 2ms default rx timeout */ | ||
995 | ti = info->default_timeout ? info->default_timeout : 0x02; | ||
996 | if (base_addr[CyRTPRL] != ti) | ||
997 | base_addr[CyRTPRL] = ti; | ||
998 | if (base_addr[CyRTPRH] != 0) | ||
999 | base_addr[CyRTPRH] = 0; | ||
1000 | |||
1001 | /* Set up RTS here also ????? RGH 141095 */ | ||
1002 | if (i == 0) { /* baud rate is zero, turn off line */ | ||
1003 | if ((base_addr[CyMSVR2] & CyDTR) == CyDTR) | ||
1004 | base_addr[CyMSVR2] = 0; | ||
1005 | #ifdef SERIAL_DEBUG_DTR | ||
1006 | printk("cyc: %d: dropping DTR\n", __LINE__); | ||
1007 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], | ||
1008 | base_addr[CyMSVR2]); | ||
1009 | #endif | ||
1010 | } else { | ||
1011 | if ((base_addr[CyMSVR2] & CyDTR) != CyDTR) | ||
1012 | base_addr[CyMSVR2] = CyDTR; | ||
1013 | #ifdef SERIAL_DEBUG_DTR | ||
1014 | printk("cyc: %d: raising DTR\n", __LINE__); | ||
1015 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], | ||
1016 | base_addr[CyMSVR2]); | ||
1017 | #endif | ||
1018 | } | ||
1019 | |||
1020 | if (info->tty) { | ||
1021 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | ||
1022 | } | ||
1023 | |||
1024 | local_irq_restore(flags); | ||
1025 | |||
1026 | } /* config_setup */ | ||
1027 | |||
1028 | static int cy_put_char(struct tty_struct *tty, unsigned char ch) | ||
1029 | { | ||
1030 | struct cyclades_port *info = tty->driver_data; | ||
1031 | unsigned long flags; | ||
1032 | |||
1033 | #ifdef SERIAL_DEBUG_IO | ||
1034 | printk("cy_put_char %s(0x%02x)\n", tty->name, ch); | ||
1035 | #endif | ||
1036 | |||
1037 | if (serial_paranoia_check(info, tty->name, "cy_put_char")) | ||
1038 | return 0; | ||
1039 | |||
1040 | if (!info->xmit_buf) | ||
1041 | return 0; | ||
1042 | |||
1043 | local_irq_save(flags); | ||
1044 | if (info->xmit_cnt >= PAGE_SIZE - 1) { | ||
1045 | local_irq_restore(flags); | ||
1046 | return 0; | ||
1047 | } | ||
1048 | |||
1049 | info->xmit_buf[info->xmit_head++] = ch; | ||
1050 | info->xmit_head &= PAGE_SIZE - 1; | ||
1051 | info->xmit_cnt++; | ||
1052 | local_irq_restore(flags); | ||
1053 | return 1; | ||
1054 | } /* cy_put_char */ | ||
1055 | |||
1056 | static void cy_flush_chars(struct tty_struct *tty) | ||
1057 | { | ||
1058 | struct cyclades_port *info = tty->driver_data; | ||
1059 | unsigned long flags; | ||
1060 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1061 | int channel; | ||
1062 | |||
1063 | #ifdef SERIAL_DEBUG_IO | ||
1064 | printk("cy_flush_chars %s\n", tty->name); /* */ | ||
1065 | #endif | ||
1066 | |||
1067 | if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) | ||
1068 | return; | ||
1069 | |||
1070 | if (info->xmit_cnt <= 0 || tty->stopped | ||
1071 | || tty->hw_stopped || !info->xmit_buf) | ||
1072 | return; | ||
1073 | |||
1074 | channel = info->line; | ||
1075 | |||
1076 | local_irq_save(flags); | ||
1077 | base_addr[CyCAR] = channel; | ||
1078 | base_addr[CyIER] |= CyTxMpty; | ||
1079 | local_irq_restore(flags); | ||
1080 | } /* cy_flush_chars */ | ||
1081 | |||
1082 | /* This routine gets called when tty_write has put something into | ||
1083 | the write_queue. If the port is not already transmitting stuff, | ||
1084 | start it off by enabling interrupts. The interrupt service | ||
1085 | routine will then ensure that the characters are sent. If the | ||
1086 | port is already active, there is no need to kick it. | ||
1087 | */ | ||
1088 | static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) | ||
1089 | { | ||
1090 | struct cyclades_port *info = tty->driver_data; | ||
1091 | unsigned long flags; | ||
1092 | int c, total = 0; | ||
1093 | |||
1094 | #ifdef SERIAL_DEBUG_IO | ||
1095 | printk("cy_write %s\n", tty->name); /* */ | ||
1096 | #endif | ||
1097 | |||
1098 | if (serial_paranoia_check(info, tty->name, "cy_write")) { | ||
1099 | return 0; | ||
1100 | } | ||
1101 | |||
1102 | if (!info->xmit_buf) { | ||
1103 | return 0; | ||
1104 | } | ||
1105 | |||
1106 | while (1) { | ||
1107 | local_irq_save(flags); | ||
1108 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | ||
1109 | SERIAL_XMIT_SIZE - info->xmit_head)); | ||
1110 | if (c <= 0) { | ||
1111 | local_irq_restore(flags); | ||
1112 | break; | ||
1113 | } | ||
1114 | |||
1115 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
1116 | info->xmit_head = | ||
1117 | (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); | ||
1118 | info->xmit_cnt += c; | ||
1119 | local_irq_restore(flags); | ||
1120 | |||
1121 | buf += c; | ||
1122 | count -= c; | ||
1123 | total += c; | ||
1124 | } | ||
1125 | |||
1126 | if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { | ||
1127 | start_xmit(info); | ||
1128 | } | ||
1129 | return total; | ||
1130 | } /* cy_write */ | ||
1131 | |||
1132 | static int cy_write_room(struct tty_struct *tty) | ||
1133 | { | ||
1134 | struct cyclades_port *info = tty->driver_data; | ||
1135 | int ret; | ||
1136 | |||
1137 | #ifdef SERIAL_DEBUG_IO | ||
1138 | printk("cy_write_room %s\n", tty->name); /* */ | ||
1139 | #endif | ||
1140 | |||
1141 | if (serial_paranoia_check(info, tty->name, "cy_write_room")) | ||
1142 | return 0; | ||
1143 | ret = PAGE_SIZE - info->xmit_cnt - 1; | ||
1144 | if (ret < 0) | ||
1145 | ret = 0; | ||
1146 | return ret; | ||
1147 | } /* cy_write_room */ | ||
1148 | |||
1149 | static int cy_chars_in_buffer(struct tty_struct *tty) | ||
1150 | { | ||
1151 | struct cyclades_port *info = tty->driver_data; | ||
1152 | |||
1153 | #ifdef SERIAL_DEBUG_IO | ||
1154 | printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */ | ||
1155 | #endif | ||
1156 | |||
1157 | if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) | ||
1158 | return 0; | ||
1159 | |||
1160 | return info->xmit_cnt; | ||
1161 | } /* cy_chars_in_buffer */ | ||
1162 | |||
1163 | static void cy_flush_buffer(struct tty_struct *tty) | ||
1164 | { | ||
1165 | struct cyclades_port *info = tty->driver_data; | ||
1166 | unsigned long flags; | ||
1167 | |||
1168 | #ifdef SERIAL_DEBUG_IO | ||
1169 | printk("cy_flush_buffer %s\n", tty->name); /* */ | ||
1170 | #endif | ||
1171 | |||
1172 | if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) | ||
1173 | return; | ||
1174 | local_irq_save(flags); | ||
1175 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
1176 | local_irq_restore(flags); | ||
1177 | tty_wakeup(tty); | ||
1178 | } /* cy_flush_buffer */ | ||
1179 | |||
1180 | /* This routine is called by the upper-layer tty layer to signal | ||
1181 | that incoming characters should be throttled or that the | ||
1182 | throttle should be released. | ||
1183 | */ | ||
1184 | static void cy_throttle(struct tty_struct *tty) | ||
1185 | { | ||
1186 | struct cyclades_port *info = tty->driver_data; | ||
1187 | unsigned long flags; | ||
1188 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1189 | int channel; | ||
1190 | |||
1191 | #ifdef SERIAL_DEBUG_THROTTLE | ||
1192 | char buf[64]; | ||
1193 | |||
1194 | printk("throttle %s: %d....\n", tty_name(tty, buf), | ||
1195 | tty->ldisc.chars_in_buffer(tty)); | ||
1196 | printk("cy_throttle %s\n", tty->name); | ||
1197 | #endif | ||
1198 | |||
1199 | if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) { | ||
1200 | return; | ||
1201 | } | ||
1202 | |||
1203 | if (I_IXOFF(tty)) { | ||
1204 | info->x_char = STOP_CHAR(tty); | ||
1205 | /* Should use the "Send Special Character" feature!!! */ | ||
1206 | } | ||
1207 | |||
1208 | channel = info->line; | ||
1209 | |||
1210 | local_irq_save(flags); | ||
1211 | base_addr[CyCAR] = (u_char) channel; | ||
1212 | base_addr[CyMSVR1] = 0; | ||
1213 | local_irq_restore(flags); | ||
1214 | } /* cy_throttle */ | ||
1215 | |||
1216 | static void cy_unthrottle(struct tty_struct *tty) | ||
1217 | { | ||
1218 | struct cyclades_port *info = tty->driver_data; | ||
1219 | unsigned long flags; | ||
1220 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1221 | int channel; | ||
1222 | |||
1223 | #ifdef SERIAL_DEBUG_THROTTLE | ||
1224 | char buf[64]; | ||
1225 | |||
1226 | printk("throttle %s: %d....\n", tty_name(tty, buf), | ||
1227 | tty->ldisc.chars_in_buffer(tty)); | ||
1228 | printk("cy_unthrottle %s\n", tty->name); | ||
1229 | #endif | ||
1230 | |||
1231 | if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) { | ||
1232 | return; | ||
1233 | } | ||
1234 | |||
1235 | if (I_IXOFF(tty)) { | ||
1236 | info->x_char = START_CHAR(tty); | ||
1237 | /* Should use the "Send Special Character" feature!!! */ | ||
1238 | } | ||
1239 | |||
1240 | channel = info->line; | ||
1241 | |||
1242 | local_irq_save(flags); | ||
1243 | base_addr[CyCAR] = (u_char) channel; | ||
1244 | base_addr[CyMSVR1] = CyRTS; | ||
1245 | local_irq_restore(flags); | ||
1246 | } /* cy_unthrottle */ | ||
1247 | |||
1248 | static int | ||
1249 | get_serial_info(struct cyclades_port *info, | ||
1250 | struct serial_struct __user * retinfo) | ||
1251 | { | ||
1252 | struct serial_struct tmp; | ||
1253 | |||
1254 | /* CP('g'); */ | ||
1255 | if (!retinfo) | ||
1256 | return -EFAULT; | ||
1257 | memset(&tmp, 0, sizeof(tmp)); | ||
1258 | tmp.type = info->type; | ||
1259 | tmp.line = info->line; | ||
1260 | tmp.port = info->line; | ||
1261 | tmp.irq = 0; | ||
1262 | tmp.flags = info->flags; | ||
1263 | tmp.baud_base = 0; /*!!! */ | ||
1264 | tmp.close_delay = info->close_delay; | ||
1265 | tmp.custom_divisor = 0; /*!!! */ | ||
1266 | tmp.hub6 = 0; /*!!! */ | ||
1267 | return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; | ||
1268 | } /* get_serial_info */ | ||
1269 | |||
1270 | static int | ||
1271 | set_serial_info(struct cyclades_port *info, | ||
1272 | struct serial_struct __user * new_info) | ||
1273 | { | ||
1274 | struct serial_struct new_serial; | ||
1275 | struct cyclades_port old_info; | ||
1276 | |||
1277 | /* CP('s'); */ | ||
1278 | if (!new_info) | ||
1279 | return -EFAULT; | ||
1280 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | ||
1281 | return -EFAULT; | ||
1282 | old_info = *info; | ||
1283 | |||
1284 | if (!capable(CAP_SYS_ADMIN)) { | ||
1285 | if ((new_serial.close_delay != info->close_delay) || | ||
1286 | ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != | ||
1287 | (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) | ||
1288 | return -EPERM; | ||
1289 | info->flags = ((info->flags & ~ASYNC_USR_MASK) | | ||
1290 | (new_serial.flags & ASYNC_USR_MASK)); | ||
1291 | goto check_and_exit; | ||
1292 | } | ||
1293 | |||
1294 | /* | ||
1295 | * OK, past this point, all the error checking has been done. | ||
1296 | * At this point, we start making changes..... | ||
1297 | */ | ||
1298 | |||
1299 | info->flags = ((info->flags & ~ASYNC_FLAGS) | | ||
1300 | (new_serial.flags & ASYNC_FLAGS)); | ||
1301 | info->close_delay = new_serial.close_delay; | ||
1302 | |||
1303 | check_and_exit: | ||
1304 | if (info->flags & ASYNC_INITIALIZED) { | ||
1305 | config_setup(info); | ||
1306 | return 0; | ||
1307 | } | ||
1308 | return startup(info); | ||
1309 | } /* set_serial_info */ | ||
1310 | |||
1311 | static int cy_tiocmget(struct tty_struct *tty) | ||
1312 | { | ||
1313 | struct cyclades_port *info = tty->driver_data; | ||
1314 | int channel; | ||
1315 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1316 | unsigned long flags; | ||
1317 | unsigned char status; | ||
1318 | |||
1319 | channel = info->line; | ||
1320 | |||
1321 | local_irq_save(flags); | ||
1322 | base_addr[CyCAR] = (u_char) channel; | ||
1323 | status = base_addr[CyMSVR1] | base_addr[CyMSVR2]; | ||
1324 | local_irq_restore(flags); | ||
1325 | |||
1326 | return ((status & CyRTS) ? TIOCM_RTS : 0) | ||
1327 | | ((status & CyDTR) ? TIOCM_DTR : 0) | ||
1328 | | ((status & CyDCD) ? TIOCM_CAR : 0) | ||
1329 | | ((status & CyDSR) ? TIOCM_DSR : 0) | ||
1330 | | ((status & CyCTS) ? TIOCM_CTS : 0); | ||
1331 | } /* cy_tiocmget */ | ||
1332 | |||
1333 | static int | ||
1334 | cy_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) | ||
1335 | { | ||
1336 | struct cyclades_port *info = tty->driver_data; | ||
1337 | int channel; | ||
1338 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1339 | unsigned long flags; | ||
1340 | |||
1341 | channel = info->line; | ||
1342 | |||
1343 | if (set & TIOCM_RTS) { | ||
1344 | local_irq_save(flags); | ||
1345 | base_addr[CyCAR] = (u_char) channel; | ||
1346 | base_addr[CyMSVR1] = CyRTS; | ||
1347 | local_irq_restore(flags); | ||
1348 | } | ||
1349 | if (set & TIOCM_DTR) { | ||
1350 | local_irq_save(flags); | ||
1351 | base_addr[CyCAR] = (u_char) channel; | ||
1352 | /* CP('S');CP('2'); */ | ||
1353 | base_addr[CyMSVR2] = CyDTR; | ||
1354 | #ifdef SERIAL_DEBUG_DTR | ||
1355 | printk("cyc: %d: raising DTR\n", __LINE__); | ||
1356 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], | ||
1357 | base_addr[CyMSVR2]); | ||
1358 | #endif | ||
1359 | local_irq_restore(flags); | ||
1360 | } | ||
1361 | |||
1362 | if (clear & TIOCM_RTS) { | ||
1363 | local_irq_save(flags); | ||
1364 | base_addr[CyCAR] = (u_char) channel; | ||
1365 | base_addr[CyMSVR1] = 0; | ||
1366 | local_irq_restore(flags); | ||
1367 | } | ||
1368 | if (clear & TIOCM_DTR) { | ||
1369 | local_irq_save(flags); | ||
1370 | base_addr[CyCAR] = (u_char) channel; | ||
1371 | /* CP('C');CP('2'); */ | ||
1372 | base_addr[CyMSVR2] = 0; | ||
1373 | #ifdef SERIAL_DEBUG_DTR | ||
1374 | printk("cyc: %d: dropping DTR\n", __LINE__); | ||
1375 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], | ||
1376 | base_addr[CyMSVR2]); | ||
1377 | #endif | ||
1378 | local_irq_restore(flags); | ||
1379 | } | ||
1380 | |||
1381 | return 0; | ||
1382 | } /* set_modem_info */ | ||
1383 | |||
1384 | static void send_break(struct cyclades_port *info, int duration) | ||
1385 | { /* Let the transmit ISR take care of this (since it | ||
1386 | requires stuffing characters into the output stream). | ||
1387 | */ | ||
1388 | info->x_break = duration; | ||
1389 | if (!info->xmit_cnt) { | ||
1390 | start_xmit(info); | ||
1391 | } | ||
1392 | } /* send_break */ | ||
1393 | |||
1394 | static int | ||
1395 | get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon) | ||
1396 | { | ||
1397 | |||
1398 | if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) | ||
1399 | return -EFAULT; | ||
1400 | info->mon.int_count = 0; | ||
1401 | info->mon.char_count = 0; | ||
1402 | info->mon.char_max = 0; | ||
1403 | info->mon.char_last = 0; | ||
1404 | return 0; | ||
1405 | } | ||
1406 | |||
1407 | static int set_threshold(struct cyclades_port *info, unsigned long __user * arg) | ||
1408 | { | ||
1409 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1410 | unsigned long value; | ||
1411 | int channel; | ||
1412 | |||
1413 | if (get_user(value, arg)) | ||
1414 | return -EFAULT; | ||
1415 | |||
1416 | channel = info->line; | ||
1417 | info->cor4 &= ~CyREC_FIFO; | ||
1418 | info->cor4 |= value & CyREC_FIFO; | ||
1419 | base_addr[CyCOR4] = info->cor4; | ||
1420 | return 0; | ||
1421 | } | ||
1422 | |||
1423 | static int | ||
1424 | get_threshold(struct cyclades_port *info, unsigned long __user * value) | ||
1425 | { | ||
1426 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1427 | int channel; | ||
1428 | unsigned long tmp; | ||
1429 | |||
1430 | channel = info->line; | ||
1431 | |||
1432 | tmp = base_addr[CyCOR4] & CyREC_FIFO; | ||
1433 | return put_user(tmp, value); | ||
1434 | } | ||
1435 | |||
1436 | static int | ||
1437 | set_default_threshold(struct cyclades_port *info, unsigned long __user * arg) | ||
1438 | { | ||
1439 | unsigned long value; | ||
1440 | |||
1441 | if (get_user(value, arg)) | ||
1442 | return -EFAULT; | ||
1443 | |||
1444 | info->default_threshold = value & 0x0f; | ||
1445 | return 0; | ||
1446 | } | ||
1447 | |||
1448 | static int | ||
1449 | get_default_threshold(struct cyclades_port *info, unsigned long __user * value) | ||
1450 | { | ||
1451 | return put_user(info->default_threshold, value); | ||
1452 | } | ||
1453 | |||
1454 | static int set_timeout(struct cyclades_port *info, unsigned long __user * arg) | ||
1455 | { | ||
1456 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1457 | int channel; | ||
1458 | unsigned long value; | ||
1459 | |||
1460 | if (get_user(value, arg)) | ||
1461 | return -EFAULT; | ||
1462 | |||
1463 | channel = info->line; | ||
1464 | |||
1465 | base_addr[CyRTPRL] = value & 0xff; | ||
1466 | base_addr[CyRTPRH] = (value >> 8) & 0xff; | ||
1467 | return 0; | ||
1468 | } | ||
1469 | |||
1470 | static int get_timeout(struct cyclades_port *info, unsigned long __user * value) | ||
1471 | { | ||
1472 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1473 | int channel; | ||
1474 | unsigned long tmp; | ||
1475 | |||
1476 | channel = info->line; | ||
1477 | |||
1478 | tmp = base_addr[CyRTPRL]; | ||
1479 | return put_user(tmp, value); | ||
1480 | } | ||
1481 | |||
1482 | static int set_default_timeout(struct cyclades_port *info, unsigned long value) | ||
1483 | { | ||
1484 | info->default_timeout = value & 0xff; | ||
1485 | return 0; | ||
1486 | } | ||
1487 | |||
1488 | static int | ||
1489 | get_default_timeout(struct cyclades_port *info, unsigned long __user * value) | ||
1490 | { | ||
1491 | return put_user(info->default_timeout, value); | ||
1492 | } | ||
1493 | |||
1494 | static int | ||
1495 | cy_ioctl(struct tty_struct *tty, | ||
1496 | unsigned int cmd, unsigned long arg) | ||
1497 | { | ||
1498 | struct cyclades_port *info = tty->driver_data; | ||
1499 | int ret_val = 0; | ||
1500 | void __user *argp = (void __user *)arg; | ||
1501 | |||
1502 | #ifdef SERIAL_DEBUG_OTHER | ||
1503 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ | ||
1504 | #endif | ||
1505 | |||
1506 | tty_lock(); | ||
1507 | |||
1508 | switch (cmd) { | ||
1509 | case CYGETMON: | ||
1510 | ret_val = get_mon_info(info, argp); | ||
1511 | break; | ||
1512 | case CYGETTHRESH: | ||
1513 | ret_val = get_threshold(info, argp); | ||
1514 | break; | ||
1515 | case CYSETTHRESH: | ||
1516 | ret_val = set_threshold(info, argp); | ||
1517 | break; | ||
1518 | case CYGETDEFTHRESH: | ||
1519 | ret_val = get_default_threshold(info, argp); | ||
1520 | break; | ||
1521 | case CYSETDEFTHRESH: | ||
1522 | ret_val = set_default_threshold(info, argp); | ||
1523 | break; | ||
1524 | case CYGETTIMEOUT: | ||
1525 | ret_val = get_timeout(info, argp); | ||
1526 | break; | ||
1527 | case CYSETTIMEOUT: | ||
1528 | ret_val = set_timeout(info, argp); | ||
1529 | break; | ||
1530 | case CYGETDEFTIMEOUT: | ||
1531 | ret_val = get_default_timeout(info, argp); | ||
1532 | break; | ||
1533 | case CYSETDEFTIMEOUT: | ||
1534 | ret_val = set_default_timeout(info, (unsigned long)arg); | ||
1535 | break; | ||
1536 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | ||
1537 | ret_val = tty_check_change(tty); | ||
1538 | if (ret_val) | ||
1539 | break; | ||
1540 | tty_wait_until_sent(tty, 0); | ||
1541 | if (!arg) | ||
1542 | send_break(info, HZ / 4); /* 1/4 second */ | ||
1543 | break; | ||
1544 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
1545 | ret_val = tty_check_change(tty); | ||
1546 | if (ret_val) | ||
1547 | break; | ||
1548 | tty_wait_until_sent(tty, 0); | ||
1549 | send_break(info, arg ? arg * (HZ / 10) : HZ / 4); | ||
1550 | break; | ||
1551 | |||
1552 | /* The following commands are incompletely implemented!!! */ | ||
1553 | case TIOCGSERIAL: | ||
1554 | ret_val = get_serial_info(info, argp); | ||
1555 | break; | ||
1556 | case TIOCSSERIAL: | ||
1557 | ret_val = set_serial_info(info, argp); | ||
1558 | break; | ||
1559 | default: | ||
1560 | ret_val = -ENOIOCTLCMD; | ||
1561 | } | ||
1562 | tty_unlock(); | ||
1563 | |||
1564 | #ifdef SERIAL_DEBUG_OTHER | ||
1565 | printk("cy_ioctl done\n"); | ||
1566 | #endif | ||
1567 | |||
1568 | return ret_val; | ||
1569 | } /* cy_ioctl */ | ||
1570 | |||
1571 | static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | ||
1572 | { | ||
1573 | struct cyclades_port *info = tty->driver_data; | ||
1574 | |||
1575 | #ifdef SERIAL_DEBUG_OTHER | ||
1576 | printk("cy_set_termios %s\n", tty->name); | ||
1577 | #endif | ||
1578 | |||
1579 | if (tty->termios->c_cflag == old_termios->c_cflag) | ||
1580 | return; | ||
1581 | config_setup(info); | ||
1582 | |||
1583 | if ((old_termios->c_cflag & CRTSCTS) && | ||
1584 | !(tty->termios->c_cflag & CRTSCTS)) { | ||
1585 | tty->stopped = 0; | ||
1586 | cy_start(tty); | ||
1587 | } | ||
1588 | #ifdef tytso_patch_94Nov25_1726 | ||
1589 | if (!(old_termios->c_cflag & CLOCAL) && | ||
1590 | (tty->termios->c_cflag & CLOCAL)) | ||
1591 | wake_up_interruptible(&info->open_wait); | ||
1592 | #endif | ||
1593 | } /* cy_set_termios */ | ||
1594 | |||
1595 | static void cy_close(struct tty_struct *tty, struct file *filp) | ||
1596 | { | ||
1597 | struct cyclades_port *info = tty->driver_data; | ||
1598 | |||
1599 | /* CP('C'); */ | ||
1600 | #ifdef SERIAL_DEBUG_OTHER | ||
1601 | printk("cy_close %s\n", tty->name); | ||
1602 | #endif | ||
1603 | |||
1604 | if (!info || serial_paranoia_check(info, tty->name, "cy_close")) { | ||
1605 | return; | ||
1606 | } | ||
1607 | #ifdef SERIAL_DEBUG_OPEN | ||
1608 | printk("cy_close %s, count = %d\n", tty->name, info->count); | ||
1609 | #endif | ||
1610 | |||
1611 | if ((tty->count == 1) && (info->count != 1)) { | ||
1612 | /* | ||
1613 | * Uh, oh. tty->count is 1, which means that the tty | ||
1614 | * structure will be freed. Info->count should always | ||
1615 | * be one in these conditions. If it's greater than | ||
1616 | * one, we've got real problems, since it means the | ||
1617 | * serial port won't be shutdown. | ||
1618 | */ | ||
1619 | printk("cy_close: bad serial port count; tty->count is 1, " | ||
1620 | "info->count is %d\n", info->count); | ||
1621 | info->count = 1; | ||
1622 | } | ||
1623 | #ifdef SERIAL_DEBUG_COUNT | ||
1624 | printk("cyc: %d: decrementing count to %d\n", __LINE__, | ||
1625 | info->count - 1); | ||
1626 | #endif | ||
1627 | if (--info->count < 0) { | ||
1628 | printk("cy_close: bad serial port count for ttys%d: %d\n", | ||
1629 | info->line, info->count); | ||
1630 | #ifdef SERIAL_DEBUG_COUNT | ||
1631 | printk("cyc: %d: setting count to 0\n", __LINE__); | ||
1632 | #endif | ||
1633 | info->count = 0; | ||
1634 | } | ||
1635 | if (info->count) | ||
1636 | return; | ||
1637 | info->flags |= ASYNC_CLOSING; | ||
1638 | if (info->flags & ASYNC_INITIALIZED) | ||
1639 | tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ | ||
1640 | shutdown(info); | ||
1641 | cy_flush_buffer(tty); | ||
1642 | tty_ldisc_flush(tty); | ||
1643 | info->tty = NULL; | ||
1644 | if (info->blocked_open) { | ||
1645 | if (info->close_delay) { | ||
1646 | msleep_interruptible(jiffies_to_msecs | ||
1647 | (info->close_delay)); | ||
1648 | } | ||
1649 | wake_up_interruptible(&info->open_wait); | ||
1650 | } | ||
1651 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | ||
1652 | wake_up_interruptible(&info->close_wait); | ||
1653 | |||
1654 | #ifdef SERIAL_DEBUG_OTHER | ||
1655 | printk("cy_close done\n"); | ||
1656 | #endif | ||
1657 | } /* cy_close */ | ||
1658 | |||
1659 | /* | ||
1660 | * cy_hangup() --- called by tty_hangup() when a hangup is signaled. | ||
1661 | */ | ||
1662 | void cy_hangup(struct tty_struct *tty) | ||
1663 | { | ||
1664 | struct cyclades_port *info = tty->driver_data; | ||
1665 | |||
1666 | #ifdef SERIAL_DEBUG_OTHER | ||
1667 | printk("cy_hangup %s\n", tty->name); /* */ | ||
1668 | #endif | ||
1669 | |||
1670 | if (serial_paranoia_check(info, tty->name, "cy_hangup")) | ||
1671 | return; | ||
1672 | |||
1673 | shutdown(info); | ||
1674 | #if 0 | ||
1675 | info->event = 0; | ||
1676 | info->count = 0; | ||
1677 | #ifdef SERIAL_DEBUG_COUNT | ||
1678 | printk("cyc: %d: setting count to 0\n", __LINE__); | ||
1679 | #endif | ||
1680 | info->tty = 0; | ||
1681 | #endif | ||
1682 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1683 | wake_up_interruptible(&info->open_wait); | ||
1684 | } /* cy_hangup */ | ||
1685 | |||
1686 | /* | ||
1687 | * ------------------------------------------------------------ | ||
1688 | * cy_open() and friends | ||
1689 | * ------------------------------------------------------------ | ||
1690 | */ | ||
1691 | |||
1692 | static int | ||
1693 | block_til_ready(struct tty_struct *tty, struct file *filp, | ||
1694 | struct cyclades_port *info) | ||
1695 | { | ||
1696 | DECLARE_WAITQUEUE(wait, current); | ||
1697 | unsigned long flags; | ||
1698 | int channel; | ||
1699 | int retval; | ||
1700 | volatile u_char *base_addr = (u_char *) BASE_ADDR; | ||
1701 | |||
1702 | /* | ||
1703 | * If the device is in the middle of being closed, then block | ||
1704 | * until it's done, and then try again. | ||
1705 | */ | ||
1706 | if (info->flags & ASYNC_CLOSING) { | ||
1707 | interruptible_sleep_on(&info->close_wait); | ||
1708 | if (info->flags & ASYNC_HUP_NOTIFY) { | ||
1709 | return -EAGAIN; | ||
1710 | } else { | ||
1711 | return -ERESTARTSYS; | ||
1712 | } | ||
1713 | } | ||
1714 | |||
1715 | /* | ||
1716 | * If non-blocking mode is set, then make the check up front | ||
1717 | * and then exit. | ||
1718 | */ | ||
1719 | if (filp->f_flags & O_NONBLOCK) { | ||
1720 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
1721 | return 0; | ||
1722 | } | ||
1723 | |||
1724 | /* | ||
1725 | * Block waiting for the carrier detect and the line to become | ||
1726 | * free (i.e., not in use by the callout). While we are in | ||
1727 | * this loop, info->count is dropped by one, so that | ||
1728 | * cy_close() knows when to free things. We restore it upon | ||
1729 | * exit, either normal or abnormal. | ||
1730 | */ | ||
1731 | retval = 0; | ||
1732 | add_wait_queue(&info->open_wait, &wait); | ||
1733 | #ifdef SERIAL_DEBUG_OPEN | ||
1734 | printk("block_til_ready before block: %s, count = %d\n", | ||
1735 | tty->name, info->count); | ||
1736 | /**/ | ||
1737 | #endif | ||
1738 | info->count--; | ||
1739 | #ifdef SERIAL_DEBUG_COUNT | ||
1740 | printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count); | ||
1741 | #endif | ||
1742 | info->blocked_open++; | ||
1743 | |||
1744 | channel = info->line; | ||
1745 | |||
1746 | while (1) { | ||
1747 | local_irq_save(flags); | ||
1748 | base_addr[CyCAR] = (u_char) channel; | ||
1749 | base_addr[CyMSVR1] = CyRTS; | ||
1750 | /* CP('S');CP('4'); */ | ||
1751 | base_addr[CyMSVR2] = CyDTR; | ||
1752 | #ifdef SERIAL_DEBUG_DTR | ||
1753 | printk("cyc: %d: raising DTR\n", __LINE__); | ||
1754 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], | ||
1755 | base_addr[CyMSVR2]); | ||
1756 | #endif | ||
1757 | local_irq_restore(flags); | ||
1758 | set_current_state(TASK_INTERRUPTIBLE); | ||
1759 | if (tty_hung_up_p(filp) | ||
1760 | || !(info->flags & ASYNC_INITIALIZED)) { | ||
1761 | if (info->flags & ASYNC_HUP_NOTIFY) { | ||
1762 | retval = -EAGAIN; | ||
1763 | } else { | ||
1764 | retval = -ERESTARTSYS; | ||
1765 | } | ||
1766 | break; | ||
1767 | } | ||
1768 | local_irq_save(flags); | ||
1769 | base_addr[CyCAR] = (u_char) channel; | ||
1770 | /* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */ | ||
1771 | if (!(info->flags & ASYNC_CLOSING) | ||
1772 | && (C_CLOCAL(tty) | ||
1773 | || (base_addr[CyMSVR1] & CyDCD))) { | ||
1774 | local_irq_restore(flags); | ||
1775 | break; | ||
1776 | } | ||
1777 | local_irq_restore(flags); | ||
1778 | if (signal_pending(current)) { | ||
1779 | retval = -ERESTARTSYS; | ||
1780 | break; | ||
1781 | } | ||
1782 | #ifdef SERIAL_DEBUG_OPEN | ||
1783 | printk("block_til_ready blocking: %s, count = %d\n", | ||
1784 | tty->name, info->count); | ||
1785 | /**/ | ||
1786 | #endif | ||
1787 | tty_unlock(); | ||
1788 | schedule(); | ||
1789 | tty_lock(); | ||
1790 | } | ||
1791 | __set_current_state(TASK_RUNNING); | ||
1792 | remove_wait_queue(&info->open_wait, &wait); | ||
1793 | if (!tty_hung_up_p(filp)) { | ||
1794 | info->count++; | ||
1795 | #ifdef SERIAL_DEBUG_COUNT | ||
1796 | printk("cyc: %d: incrementing count to %d\n", __LINE__, | ||
1797 | info->count); | ||
1798 | #endif | ||
1799 | } | ||
1800 | info->blocked_open--; | ||
1801 | #ifdef SERIAL_DEBUG_OPEN | ||
1802 | printk("block_til_ready after blocking: %s, count = %d\n", | ||
1803 | tty->name, info->count); | ||
1804 | /**/ | ||
1805 | #endif | ||
1806 | if (retval) | ||
1807 | return retval; | ||
1808 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
1809 | return 0; | ||
1810 | } /* block_til_ready */ | ||
1811 | |||
1812 | /* | ||
1813 | * This routine is called whenever a serial port is opened. It | ||
1814 | * performs the serial-specific initialization for the tty structure. | ||
1815 | */ | ||
1816 | int cy_open(struct tty_struct *tty, struct file *filp) | ||
1817 | { | ||
1818 | struct cyclades_port *info; | ||
1819 | int retval, line; | ||
1820 | |||
1821 | /* CP('O'); */ | ||
1822 | line = tty->index; | ||
1823 | if ((line < 0) || (NR_PORTS <= line)) { | ||
1824 | return -ENODEV; | ||
1825 | } | ||
1826 | info = &cy_port[line]; | ||
1827 | if (info->line < 0) { | ||
1828 | return -ENODEV; | ||
1829 | } | ||
1830 | #ifdef SERIAL_DEBUG_OTHER | ||
1831 | printk("cy_open %s\n", tty->name); /* */ | ||
1832 | #endif | ||
1833 | if (serial_paranoia_check(info, tty->name, "cy_open")) { | ||
1834 | return -ENODEV; | ||
1835 | } | ||
1836 | #ifdef SERIAL_DEBUG_OPEN | ||
1837 | printk("cy_open %s, count = %d\n", tty->name, info->count); | ||
1838 | /**/ | ||
1839 | #endif | ||
1840 | info->count++; | ||
1841 | #ifdef SERIAL_DEBUG_COUNT | ||
1842 | printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); | ||
1843 | #endif | ||
1844 | tty->driver_data = info; | ||
1845 | info->tty = tty; | ||
1846 | |||
1847 | /* | ||
1848 | * Start up serial port | ||
1849 | */ | ||
1850 | retval = startup(info); | ||
1851 | if (retval) { | ||
1852 | return retval; | ||
1853 | } | ||
1854 | |||
1855 | retval = block_til_ready(tty, filp, info); | ||
1856 | if (retval) { | ||
1857 | #ifdef SERIAL_DEBUG_OPEN | ||
1858 | printk("cy_open returning after block_til_ready with %d\n", | ||
1859 | retval); | ||
1860 | #endif | ||
1861 | return retval; | ||
1862 | } | ||
1863 | #ifdef SERIAL_DEBUG_OPEN | ||
1864 | printk("cy_open done\n"); | ||
1865 | /**/ | ||
1866 | #endif | ||
1867 | return 0; | ||
1868 | } /* cy_open */ | ||
1869 | |||
1870 | /* | ||
1871 | * --------------------------------------------------------------------- | ||
1872 | * serial167_init() and friends | ||
1873 | * | ||
1874 | * serial167_init() is called at boot-time to initialize the serial driver. | ||
1875 | * --------------------------------------------------------------------- | ||
1876 | */ | ||
1877 | |||
1878 | /* | ||
1879 | * This routine prints out the appropriate serial driver version | ||
1880 | * number, and identifies which options were configured into this | ||
1881 | * driver. | ||
1882 | */ | ||
1883 | static void show_version(void) | ||
1884 | { | ||
1885 | printk("MVME166/167 cd2401 driver\n"); | ||
1886 | } /* show_version */ | ||
1887 | |||
1888 | /* initialize chips on card -- return number of valid | ||
1889 | chips (which is number of ports/4) */ | ||
1890 | |||
1891 | /* | ||
1892 | * This initialises the hardware to a reasonable state. It should | ||
1893 | * probe the chip first so as to copy 166-Bug setup as a default for | ||
1894 | * port 0. It initialises CMR to CyASYNC; that is never done again, so | ||
1895 | * as to limit the number of CyINIT_CHAN commands in normal running. | ||
1896 | * | ||
1897 | * ... I wonder what I should do if this fails ... | ||
1898 | */ | ||
1899 | |||
1900 | void mvme167_serial_console_setup(int cflag) | ||
1901 | { | ||
1902 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1903 | int ch; | ||
1904 | u_char spd; | ||
1905 | u_char rcor, rbpr, badspeed = 0; | ||
1906 | unsigned long flags; | ||
1907 | |||
1908 | local_irq_save(flags); | ||
1909 | |||
1910 | /* | ||
1911 | * First probe channel zero of the chip, to see what speed has | ||
1912 | * been selected. | ||
1913 | */ | ||
1914 | |||
1915 | base_addr[CyCAR] = 0; | ||
1916 | |||
1917 | rcor = base_addr[CyRCOR] << 5; | ||
1918 | rbpr = base_addr[CyRBPR]; | ||
1919 | |||
1920 | for (spd = 0; spd < sizeof(baud_bpr); spd++) | ||
1921 | if (rbpr == baud_bpr[spd] && rcor == baud_co[spd]) | ||
1922 | break; | ||
1923 | if (spd >= sizeof(baud_bpr)) { | ||
1924 | spd = 14; /* 19200 */ | ||
1925 | badspeed = 1; /* Failed to identify speed */ | ||
1926 | } | ||
1927 | initial_console_speed = spd; | ||
1928 | |||
1929 | /* OK, we have chosen a speed, now reset and reinitialise */ | ||
1930 | |||
1931 | my_udelay(20000L); /* Allow time for any active o/p to complete */ | ||
1932 | if (base_addr[CyCCR] != 0x00) { | ||
1933 | local_irq_restore(flags); | ||
1934 | /* printk(" chip is never idle (CCR != 0)\n"); */ | ||
1935 | return; | ||
1936 | } | ||
1937 | |||
1938 | base_addr[CyCCR] = CyCHIP_RESET; /* Reset the chip */ | ||
1939 | my_udelay(1000L); | ||
1940 | |||
1941 | if (base_addr[CyGFRCR] == 0x00) { | ||
1942 | local_irq_restore(flags); | ||
1943 | /* printk(" chip is not responding (GFRCR stayed 0)\n"); */ | ||
1944 | return; | ||
1945 | } | ||
1946 | |||
1947 | /* | ||
1948 | * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms | ||
1949 | * tick | ||
1950 | */ | ||
1951 | |||
1952 | base_addr[CyTPR] = 10; | ||
1953 | |||
1954 | base_addr[CyPILR1] = 0x01; /* Interrupt level for modem change */ | ||
1955 | base_addr[CyPILR2] = 0x02; /* Interrupt level for tx ints */ | ||
1956 | base_addr[CyPILR3] = 0x03; /* Interrupt level for rx ints */ | ||
1957 | |||
1958 | /* | ||
1959 | * Attempt to set up all channels to something reasonable, and | ||
1960 | * bang out a INIT_CHAN command. We should then be able to limit | ||
1961 | * the amount of fiddling we have to do in normal running. | ||
1962 | */ | ||
1963 | |||
1964 | for (ch = 3; ch >= 0; ch--) { | ||
1965 | base_addr[CyCAR] = (u_char) ch; | ||
1966 | base_addr[CyIER] = 0; | ||
1967 | base_addr[CyCMR] = CyASYNC; | ||
1968 | base_addr[CyLICR] = (u_char) ch << 2; | ||
1969 | base_addr[CyLIVR] = 0x5c; | ||
1970 | base_addr[CyTCOR] = baud_co[spd]; | ||
1971 | base_addr[CyTBPR] = baud_bpr[spd]; | ||
1972 | base_addr[CyRCOR] = baud_co[spd] >> 5; | ||
1973 | base_addr[CyRBPR] = baud_bpr[spd]; | ||
1974 | base_addr[CySCHR1] = 'Q' & 0x1f; | ||
1975 | base_addr[CySCHR2] = 'X' & 0x1f; | ||
1976 | base_addr[CySCRL] = 0; | ||
1977 | base_addr[CySCRH] = 0; | ||
1978 | base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE; | ||
1979 | base_addr[CyCOR2] = 0; | ||
1980 | base_addr[CyCOR3] = Cy_1_STOP; | ||
1981 | base_addr[CyCOR4] = baud_cor4[spd]; | ||
1982 | base_addr[CyCOR5] = 0; | ||
1983 | base_addr[CyCOR6] = 0; | ||
1984 | base_addr[CyCOR7] = 0; | ||
1985 | base_addr[CyRTPRL] = 2; | ||
1986 | base_addr[CyRTPRH] = 0; | ||
1987 | base_addr[CyMSVR1] = 0; | ||
1988 | base_addr[CyMSVR2] = 0; | ||
1989 | write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR); | ||
1990 | } | ||
1991 | |||
1992 | /* | ||
1993 | * Now do specials for channel zero.... | ||
1994 | */ | ||
1995 | |||
1996 | base_addr[CyMSVR1] = CyRTS; | ||
1997 | base_addr[CyMSVR2] = CyDTR; | ||
1998 | base_addr[CyIER] = CyRxData; | ||
1999 | write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR); | ||
2000 | |||
2001 | local_irq_restore(flags); | ||
2002 | |||
2003 | my_udelay(20000L); /* Let it all settle down */ | ||
2004 | |||
2005 | printk("CD2401 initialised, chip is rev 0x%02x\n", base_addr[CyGFRCR]); | ||
2006 | if (badspeed) | ||
2007 | printk | ||
2008 | (" WARNING: Failed to identify line speed, rcor=%02x,rbpr=%02x\n", | ||
2009 | rcor >> 5, rbpr); | ||
2010 | } /* serial_console_init */ | ||
2011 | |||
2012 | static const struct tty_operations cy_ops = { | ||
2013 | .open = cy_open, | ||
2014 | .close = cy_close, | ||
2015 | .write = cy_write, | ||
2016 | .put_char = cy_put_char, | ||
2017 | .flush_chars = cy_flush_chars, | ||
2018 | .write_room = cy_write_room, | ||
2019 | .chars_in_buffer = cy_chars_in_buffer, | ||
2020 | .flush_buffer = cy_flush_buffer, | ||
2021 | .ioctl = cy_ioctl, | ||
2022 | .throttle = cy_throttle, | ||
2023 | .unthrottle = cy_unthrottle, | ||
2024 | .set_termios = cy_set_termios, | ||
2025 | .stop = cy_stop, | ||
2026 | .start = cy_start, | ||
2027 | .hangup = cy_hangup, | ||
2028 | .tiocmget = cy_tiocmget, | ||
2029 | .tiocmset = cy_tiocmset, | ||
2030 | }; | ||
2031 | |||
2032 | /* The serial driver boot-time initialization code! | ||
2033 | Hardware I/O ports are mapped to character special devices on a | ||
2034 | first found, first allocated manner. That is, this code searches | ||
2035 | for Cyclom cards in the system. As each is found, it is probed | ||
2036 | to discover how many chips (and thus how many ports) are present. | ||
2037 | These ports are mapped to the tty ports 64 and upward in monotonic | ||
2038 | fashion. If an 8-port card is replaced with a 16-port card, the | ||
2039 | port mapping on a following card will shift. | ||
2040 | |||
2041 | This approach is different from what is used in the other serial | ||
2042 | device driver because the Cyclom is more properly a multiplexer, | ||
2043 | not just an aggregation of serial ports on one card. | ||
2044 | |||
2045 | If there are more cards with more ports than have been statically | ||
2046 | allocated above, a warning is printed and the extra ports are ignored. | ||
2047 | */ | ||
2048 | static int __init serial167_init(void) | ||
2049 | { | ||
2050 | struct cyclades_port *info; | ||
2051 | int ret = 0; | ||
2052 | int good_ports = 0; | ||
2053 | int port_num = 0; | ||
2054 | int index; | ||
2055 | int DefSpeed; | ||
2056 | #ifdef notyet | ||
2057 | struct sigaction sa; | ||
2058 | #endif | ||
2059 | |||
2060 | if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401)) | ||
2061 | return 0; | ||
2062 | |||
2063 | cy_serial_driver = alloc_tty_driver(NR_PORTS); | ||
2064 | if (!cy_serial_driver) | ||
2065 | return -ENOMEM; | ||
2066 | |||
2067 | #if 0 | ||
2068 | scrn[1] = '\0'; | ||
2069 | #endif | ||
2070 | |||
2071 | show_version(); | ||
2072 | |||
2073 | /* Has "console=0,9600n8" been used in bootinfo to change speed? */ | ||
2074 | if (serial_console_cflag) | ||
2075 | DefSpeed = serial_console_cflag & 0017; | ||
2076 | else { | ||
2077 | DefSpeed = initial_console_speed; | ||
2078 | serial_console_info = &cy_port[0]; | ||
2079 | serial_console_cflag = DefSpeed | CS8; | ||
2080 | #if 0 | ||
2081 | serial_console = 64; /*callout_driver.minor_start */ | ||
2082 | #endif | ||
2083 | } | ||
2084 | |||
2085 | /* Initialize the tty_driver structure */ | ||
2086 | |||
2087 | cy_serial_driver->owner = THIS_MODULE; | ||
2088 | cy_serial_driver->name = "ttyS"; | ||
2089 | cy_serial_driver->major = TTY_MAJOR; | ||
2090 | cy_serial_driver->minor_start = 64; | ||
2091 | cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2092 | cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
2093 | cy_serial_driver->init_termios = tty_std_termios; | ||
2094 | cy_serial_driver->init_termios.c_cflag = | ||
2095 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
2096 | cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; | ||
2097 | tty_set_operations(cy_serial_driver, &cy_ops); | ||
2098 | |||
2099 | ret = tty_register_driver(cy_serial_driver); | ||
2100 | if (ret) { | ||
2101 | printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n"); | ||
2102 | put_tty_driver(cy_serial_driver); | ||
2103 | return ret; | ||
2104 | } | ||
2105 | |||
2106 | port_num = 0; | ||
2107 | info = cy_port; | ||
2108 | for (index = 0; index < 1; index++) { | ||
2109 | |||
2110 | good_ports = 4; | ||
2111 | |||
2112 | if (port_num < NR_PORTS) { | ||
2113 | while (good_ports-- && port_num < NR_PORTS) { | ||
2114 | /*** initialize port ***/ | ||
2115 | info->magic = CYCLADES_MAGIC; | ||
2116 | info->type = PORT_CIRRUS; | ||
2117 | info->card = index; | ||
2118 | info->line = port_num; | ||
2119 | info->flags = STD_COM_FLAGS; | ||
2120 | info->tty = NULL; | ||
2121 | info->xmit_fifo_size = 12; | ||
2122 | info->cor1 = CyPARITY_NONE | Cy_8_BITS; | ||
2123 | info->cor2 = CyETC; | ||
2124 | info->cor3 = Cy_1_STOP; | ||
2125 | info->cor4 = 0x08; /* _very_ small receive threshold */ | ||
2126 | info->cor5 = 0; | ||
2127 | info->cor6 = 0; | ||
2128 | info->cor7 = 0; | ||
2129 | info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */ | ||
2130 | info->tco = baud_co[DefSpeed]; /* Tx CO */ | ||
2131 | info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */ | ||
2132 | info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ | ||
2133 | info->close_delay = 0; | ||
2134 | info->x_char = 0; | ||
2135 | info->count = 0; | ||
2136 | #ifdef SERIAL_DEBUG_COUNT | ||
2137 | printk("cyc: %d: setting count to 0\n", | ||
2138 | __LINE__); | ||
2139 | #endif | ||
2140 | info->blocked_open = 0; | ||
2141 | info->default_threshold = 0; | ||
2142 | info->default_timeout = 0; | ||
2143 | init_waitqueue_head(&info->open_wait); | ||
2144 | init_waitqueue_head(&info->close_wait); | ||
2145 | /* info->session */ | ||
2146 | /* info->pgrp */ | ||
2147 | /*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/ | ||
2148 | info->read_status_mask = | ||
2149 | CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY | | ||
2150 | CyFRAME | CyOVERRUN; | ||
2151 | /* info->timeout */ | ||
2152 | |||
2153 | printk("ttyS%d ", info->line); | ||
2154 | port_num++; | ||
2155 | info++; | ||
2156 | if (!(port_num & 7)) { | ||
2157 | printk("\n "); | ||
2158 | } | ||
2159 | } | ||
2160 | } | ||
2161 | printk("\n"); | ||
2162 | } | ||
2163 | while (port_num < NR_PORTS) { | ||
2164 | info->line = -1; | ||
2165 | port_num++; | ||
2166 | info++; | ||
2167 | } | ||
2168 | |||
2169 | ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, | ||
2170 | "cd2401_errors", cd2401_rxerr_interrupt); | ||
2171 | if (ret) { | ||
2172 | printk(KERN_ERR "Could't get cd2401_errors IRQ"); | ||
2173 | goto cleanup_serial_driver; | ||
2174 | } | ||
2175 | |||
2176 | ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0, | ||
2177 | "cd2401_modem", cd2401_modem_interrupt); | ||
2178 | if (ret) { | ||
2179 | printk(KERN_ERR "Could't get cd2401_modem IRQ"); | ||
2180 | goto cleanup_irq_cd2401_errors; | ||
2181 | } | ||
2182 | |||
2183 | ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0, | ||
2184 | "cd2401_txints", cd2401_tx_interrupt); | ||
2185 | if (ret) { | ||
2186 | printk(KERN_ERR "Could't get cd2401_txints IRQ"); | ||
2187 | goto cleanup_irq_cd2401_modem; | ||
2188 | } | ||
2189 | |||
2190 | ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0, | ||
2191 | "cd2401_rxints", cd2401_rx_interrupt); | ||
2192 | if (ret) { | ||
2193 | printk(KERN_ERR "Could't get cd2401_rxints IRQ"); | ||
2194 | goto cleanup_irq_cd2401_txints; | ||
2195 | } | ||
2196 | |||
2197 | /* Now we have registered the interrupt handlers, allow the interrupts */ | ||
2198 | |||
2199 | pcc2chip[PccSCCMICR] = 0x15; /* Serial ints are level 5 */ | ||
2200 | pcc2chip[PccSCCTICR] = 0x15; | ||
2201 | pcc2chip[PccSCCRICR] = 0x15; | ||
2202 | |||
2203 | pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */ | ||
2204 | |||
2205 | return 0; | ||
2206 | cleanup_irq_cd2401_txints: | ||
2207 | free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt); | ||
2208 | cleanup_irq_cd2401_modem: | ||
2209 | free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt); | ||
2210 | cleanup_irq_cd2401_errors: | ||
2211 | free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt); | ||
2212 | cleanup_serial_driver: | ||
2213 | if (tty_unregister_driver(cy_serial_driver)) | ||
2214 | printk(KERN_ERR | ||
2215 | "Couldn't unregister MVME166/7 serial driver\n"); | ||
2216 | put_tty_driver(cy_serial_driver); | ||
2217 | return ret; | ||
2218 | } /* serial167_init */ | ||
2219 | |||
2220 | module_init(serial167_init); | ||
2221 | |||
2222 | #ifdef CYCLOM_SHOW_STATUS | ||
2223 | static void show_status(int line_num) | ||
2224 | { | ||
2225 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
2226 | int channel; | ||
2227 | struct cyclades_port *info; | ||
2228 | unsigned long flags; | ||
2229 | |||
2230 | info = &cy_port[line_num]; | ||
2231 | channel = info->line; | ||
2232 | printk(" channel %d\n", channel); | ||
2233 | /**/ printk(" cy_port\n"); | ||
2234 | printk(" card line flags = %d %d %x\n", | ||
2235 | info->card, info->line, info->flags); | ||
2236 | printk | ||
2237 | (" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n", | ||
2238 | (long)info->tty, info->read_status_mask, info->timeout, | ||
2239 | info->xmit_fifo_size); | ||
2240 | printk(" cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n", | ||
2241 | info->cor1, info->cor2, info->cor3, info->cor4, info->cor5, | ||
2242 | info->cor6, info->cor7); | ||
2243 | printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco, | ||
2244 | info->rbpr, info->rco); | ||
2245 | printk(" close_delay event count = %d %d %d\n", info->close_delay, | ||
2246 | info->event, info->count); | ||
2247 | printk(" x_char blocked_open = %x %x\n", info->x_char, | ||
2248 | info->blocked_open); | ||
2249 | printk(" open_wait = %lx %lx %lx\n", (long)info->open_wait); | ||
2250 | |||
2251 | local_irq_save(flags); | ||
2252 | |||
2253 | /* Global Registers */ | ||
2254 | |||
2255 | printk(" CyGFRCR %x\n", base_addr[CyGFRCR]); | ||
2256 | printk(" CyCAR %x\n", base_addr[CyCAR]); | ||
2257 | printk(" CyRISR %x\n", base_addr[CyRISR]); | ||
2258 | printk(" CyTISR %x\n", base_addr[CyTISR]); | ||
2259 | printk(" CyMISR %x\n", base_addr[CyMISR]); | ||
2260 | printk(" CyRIR %x\n", base_addr[CyRIR]); | ||
2261 | printk(" CyTIR %x\n", base_addr[CyTIR]); | ||
2262 | printk(" CyMIR %x\n", base_addr[CyMIR]); | ||
2263 | printk(" CyTPR %x\n", base_addr[CyTPR]); | ||
2264 | |||
2265 | base_addr[CyCAR] = (u_char) channel; | ||
2266 | |||
2267 | /* Virtual Registers */ | ||
2268 | |||
2269 | #if 0 | ||
2270 | printk(" CyRIVR %x\n", base_addr[CyRIVR]); | ||
2271 | printk(" CyTIVR %x\n", base_addr[CyTIVR]); | ||
2272 | printk(" CyMIVR %x\n", base_addr[CyMIVR]); | ||
2273 | printk(" CyMISR %x\n", base_addr[CyMISR]); | ||
2274 | #endif | ||
2275 | |||
2276 | /* Channel Registers */ | ||
2277 | |||
2278 | printk(" CyCCR %x\n", base_addr[CyCCR]); | ||
2279 | printk(" CyIER %x\n", base_addr[CyIER]); | ||
2280 | printk(" CyCOR1 %x\n", base_addr[CyCOR1]); | ||
2281 | printk(" CyCOR2 %x\n", base_addr[CyCOR2]); | ||
2282 | printk(" CyCOR3 %x\n", base_addr[CyCOR3]); | ||
2283 | printk(" CyCOR4 %x\n", base_addr[CyCOR4]); | ||
2284 | printk(" CyCOR5 %x\n", base_addr[CyCOR5]); | ||
2285 | #if 0 | ||
2286 | printk(" CyCCSR %x\n", base_addr[CyCCSR]); | ||
2287 | printk(" CyRDCR %x\n", base_addr[CyRDCR]); | ||
2288 | #endif | ||
2289 | printk(" CySCHR1 %x\n", base_addr[CySCHR1]); | ||
2290 | printk(" CySCHR2 %x\n", base_addr[CySCHR2]); | ||
2291 | #if 0 | ||
2292 | printk(" CySCHR3 %x\n", base_addr[CySCHR3]); | ||
2293 | printk(" CySCHR4 %x\n", base_addr[CySCHR4]); | ||
2294 | printk(" CySCRL %x\n", base_addr[CySCRL]); | ||
2295 | printk(" CySCRH %x\n", base_addr[CySCRH]); | ||
2296 | printk(" CyLNC %x\n", base_addr[CyLNC]); | ||
2297 | printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]); | ||
2298 | printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]); | ||
2299 | #endif | ||
2300 | printk(" CyRTPRL %x\n", base_addr[CyRTPRL]); | ||
2301 | printk(" CyRTPRH %x\n", base_addr[CyRTPRH]); | ||
2302 | printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]); | ||
2303 | printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]); | ||
2304 | printk(" CyRBPR %x\n", base_addr[CyRBPR]); | ||
2305 | printk(" CyRCOR %x\n", base_addr[CyRCOR]); | ||
2306 | printk(" CyTBPR %x\n", base_addr[CyTBPR]); | ||
2307 | printk(" CyTCOR %x\n", base_addr[CyTCOR]); | ||
2308 | |||
2309 | local_irq_restore(flags); | ||
2310 | } /* show_status */ | ||
2311 | #endif | ||
2312 | |||
2313 | #if 0 | ||
2314 | /* Dummy routine in mvme16x/config.c for now */ | ||
2315 | |||
2316 | /* Serial console setup. Called from linux/init/main.c */ | ||
2317 | |||
2318 | void console_setup(char *str, int *ints) | ||
2319 | { | ||
2320 | char *s; | ||
2321 | int baud, bits, parity; | ||
2322 | int cflag = 0; | ||
2323 | |||
2324 | /* Sanity check. */ | ||
2325 | if (ints[0] > 3 || ints[1] > 3) | ||
2326 | return; | ||
2327 | |||
2328 | /* Get baud, bits and parity */ | ||
2329 | baud = 2400; | ||
2330 | bits = 8; | ||
2331 | parity = 'n'; | ||
2332 | if (ints[2]) | ||
2333 | baud = ints[2]; | ||
2334 | if ((s = strchr(str, ','))) { | ||
2335 | do { | ||
2336 | s++; | ||
2337 | } while (*s >= '0' && *s <= '9'); | ||
2338 | if (*s) | ||
2339 | parity = *s++; | ||
2340 | if (*s) | ||
2341 | bits = *s - '0'; | ||
2342 | } | ||
2343 | |||
2344 | /* Now construct a cflag setting. */ | ||
2345 | switch (baud) { | ||
2346 | case 1200: | ||
2347 | cflag |= B1200; | ||
2348 | break; | ||
2349 | case 9600: | ||
2350 | cflag |= B9600; | ||
2351 | break; | ||
2352 | case 19200: | ||
2353 | cflag |= B19200; | ||
2354 | break; | ||
2355 | case 38400: | ||
2356 | cflag |= B38400; | ||
2357 | break; | ||
2358 | case 2400: | ||
2359 | default: | ||
2360 | cflag |= B2400; | ||
2361 | break; | ||
2362 | } | ||
2363 | switch (bits) { | ||
2364 | case 7: | ||
2365 | cflag |= CS7; | ||
2366 | break; | ||
2367 | default: | ||
2368 | case 8: | ||
2369 | cflag |= CS8; | ||
2370 | break; | ||
2371 | } | ||
2372 | switch (parity) { | ||
2373 | case 'o': | ||
2374 | case 'O': | ||
2375 | cflag |= PARODD; | ||
2376 | break; | ||
2377 | case 'e': | ||
2378 | case 'E': | ||
2379 | cflag |= PARENB; | ||
2380 | break; | ||
2381 | } | ||
2382 | |||
2383 | serial_console_info = &cy_port[ints[1]]; | ||
2384 | serial_console_cflag = cflag; | ||
2385 | serial_console = ints[1] + 64; /*callout_driver.minor_start */ | ||
2386 | } | ||
2387 | #endif | ||
2388 | |||
2389 | /* | ||
2390 | * The following is probably out of date for 2.1.x serial console stuff. | ||
2391 | * | ||
2392 | * The console is registered early on from arch/m68k/kernel/setup.c, and | ||
2393 | * it therefore relies on the chip being setup correctly by 166-Bug. This | ||
2394 | * seems reasonable, as the serial port has been used to invoke the system | ||
2395 | * boot. It also means that this function must not rely on any data | ||
2396 | * initialisation performed by serial167_init() etc. | ||
2397 | * | ||
2398 | * Of course, once the console has been registered, we had better ensure | ||
2399 | * that serial167_init() doesn't leave the chip non-functional. | ||
2400 | * | ||
2401 | * The console must be locked when we get here. | ||
2402 | */ | ||
2403 | |||
2404 | void serial167_console_write(struct console *co, const char *str, | ||
2405 | unsigned count) | ||
2406 | { | ||
2407 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
2408 | unsigned long flags; | ||
2409 | volatile u_char sink; | ||
2410 | u_char ier; | ||
2411 | int port; | ||
2412 | u_char do_lf = 0; | ||
2413 | int i = 0; | ||
2414 | |||
2415 | local_irq_save(flags); | ||
2416 | |||
2417 | /* Ensure transmitter is enabled! */ | ||
2418 | |||
2419 | port = 0; | ||
2420 | base_addr[CyCAR] = (u_char) port; | ||
2421 | while (base_addr[CyCCR]) | ||
2422 | ; | ||
2423 | base_addr[CyCCR] = CyENB_XMTR; | ||
2424 | |||
2425 | ier = base_addr[CyIER]; | ||
2426 | base_addr[CyIER] = CyTxMpty; | ||
2427 | |||
2428 | while (1) { | ||
2429 | if (pcc2chip[PccSCCTICR] & 0x20) { | ||
2430 | /* We have a Tx int. Acknowledge it */ | ||
2431 | sink = pcc2chip[PccTPIACKR]; | ||
2432 | if ((base_addr[CyLICR] >> 2) == port) { | ||
2433 | if (i == count) { | ||
2434 | /* Last char of string is now output */ | ||
2435 | base_addr[CyTEOIR] = CyNOTRANS; | ||
2436 | break; | ||
2437 | } | ||
2438 | if (do_lf) { | ||
2439 | base_addr[CyTDR] = '\n'; | ||
2440 | str++; | ||
2441 | i++; | ||
2442 | do_lf = 0; | ||
2443 | } else if (*str == '\n') { | ||
2444 | base_addr[CyTDR] = '\r'; | ||
2445 | do_lf = 1; | ||
2446 | } else { | ||
2447 | base_addr[CyTDR] = *str++; | ||
2448 | i++; | ||
2449 | } | ||
2450 | base_addr[CyTEOIR] = 0; | ||
2451 | } else | ||
2452 | base_addr[CyTEOIR] = CyNOTRANS; | ||
2453 | } | ||
2454 | } | ||
2455 | |||
2456 | base_addr[CyIER] = ier; | ||
2457 | |||
2458 | local_irq_restore(flags); | ||
2459 | } | ||
2460 | |||
2461 | static struct tty_driver *serial167_console_device(struct console *c, | ||
2462 | int *index) | ||
2463 | { | ||
2464 | *index = c->index; | ||
2465 | return cy_serial_driver; | ||
2466 | } | ||
2467 | |||
2468 | static struct console sercons = { | ||
2469 | .name = "ttyS", | ||
2470 | .write = serial167_console_write, | ||
2471 | .device = serial167_console_device, | ||
2472 | .flags = CON_PRINTBUFFER, | ||
2473 | .index = -1, | ||
2474 | }; | ||
2475 | |||
2476 | static int __init serial167_console_init(void) | ||
2477 | { | ||
2478 | if (vme_brdtype == VME_TYPE_MVME166 || | ||
2479 | vme_brdtype == VME_TYPE_MVME167 || | ||
2480 | vme_brdtype == VME_TYPE_MVME177) { | ||
2481 | mvme167_serial_console_setup(0); | ||
2482 | register_console(&sercons); | ||
2483 | } | ||
2484 | return 0; | ||
2485 | } | ||
2486 | |||
2487 | console_initcall(serial167_console_init); | ||
2488 | |||
2489 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c deleted file mode 100644 index 47e5753f732a..000000000000 --- a/drivers/char/specialix.c +++ /dev/null | |||
@@ -1,2368 +0,0 @@ | |||
1 | /* | ||
2 | * specialix.c -- specialix IO8+ multiport serial driver. | ||
3 | * | ||
4 | * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) | ||
5 | * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) | ||
6 | * | ||
7 | * Specialix pays for the development and support of this driver. | ||
8 | * Please DO contact io8-linux@specialix.co.uk if you require | ||
9 | * support. But please read the documentation (specialix.txt) | ||
10 | * first. | ||
11 | * | ||
12 | * This driver was developped in the BitWizard linux device | ||
13 | * driver service. If you require a linux device driver for your | ||
14 | * product, please contact devices@BitWizard.nl for a quote. | ||
15 | * | ||
16 | * This code is firmly based on the riscom/8 serial driver, | ||
17 | * written by Dmitry Gorodchanin. The specialix IO8+ card | ||
18 | * programming information was obtained from the CL-CD1865 Data | ||
19 | * Book, and Specialix document number 6200059: IO8+ Hardware | ||
20 | * Functional Specification. | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or | ||
23 | * modify it under the terms of the GNU General Public License as | ||
24 | * published by the Free Software Foundation; either version 2 of | ||
25 | * the License, or (at your option) any later version. | ||
26 | * | ||
27 | * This program is distributed in the hope that it will be | ||
28 | * useful, but WITHOUT ANY WARRANTY; without even the implied | ||
29 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
30 | * PURPOSE. See the GNU General Public License for more details. | ||
31 | * | ||
32 | * You should have received a copy of the GNU General Public | ||
33 | * License along with this program; if not, write to the Free | ||
34 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, | ||
35 | * USA. | ||
36 | * | ||
37 | * Revision history: | ||
38 | * | ||
39 | * Revision 1.0: April 1st 1997. | ||
40 | * Initial release for alpha testing. | ||
41 | * Revision 1.1: April 14th 1997. | ||
42 | * Incorporated Richard Hudsons suggestions, | ||
43 | * removed some debugging printk's. | ||
44 | * Revision 1.2: April 15th 1997. | ||
45 | * Ported to 2.1.x kernels. | ||
46 | * Revision 1.3: April 17th 1997 | ||
47 | * Backported to 2.0. (Compatibility macros). | ||
48 | * Revision 1.4: April 18th 1997 | ||
49 | * Fixed DTR/RTS bug that caused the card to indicate | ||
50 | * "don't send data" to a modem after the password prompt. | ||
51 | * Fixed bug for premature (fake) interrupts. | ||
52 | * Revision 1.5: April 19th 1997 | ||
53 | * fixed a minor typo in the header file, cleanup a little. | ||
54 | * performance warnings are now MAXed at once per minute. | ||
55 | * Revision 1.6: May 23 1997 | ||
56 | * Changed the specialix=... format to include interrupt. | ||
57 | * Revision 1.7: May 27 1997 | ||
58 | * Made many more debug printk's a compile time option. | ||
59 | * Revision 1.8: Jul 1 1997 | ||
60 | * port to linux-2.1.43 kernel. | ||
61 | * Revision 1.9: Oct 9 1998 | ||
62 | * Added stuff for the IO8+/PCI version. | ||
63 | * Revision 1.10: Oct 22 1999 / Jan 21 2000. | ||
64 | * Added stuff for setserial. | ||
65 | * Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr) | ||
66 | * | ||
67 | */ | ||
68 | |||
69 | #define VERSION "1.11" | ||
70 | |||
71 | |||
72 | /* | ||
73 | * There is a bunch of documentation about the card, jumpers, config | ||
74 | * settings, restrictions, cables, device names and numbers in | ||
75 | * Documentation/serial/specialix.txt | ||
76 | */ | ||
77 | |||
78 | #include <linux/module.h> | ||
79 | |||
80 | #include <linux/io.h> | ||
81 | #include <linux/kernel.h> | ||
82 | #include <linux/sched.h> | ||
83 | #include <linux/ioport.h> | ||
84 | #include <linux/interrupt.h> | ||
85 | #include <linux/errno.h> | ||
86 | #include <linux/tty.h> | ||
87 | #include <linux/tty_flip.h> | ||
88 | #include <linux/mm.h> | ||
89 | #include <linux/serial.h> | ||
90 | #include <linux/fcntl.h> | ||
91 | #include <linux/major.h> | ||
92 | #include <linux/delay.h> | ||
93 | #include <linux/pci.h> | ||
94 | #include <linux/init.h> | ||
95 | #include <linux/uaccess.h> | ||
96 | #include <linux/gfp.h> | ||
97 | |||
98 | #include "specialix_io8.h" | ||
99 | #include "cd1865.h" | ||
100 | |||
101 | |||
102 | /* | ||
103 | This driver can spew a whole lot of debugging output at you. If you | ||
104 | need maximum performance, you should disable the DEBUG define. To | ||
105 | aid in debugging in the field, I'm leaving the compile-time debug | ||
106 | features enabled, and disable them "runtime". That allows me to | ||
107 | instruct people with problems to enable debugging without requiring | ||
108 | them to recompile... | ||
109 | */ | ||
110 | #define DEBUG | ||
111 | |||
112 | static int sx_debug; | ||
113 | static int sx_rxfifo = SPECIALIX_RXFIFO; | ||
114 | static int sx_rtscts; | ||
115 | |||
116 | #ifdef DEBUG | ||
117 | #define dprintk(f, str...) if (sx_debug & f) printk(str) | ||
118 | #else | ||
119 | #define dprintk(f, str...) /* nothing */ | ||
120 | #endif | ||
121 | |||
122 | #define SX_DEBUG_FLOW 0x0001 | ||
123 | #define SX_DEBUG_DATA 0x0002 | ||
124 | #define SX_DEBUG_PROBE 0x0004 | ||
125 | #define SX_DEBUG_CHAN 0x0008 | ||
126 | #define SX_DEBUG_INIT 0x0010 | ||
127 | #define SX_DEBUG_RX 0x0020 | ||
128 | #define SX_DEBUG_TX 0x0040 | ||
129 | #define SX_DEBUG_IRQ 0x0080 | ||
130 | #define SX_DEBUG_OPEN 0x0100 | ||
131 | #define SX_DEBUG_TERMIOS 0x0200 | ||
132 | #define SX_DEBUG_SIGNALS 0x0400 | ||
133 | #define SX_DEBUG_FIFO 0x0800 | ||
134 | |||
135 | |||
136 | #define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__) | ||
137 | #define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__) | ||
138 | |||
139 | |||
140 | /* Configurable options: */ | ||
141 | |||
142 | /* Am I paranoid or not ? ;-) */ | ||
143 | #define SPECIALIX_PARANOIA_CHECK | ||
144 | |||
145 | /* | ||
146 | * The following defines are mostly for testing purposes. But if you need | ||
147 | * some nice reporting in your syslog, you can define them also. | ||
148 | */ | ||
149 | #undef SX_REPORT_FIFO | ||
150 | #undef SX_REPORT_OVERRUN | ||
151 | |||
152 | |||
153 | |||
154 | |||
155 | #define SPECIALIX_LEGAL_FLAGS \ | ||
156 | (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ | ||
157 | ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ | ||
158 | ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) | ||
159 | |||
160 | static struct tty_driver *specialix_driver; | ||
161 | |||
162 | static struct specialix_board sx_board[SX_NBOARD] = { | ||
163 | { 0, SX_IOBASE1, 9, }, | ||
164 | { 0, SX_IOBASE2, 11, }, | ||
165 | { 0, SX_IOBASE3, 12, }, | ||
166 | { 0, SX_IOBASE4, 15, }, | ||
167 | }; | ||
168 | |||
169 | static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; | ||
170 | |||
171 | |||
172 | static int sx_paranoia_check(struct specialix_port const *port, | ||
173 | char *name, const char *routine) | ||
174 | { | ||
175 | #ifdef SPECIALIX_PARANOIA_CHECK | ||
176 | static const char *badmagic = KERN_ERR | ||
177 | "sx: Warning: bad specialix port magic number for device %s in %s\n"; | ||
178 | static const char *badinfo = KERN_ERR | ||
179 | "sx: Warning: null specialix port for device %s in %s\n"; | ||
180 | |||
181 | if (!port) { | ||
182 | printk(badinfo, name, routine); | ||
183 | return 1; | ||
184 | } | ||
185 | if (port->magic != SPECIALIX_MAGIC) { | ||
186 | printk(badmagic, name, routine); | ||
187 | return 1; | ||
188 | } | ||
189 | #endif | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | |||
194 | /* | ||
195 | * | ||
196 | * Service functions for specialix IO8+ driver. | ||
197 | * | ||
198 | */ | ||
199 | |||
200 | /* Get board number from pointer */ | ||
201 | static inline int board_No(struct specialix_board *bp) | ||
202 | { | ||
203 | return bp - sx_board; | ||
204 | } | ||
205 | |||
206 | |||
207 | /* Get port number from pointer */ | ||
208 | static inline int port_No(struct specialix_port const *port) | ||
209 | { | ||
210 | return SX_PORT(port - sx_port); | ||
211 | } | ||
212 | |||
213 | |||
214 | /* Get pointer to board from pointer to port */ | ||
215 | static inline struct specialix_board *port_Board( | ||
216 | struct specialix_port const *port) | ||
217 | { | ||
218 | return &sx_board[SX_BOARD(port - sx_port)]; | ||
219 | } | ||
220 | |||
221 | |||
222 | /* Input Byte from CL CD186x register */ | ||
223 | static inline unsigned char sx_in(struct specialix_board *bp, | ||
224 | unsigned short reg) | ||
225 | { | ||
226 | bp->reg = reg | 0x80; | ||
227 | outb(reg | 0x80, bp->base + SX_ADDR_REG); | ||
228 | return inb(bp->base + SX_DATA_REG); | ||
229 | } | ||
230 | |||
231 | |||
232 | /* Output Byte to CL CD186x register */ | ||
233 | static inline void sx_out(struct specialix_board *bp, unsigned short reg, | ||
234 | unsigned char val) | ||
235 | { | ||
236 | bp->reg = reg | 0x80; | ||
237 | outb(reg | 0x80, bp->base + SX_ADDR_REG); | ||
238 | outb(val, bp->base + SX_DATA_REG); | ||
239 | } | ||
240 | |||
241 | |||
242 | /* Input Byte from CL CD186x register */ | ||
243 | static inline unsigned char sx_in_off(struct specialix_board *bp, | ||
244 | unsigned short reg) | ||
245 | { | ||
246 | bp->reg = reg; | ||
247 | outb(reg, bp->base + SX_ADDR_REG); | ||
248 | return inb(bp->base + SX_DATA_REG); | ||
249 | } | ||
250 | |||
251 | |||
252 | /* Output Byte to CL CD186x register */ | ||
253 | static inline void sx_out_off(struct specialix_board *bp, | ||
254 | unsigned short reg, unsigned char val) | ||
255 | { | ||
256 | bp->reg = reg; | ||
257 | outb(reg, bp->base + SX_ADDR_REG); | ||
258 | outb(val, bp->base + SX_DATA_REG); | ||
259 | } | ||
260 | |||
261 | |||
262 | /* Wait for Channel Command Register ready */ | ||
263 | static void sx_wait_CCR(struct specialix_board *bp) | ||
264 | { | ||
265 | unsigned long delay, flags; | ||
266 | unsigned char ccr; | ||
267 | |||
268 | for (delay = SX_CCR_TIMEOUT; delay; delay--) { | ||
269 | spin_lock_irqsave(&bp->lock, flags); | ||
270 | ccr = sx_in(bp, CD186x_CCR); | ||
271 | spin_unlock_irqrestore(&bp->lock, flags); | ||
272 | if (!ccr) | ||
273 | return; | ||
274 | udelay(1); | ||
275 | } | ||
276 | |||
277 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); | ||
278 | } | ||
279 | |||
280 | |||
281 | /* Wait for Channel Command Register ready */ | ||
282 | static void sx_wait_CCR_off(struct specialix_board *bp) | ||
283 | { | ||
284 | unsigned long delay; | ||
285 | unsigned char crr; | ||
286 | unsigned long flags; | ||
287 | |||
288 | for (delay = SX_CCR_TIMEOUT; delay; delay--) { | ||
289 | spin_lock_irqsave(&bp->lock, flags); | ||
290 | crr = sx_in_off(bp, CD186x_CCR); | ||
291 | spin_unlock_irqrestore(&bp->lock, flags); | ||
292 | if (!crr) | ||
293 | return; | ||
294 | udelay(1); | ||
295 | } | ||
296 | |||
297 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); | ||
298 | } | ||
299 | |||
300 | |||
301 | /* | ||
302 | * specialix IO8+ IO range functions. | ||
303 | */ | ||
304 | |||
305 | static int sx_request_io_range(struct specialix_board *bp) | ||
306 | { | ||
307 | return request_region(bp->base, | ||
308 | bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, | ||
309 | "specialix IO8+") == NULL; | ||
310 | } | ||
311 | |||
312 | |||
313 | static void sx_release_io_range(struct specialix_board *bp) | ||
314 | { | ||
315 | release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? | ||
316 | SX_PCI_IO_SPACE : SX_IO_SPACE); | ||
317 | } | ||
318 | |||
319 | |||
320 | /* Set the IRQ using the RTS lines that run to the PAL on the board.... */ | ||
321 | static int sx_set_irq(struct specialix_board *bp) | ||
322 | { | ||
323 | int virq; | ||
324 | int i; | ||
325 | unsigned long flags; | ||
326 | |||
327 | if (bp->flags & SX_BOARD_IS_PCI) | ||
328 | return 1; | ||
329 | switch (bp->irq) { | ||
330 | /* In the same order as in the docs... */ | ||
331 | case 15: | ||
332 | virq = 0; | ||
333 | break; | ||
334 | case 12: | ||
335 | virq = 1; | ||
336 | break; | ||
337 | case 11: | ||
338 | virq = 2; | ||
339 | break; | ||
340 | case 9: | ||
341 | virq = 3; | ||
342 | break; | ||
343 | default:printk(KERN_ERR | ||
344 | "Speclialix: cannot set irq to %d.\n", bp->irq); | ||
345 | return 0; | ||
346 | } | ||
347 | spin_lock_irqsave(&bp->lock, flags); | ||
348 | for (i = 0; i < 2; i++) { | ||
349 | sx_out(bp, CD186x_CAR, i); | ||
350 | sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); | ||
351 | } | ||
352 | spin_unlock_irqrestore(&bp->lock, flags); | ||
353 | return 1; | ||
354 | } | ||
355 | |||
356 | |||
357 | /* Reset and setup CD186x chip */ | ||
358 | static int sx_init_CD186x(struct specialix_board *bp) | ||
359 | { | ||
360 | unsigned long flags; | ||
361 | int scaler; | ||
362 | int rv = 1; | ||
363 | |||
364 | func_enter(); | ||
365 | sx_wait_CCR_off(bp); /* Wait for CCR ready */ | ||
366 | spin_lock_irqsave(&bp->lock, flags); | ||
367 | sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */ | ||
368 | spin_unlock_irqrestore(&bp->lock, flags); | ||
369 | msleep(50); /* Delay 0.05 sec */ | ||
370 | spin_lock_irqsave(&bp->lock, flags); | ||
371 | sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */ | ||
372 | sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */ | ||
373 | sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT); /* Prio for modem intr */ | ||
374 | sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ | ||
375 | sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ | ||
376 | /* Set RegAckEn */ | ||
377 | sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN); | ||
378 | |||
379 | /* Setting up prescaler. We need 4 ticks per 1 ms */ | ||
380 | scaler = SX_OSCFREQ/SPECIALIX_TPS; | ||
381 | |||
382 | sx_out_off(bp, CD186x_PPRH, scaler >> 8); | ||
383 | sx_out_off(bp, CD186x_PPRL, scaler & 0xff); | ||
384 | spin_unlock_irqrestore(&bp->lock, flags); | ||
385 | |||
386 | if (!sx_set_irq(bp)) { | ||
387 | /* Figure out how to pass this along... */ | ||
388 | printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq); | ||
389 | rv = 0; | ||
390 | } | ||
391 | |||
392 | func_exit(); | ||
393 | return rv; | ||
394 | } | ||
395 | |||
396 | |||
397 | static int read_cross_byte(struct specialix_board *bp, int reg, int bit) | ||
398 | { | ||
399 | int i; | ||
400 | int t; | ||
401 | unsigned long flags; | ||
402 | |||
403 | spin_lock_irqsave(&bp->lock, flags); | ||
404 | for (i = 0, t = 0; i < 8; i++) { | ||
405 | sx_out_off(bp, CD186x_CAR, i); | ||
406 | if (sx_in_off(bp, reg) & bit) | ||
407 | t |= 1 << i; | ||
408 | } | ||
409 | spin_unlock_irqrestore(&bp->lock, flags); | ||
410 | |||
411 | return t; | ||
412 | } | ||
413 | |||
414 | |||
415 | /* Main probing routine, also sets irq. */ | ||
416 | static int sx_probe(struct specialix_board *bp) | ||
417 | { | ||
418 | unsigned char val1, val2; | ||
419 | int rev; | ||
420 | int chip; | ||
421 | |||
422 | func_enter(); | ||
423 | |||
424 | if (sx_request_io_range(bp)) { | ||
425 | func_exit(); | ||
426 | return 1; | ||
427 | } | ||
428 | |||
429 | /* Are the I/O ports here ? */ | ||
430 | sx_out_off(bp, CD186x_PPRL, 0x5a); | ||
431 | udelay(1); | ||
432 | val1 = sx_in_off(bp, CD186x_PPRL); | ||
433 | |||
434 | sx_out_off(bp, CD186x_PPRL, 0xa5); | ||
435 | udelay(1); | ||
436 | val2 = sx_in_off(bp, CD186x_PPRL); | ||
437 | |||
438 | |||
439 | if (val1 != 0x5a || val2 != 0xa5) { | ||
440 | printk(KERN_INFO | ||
441 | "sx%d: specialix IO8+ Board at 0x%03x not found.\n", | ||
442 | board_No(bp), bp->base); | ||
443 | sx_release_io_range(bp); | ||
444 | func_exit(); | ||
445 | return 1; | ||
446 | } | ||
447 | |||
448 | /* Check the DSR lines that Specialix uses as board | ||
449 | identification */ | ||
450 | val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR); | ||
451 | val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS); | ||
452 | dprintk(SX_DEBUG_INIT, | ||
453 | "sx%d: DSR lines are: %02x, rts lines are: %02x\n", | ||
454 | board_No(bp), val1, val2); | ||
455 | |||
456 | /* They managed to switch the bit order between the docs and | ||
457 | the IO8+ card. The new PCI card now conforms to old docs. | ||
458 | They changed the PCI docs to reflect the situation on the | ||
459 | old card. */ | ||
460 | val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; | ||
461 | if (val1 != val2) { | ||
462 | printk(KERN_INFO | ||
463 | "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", | ||
464 | board_No(bp), val2, bp->base, val1); | ||
465 | sx_release_io_range(bp); | ||
466 | func_exit(); | ||
467 | return 1; | ||
468 | } | ||
469 | |||
470 | |||
471 | /* Reset CD186x again */ | ||
472 | if (!sx_init_CD186x(bp)) { | ||
473 | sx_release_io_range(bp); | ||
474 | func_exit(); | ||
475 | return 1; | ||
476 | } | ||
477 | |||
478 | sx_request_io_range(bp); | ||
479 | bp->flags |= SX_BOARD_PRESENT; | ||
480 | |||
481 | /* Chip revcode pkgtype | ||
482 | GFRCR SRCR bit 7 | ||
483 | CD180 rev B 0x81 0 | ||
484 | CD180 rev C 0x82 0 | ||
485 | CD1864 rev A 0x82 1 | ||
486 | CD1865 rev A 0x83 1 -- Do not use!!! Does not work. | ||
487 | CD1865 rev B 0x84 1 | ||
488 | -- Thanks to Gwen Wang, Cirrus Logic. | ||
489 | */ | ||
490 | |||
491 | switch (sx_in_off(bp, CD186x_GFRCR)) { | ||
492 | case 0x82: | ||
493 | chip = 1864; | ||
494 | rev = 'A'; | ||
495 | break; | ||
496 | case 0x83: | ||
497 | chip = 1865; | ||
498 | rev = 'A'; | ||
499 | break; | ||
500 | case 0x84: | ||
501 | chip = 1865; | ||
502 | rev = 'B'; | ||
503 | break; | ||
504 | case 0x85: | ||
505 | chip = 1865; | ||
506 | rev = 'C'; | ||
507 | break; /* Does not exist at this time */ | ||
508 | default: | ||
509 | chip = -1; | ||
510 | rev = 'x'; | ||
511 | } | ||
512 | |||
513 | dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR)); | ||
514 | |||
515 | printk(KERN_INFO | ||
516 | "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", | ||
517 | board_No(bp), bp->base, bp->irq, chip, rev); | ||
518 | |||
519 | func_exit(); | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | /* | ||
524 | * | ||
525 | * Interrupt processing routines. | ||
526 | * */ | ||
527 | |||
528 | static struct specialix_port *sx_get_port(struct specialix_board *bp, | ||
529 | unsigned char const *what) | ||
530 | { | ||
531 | unsigned char channel; | ||
532 | struct specialix_port *port = NULL; | ||
533 | |||
534 | channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; | ||
535 | dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel); | ||
536 | if (channel < CD186x_NCH) { | ||
537 | port = &sx_port[board_No(bp) * SX_NPORT + channel]; | ||
538 | dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n", | ||
539 | board_No(bp) * SX_NPORT + channel, port, | ||
540 | port->port.flags & ASYNC_INITIALIZED); | ||
541 | |||
542 | if (port->port.flags & ASYNC_INITIALIZED) { | ||
543 | dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port); | ||
544 | func_exit(); | ||
545 | return port; | ||
546 | } | ||
547 | } | ||
548 | printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n", | ||
549 | board_No(bp), what, channel); | ||
550 | return NULL; | ||
551 | } | ||
552 | |||
553 | |||
554 | static void sx_receive_exc(struct specialix_board *bp) | ||
555 | { | ||
556 | struct specialix_port *port; | ||
557 | struct tty_struct *tty; | ||
558 | unsigned char status; | ||
559 | unsigned char ch, flag; | ||
560 | |||
561 | func_enter(); | ||
562 | |||
563 | port = sx_get_port(bp, "Receive"); | ||
564 | if (!port) { | ||
565 | dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | ||
566 | func_exit(); | ||
567 | return; | ||
568 | } | ||
569 | tty = port->port.tty; | ||
570 | |||
571 | status = sx_in(bp, CD186x_RCSR); | ||
572 | |||
573 | dprintk(SX_DEBUG_RX, "status: 0x%x\n", status); | ||
574 | if (status & RCSR_OE) { | ||
575 | port->overrun++; | ||
576 | dprintk(SX_DEBUG_FIFO, | ||
577 | "sx%d: port %d: Overrun. Total %ld overruns.\n", | ||
578 | board_No(bp), port_No(port), port->overrun); | ||
579 | } | ||
580 | status &= port->mark_mask; | ||
581 | |||
582 | /* This flip buffer check needs to be below the reading of the | ||
583 | status register to reset the chip's IRQ.... */ | ||
584 | if (tty_buffer_request_room(tty, 1) == 0) { | ||
585 | dprintk(SX_DEBUG_FIFO, | ||
586 | "sx%d: port %d: Working around flip buffer overflow.\n", | ||
587 | board_No(bp), port_No(port)); | ||
588 | func_exit(); | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | ch = sx_in(bp, CD186x_RDR); | ||
593 | if (!status) { | ||
594 | func_exit(); | ||
595 | return; | ||
596 | } | ||
597 | if (status & RCSR_TOUT) { | ||
598 | printk(KERN_INFO | ||
599 | "sx%d: port %d: Receiver timeout. Hardware problems ?\n", | ||
600 | board_No(bp), port_No(port)); | ||
601 | func_exit(); | ||
602 | return; | ||
603 | |||
604 | } else if (status & RCSR_BREAK) { | ||
605 | dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n", | ||
606 | board_No(bp), port_No(port)); | ||
607 | flag = TTY_BREAK; | ||
608 | if (port->port.flags & ASYNC_SAK) | ||
609 | do_SAK(tty); | ||
610 | |||
611 | } else if (status & RCSR_PE) | ||
612 | flag = TTY_PARITY; | ||
613 | |||
614 | else if (status & RCSR_FE) | ||
615 | flag = TTY_FRAME; | ||
616 | |||
617 | else if (status & RCSR_OE) | ||
618 | flag = TTY_OVERRUN; | ||
619 | |||
620 | else | ||
621 | flag = TTY_NORMAL; | ||
622 | |||
623 | if (tty_insert_flip_char(tty, ch, flag)) | ||
624 | tty_flip_buffer_push(tty); | ||
625 | func_exit(); | ||
626 | } | ||
627 | |||
628 | |||
629 | static void sx_receive(struct specialix_board *bp) | ||
630 | { | ||
631 | struct specialix_port *port; | ||
632 | struct tty_struct *tty; | ||
633 | unsigned char count; | ||
634 | |||
635 | func_enter(); | ||
636 | |||
637 | port = sx_get_port(bp, "Receive"); | ||
638 | if (port == NULL) { | ||
639 | dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | ||
640 | func_exit(); | ||
641 | return; | ||
642 | } | ||
643 | tty = port->port.tty; | ||
644 | |||
645 | count = sx_in(bp, CD186x_RDCR); | ||
646 | dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); | ||
647 | port->hits[count > 8 ? 9 : count]++; | ||
648 | |||
649 | while (count--) | ||
650 | tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); | ||
651 | tty_flip_buffer_push(tty); | ||
652 | func_exit(); | ||
653 | } | ||
654 | |||
655 | |||
656 | static void sx_transmit(struct specialix_board *bp) | ||
657 | { | ||
658 | struct specialix_port *port; | ||
659 | struct tty_struct *tty; | ||
660 | unsigned char count; | ||
661 | |||
662 | func_enter(); | ||
663 | port = sx_get_port(bp, "Transmit"); | ||
664 | if (port == NULL) { | ||
665 | func_exit(); | ||
666 | return; | ||
667 | } | ||
668 | dprintk(SX_DEBUG_TX, "port: %p\n", port); | ||
669 | tty = port->port.tty; | ||
670 | |||
671 | if (port->IER & IER_TXEMPTY) { | ||
672 | /* FIFO drained */ | ||
673 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
674 | port->IER &= ~IER_TXEMPTY; | ||
675 | sx_out(bp, CD186x_IER, port->IER); | ||
676 | func_exit(); | ||
677 | return; | ||
678 | } | ||
679 | |||
680 | if ((port->xmit_cnt <= 0 && !port->break_length) | ||
681 | || tty->stopped || tty->hw_stopped) { | ||
682 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
683 | port->IER &= ~IER_TXRDY; | ||
684 | sx_out(bp, CD186x_IER, port->IER); | ||
685 | func_exit(); | ||
686 | return; | ||
687 | } | ||
688 | |||
689 | if (port->break_length) { | ||
690 | if (port->break_length > 0) { | ||
691 | if (port->COR2 & COR2_ETC) { | ||
692 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); | ||
693 | sx_out(bp, CD186x_TDR, CD186x_C_SBRK); | ||
694 | port->COR2 &= ~COR2_ETC; | ||
695 | } | ||
696 | count = min_t(int, port->break_length, 0xff); | ||
697 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); | ||
698 | sx_out(bp, CD186x_TDR, CD186x_C_DELAY); | ||
699 | sx_out(bp, CD186x_TDR, count); | ||
700 | port->break_length -= count; | ||
701 | if (port->break_length == 0) | ||
702 | port->break_length--; | ||
703 | } else { | ||
704 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); | ||
705 | sx_out(bp, CD186x_TDR, CD186x_C_EBRK); | ||
706 | sx_out(bp, CD186x_COR2, port->COR2); | ||
707 | sx_wait_CCR(bp); | ||
708 | sx_out(bp, CD186x_CCR, CCR_CORCHG2); | ||
709 | port->break_length = 0; | ||
710 | } | ||
711 | |||
712 | func_exit(); | ||
713 | return; | ||
714 | } | ||
715 | |||
716 | count = CD186x_NFIFO; | ||
717 | do { | ||
718 | sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]); | ||
719 | port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); | ||
720 | if (--port->xmit_cnt <= 0) | ||
721 | break; | ||
722 | } while (--count > 0); | ||
723 | |||
724 | if (port->xmit_cnt <= 0) { | ||
725 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
726 | port->IER &= ~IER_TXRDY; | ||
727 | sx_out(bp, CD186x_IER, port->IER); | ||
728 | } | ||
729 | if (port->xmit_cnt <= port->wakeup_chars) | ||
730 | tty_wakeup(tty); | ||
731 | |||
732 | func_exit(); | ||
733 | } | ||
734 | |||
735 | |||
736 | static void sx_check_modem(struct specialix_board *bp) | ||
737 | { | ||
738 | struct specialix_port *port; | ||
739 | struct tty_struct *tty; | ||
740 | unsigned char mcr; | ||
741 | int msvr_cd; | ||
742 | |||
743 | dprintk(SX_DEBUG_SIGNALS, "Modem intr. "); | ||
744 | port = sx_get_port(bp, "Modem"); | ||
745 | if (port == NULL) | ||
746 | return; | ||
747 | |||
748 | tty = port->port.tty; | ||
749 | |||
750 | mcr = sx_in(bp, CD186x_MCR); | ||
751 | |||
752 | if ((mcr & MCR_CDCHG)) { | ||
753 | dprintk(SX_DEBUG_SIGNALS, "CD just changed... "); | ||
754 | msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; | ||
755 | if (msvr_cd) { | ||
756 | dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); | ||
757 | wake_up_interruptible(&port->port.open_wait); | ||
758 | } else { | ||
759 | dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n"); | ||
760 | tty_hangup(tty); | ||
761 | } | ||
762 | } | ||
763 | |||
764 | #ifdef SPECIALIX_BRAIN_DAMAGED_CTS | ||
765 | if (mcr & MCR_CTSCHG) { | ||
766 | if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) { | ||
767 | tty->hw_stopped = 0; | ||
768 | port->IER |= IER_TXRDY; | ||
769 | if (port->xmit_cnt <= port->wakeup_chars) | ||
770 | tty_wakeup(tty); | ||
771 | } else { | ||
772 | tty->hw_stopped = 1; | ||
773 | port->IER &= ~IER_TXRDY; | ||
774 | } | ||
775 | sx_out(bp, CD186x_IER, port->IER); | ||
776 | } | ||
777 | if (mcr & MCR_DSSXHG) { | ||
778 | if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) { | ||
779 | tty->hw_stopped = 0; | ||
780 | port->IER |= IER_TXRDY; | ||
781 | if (port->xmit_cnt <= port->wakeup_chars) | ||
782 | tty_wakeup(tty); | ||
783 | } else { | ||
784 | tty->hw_stopped = 1; | ||
785 | port->IER &= ~IER_TXRDY; | ||
786 | } | ||
787 | sx_out(bp, CD186x_IER, port->IER); | ||
788 | } | ||
789 | #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */ | ||
790 | |||
791 | /* Clear change bits */ | ||
792 | sx_out(bp, CD186x_MCR, 0); | ||
793 | } | ||
794 | |||
795 | |||
796 | /* The main interrupt processing routine */ | ||
797 | static irqreturn_t sx_interrupt(int dummy, void *dev_id) | ||
798 | { | ||
799 | unsigned char status; | ||
800 | unsigned char ack; | ||
801 | struct specialix_board *bp = dev_id; | ||
802 | unsigned long loop = 0; | ||
803 | int saved_reg; | ||
804 | unsigned long flags; | ||
805 | |||
806 | func_enter(); | ||
807 | |||
808 | spin_lock_irqsave(&bp->lock, flags); | ||
809 | |||
810 | dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, | ||
811 | port_No(sx_get_port(bp, "INT")), | ||
812 | SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); | ||
813 | if (!(bp->flags & SX_BOARD_ACTIVE)) { | ||
814 | dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", | ||
815 | bp->irq); | ||
816 | spin_unlock_irqrestore(&bp->lock, flags); | ||
817 | func_exit(); | ||
818 | return IRQ_NONE; | ||
819 | } | ||
820 | |||
821 | saved_reg = bp->reg; | ||
822 | |||
823 | while (++loop < 16) { | ||
824 | status = sx_in(bp, CD186x_SRSR) & | ||
825 | (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint); | ||
826 | if (status == 0) | ||
827 | break; | ||
828 | if (status & SRSR_RREQint) { | ||
829 | ack = sx_in(bp, CD186x_RRAR); | ||
830 | |||
831 | if (ack == (SX_ID | GIVR_IT_RCV)) | ||
832 | sx_receive(bp); | ||
833 | else if (ack == (SX_ID | GIVR_IT_REXC)) | ||
834 | sx_receive_exc(bp); | ||
835 | else | ||
836 | printk(KERN_ERR | ||
837 | "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", | ||
838 | board_No(bp), status, ack); | ||
839 | |||
840 | } else if (status & SRSR_TREQint) { | ||
841 | ack = sx_in(bp, CD186x_TRAR); | ||
842 | |||
843 | if (ack == (SX_ID | GIVR_IT_TX)) | ||
844 | sx_transmit(bp); | ||
845 | else | ||
846 | printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", | ||
847 | board_No(bp), status, ack, | ||
848 | port_No(sx_get_port(bp, "Int"))); | ||
849 | } else if (status & SRSR_MREQint) { | ||
850 | ack = sx_in(bp, CD186x_MRAR); | ||
851 | |||
852 | if (ack == (SX_ID | GIVR_IT_MODEM)) | ||
853 | sx_check_modem(bp); | ||
854 | else | ||
855 | printk(KERN_ERR | ||
856 | "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", | ||
857 | board_No(bp), status, ack); | ||
858 | |||
859 | } | ||
860 | |||
861 | sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ | ||
862 | } | ||
863 | bp->reg = saved_reg; | ||
864 | outb(bp->reg, bp->base + SX_ADDR_REG); | ||
865 | spin_unlock_irqrestore(&bp->lock, flags); | ||
866 | func_exit(); | ||
867 | return IRQ_HANDLED; | ||
868 | } | ||
869 | |||
870 | |||
871 | /* | ||
872 | * Routines for open & close processing. | ||
873 | */ | ||
874 | |||
875 | static void turn_ints_off(struct specialix_board *bp) | ||
876 | { | ||
877 | unsigned long flags; | ||
878 | |||
879 | func_enter(); | ||
880 | spin_lock_irqsave(&bp->lock, flags); | ||
881 | (void) sx_in_off(bp, 0); /* Turn off interrupts. */ | ||
882 | spin_unlock_irqrestore(&bp->lock, flags); | ||
883 | |||
884 | func_exit(); | ||
885 | } | ||
886 | |||
887 | static void turn_ints_on(struct specialix_board *bp) | ||
888 | { | ||
889 | unsigned long flags; | ||
890 | |||
891 | func_enter(); | ||
892 | |||
893 | spin_lock_irqsave(&bp->lock, flags); | ||
894 | (void) sx_in(bp, 0); /* Turn ON interrupts. */ | ||
895 | spin_unlock_irqrestore(&bp->lock, flags); | ||
896 | |||
897 | func_exit(); | ||
898 | } | ||
899 | |||
900 | |||
901 | /* Called with disabled interrupts */ | ||
902 | static int sx_setup_board(struct specialix_board *bp) | ||
903 | { | ||
904 | int error; | ||
905 | |||
906 | if (bp->flags & SX_BOARD_ACTIVE) | ||
907 | return 0; | ||
908 | |||
909 | if (bp->flags & SX_BOARD_IS_PCI) | ||
910 | error = request_irq(bp->irq, sx_interrupt, | ||
911 | IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); | ||
912 | else | ||
913 | error = request_irq(bp->irq, sx_interrupt, | ||
914 | IRQF_DISABLED, "specialix IO8+", bp); | ||
915 | |||
916 | if (error) | ||
917 | return error; | ||
918 | |||
919 | turn_ints_on(bp); | ||
920 | bp->flags |= SX_BOARD_ACTIVE; | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | |||
926 | /* Called with disabled interrupts */ | ||
927 | static void sx_shutdown_board(struct specialix_board *bp) | ||
928 | { | ||
929 | func_enter(); | ||
930 | |||
931 | if (!(bp->flags & SX_BOARD_ACTIVE)) { | ||
932 | func_exit(); | ||
933 | return; | ||
934 | } | ||
935 | |||
936 | bp->flags &= ~SX_BOARD_ACTIVE; | ||
937 | |||
938 | dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", | ||
939 | bp->irq, board_No(bp)); | ||
940 | free_irq(bp->irq, bp); | ||
941 | turn_ints_off(bp); | ||
942 | func_exit(); | ||
943 | } | ||
944 | |||
945 | static unsigned int sx_crtscts(struct tty_struct *tty) | ||
946 | { | ||
947 | if (sx_rtscts) | ||
948 | return C_CRTSCTS(tty); | ||
949 | return 1; | ||
950 | } | ||
951 | |||
952 | /* | ||
953 | * Setting up port characteristics. | ||
954 | * Must be called with disabled interrupts | ||
955 | */ | ||
956 | static void sx_change_speed(struct specialix_board *bp, | ||
957 | struct specialix_port *port) | ||
958 | { | ||
959 | struct tty_struct *tty; | ||
960 | unsigned long baud; | ||
961 | long tmp; | ||
962 | unsigned char cor1 = 0, cor3 = 0; | ||
963 | unsigned char mcor1 = 0, mcor2 = 0; | ||
964 | static unsigned long again; | ||
965 | unsigned long flags; | ||
966 | |||
967 | func_enter(); | ||
968 | |||
969 | tty = port->port.tty; | ||
970 | if (!tty || !tty->termios) { | ||
971 | func_exit(); | ||
972 | return; | ||
973 | } | ||
974 | |||
975 | port->IER = 0; | ||
976 | port->COR2 = 0; | ||
977 | /* Select port on the board */ | ||
978 | spin_lock_irqsave(&bp->lock, flags); | ||
979 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
980 | |||
981 | /* The Specialix board doens't implement the RTS lines. | ||
982 | They are used to set the IRQ level. Don't touch them. */ | ||
983 | if (sx_crtscts(tty)) | ||
984 | port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS); | ||
985 | else | ||
986 | port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); | ||
987 | spin_unlock_irqrestore(&bp->lock, flags); | ||
988 | dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); | ||
989 | baud = tty_get_baud_rate(tty); | ||
990 | |||
991 | if (baud == 38400) { | ||
992 | if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
993 | baud = 57600; | ||
994 | if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
995 | baud = 115200; | ||
996 | } | ||
997 | |||
998 | if (!baud) { | ||
999 | /* Drop DTR & exit */ | ||
1000 | dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); | ||
1001 | if (!sx_crtscts(tty)) { | ||
1002 | port->MSVR &= ~MSVR_DTR; | ||
1003 | spin_lock_irqsave(&bp->lock, flags); | ||
1004 | sx_out(bp, CD186x_MSVR, port->MSVR); | ||
1005 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1006 | } else | ||
1007 | dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); | ||
1008 | return; | ||
1009 | } else { | ||
1010 | /* Set DTR on */ | ||
1011 | if (!sx_crtscts(tty)) | ||
1012 | port->MSVR |= MSVR_DTR; | ||
1013 | } | ||
1014 | |||
1015 | /* | ||
1016 | * Now we must calculate some speed depended things | ||
1017 | */ | ||
1018 | |||
1019 | /* Set baud rate for port */ | ||
1020 | tmp = port->custom_divisor ; | ||
1021 | if (tmp) | ||
1022 | printk(KERN_INFO | ||
1023 | "sx%d: Using custom baud rate divisor %ld. \n" | ||
1024 | "This is an untested option, please be careful.\n", | ||
1025 | port_No(port), tmp); | ||
1026 | else | ||
1027 | tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) / | ||
1028 | CD186x_TPC); | ||
1029 | |||
1030 | if (tmp < 0x10 && time_before(again, jiffies)) { | ||
1031 | again = jiffies + HZ * 60; | ||
1032 | /* Page 48 of version 2.0 of the CL-CD1865 databook */ | ||
1033 | if (tmp >= 12) { | ||
1034 | printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" | ||
1035 | "Performance degradation is possible.\n" | ||
1036 | "Read specialix.txt for more info.\n", | ||
1037 | port_No(port), tmp); | ||
1038 | } else { | ||
1039 | printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" | ||
1040 | "Warning: overstressing Cirrus chip. This might not work.\n" | ||
1041 | "Read specialix.txt for more info.\n", port_No(port), tmp); | ||
1042 | } | ||
1043 | } | ||
1044 | spin_lock_irqsave(&bp->lock, flags); | ||
1045 | sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); | ||
1046 | sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); | ||
1047 | sx_out(bp, CD186x_RBPRL, tmp & 0xff); | ||
1048 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); | ||
1049 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1050 | if (port->custom_divisor) | ||
1051 | baud = (SX_OSCFREQ + port->custom_divisor/2) / | ||
1052 | port->custom_divisor; | ||
1053 | baud = (baud + 5) / 10; /* Estimated CPS */ | ||
1054 | |||
1055 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ | ||
1056 | tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; | ||
1057 | port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? | ||
1058 | SERIAL_XMIT_SIZE - 1 : tmp); | ||
1059 | |||
1060 | /* Receiver timeout will be transmission time for 1.5 chars */ | ||
1061 | tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud; | ||
1062 | tmp = (tmp > 0xff) ? 0xff : tmp; | ||
1063 | spin_lock_irqsave(&bp->lock, flags); | ||
1064 | sx_out(bp, CD186x_RTPR, tmp); | ||
1065 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1066 | switch (C_CSIZE(tty)) { | ||
1067 | case CS5: | ||
1068 | cor1 |= COR1_5BITS; | ||
1069 | break; | ||
1070 | case CS6: | ||
1071 | cor1 |= COR1_6BITS; | ||
1072 | break; | ||
1073 | case CS7: | ||
1074 | cor1 |= COR1_7BITS; | ||
1075 | break; | ||
1076 | case CS8: | ||
1077 | cor1 |= COR1_8BITS; | ||
1078 | break; | ||
1079 | } | ||
1080 | |||
1081 | if (C_CSTOPB(tty)) | ||
1082 | cor1 |= COR1_2SB; | ||
1083 | |||
1084 | cor1 |= COR1_IGNORE; | ||
1085 | if (C_PARENB(tty)) { | ||
1086 | cor1 |= COR1_NORMPAR; | ||
1087 | if (C_PARODD(tty)) | ||
1088 | cor1 |= COR1_ODDP; | ||
1089 | if (I_INPCK(tty)) | ||
1090 | cor1 &= ~COR1_IGNORE; | ||
1091 | } | ||
1092 | /* Set marking of some errors */ | ||
1093 | port->mark_mask = RCSR_OE | RCSR_TOUT; | ||
1094 | if (I_INPCK(tty)) | ||
1095 | port->mark_mask |= RCSR_FE | RCSR_PE; | ||
1096 | if (I_BRKINT(tty) || I_PARMRK(tty)) | ||
1097 | port->mark_mask |= RCSR_BREAK; | ||
1098 | if (I_IGNPAR(tty)) | ||
1099 | port->mark_mask &= ~(RCSR_FE | RCSR_PE); | ||
1100 | if (I_IGNBRK(tty)) { | ||
1101 | port->mark_mask &= ~RCSR_BREAK; | ||
1102 | if (I_IGNPAR(tty)) | ||
1103 | /* Real raw mode. Ignore all */ | ||
1104 | port->mark_mask &= ~RCSR_OE; | ||
1105 | } | ||
1106 | /* Enable Hardware Flow Control */ | ||
1107 | if (C_CRTSCTS(tty)) { | ||
1108 | #ifdef SPECIALIX_BRAIN_DAMAGED_CTS | ||
1109 | port->IER |= IER_DSR | IER_CTS; | ||
1110 | mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; | ||
1111 | mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; | ||
1112 | spin_lock_irqsave(&bp->lock, flags); | ||
1113 | tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & | ||
1114 | (MSVR_CTS|MSVR_DSR)); | ||
1115 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1116 | #else | ||
1117 | port->COR2 |= COR2_CTSAE; | ||
1118 | #endif | ||
1119 | } | ||
1120 | /* Enable Software Flow Control. FIXME: I'm not sure about this */ | ||
1121 | /* Some people reported that it works, but I still doubt it */ | ||
1122 | if (I_IXON(tty)) { | ||
1123 | port->COR2 |= COR2_TXIBE; | ||
1124 | cor3 |= (COR3_FCT | COR3_SCDE); | ||
1125 | if (I_IXANY(tty)) | ||
1126 | port->COR2 |= COR2_IXM; | ||
1127 | spin_lock_irqsave(&bp->lock, flags); | ||
1128 | sx_out(bp, CD186x_SCHR1, START_CHAR(tty)); | ||
1129 | sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty)); | ||
1130 | sx_out(bp, CD186x_SCHR3, START_CHAR(tty)); | ||
1131 | sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty)); | ||
1132 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1133 | } | ||
1134 | if (!C_CLOCAL(tty)) { | ||
1135 | /* Enable CD check */ | ||
1136 | port->IER |= IER_CD; | ||
1137 | mcor1 |= MCOR1_CDZD; | ||
1138 | mcor2 |= MCOR2_CDOD; | ||
1139 | } | ||
1140 | |||
1141 | if (C_CREAD(tty)) | ||
1142 | /* Enable receiver */ | ||
1143 | port->IER |= IER_RXD; | ||
1144 | |||
1145 | /* Set input FIFO size (1-8 bytes) */ | ||
1146 | cor3 |= sx_rxfifo; | ||
1147 | /* Setting up CD186x channel registers */ | ||
1148 | spin_lock_irqsave(&bp->lock, flags); | ||
1149 | sx_out(bp, CD186x_COR1, cor1); | ||
1150 | sx_out(bp, CD186x_COR2, port->COR2); | ||
1151 | sx_out(bp, CD186x_COR3, cor3); | ||
1152 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1153 | /* Make CD186x know about registers change */ | ||
1154 | sx_wait_CCR(bp); | ||
1155 | spin_lock_irqsave(&bp->lock, flags); | ||
1156 | sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); | ||
1157 | /* Setting up modem option registers */ | ||
1158 | dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", | ||
1159 | mcor1, mcor2); | ||
1160 | sx_out(bp, CD186x_MCOR1, mcor1); | ||
1161 | sx_out(bp, CD186x_MCOR2, mcor2); | ||
1162 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1163 | /* Enable CD186x transmitter & receiver */ | ||
1164 | sx_wait_CCR(bp); | ||
1165 | spin_lock_irqsave(&bp->lock, flags); | ||
1166 | sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN); | ||
1167 | /* Enable interrupts */ | ||
1168 | sx_out(bp, CD186x_IER, port->IER); | ||
1169 | /* And finally set the modem lines... */ | ||
1170 | sx_out(bp, CD186x_MSVR, port->MSVR); | ||
1171 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1172 | |||
1173 | func_exit(); | ||
1174 | } | ||
1175 | |||
1176 | |||
1177 | /* Must be called with interrupts enabled */ | ||
1178 | static int sx_setup_port(struct specialix_board *bp, | ||
1179 | struct specialix_port *port) | ||
1180 | { | ||
1181 | unsigned long flags; | ||
1182 | |||
1183 | func_enter(); | ||
1184 | |||
1185 | if (port->port.flags & ASYNC_INITIALIZED) { | ||
1186 | func_exit(); | ||
1187 | return 0; | ||
1188 | } | ||
1189 | |||
1190 | if (!port->xmit_buf) { | ||
1191 | /* We may sleep in get_zeroed_page() */ | ||
1192 | unsigned long tmp; | ||
1193 | |||
1194 | tmp = get_zeroed_page(GFP_KERNEL); | ||
1195 | if (tmp == 0L) { | ||
1196 | func_exit(); | ||
1197 | return -ENOMEM; | ||
1198 | } | ||
1199 | |||
1200 | if (port->xmit_buf) { | ||
1201 | free_page(tmp); | ||
1202 | func_exit(); | ||
1203 | return -ERESTARTSYS; | ||
1204 | } | ||
1205 | port->xmit_buf = (unsigned char *) tmp; | ||
1206 | } | ||
1207 | |||
1208 | spin_lock_irqsave(&port->lock, flags); | ||
1209 | |||
1210 | if (port->port.tty) | ||
1211 | clear_bit(TTY_IO_ERROR, &port->port.tty->flags); | ||
1212 | |||
1213 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | ||
1214 | sx_change_speed(bp, port); | ||
1215 | port->port.flags |= ASYNC_INITIALIZED; | ||
1216 | |||
1217 | spin_unlock_irqrestore(&port->lock, flags); | ||
1218 | |||
1219 | |||
1220 | func_exit(); | ||
1221 | return 0; | ||
1222 | } | ||
1223 | |||
1224 | |||
1225 | /* Must be called with interrupts disabled */ | ||
1226 | static void sx_shutdown_port(struct specialix_board *bp, | ||
1227 | struct specialix_port *port) | ||
1228 | { | ||
1229 | struct tty_struct *tty; | ||
1230 | int i; | ||
1231 | unsigned long flags; | ||
1232 | |||
1233 | func_enter(); | ||
1234 | |||
1235 | if (!(port->port.flags & ASYNC_INITIALIZED)) { | ||
1236 | func_exit(); | ||
1237 | return; | ||
1238 | } | ||
1239 | |||
1240 | if (sx_debug & SX_DEBUG_FIFO) { | ||
1241 | dprintk(SX_DEBUG_FIFO, | ||
1242 | "sx%d: port %d: %ld overruns, FIFO hits [ ", | ||
1243 | board_No(bp), port_No(port), port->overrun); | ||
1244 | for (i = 0; i < 10; i++) | ||
1245 | dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); | ||
1246 | dprintk(SX_DEBUG_FIFO, "].\n"); | ||
1247 | } | ||
1248 | |||
1249 | if (port->xmit_buf) { | ||
1250 | free_page((unsigned long) port->xmit_buf); | ||
1251 | port->xmit_buf = NULL; | ||
1252 | } | ||
1253 | |||
1254 | /* Select port */ | ||
1255 | spin_lock_irqsave(&bp->lock, flags); | ||
1256 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
1257 | |||
1258 | tty = port->port.tty; | ||
1259 | if (tty == NULL || C_HUPCL(tty)) { | ||
1260 | /* Drop DTR */ | ||
1261 | sx_out(bp, CD186x_MSVDTR, 0); | ||
1262 | } | ||
1263 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1264 | /* Reset port */ | ||
1265 | sx_wait_CCR(bp); | ||
1266 | spin_lock_irqsave(&bp->lock, flags); | ||
1267 | sx_out(bp, CD186x_CCR, CCR_SOFTRESET); | ||
1268 | /* Disable all interrupts from this port */ | ||
1269 | port->IER = 0; | ||
1270 | sx_out(bp, CD186x_IER, port->IER); | ||
1271 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1272 | if (tty) | ||
1273 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
1274 | port->port.flags &= ~ASYNC_INITIALIZED; | ||
1275 | |||
1276 | if (!bp->count) | ||
1277 | sx_shutdown_board(bp); | ||
1278 | func_exit(); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | ||
1283 | struct specialix_port *port) | ||
1284 | { | ||
1285 | DECLARE_WAITQUEUE(wait, current); | ||
1286 | struct specialix_board *bp = port_Board(port); | ||
1287 | int retval; | ||
1288 | int do_clocal = 0; | ||
1289 | int CD; | ||
1290 | unsigned long flags; | ||
1291 | |||
1292 | func_enter(); | ||
1293 | |||
1294 | /* | ||
1295 | * If the device is in the middle of being closed, then block | ||
1296 | * until it's done, and then try again. | ||
1297 | */ | ||
1298 | if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { | ||
1299 | interruptible_sleep_on(&port->port.close_wait); | ||
1300 | if (port->port.flags & ASYNC_HUP_NOTIFY) { | ||
1301 | func_exit(); | ||
1302 | return -EAGAIN; | ||
1303 | } else { | ||
1304 | func_exit(); | ||
1305 | return -ERESTARTSYS; | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | /* | ||
1310 | * If non-blocking mode is set, or the port is not enabled, | ||
1311 | * then make the check up front and then exit. | ||
1312 | */ | ||
1313 | if ((filp->f_flags & O_NONBLOCK) || | ||
1314 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
1315 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
1316 | func_exit(); | ||
1317 | return 0; | ||
1318 | } | ||
1319 | |||
1320 | if (C_CLOCAL(tty)) | ||
1321 | do_clocal = 1; | ||
1322 | |||
1323 | /* | ||
1324 | * Block waiting for the carrier detect and the line to become | ||
1325 | * free (i.e., not in use by the callout). While we are in | ||
1326 | * this loop, info->count is dropped by one, so that | ||
1327 | * rs_close() knows when to free things. We restore it upon | ||
1328 | * exit, either normal or abnormal. | ||
1329 | */ | ||
1330 | retval = 0; | ||
1331 | add_wait_queue(&port->port.open_wait, &wait); | ||
1332 | spin_lock_irqsave(&port->lock, flags); | ||
1333 | if (!tty_hung_up_p(filp)) | ||
1334 | port->port.count--; | ||
1335 | spin_unlock_irqrestore(&port->lock, flags); | ||
1336 | port->port.blocked_open++; | ||
1337 | while (1) { | ||
1338 | spin_lock_irqsave(&bp->lock, flags); | ||
1339 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
1340 | CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; | ||
1341 | if (sx_crtscts(tty)) { | ||
1342 | /* Activate RTS */ | ||
1343 | port->MSVR |= MSVR_DTR; /* WTF? */ | ||
1344 | sx_out(bp, CD186x_MSVR, port->MSVR); | ||
1345 | } else { | ||
1346 | /* Activate DTR */ | ||
1347 | port->MSVR |= MSVR_DTR; | ||
1348 | sx_out(bp, CD186x_MSVR, port->MSVR); | ||
1349 | } | ||
1350 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1351 | set_current_state(TASK_INTERRUPTIBLE); | ||
1352 | if (tty_hung_up_p(filp) || | ||
1353 | !(port->port.flags & ASYNC_INITIALIZED)) { | ||
1354 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
1355 | retval = -EAGAIN; | ||
1356 | else | ||
1357 | retval = -ERESTARTSYS; | ||
1358 | break; | ||
1359 | } | ||
1360 | if (!(port->port.flags & ASYNC_CLOSING) && | ||
1361 | (do_clocal || CD)) | ||
1362 | break; | ||
1363 | if (signal_pending(current)) { | ||
1364 | retval = -ERESTARTSYS; | ||
1365 | break; | ||
1366 | } | ||
1367 | tty_unlock(); | ||
1368 | schedule(); | ||
1369 | tty_lock(); | ||
1370 | } | ||
1371 | |||
1372 | set_current_state(TASK_RUNNING); | ||
1373 | remove_wait_queue(&port->port.open_wait, &wait); | ||
1374 | spin_lock_irqsave(&port->lock, flags); | ||
1375 | if (!tty_hung_up_p(filp)) | ||
1376 | port->port.count++; | ||
1377 | port->port.blocked_open--; | ||
1378 | spin_unlock_irqrestore(&port->lock, flags); | ||
1379 | if (retval) { | ||
1380 | func_exit(); | ||
1381 | return retval; | ||
1382 | } | ||
1383 | |||
1384 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
1385 | func_exit(); | ||
1386 | return 0; | ||
1387 | } | ||
1388 | |||
1389 | |||
1390 | static int sx_open(struct tty_struct *tty, struct file *filp) | ||
1391 | { | ||
1392 | int board; | ||
1393 | int error; | ||
1394 | struct specialix_port *port; | ||
1395 | struct specialix_board *bp; | ||
1396 | int i; | ||
1397 | unsigned long flags; | ||
1398 | |||
1399 | func_enter(); | ||
1400 | |||
1401 | board = SX_BOARD(tty->index); | ||
1402 | |||
1403 | if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) { | ||
1404 | func_exit(); | ||
1405 | return -ENODEV; | ||
1406 | } | ||
1407 | |||
1408 | bp = &sx_board[board]; | ||
1409 | port = sx_port + board * SX_NPORT + SX_PORT(tty->index); | ||
1410 | port->overrun = 0; | ||
1411 | for (i = 0; i < 10; i++) | ||
1412 | port->hits[i] = 0; | ||
1413 | |||
1414 | dprintk(SX_DEBUG_OPEN, | ||
1415 | "Board = %d, bp = %p, port = %p, portno = %d.\n", | ||
1416 | board, bp, port, SX_PORT(tty->index)); | ||
1417 | |||
1418 | if (sx_paranoia_check(port, tty->name, "sx_open")) { | ||
1419 | func_enter(); | ||
1420 | return -ENODEV; | ||
1421 | } | ||
1422 | |||
1423 | error = sx_setup_board(bp); | ||
1424 | if (error) { | ||
1425 | func_exit(); | ||
1426 | return error; | ||
1427 | } | ||
1428 | |||
1429 | spin_lock_irqsave(&bp->lock, flags); | ||
1430 | port->port.count++; | ||
1431 | bp->count++; | ||
1432 | tty->driver_data = port; | ||
1433 | port->port.tty = tty; | ||
1434 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1435 | |||
1436 | error = sx_setup_port(bp, port); | ||
1437 | if (error) { | ||
1438 | func_enter(); | ||
1439 | return error; | ||
1440 | } | ||
1441 | |||
1442 | error = block_til_ready(tty, filp, port); | ||
1443 | if (error) { | ||
1444 | func_enter(); | ||
1445 | return error; | ||
1446 | } | ||
1447 | |||
1448 | func_exit(); | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | static void sx_flush_buffer(struct tty_struct *tty) | ||
1453 | { | ||
1454 | struct specialix_port *port = tty->driver_data; | ||
1455 | unsigned long flags; | ||
1456 | struct specialix_board *bp; | ||
1457 | |||
1458 | func_enter(); | ||
1459 | |||
1460 | if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) { | ||
1461 | func_exit(); | ||
1462 | return; | ||
1463 | } | ||
1464 | |||
1465 | bp = port_Board(port); | ||
1466 | spin_lock_irqsave(&port->lock, flags); | ||
1467 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | ||
1468 | spin_unlock_irqrestore(&port->lock, flags); | ||
1469 | tty_wakeup(tty); | ||
1470 | |||
1471 | func_exit(); | ||
1472 | } | ||
1473 | |||
1474 | static void sx_close(struct tty_struct *tty, struct file *filp) | ||
1475 | { | ||
1476 | struct specialix_port *port = tty->driver_data; | ||
1477 | struct specialix_board *bp; | ||
1478 | unsigned long flags; | ||
1479 | unsigned long timeout; | ||
1480 | |||
1481 | func_enter(); | ||
1482 | if (!port || sx_paranoia_check(port, tty->name, "close")) { | ||
1483 | func_exit(); | ||
1484 | return; | ||
1485 | } | ||
1486 | spin_lock_irqsave(&port->lock, flags); | ||
1487 | |||
1488 | if (tty_hung_up_p(filp)) { | ||
1489 | spin_unlock_irqrestore(&port->lock, flags); | ||
1490 | func_exit(); | ||
1491 | return; | ||
1492 | } | ||
1493 | |||
1494 | bp = port_Board(port); | ||
1495 | if (tty->count == 1 && port->port.count != 1) { | ||
1496 | printk(KERN_ERR "sx%d: sx_close: bad port count;" | ||
1497 | " tty->count is 1, port count is %d\n", | ||
1498 | board_No(bp), port->port.count); | ||
1499 | port->port.count = 1; | ||
1500 | } | ||
1501 | |||
1502 | if (port->port.count > 1) { | ||
1503 | port->port.count--; | ||
1504 | bp->count--; | ||
1505 | |||
1506 | spin_unlock_irqrestore(&port->lock, flags); | ||
1507 | |||
1508 | func_exit(); | ||
1509 | return; | ||
1510 | } | ||
1511 | port->port.flags |= ASYNC_CLOSING; | ||
1512 | /* | ||
1513 | * Now we wait for the transmit buffer to clear; and we notify | ||
1514 | * the line discipline to only process XON/XOFF characters. | ||
1515 | */ | ||
1516 | tty->closing = 1; | ||
1517 | spin_unlock_irqrestore(&port->lock, flags); | ||
1518 | dprintk(SX_DEBUG_OPEN, "Closing\n"); | ||
1519 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1520 | tty_wait_until_sent(tty, port->port.closing_wait); | ||
1521 | /* | ||
1522 | * At this point we stop accepting input. To do this, we | ||
1523 | * disable the receive line status interrupts, and tell the | ||
1524 | * interrupt driver to stop checking the data ready bit in the | ||
1525 | * line status register. | ||
1526 | */ | ||
1527 | dprintk(SX_DEBUG_OPEN, "Closed\n"); | ||
1528 | port->IER &= ~IER_RXD; | ||
1529 | if (port->port.flags & ASYNC_INITIALIZED) { | ||
1530 | port->IER &= ~IER_TXRDY; | ||
1531 | port->IER |= IER_TXEMPTY; | ||
1532 | spin_lock_irqsave(&bp->lock, flags); | ||
1533 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
1534 | sx_out(bp, CD186x_IER, port->IER); | ||
1535 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1536 | /* | ||
1537 | * Before we drop DTR, make sure the UART transmitter | ||
1538 | * has completely drained; this is especially | ||
1539 | * important if there is a transmit FIFO! | ||
1540 | */ | ||
1541 | timeout = jiffies+HZ; | ||
1542 | while (port->IER & IER_TXEMPTY) { | ||
1543 | set_current_state(TASK_INTERRUPTIBLE); | ||
1544 | msleep_interruptible(jiffies_to_msecs(port->timeout)); | ||
1545 | if (time_after(jiffies, timeout)) { | ||
1546 | printk(KERN_INFO "Timeout waiting for close\n"); | ||
1547 | break; | ||
1548 | } | ||
1549 | } | ||
1550 | |||
1551 | } | ||
1552 | |||
1553 | if (--bp->count < 0) { | ||
1554 | printk(KERN_ERR | ||
1555 | "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", | ||
1556 | board_No(bp), bp->count, tty->index); | ||
1557 | bp->count = 0; | ||
1558 | } | ||
1559 | if (--port->port.count < 0) { | ||
1560 | printk(KERN_ERR | ||
1561 | "sx%d: sx_close: bad port count for tty%d: %d\n", | ||
1562 | board_No(bp), port_No(port), port->port.count); | ||
1563 | port->port.count = 0; | ||
1564 | } | ||
1565 | |||
1566 | sx_shutdown_port(bp, port); | ||
1567 | sx_flush_buffer(tty); | ||
1568 | tty_ldisc_flush(tty); | ||
1569 | spin_lock_irqsave(&port->lock, flags); | ||
1570 | tty->closing = 0; | ||
1571 | port->port.tty = NULL; | ||
1572 | spin_unlock_irqrestore(&port->lock, flags); | ||
1573 | if (port->port.blocked_open) { | ||
1574 | if (port->port.close_delay) | ||
1575 | msleep_interruptible( | ||
1576 | jiffies_to_msecs(port->port.close_delay)); | ||
1577 | wake_up_interruptible(&port->port.open_wait); | ||
1578 | } | ||
1579 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
1580 | wake_up_interruptible(&port->port.close_wait); | ||
1581 | |||
1582 | func_exit(); | ||
1583 | } | ||
1584 | |||
1585 | |||
1586 | static int sx_write(struct tty_struct *tty, | ||
1587 | const unsigned char *buf, int count) | ||
1588 | { | ||
1589 | struct specialix_port *port = tty->driver_data; | ||
1590 | struct specialix_board *bp; | ||
1591 | int c, total = 0; | ||
1592 | unsigned long flags; | ||
1593 | |||
1594 | func_enter(); | ||
1595 | if (sx_paranoia_check(port, tty->name, "sx_write")) { | ||
1596 | func_exit(); | ||
1597 | return 0; | ||
1598 | } | ||
1599 | |||
1600 | bp = port_Board(port); | ||
1601 | |||
1602 | if (!port->xmit_buf) { | ||
1603 | func_exit(); | ||
1604 | return 0; | ||
1605 | } | ||
1606 | |||
1607 | while (1) { | ||
1608 | spin_lock_irqsave(&port->lock, flags); | ||
1609 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, | ||
1610 | SERIAL_XMIT_SIZE - port->xmit_head)); | ||
1611 | if (c <= 0) { | ||
1612 | spin_unlock_irqrestore(&port->lock, flags); | ||
1613 | break; | ||
1614 | } | ||
1615 | memcpy(port->xmit_buf + port->xmit_head, buf, c); | ||
1616 | port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | ||
1617 | port->xmit_cnt += c; | ||
1618 | spin_unlock_irqrestore(&port->lock, flags); | ||
1619 | |||
1620 | buf += c; | ||
1621 | count -= c; | ||
1622 | total += c; | ||
1623 | } | ||
1624 | |||
1625 | spin_lock_irqsave(&bp->lock, flags); | ||
1626 | if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && | ||
1627 | !(port->IER & IER_TXRDY)) { | ||
1628 | port->IER |= IER_TXRDY; | ||
1629 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
1630 | sx_out(bp, CD186x_IER, port->IER); | ||
1631 | } | ||
1632 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1633 | func_exit(); | ||
1634 | |||
1635 | return total; | ||
1636 | } | ||
1637 | |||
1638 | |||
1639 | static int sx_put_char(struct tty_struct *tty, unsigned char ch) | ||
1640 | { | ||
1641 | struct specialix_port *port = tty->driver_data; | ||
1642 | unsigned long flags; | ||
1643 | struct specialix_board *bp; | ||
1644 | |||
1645 | func_enter(); | ||
1646 | |||
1647 | if (sx_paranoia_check(port, tty->name, "sx_put_char")) { | ||
1648 | func_exit(); | ||
1649 | return 0; | ||
1650 | } | ||
1651 | dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); | ||
1652 | if (!port->xmit_buf) { | ||
1653 | func_exit(); | ||
1654 | return 0; | ||
1655 | } | ||
1656 | bp = port_Board(port); | ||
1657 | spin_lock_irqsave(&port->lock, flags); | ||
1658 | |||
1659 | dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", | ||
1660 | port->xmit_cnt, port->xmit_buf); | ||
1661 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) { | ||
1662 | spin_unlock_irqrestore(&port->lock, flags); | ||
1663 | dprintk(SX_DEBUG_TX, "Exit size\n"); | ||
1664 | func_exit(); | ||
1665 | return 0; | ||
1666 | } | ||
1667 | dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); | ||
1668 | port->xmit_buf[port->xmit_head++] = ch; | ||
1669 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | ||
1670 | port->xmit_cnt++; | ||
1671 | spin_unlock_irqrestore(&port->lock, flags); | ||
1672 | |||
1673 | func_exit(); | ||
1674 | return 1; | ||
1675 | } | ||
1676 | |||
1677 | |||
1678 | static void sx_flush_chars(struct tty_struct *tty) | ||
1679 | { | ||
1680 | struct specialix_port *port = tty->driver_data; | ||
1681 | unsigned long flags; | ||
1682 | struct specialix_board *bp = port_Board(port); | ||
1683 | |||
1684 | func_enter(); | ||
1685 | |||
1686 | if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) { | ||
1687 | func_exit(); | ||
1688 | return; | ||
1689 | } | ||
1690 | if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || | ||
1691 | !port->xmit_buf) { | ||
1692 | func_exit(); | ||
1693 | return; | ||
1694 | } | ||
1695 | spin_lock_irqsave(&bp->lock, flags); | ||
1696 | port->IER |= IER_TXRDY; | ||
1697 | sx_out(port_Board(port), CD186x_CAR, port_No(port)); | ||
1698 | sx_out(port_Board(port), CD186x_IER, port->IER); | ||
1699 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1700 | |||
1701 | func_exit(); | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | static int sx_write_room(struct tty_struct *tty) | ||
1706 | { | ||
1707 | struct specialix_port *port = tty->driver_data; | ||
1708 | int ret; | ||
1709 | |||
1710 | func_enter(); | ||
1711 | |||
1712 | if (sx_paranoia_check(port, tty->name, "sx_write_room")) { | ||
1713 | func_exit(); | ||
1714 | return 0; | ||
1715 | } | ||
1716 | |||
1717 | ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; | ||
1718 | if (ret < 0) | ||
1719 | ret = 0; | ||
1720 | |||
1721 | func_exit(); | ||
1722 | return ret; | ||
1723 | } | ||
1724 | |||
1725 | |||
1726 | static int sx_chars_in_buffer(struct tty_struct *tty) | ||
1727 | { | ||
1728 | struct specialix_port *port = tty->driver_data; | ||
1729 | |||
1730 | func_enter(); | ||
1731 | |||
1732 | if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) { | ||
1733 | func_exit(); | ||
1734 | return 0; | ||
1735 | } | ||
1736 | func_exit(); | ||
1737 | return port->xmit_cnt; | ||
1738 | } | ||
1739 | |||
1740 | static int sx_tiocmget(struct tty_struct *tty) | ||
1741 | { | ||
1742 | struct specialix_port *port = tty->driver_data; | ||
1743 | struct specialix_board *bp; | ||
1744 | unsigned char status; | ||
1745 | unsigned int result; | ||
1746 | unsigned long flags; | ||
1747 | |||
1748 | func_enter(); | ||
1749 | |||
1750 | if (sx_paranoia_check(port, tty->name, __func__)) { | ||
1751 | func_exit(); | ||
1752 | return -ENODEV; | ||
1753 | } | ||
1754 | |||
1755 | bp = port_Board(port); | ||
1756 | spin_lock_irqsave(&bp->lock, flags); | ||
1757 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
1758 | status = sx_in(bp, CD186x_MSVR); | ||
1759 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1760 | dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", | ||
1761 | port_No(port), status, sx_in(bp, CD186x_CAR)); | ||
1762 | dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); | ||
1763 | if (sx_crtscts(port->port.tty)) { | ||
1764 | result = TIOCM_DTR | TIOCM_DSR | ||
1765 | | ((status & MSVR_DTR) ? TIOCM_RTS : 0) | ||
1766 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | ||
1767 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); | ||
1768 | } else { | ||
1769 | result = TIOCM_RTS | TIOCM_DSR | ||
1770 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | ||
1771 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | ||
1772 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); | ||
1773 | } | ||
1774 | |||
1775 | func_exit(); | ||
1776 | |||
1777 | return result; | ||
1778 | } | ||
1779 | |||
1780 | |||
1781 | static int sx_tiocmset(struct tty_struct *tty, | ||
1782 | unsigned int set, unsigned int clear) | ||
1783 | { | ||
1784 | struct specialix_port *port = tty->driver_data; | ||
1785 | unsigned long flags; | ||
1786 | struct specialix_board *bp; | ||
1787 | |||
1788 | func_enter(); | ||
1789 | |||
1790 | if (sx_paranoia_check(port, tty->name, __func__)) { | ||
1791 | func_exit(); | ||
1792 | return -ENODEV; | ||
1793 | } | ||
1794 | |||
1795 | bp = port_Board(port); | ||
1796 | |||
1797 | spin_lock_irqsave(&port->lock, flags); | ||
1798 | if (sx_crtscts(port->port.tty)) { | ||
1799 | if (set & TIOCM_RTS) | ||
1800 | port->MSVR |= MSVR_DTR; | ||
1801 | } else { | ||
1802 | if (set & TIOCM_DTR) | ||
1803 | port->MSVR |= MSVR_DTR; | ||
1804 | } | ||
1805 | if (sx_crtscts(port->port.tty)) { | ||
1806 | if (clear & TIOCM_RTS) | ||
1807 | port->MSVR &= ~MSVR_DTR; | ||
1808 | } else { | ||
1809 | if (clear & TIOCM_DTR) | ||
1810 | port->MSVR &= ~MSVR_DTR; | ||
1811 | } | ||
1812 | spin_lock(&bp->lock); | ||
1813 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
1814 | sx_out(bp, CD186x_MSVR, port->MSVR); | ||
1815 | spin_unlock(&bp->lock); | ||
1816 | spin_unlock_irqrestore(&port->lock, flags); | ||
1817 | func_exit(); | ||
1818 | return 0; | ||
1819 | } | ||
1820 | |||
1821 | |||
1822 | static int sx_send_break(struct tty_struct *tty, int length) | ||
1823 | { | ||
1824 | struct specialix_port *port = tty->driver_data; | ||
1825 | struct specialix_board *bp = port_Board(port); | ||
1826 | unsigned long flags; | ||
1827 | |||
1828 | func_enter(); | ||
1829 | if (length == 0 || length == -1) | ||
1830 | return -EOPNOTSUPP; | ||
1831 | |||
1832 | spin_lock_irqsave(&port->lock, flags); | ||
1833 | port->break_length = SPECIALIX_TPS / HZ * length; | ||
1834 | port->COR2 |= COR2_ETC; | ||
1835 | port->IER |= IER_TXRDY; | ||
1836 | spin_lock(&bp->lock); | ||
1837 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
1838 | sx_out(bp, CD186x_COR2, port->COR2); | ||
1839 | sx_out(bp, CD186x_IER, port->IER); | ||
1840 | spin_unlock(&bp->lock); | ||
1841 | spin_unlock_irqrestore(&port->lock, flags); | ||
1842 | sx_wait_CCR(bp); | ||
1843 | spin_lock_irqsave(&bp->lock, flags); | ||
1844 | sx_out(bp, CD186x_CCR, CCR_CORCHG2); | ||
1845 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1846 | sx_wait_CCR(bp); | ||
1847 | |||
1848 | func_exit(); | ||
1849 | return 0; | ||
1850 | } | ||
1851 | |||
1852 | |||
1853 | static int sx_set_serial_info(struct specialix_port *port, | ||
1854 | struct serial_struct __user *newinfo) | ||
1855 | { | ||
1856 | struct serial_struct tmp; | ||
1857 | struct specialix_board *bp = port_Board(port); | ||
1858 | int change_speed; | ||
1859 | |||
1860 | func_enter(); | ||
1861 | |||
1862 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) { | ||
1863 | func_enter(); | ||
1864 | return -EFAULT; | ||
1865 | } | ||
1866 | |||
1867 | mutex_lock(&port->port.mutex); | ||
1868 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != | ||
1869 | (tmp.flags & ASYNC_SPD_MASK)); | ||
1870 | change_speed |= (tmp.custom_divisor != port->custom_divisor); | ||
1871 | |||
1872 | if (!capable(CAP_SYS_ADMIN)) { | ||
1873 | if ((tmp.close_delay != port->port.close_delay) || | ||
1874 | (tmp.closing_wait != port->port.closing_wait) || | ||
1875 | ((tmp.flags & ~ASYNC_USR_MASK) != | ||
1876 | (port->port.flags & ~ASYNC_USR_MASK))) { | ||
1877 | func_exit(); | ||
1878 | mutex_unlock(&port->port.mutex); | ||
1879 | return -EPERM; | ||
1880 | } | ||
1881 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | ||
1882 | (tmp.flags & ASYNC_USR_MASK)); | ||
1883 | port->custom_divisor = tmp.custom_divisor; | ||
1884 | } else { | ||
1885 | port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | | ||
1886 | (tmp.flags & ASYNC_FLAGS)); | ||
1887 | port->port.close_delay = tmp.close_delay; | ||
1888 | port->port.closing_wait = tmp.closing_wait; | ||
1889 | port->custom_divisor = tmp.custom_divisor; | ||
1890 | } | ||
1891 | if (change_speed) | ||
1892 | sx_change_speed(bp, port); | ||
1893 | |||
1894 | func_exit(); | ||
1895 | mutex_unlock(&port->port.mutex); | ||
1896 | return 0; | ||
1897 | } | ||
1898 | |||
1899 | |||
1900 | static int sx_get_serial_info(struct specialix_port *port, | ||
1901 | struct serial_struct __user *retinfo) | ||
1902 | { | ||
1903 | struct serial_struct tmp; | ||
1904 | struct specialix_board *bp = port_Board(port); | ||
1905 | |||
1906 | func_enter(); | ||
1907 | |||
1908 | memset(&tmp, 0, sizeof(tmp)); | ||
1909 | mutex_lock(&port->port.mutex); | ||
1910 | tmp.type = PORT_CIRRUS; | ||
1911 | tmp.line = port - sx_port; | ||
1912 | tmp.port = bp->base; | ||
1913 | tmp.irq = bp->irq; | ||
1914 | tmp.flags = port->port.flags; | ||
1915 | tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC; | ||
1916 | tmp.close_delay = port->port.close_delay * HZ/100; | ||
1917 | tmp.closing_wait = port->port.closing_wait * HZ/100; | ||
1918 | tmp.custom_divisor = port->custom_divisor; | ||
1919 | tmp.xmit_fifo_size = CD186x_NFIFO; | ||
1920 | mutex_unlock(&port->port.mutex); | ||
1921 | if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { | ||
1922 | func_exit(); | ||
1923 | return -EFAULT; | ||
1924 | } | ||
1925 | |||
1926 | func_exit(); | ||
1927 | return 0; | ||
1928 | } | ||
1929 | |||
1930 | |||
1931 | static int sx_ioctl(struct tty_struct *tty, | ||
1932 | unsigned int cmd, unsigned long arg) | ||
1933 | { | ||
1934 | struct specialix_port *port = tty->driver_data; | ||
1935 | void __user *argp = (void __user *)arg; | ||
1936 | |||
1937 | func_enter(); | ||
1938 | |||
1939 | if (sx_paranoia_check(port, tty->name, "sx_ioctl")) { | ||
1940 | func_exit(); | ||
1941 | return -ENODEV; | ||
1942 | } | ||
1943 | |||
1944 | switch (cmd) { | ||
1945 | case TIOCGSERIAL: | ||
1946 | func_exit(); | ||
1947 | return sx_get_serial_info(port, argp); | ||
1948 | case TIOCSSERIAL: | ||
1949 | func_exit(); | ||
1950 | return sx_set_serial_info(port, argp); | ||
1951 | default: | ||
1952 | func_exit(); | ||
1953 | return -ENOIOCTLCMD; | ||
1954 | } | ||
1955 | func_exit(); | ||
1956 | return 0; | ||
1957 | } | ||
1958 | |||
1959 | |||
1960 | static void sx_throttle(struct tty_struct *tty) | ||
1961 | { | ||
1962 | struct specialix_port *port = tty->driver_data; | ||
1963 | struct specialix_board *bp; | ||
1964 | unsigned long flags; | ||
1965 | |||
1966 | func_enter(); | ||
1967 | |||
1968 | if (sx_paranoia_check(port, tty->name, "sx_throttle")) { | ||
1969 | func_exit(); | ||
1970 | return; | ||
1971 | } | ||
1972 | |||
1973 | bp = port_Board(port); | ||
1974 | |||
1975 | /* Use DTR instead of RTS ! */ | ||
1976 | if (sx_crtscts(tty)) | ||
1977 | port->MSVR &= ~MSVR_DTR; | ||
1978 | else { | ||
1979 | /* Auch!!! I think the system shouldn't call this then. */ | ||
1980 | /* Or maybe we're supposed (allowed?) to do our side of hw | ||
1981 | handshake anyway, even when hardware handshake is off. | ||
1982 | When you see this in your logs, please report.... */ | ||
1983 | printk(KERN_ERR | ||
1984 | "sx%d: Need to throttle, but can't (hardware hs is off)\n", | ||
1985 | port_No(port)); | ||
1986 | } | ||
1987 | spin_lock_irqsave(&bp->lock, flags); | ||
1988 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
1989 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1990 | if (I_IXOFF(tty)) { | ||
1991 | sx_wait_CCR(bp); | ||
1992 | spin_lock_irqsave(&bp->lock, flags); | ||
1993 | sx_out(bp, CD186x_CCR, CCR_SSCH2); | ||
1994 | spin_unlock_irqrestore(&bp->lock, flags); | ||
1995 | sx_wait_CCR(bp); | ||
1996 | } | ||
1997 | spin_lock_irqsave(&bp->lock, flags); | ||
1998 | sx_out(bp, CD186x_MSVR, port->MSVR); | ||
1999 | spin_unlock_irqrestore(&bp->lock, flags); | ||
2000 | |||
2001 | func_exit(); | ||
2002 | } | ||
2003 | |||
2004 | |||
2005 | static void sx_unthrottle(struct tty_struct *tty) | ||
2006 | { | ||
2007 | struct specialix_port *port = tty->driver_data; | ||
2008 | struct specialix_board *bp; | ||
2009 | unsigned long flags; | ||
2010 | |||
2011 | func_enter(); | ||
2012 | |||
2013 | if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) { | ||
2014 | func_exit(); | ||
2015 | return; | ||
2016 | } | ||
2017 | |||
2018 | bp = port_Board(port); | ||
2019 | |||
2020 | spin_lock_irqsave(&port->lock, flags); | ||
2021 | /* XXXX Use DTR INSTEAD???? */ | ||
2022 | if (sx_crtscts(tty)) | ||
2023 | port->MSVR |= MSVR_DTR; | ||
2024 | /* Else clause: see remark in "sx_throttle"... */ | ||
2025 | spin_lock(&bp->lock); | ||
2026 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
2027 | spin_unlock(&bp->lock); | ||
2028 | if (I_IXOFF(tty)) { | ||
2029 | spin_unlock_irqrestore(&port->lock, flags); | ||
2030 | sx_wait_CCR(bp); | ||
2031 | spin_lock_irqsave(&bp->lock, flags); | ||
2032 | sx_out(bp, CD186x_CCR, CCR_SSCH1); | ||
2033 | spin_unlock_irqrestore(&bp->lock, flags); | ||
2034 | sx_wait_CCR(bp); | ||
2035 | spin_lock_irqsave(&port->lock, flags); | ||
2036 | } | ||
2037 | spin_lock(&bp->lock); | ||
2038 | sx_out(bp, CD186x_MSVR, port->MSVR); | ||
2039 | spin_unlock(&bp->lock); | ||
2040 | spin_unlock_irqrestore(&port->lock, flags); | ||
2041 | |||
2042 | func_exit(); | ||
2043 | } | ||
2044 | |||
2045 | |||
2046 | static void sx_stop(struct tty_struct *tty) | ||
2047 | { | ||
2048 | struct specialix_port *port = tty->driver_data; | ||
2049 | struct specialix_board *bp; | ||
2050 | unsigned long flags; | ||
2051 | |||
2052 | func_enter(); | ||
2053 | |||
2054 | if (sx_paranoia_check(port, tty->name, "sx_stop")) { | ||
2055 | func_exit(); | ||
2056 | return; | ||
2057 | } | ||
2058 | |||
2059 | bp = port_Board(port); | ||
2060 | |||
2061 | spin_lock_irqsave(&port->lock, flags); | ||
2062 | port->IER &= ~IER_TXRDY; | ||
2063 | spin_lock(&bp->lock); | ||
2064 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
2065 | sx_out(bp, CD186x_IER, port->IER); | ||
2066 | spin_unlock(&bp->lock); | ||
2067 | spin_unlock_irqrestore(&port->lock, flags); | ||
2068 | |||
2069 | func_exit(); | ||
2070 | } | ||
2071 | |||
2072 | |||
2073 | static void sx_start(struct tty_struct *tty) | ||
2074 | { | ||
2075 | struct specialix_port *port = tty->driver_data; | ||
2076 | struct specialix_board *bp; | ||
2077 | unsigned long flags; | ||
2078 | |||
2079 | func_enter(); | ||
2080 | |||
2081 | if (sx_paranoia_check(port, tty->name, "sx_start")) { | ||
2082 | func_exit(); | ||
2083 | return; | ||
2084 | } | ||
2085 | |||
2086 | bp = port_Board(port); | ||
2087 | |||
2088 | spin_lock_irqsave(&port->lock, flags); | ||
2089 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { | ||
2090 | port->IER |= IER_TXRDY; | ||
2091 | spin_lock(&bp->lock); | ||
2092 | sx_out(bp, CD186x_CAR, port_No(port)); | ||
2093 | sx_out(bp, CD186x_IER, port->IER); | ||
2094 | spin_unlock(&bp->lock); | ||
2095 | } | ||
2096 | spin_unlock_irqrestore(&port->lock, flags); | ||
2097 | |||
2098 | func_exit(); | ||
2099 | } | ||
2100 | |||
2101 | static void sx_hangup(struct tty_struct *tty) | ||
2102 | { | ||
2103 | struct specialix_port *port = tty->driver_data; | ||
2104 | struct specialix_board *bp; | ||
2105 | unsigned long flags; | ||
2106 | |||
2107 | func_enter(); | ||
2108 | |||
2109 | if (sx_paranoia_check(port, tty->name, "sx_hangup")) { | ||
2110 | func_exit(); | ||
2111 | return; | ||
2112 | } | ||
2113 | |||
2114 | bp = port_Board(port); | ||
2115 | |||
2116 | sx_shutdown_port(bp, port); | ||
2117 | spin_lock_irqsave(&port->lock, flags); | ||
2118 | bp->count -= port->port.count; | ||
2119 | if (bp->count < 0) { | ||
2120 | printk(KERN_ERR | ||
2121 | "sx%d: sx_hangup: bad board count: %d port: %d\n", | ||
2122 | board_No(bp), bp->count, tty->index); | ||
2123 | bp->count = 0; | ||
2124 | } | ||
2125 | port->port.count = 0; | ||
2126 | port->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
2127 | port->port.tty = NULL; | ||
2128 | spin_unlock_irqrestore(&port->lock, flags); | ||
2129 | wake_up_interruptible(&port->port.open_wait); | ||
2130 | |||
2131 | func_exit(); | ||
2132 | } | ||
2133 | |||
2134 | |||
2135 | static void sx_set_termios(struct tty_struct *tty, | ||
2136 | struct ktermios *old_termios) | ||
2137 | { | ||
2138 | struct specialix_port *port = tty->driver_data; | ||
2139 | unsigned long flags; | ||
2140 | struct specialix_board *bp; | ||
2141 | |||
2142 | if (sx_paranoia_check(port, tty->name, "sx_set_termios")) | ||
2143 | return; | ||
2144 | |||
2145 | bp = port_Board(port); | ||
2146 | spin_lock_irqsave(&port->lock, flags); | ||
2147 | sx_change_speed(port_Board(port), port); | ||
2148 | spin_unlock_irqrestore(&port->lock, flags); | ||
2149 | |||
2150 | if ((old_termios->c_cflag & CRTSCTS) && | ||
2151 | !(tty->termios->c_cflag & CRTSCTS)) { | ||
2152 | tty->hw_stopped = 0; | ||
2153 | sx_start(tty); | ||
2154 | } | ||
2155 | } | ||
2156 | |||
2157 | static const struct tty_operations sx_ops = { | ||
2158 | .open = sx_open, | ||
2159 | .close = sx_close, | ||
2160 | .write = sx_write, | ||
2161 | .put_char = sx_put_char, | ||
2162 | .flush_chars = sx_flush_chars, | ||
2163 | .write_room = sx_write_room, | ||
2164 | .chars_in_buffer = sx_chars_in_buffer, | ||
2165 | .flush_buffer = sx_flush_buffer, | ||
2166 | .ioctl = sx_ioctl, | ||
2167 | .throttle = sx_throttle, | ||
2168 | .unthrottle = sx_unthrottle, | ||
2169 | .set_termios = sx_set_termios, | ||
2170 | .stop = sx_stop, | ||
2171 | .start = sx_start, | ||
2172 | .hangup = sx_hangup, | ||
2173 | .tiocmget = sx_tiocmget, | ||
2174 | .tiocmset = sx_tiocmset, | ||
2175 | .break_ctl = sx_send_break, | ||
2176 | }; | ||
2177 | |||
2178 | static int sx_init_drivers(void) | ||
2179 | { | ||
2180 | int error; | ||
2181 | int i; | ||
2182 | |||
2183 | func_enter(); | ||
2184 | |||
2185 | specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT); | ||
2186 | if (!specialix_driver) { | ||
2187 | printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n"); | ||
2188 | func_exit(); | ||
2189 | return 1; | ||
2190 | } | ||
2191 | |||
2192 | specialix_driver->owner = THIS_MODULE; | ||
2193 | specialix_driver->name = "ttyW"; | ||
2194 | specialix_driver->major = SPECIALIX_NORMAL_MAJOR; | ||
2195 | specialix_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2196 | specialix_driver->subtype = SERIAL_TYPE_NORMAL; | ||
2197 | specialix_driver->init_termios = tty_std_termios; | ||
2198 | specialix_driver->init_termios.c_cflag = | ||
2199 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
2200 | specialix_driver->init_termios.c_ispeed = 9600; | ||
2201 | specialix_driver->init_termios.c_ospeed = 9600; | ||
2202 | specialix_driver->flags = TTY_DRIVER_REAL_RAW | | ||
2203 | TTY_DRIVER_HARDWARE_BREAK; | ||
2204 | tty_set_operations(specialix_driver, &sx_ops); | ||
2205 | |||
2206 | error = tty_register_driver(specialix_driver); | ||
2207 | if (error) { | ||
2208 | put_tty_driver(specialix_driver); | ||
2209 | printk(KERN_ERR | ||
2210 | "sx: Couldn't register specialix IO8+ driver, error = %d\n", | ||
2211 | error); | ||
2212 | func_exit(); | ||
2213 | return 1; | ||
2214 | } | ||
2215 | memset(sx_port, 0, sizeof(sx_port)); | ||
2216 | for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { | ||
2217 | sx_port[i].magic = SPECIALIX_MAGIC; | ||
2218 | tty_port_init(&sx_port[i].port); | ||
2219 | spin_lock_init(&sx_port[i].lock); | ||
2220 | } | ||
2221 | |||
2222 | func_exit(); | ||
2223 | return 0; | ||
2224 | } | ||
2225 | |||
2226 | static void sx_release_drivers(void) | ||
2227 | { | ||
2228 | func_enter(); | ||
2229 | |||
2230 | tty_unregister_driver(specialix_driver); | ||
2231 | put_tty_driver(specialix_driver); | ||
2232 | func_exit(); | ||
2233 | } | ||
2234 | |||
2235 | /* | ||
2236 | * This routine must be called by kernel at boot time | ||
2237 | */ | ||
2238 | static int __init specialix_init(void) | ||
2239 | { | ||
2240 | int i; | ||
2241 | int found = 0; | ||
2242 | |||
2243 | func_enter(); | ||
2244 | |||
2245 | printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); | ||
2246 | printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); | ||
2247 | if (sx_rtscts) | ||
2248 | printk(KERN_INFO | ||
2249 | "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); | ||
2250 | else | ||
2251 | printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); | ||
2252 | |||
2253 | for (i = 0; i < SX_NBOARD; i++) | ||
2254 | spin_lock_init(&sx_board[i].lock); | ||
2255 | |||
2256 | if (sx_init_drivers()) { | ||
2257 | func_exit(); | ||
2258 | return -EIO; | ||
2259 | } | ||
2260 | |||
2261 | for (i = 0; i < SX_NBOARD; i++) | ||
2262 | if (sx_board[i].base && !sx_probe(&sx_board[i])) | ||
2263 | found++; | ||
2264 | |||
2265 | #ifdef CONFIG_PCI | ||
2266 | { | ||
2267 | struct pci_dev *pdev = NULL; | ||
2268 | |||
2269 | i = 0; | ||
2270 | while (i < SX_NBOARD) { | ||
2271 | if (sx_board[i].flags & SX_BOARD_PRESENT) { | ||
2272 | i++; | ||
2273 | continue; | ||
2274 | } | ||
2275 | pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, | ||
2276 | PCI_DEVICE_ID_SPECIALIX_IO8, pdev); | ||
2277 | if (!pdev) | ||
2278 | break; | ||
2279 | |||
2280 | if (pci_enable_device(pdev)) | ||
2281 | continue; | ||
2282 | |||
2283 | sx_board[i].irq = pdev->irq; | ||
2284 | |||
2285 | sx_board[i].base = pci_resource_start(pdev, 2); | ||
2286 | |||
2287 | sx_board[i].flags |= SX_BOARD_IS_PCI; | ||
2288 | if (!sx_probe(&sx_board[i])) | ||
2289 | found++; | ||
2290 | } | ||
2291 | /* May exit pci_get sequence early with lots of boards */ | ||
2292 | if (pdev != NULL) | ||
2293 | pci_dev_put(pdev); | ||
2294 | } | ||
2295 | #endif | ||
2296 | |||
2297 | if (!found) { | ||
2298 | sx_release_drivers(); | ||
2299 | printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n"); | ||
2300 | func_exit(); | ||
2301 | return -EIO; | ||
2302 | } | ||
2303 | |||
2304 | func_exit(); | ||
2305 | return 0; | ||
2306 | } | ||
2307 | |||
2308 | static int iobase[SX_NBOARD] = {0,}; | ||
2309 | static int irq[SX_NBOARD] = {0,}; | ||
2310 | |||
2311 | module_param_array(iobase, int, NULL, 0); | ||
2312 | module_param_array(irq, int, NULL, 0); | ||
2313 | module_param(sx_debug, int, 0); | ||
2314 | module_param(sx_rtscts, int, 0); | ||
2315 | module_param(sx_rxfifo, int, 0); | ||
2316 | |||
2317 | /* | ||
2318 | * You can setup up to 4 boards. | ||
2319 | * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter. | ||
2320 | * You should specify the IRQs too in that case "irq=....,...". | ||
2321 | * | ||
2322 | * More than 4 boards in one computer is not possible, as the card can | ||
2323 | * only use 4 different interrupts. | ||
2324 | * | ||
2325 | */ | ||
2326 | static int __init specialix_init_module(void) | ||
2327 | { | ||
2328 | int i; | ||
2329 | |||
2330 | func_enter(); | ||
2331 | |||
2332 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { | ||
2333 | for (i = 0; i < SX_NBOARD; i++) { | ||
2334 | sx_board[i].base = iobase[i]; | ||
2335 | sx_board[i].irq = irq[i]; | ||
2336 | sx_board[i].count = 0; | ||
2337 | } | ||
2338 | } | ||
2339 | |||
2340 | func_exit(); | ||
2341 | |||
2342 | return specialix_init(); | ||
2343 | } | ||
2344 | |||
2345 | static void __exit specialix_exit_module(void) | ||
2346 | { | ||
2347 | int i; | ||
2348 | |||
2349 | func_enter(); | ||
2350 | |||
2351 | sx_release_drivers(); | ||
2352 | for (i = 0; i < SX_NBOARD; i++) | ||
2353 | if (sx_board[i].flags & SX_BOARD_PRESENT) | ||
2354 | sx_release_io_range(&sx_board[i]); | ||
2355 | func_exit(); | ||
2356 | } | ||
2357 | |||
2358 | static struct pci_device_id specialx_pci_tbl[] __devinitdata __used = { | ||
2359 | { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) }, | ||
2360 | { } | ||
2361 | }; | ||
2362 | MODULE_DEVICE_TABLE(pci, specialx_pci_tbl); | ||
2363 | |||
2364 | module_init(specialix_init_module); | ||
2365 | module_exit(specialix_exit_module); | ||
2366 | |||
2367 | MODULE_LICENSE("GPL"); | ||
2368 | MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR); | ||
diff --git a/drivers/char/specialix_io8.h b/drivers/char/specialix_io8.h deleted file mode 100644 index c63005274d9b..000000000000 --- a/drivers/char/specialix_io8.h +++ /dev/null | |||
@@ -1,140 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/char/specialix_io8.h -- | ||
3 | * Specialix IO8+ multiport serial driver. | ||
4 | * | ||
5 | * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) | ||
6 | * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) | ||
7 | * | ||
8 | * | ||
9 | * Specialix pays for the development and support of this driver. | ||
10 | * Please DO contact io8-linux@specialix.co.uk if you require | ||
11 | * support. | ||
12 | * | ||
13 | * This driver was developped in the BitWizard linux device | ||
14 | * driver service. If you require a linux device driver for your | ||
15 | * product, please contact devices@BitWizard.nl for a quote. | ||
16 | * | ||
17 | * This code is firmly based on the riscom/8 serial driver, | ||
18 | * written by Dmitry Gorodchanin. The specialix IO8+ card | ||
19 | * programming information was obtained from the CL-CD1865 Data | ||
20 | * Book, and Specialix document number 6200059: IO8+ Hardware | ||
21 | * Functional Specification. | ||
22 | * | ||
23 | * This program is free software; you can redistribute it and/or | ||
24 | * modify it under the terms of the GNU General Public License as | ||
25 | * published by the Free Software Foundation; either version 2 of | ||
26 | * the License, or (at your option) any later version. | ||
27 | * | ||
28 | * This program is distributed in the hope that it will be | ||
29 | * useful, but WITHOUT ANY WARRANTY; without even the implied | ||
30 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
31 | * PURPOSE. See the GNU General Public License for more details. | ||
32 | * | ||
33 | * You should have received a copy of the GNU General Public | ||
34 | * License along with this program; if not, write to the Free | ||
35 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, | ||
36 | * USA. | ||
37 | * */ | ||
38 | |||
39 | #ifndef __LINUX_SPECIALIX_H | ||
40 | #define __LINUX_SPECIALIX_H | ||
41 | |||
42 | #include <linux/serial.h> | ||
43 | |||
44 | #ifdef __KERNEL__ | ||
45 | |||
46 | /* You can have max 4 ISA cards in one PC, and I recommend not much | ||
47 | more than a few PCI versions of the card. */ | ||
48 | |||
49 | #define SX_NBOARD 8 | ||
50 | |||
51 | /* NOTE: Specialix decoder recognizes 4 addresses, but only two are used.... */ | ||
52 | #define SX_IO_SPACE 4 | ||
53 | /* The PCI version decodes 8 addresses, but still only 2 are used. */ | ||
54 | #define SX_PCI_IO_SPACE 8 | ||
55 | |||
56 | /* eight ports per board. */ | ||
57 | #define SX_NPORT 8 | ||
58 | #define SX_BOARD(line) ((line) / SX_NPORT) | ||
59 | #define SX_PORT(line) ((line) & (SX_NPORT - 1)) | ||
60 | |||
61 | |||
62 | #define SX_DATA_REG 0 /* Base+0 : Data register */ | ||
63 | #define SX_ADDR_REG 1 /* base+1 : Address register. */ | ||
64 | |||
65 | #define MHz *1000000 /* I'm ashamed of myself. */ | ||
66 | |||
67 | /* On-board oscillator frequency */ | ||
68 | #define SX_OSCFREQ (25 MHz/2) | ||
69 | /* There is a 25MHz crystal on the board, but the chip is in /2 mode */ | ||
70 | |||
71 | |||
72 | /* Ticks per sec. Used for setting receiver timeout and break length */ | ||
73 | #define SPECIALIX_TPS 4000 | ||
74 | |||
75 | /* Yeah, after heavy testing I decided it must be 6. | ||
76 | * Sure, You can change it if needed. | ||
77 | */ | ||
78 | #define SPECIALIX_RXFIFO 6 /* Max. receiver FIFO size (1-8) */ | ||
79 | |||
80 | #define SPECIALIX_MAGIC 0x0907 | ||
81 | |||
82 | #define SX_CCR_TIMEOUT 10000 /* CCR timeout. You may need to wait upto | ||
83 | 10 milliseconds before the internal | ||
84 | processor is available again after | ||
85 | you give it a command */ | ||
86 | |||
87 | #define SX_IOBASE1 0x100 | ||
88 | #define SX_IOBASE2 0x180 | ||
89 | #define SX_IOBASE3 0x250 | ||
90 | #define SX_IOBASE4 0x260 | ||
91 | |||
92 | struct specialix_board { | ||
93 | unsigned long flags; | ||
94 | unsigned short base; | ||
95 | unsigned char irq; | ||
96 | //signed char count; | ||
97 | int count; | ||
98 | unsigned char DTR; | ||
99 | int reg; | ||
100 | spinlock_t lock; | ||
101 | }; | ||
102 | |||
103 | #define SX_BOARD_PRESENT 0x00000001 | ||
104 | #define SX_BOARD_ACTIVE 0x00000002 | ||
105 | #define SX_BOARD_IS_PCI 0x00000004 | ||
106 | |||
107 | |||
108 | struct specialix_port { | ||
109 | int magic; | ||
110 | struct tty_port port; | ||
111 | int baud_base; | ||
112 | int flags; | ||
113 | int timeout; | ||
114 | unsigned char * xmit_buf; | ||
115 | int custom_divisor; | ||
116 | int xmit_head; | ||
117 | int xmit_tail; | ||
118 | int xmit_cnt; | ||
119 | short wakeup_chars; | ||
120 | short break_length; | ||
121 | unsigned char mark_mask; | ||
122 | unsigned char IER; | ||
123 | unsigned char MSVR; | ||
124 | unsigned char COR2; | ||
125 | unsigned long overrun; | ||
126 | unsigned long hits[10]; | ||
127 | spinlock_t lock; | ||
128 | }; | ||
129 | |||
130 | #endif /* __KERNEL__ */ | ||
131 | #endif /* __LINUX_SPECIALIX_H */ | ||
132 | |||
133 | |||
134 | |||
135 | |||
136 | |||
137 | |||
138 | |||
139 | |||
140 | |||
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c deleted file mode 100644 index 4fff5cd3b163..000000000000 --- a/drivers/char/stallion.c +++ /dev/null | |||
@@ -1,4651 +0,0 @@ | |||
1 | /*****************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * stallion.c -- stallion multiport serial driver. | ||
5 | * | ||
6 | * Copyright (C) 1996-1999 Stallion Technologies | ||
7 | * Copyright (C) 1994-1996 Greg Ungerer. | ||
8 | * | ||
9 | * This code is loosely based on the Linux serial driver, written by | ||
10 | * Linus Torvalds, Theodore T'so and others. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | /*****************************************************************************/ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/tty.h> | ||
34 | #include <linux/tty_flip.h> | ||
35 | #include <linux/serial.h> | ||
36 | #include <linux/seq_file.h> | ||
37 | #include <linux/cd1400.h> | ||
38 | #include <linux/sc26198.h> | ||
39 | #include <linux/comstats.h> | ||
40 | #include <linux/stallion.h> | ||
41 | #include <linux/ioport.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/device.h> | ||
44 | #include <linux/delay.h> | ||
45 | #include <linux/ctype.h> | ||
46 | |||
47 | #include <asm/io.h> | ||
48 | #include <asm/uaccess.h> | ||
49 | |||
50 | #include <linux/pci.h> | ||
51 | |||
52 | /*****************************************************************************/ | ||
53 | |||
54 | /* | ||
55 | * Define different board types. Use the standard Stallion "assigned" | ||
56 | * board numbers. Boards supported in this driver are abbreviated as | ||
57 | * EIO = EasyIO and ECH = EasyConnection 8/32. | ||
58 | */ | ||
59 | #define BRD_EASYIO 20 | ||
60 | #define BRD_ECH 21 | ||
61 | #define BRD_ECHMC 22 | ||
62 | #define BRD_ECHPCI 26 | ||
63 | #define BRD_ECH64PCI 27 | ||
64 | #define BRD_EASYIOPCI 28 | ||
65 | |||
66 | struct stlconf { | ||
67 | unsigned int brdtype; | ||
68 | int ioaddr1; | ||
69 | int ioaddr2; | ||
70 | unsigned long memaddr; | ||
71 | int irq; | ||
72 | int irqtype; | ||
73 | }; | ||
74 | |||
75 | static unsigned int stl_nrbrds; | ||
76 | |||
77 | /*****************************************************************************/ | ||
78 | |||
79 | /* | ||
80 | * Define some important driver characteristics. Device major numbers | ||
81 | * allocated as per Linux Device Registry. | ||
82 | */ | ||
83 | #ifndef STL_SIOMEMMAJOR | ||
84 | #define STL_SIOMEMMAJOR 28 | ||
85 | #endif | ||
86 | #ifndef STL_SERIALMAJOR | ||
87 | #define STL_SERIALMAJOR 24 | ||
88 | #endif | ||
89 | #ifndef STL_CALLOUTMAJOR | ||
90 | #define STL_CALLOUTMAJOR 25 | ||
91 | #endif | ||
92 | |||
93 | /* | ||
94 | * Set the TX buffer size. Bigger is better, but we don't want | ||
95 | * to chew too much memory with buffers! | ||
96 | */ | ||
97 | #define STL_TXBUFLOW 512 | ||
98 | #define STL_TXBUFSIZE 4096 | ||
99 | |||
100 | /*****************************************************************************/ | ||
101 | |||
102 | /* | ||
103 | * Define our local driver identity first. Set up stuff to deal with | ||
104 | * all the local structures required by a serial tty driver. | ||
105 | */ | ||
106 | static char *stl_drvtitle = "Stallion Multiport Serial Driver"; | ||
107 | static char *stl_drvname = "stallion"; | ||
108 | static char *stl_drvversion = "5.6.0"; | ||
109 | |||
110 | static struct tty_driver *stl_serial; | ||
111 | |||
112 | /* | ||
113 | * Define a local default termios struct. All ports will be created | ||
114 | * with this termios initially. Basically all it defines is a raw port | ||
115 | * at 9600, 8 data bits, 1 stop bit. | ||
116 | */ | ||
117 | static struct ktermios stl_deftermios = { | ||
118 | .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), | ||
119 | .c_cc = INIT_C_CC, | ||
120 | .c_ispeed = 9600, | ||
121 | .c_ospeed = 9600, | ||
122 | }; | ||
123 | |||
124 | /* | ||
125 | * Define global place to put buffer overflow characters. | ||
126 | */ | ||
127 | static char stl_unwanted[SC26198_RXFIFOSIZE]; | ||
128 | |||
129 | /*****************************************************************************/ | ||
130 | |||
131 | static DEFINE_MUTEX(stl_brdslock); | ||
132 | static struct stlbrd *stl_brds[STL_MAXBRDS]; | ||
133 | |||
134 | static const struct tty_port_operations stl_port_ops; | ||
135 | |||
136 | /* | ||
137 | * Per board state flags. Used with the state field of the board struct. | ||
138 | * Not really much here! | ||
139 | */ | ||
140 | #define BRD_FOUND 0x1 | ||
141 | #define STL_PROBED 0x2 | ||
142 | |||
143 | |||
144 | /* | ||
145 | * Define the port structure istate flags. These set of flags are | ||
146 | * modified at interrupt time - so setting and reseting them needs | ||
147 | * to be atomic. Use the bit clear/setting routines for this. | ||
148 | */ | ||
149 | #define ASYI_TXBUSY 1 | ||
150 | #define ASYI_TXLOW 2 | ||
151 | #define ASYI_TXFLOWED 3 | ||
152 | |||
153 | /* | ||
154 | * Define an array of board names as printable strings. Handy for | ||
155 | * referencing boards when printing trace and stuff. | ||
156 | */ | ||
157 | static char *stl_brdnames[] = { | ||
158 | NULL, | ||
159 | NULL, | ||
160 | NULL, | ||
161 | NULL, | ||
162 | NULL, | ||
163 | NULL, | ||
164 | NULL, | ||
165 | NULL, | ||
166 | NULL, | ||
167 | NULL, | ||
168 | NULL, | ||
169 | NULL, | ||
170 | NULL, | ||
171 | NULL, | ||
172 | NULL, | ||
173 | NULL, | ||
174 | NULL, | ||
175 | NULL, | ||
176 | NULL, | ||
177 | NULL, | ||
178 | "EasyIO", | ||
179 | "EC8/32-AT", | ||
180 | "EC8/32-MC", | ||
181 | NULL, | ||
182 | NULL, | ||
183 | NULL, | ||
184 | "EC8/32-PCI", | ||
185 | "EC8/64-PCI", | ||
186 | "EasyIO-PCI", | ||
187 | }; | ||
188 | |||
189 | /*****************************************************************************/ | ||
190 | |||
191 | /* | ||
192 | * Define some string labels for arguments passed from the module | ||
193 | * load line. These allow for easy board definitions, and easy | ||
194 | * modification of the io, memory and irq resoucres. | ||
195 | */ | ||
196 | static unsigned int stl_nargs; | ||
197 | static char *board0[4]; | ||
198 | static char *board1[4]; | ||
199 | static char *board2[4]; | ||
200 | static char *board3[4]; | ||
201 | |||
202 | static char **stl_brdsp[] = { | ||
203 | (char **) &board0, | ||
204 | (char **) &board1, | ||
205 | (char **) &board2, | ||
206 | (char **) &board3 | ||
207 | }; | ||
208 | |||
209 | /* | ||
210 | * Define a set of common board names, and types. This is used to | ||
211 | * parse any module arguments. | ||
212 | */ | ||
213 | |||
214 | static struct { | ||
215 | char *name; | ||
216 | int type; | ||
217 | } stl_brdstr[] = { | ||
218 | { "easyio", BRD_EASYIO }, | ||
219 | { "eio", BRD_EASYIO }, | ||
220 | { "20", BRD_EASYIO }, | ||
221 | { "ec8/32", BRD_ECH }, | ||
222 | { "ec8/32-at", BRD_ECH }, | ||
223 | { "ec8/32-isa", BRD_ECH }, | ||
224 | { "ech", BRD_ECH }, | ||
225 | { "echat", BRD_ECH }, | ||
226 | { "21", BRD_ECH }, | ||
227 | { "ec8/32-mc", BRD_ECHMC }, | ||
228 | { "ec8/32-mca", BRD_ECHMC }, | ||
229 | { "echmc", BRD_ECHMC }, | ||
230 | { "echmca", BRD_ECHMC }, | ||
231 | { "22", BRD_ECHMC }, | ||
232 | { "ec8/32-pc", BRD_ECHPCI }, | ||
233 | { "ec8/32-pci", BRD_ECHPCI }, | ||
234 | { "26", BRD_ECHPCI }, | ||
235 | { "ec8/64-pc", BRD_ECH64PCI }, | ||
236 | { "ec8/64-pci", BRD_ECH64PCI }, | ||
237 | { "ech-pci", BRD_ECH64PCI }, | ||
238 | { "echpci", BRD_ECH64PCI }, | ||
239 | { "echpc", BRD_ECH64PCI }, | ||
240 | { "27", BRD_ECH64PCI }, | ||
241 | { "easyio-pc", BRD_EASYIOPCI }, | ||
242 | { "easyio-pci", BRD_EASYIOPCI }, | ||
243 | { "eio-pci", BRD_EASYIOPCI }, | ||
244 | { "eiopci", BRD_EASYIOPCI }, | ||
245 | { "28", BRD_EASYIOPCI }, | ||
246 | }; | ||
247 | |||
248 | /* | ||
249 | * Define the module agruments. | ||
250 | */ | ||
251 | |||
252 | module_param_array(board0, charp, &stl_nargs, 0); | ||
253 | MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]"); | ||
254 | module_param_array(board1, charp, &stl_nargs, 0); | ||
255 | MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]"); | ||
256 | module_param_array(board2, charp, &stl_nargs, 0); | ||
257 | MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]"); | ||
258 | module_param_array(board3, charp, &stl_nargs, 0); | ||
259 | MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]"); | ||
260 | |||
261 | /*****************************************************************************/ | ||
262 | |||
263 | /* | ||
264 | * Hardware ID bits for the EasyIO and ECH boards. These defines apply | ||
265 | * to the directly accessible io ports of these boards (not the uarts - | ||
266 | * they are in cd1400.h and sc26198.h). | ||
267 | */ | ||
268 | #define EIO_8PORTRS 0x04 | ||
269 | #define EIO_4PORTRS 0x05 | ||
270 | #define EIO_8PORTDI 0x00 | ||
271 | #define EIO_8PORTM 0x06 | ||
272 | #define EIO_MK3 0x03 | ||
273 | #define EIO_IDBITMASK 0x07 | ||
274 | |||
275 | #define EIO_BRDMASK 0xf0 | ||
276 | #define ID_BRD4 0x10 | ||
277 | #define ID_BRD8 0x20 | ||
278 | #define ID_BRD16 0x30 | ||
279 | |||
280 | #define EIO_INTRPEND 0x08 | ||
281 | #define EIO_INTEDGE 0x00 | ||
282 | #define EIO_INTLEVEL 0x08 | ||
283 | #define EIO_0WS 0x10 | ||
284 | |||
285 | #define ECH_ID 0xa0 | ||
286 | #define ECH_IDBITMASK 0xe0 | ||
287 | #define ECH_BRDENABLE 0x08 | ||
288 | #define ECH_BRDDISABLE 0x00 | ||
289 | #define ECH_INTENABLE 0x01 | ||
290 | #define ECH_INTDISABLE 0x00 | ||
291 | #define ECH_INTLEVEL 0x02 | ||
292 | #define ECH_INTEDGE 0x00 | ||
293 | #define ECH_INTRPEND 0x01 | ||
294 | #define ECH_BRDRESET 0x01 | ||
295 | |||
296 | #define ECHMC_INTENABLE 0x01 | ||
297 | #define ECHMC_BRDRESET 0x02 | ||
298 | |||
299 | #define ECH_PNLSTATUS 2 | ||
300 | #define ECH_PNL16PORT 0x20 | ||
301 | #define ECH_PNLIDMASK 0x07 | ||
302 | #define ECH_PNLXPID 0x40 | ||
303 | #define ECH_PNLINTRPEND 0x80 | ||
304 | |||
305 | #define ECH_ADDR2MASK 0x1e0 | ||
306 | |||
307 | /* | ||
308 | * Define the vector mapping bits for the programmable interrupt board | ||
309 | * hardware. These bits encode the interrupt for the board to use - it | ||
310 | * is software selectable (except the EIO-8M). | ||
311 | */ | ||
312 | static unsigned char stl_vecmap[] = { | ||
313 | 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07, | ||
314 | 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03 | ||
315 | }; | ||
316 | |||
317 | /* | ||
318 | * Lock ordering is that you may not take stallion_lock holding | ||
319 | * brd_lock. | ||
320 | */ | ||
321 | |||
322 | static spinlock_t brd_lock; /* Guard the board mapping */ | ||
323 | static spinlock_t stallion_lock; /* Guard the tty driver */ | ||
324 | |||
325 | /* | ||
326 | * Set up enable and disable macros for the ECH boards. They require | ||
327 | * the secondary io address space to be activated and deactivated. | ||
328 | * This way all ECH boards can share their secondary io region. | ||
329 | * If this is an ECH-PCI board then also need to set the page pointer | ||
330 | * to point to the correct page. | ||
331 | */ | ||
332 | #define BRDENABLE(brdnr,pagenr) \ | ||
333 | if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ | ||
334 | outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \ | ||
335 | stl_brds[(brdnr)]->ioctrl); \ | ||
336 | else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \ | ||
337 | outb((pagenr), stl_brds[(brdnr)]->ioctrl); | ||
338 | |||
339 | #define BRDDISABLE(brdnr) \ | ||
340 | if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ | ||
341 | outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \ | ||
342 | stl_brds[(brdnr)]->ioctrl); | ||
343 | |||
344 | #define STL_CD1400MAXBAUD 230400 | ||
345 | #define STL_SC26198MAXBAUD 460800 | ||
346 | |||
347 | #define STL_BAUDBASE 115200 | ||
348 | #define STL_CLOSEDELAY (5 * HZ / 10) | ||
349 | |||
350 | /*****************************************************************************/ | ||
351 | |||
352 | /* | ||
353 | * Define the Stallion PCI vendor and device IDs. | ||
354 | */ | ||
355 | #ifndef PCI_VENDOR_ID_STALLION | ||
356 | #define PCI_VENDOR_ID_STALLION 0x124d | ||
357 | #endif | ||
358 | #ifndef PCI_DEVICE_ID_ECHPCI832 | ||
359 | #define PCI_DEVICE_ID_ECHPCI832 0x0000 | ||
360 | #endif | ||
361 | #ifndef PCI_DEVICE_ID_ECHPCI864 | ||
362 | #define PCI_DEVICE_ID_ECHPCI864 0x0002 | ||
363 | #endif | ||
364 | #ifndef PCI_DEVICE_ID_EIOPCI | ||
365 | #define PCI_DEVICE_ID_EIOPCI 0x0003 | ||
366 | #endif | ||
367 | |||
368 | /* | ||
369 | * Define structure to hold all Stallion PCI boards. | ||
370 | */ | ||
371 | |||
372 | static struct pci_device_id stl_pcibrds[] = { | ||
373 | { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864), | ||
374 | .driver_data = BRD_ECH64PCI }, | ||
375 | { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI), | ||
376 | .driver_data = BRD_EASYIOPCI }, | ||
377 | { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832), | ||
378 | .driver_data = BRD_ECHPCI }, | ||
379 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410), | ||
380 | .driver_data = BRD_ECHPCI }, | ||
381 | { } | ||
382 | }; | ||
383 | MODULE_DEVICE_TABLE(pci, stl_pcibrds); | ||
384 | |||
385 | /*****************************************************************************/ | ||
386 | |||
387 | /* | ||
388 | * Define macros to extract a brd/port number from a minor number. | ||
389 | */ | ||
390 | #define MINOR2BRD(min) (((min) & 0xc0) >> 6) | ||
391 | #define MINOR2PORT(min) ((min) & 0x3f) | ||
392 | |||
393 | /* | ||
394 | * Define a baud rate table that converts termios baud rate selector | ||
395 | * into the actual baud rate value. All baud rate calculations are | ||
396 | * based on the actual baud rate required. | ||
397 | */ | ||
398 | static unsigned int stl_baudrates[] = { | ||
399 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | ||
400 | 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 | ||
401 | }; | ||
402 | |||
403 | /*****************************************************************************/ | ||
404 | |||
405 | /* | ||
406 | * Declare all those functions in this driver! | ||
407 | */ | ||
408 | |||
409 | static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); | ||
410 | static int stl_brdinit(struct stlbrd *brdp); | ||
411 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); | ||
412 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); | ||
413 | |||
414 | /* | ||
415 | * CD1400 uart specific handling functions. | ||
416 | */ | ||
417 | static void stl_cd1400setreg(struct stlport *portp, int regnr, int value); | ||
418 | static int stl_cd1400getreg(struct stlport *portp, int regnr); | ||
419 | static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value); | ||
420 | static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp); | ||
421 | static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); | ||
422 | static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp); | ||
423 | static int stl_cd1400getsignals(struct stlport *portp); | ||
424 | static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts); | ||
425 | static void stl_cd1400ccrwait(struct stlport *portp); | ||
426 | static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx); | ||
427 | static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx); | ||
428 | static void stl_cd1400disableintrs(struct stlport *portp); | ||
429 | static void stl_cd1400sendbreak(struct stlport *portp, int len); | ||
430 | static void stl_cd1400flowctrl(struct stlport *portp, int state); | ||
431 | static void stl_cd1400sendflow(struct stlport *portp, int state); | ||
432 | static void stl_cd1400flush(struct stlport *portp); | ||
433 | static int stl_cd1400datastate(struct stlport *portp); | ||
434 | static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase); | ||
435 | static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase); | ||
436 | static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr); | ||
437 | static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr); | ||
438 | static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr); | ||
439 | |||
440 | static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr); | ||
441 | |||
442 | /* | ||
443 | * SC26198 uart specific handling functions. | ||
444 | */ | ||
445 | static void stl_sc26198setreg(struct stlport *portp, int regnr, int value); | ||
446 | static int stl_sc26198getreg(struct stlport *portp, int regnr); | ||
447 | static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value); | ||
448 | static int stl_sc26198getglobreg(struct stlport *portp, int regnr); | ||
449 | static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp); | ||
450 | static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); | ||
451 | static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp); | ||
452 | static int stl_sc26198getsignals(struct stlport *portp); | ||
453 | static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts); | ||
454 | static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx); | ||
455 | static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx); | ||
456 | static void stl_sc26198disableintrs(struct stlport *portp); | ||
457 | static void stl_sc26198sendbreak(struct stlport *portp, int len); | ||
458 | static void stl_sc26198flowctrl(struct stlport *portp, int state); | ||
459 | static void stl_sc26198sendflow(struct stlport *portp, int state); | ||
460 | static void stl_sc26198flush(struct stlport *portp); | ||
461 | static int stl_sc26198datastate(struct stlport *portp); | ||
462 | static void stl_sc26198wait(struct stlport *portp); | ||
463 | static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty); | ||
464 | static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase); | ||
465 | static void stl_sc26198txisr(struct stlport *port); | ||
466 | static void stl_sc26198rxisr(struct stlport *port, unsigned int iack); | ||
467 | static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch); | ||
468 | static void stl_sc26198rxbadchars(struct stlport *portp); | ||
469 | static void stl_sc26198otherisr(struct stlport *port, unsigned int iack); | ||
470 | |||
471 | /*****************************************************************************/ | ||
472 | |||
473 | /* | ||
474 | * Generic UART support structure. | ||
475 | */ | ||
476 | typedef struct uart { | ||
477 | int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp); | ||
478 | void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); | ||
479 | void (*setport)(struct stlport *portp, struct ktermios *tiosp); | ||
480 | int (*getsignals)(struct stlport *portp); | ||
481 | void (*setsignals)(struct stlport *portp, int dtr, int rts); | ||
482 | void (*enablerxtx)(struct stlport *portp, int rx, int tx); | ||
483 | void (*startrxtx)(struct stlport *portp, int rx, int tx); | ||
484 | void (*disableintrs)(struct stlport *portp); | ||
485 | void (*sendbreak)(struct stlport *portp, int len); | ||
486 | void (*flowctrl)(struct stlport *portp, int state); | ||
487 | void (*sendflow)(struct stlport *portp, int state); | ||
488 | void (*flush)(struct stlport *portp); | ||
489 | int (*datastate)(struct stlport *portp); | ||
490 | void (*intr)(struct stlpanel *panelp, unsigned int iobase); | ||
491 | } uart_t; | ||
492 | |||
493 | /* | ||
494 | * Define some macros to make calling these functions nice and clean. | ||
495 | */ | ||
496 | #define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit) | ||
497 | #define stl_portinit (* ((uart_t *) portp->uartp)->portinit) | ||
498 | #define stl_setport (* ((uart_t *) portp->uartp)->setport) | ||
499 | #define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals) | ||
500 | #define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals) | ||
501 | #define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx) | ||
502 | #define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx) | ||
503 | #define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs) | ||
504 | #define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak) | ||
505 | #define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl) | ||
506 | #define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow) | ||
507 | #define stl_flush (* ((uart_t *) portp->uartp)->flush) | ||
508 | #define stl_datastate (* ((uart_t *) portp->uartp)->datastate) | ||
509 | |||
510 | /*****************************************************************************/ | ||
511 | |||
512 | /* | ||
513 | * CD1400 UART specific data initialization. | ||
514 | */ | ||
515 | static uart_t stl_cd1400uart = { | ||
516 | stl_cd1400panelinit, | ||
517 | stl_cd1400portinit, | ||
518 | stl_cd1400setport, | ||
519 | stl_cd1400getsignals, | ||
520 | stl_cd1400setsignals, | ||
521 | stl_cd1400enablerxtx, | ||
522 | stl_cd1400startrxtx, | ||
523 | stl_cd1400disableintrs, | ||
524 | stl_cd1400sendbreak, | ||
525 | stl_cd1400flowctrl, | ||
526 | stl_cd1400sendflow, | ||
527 | stl_cd1400flush, | ||
528 | stl_cd1400datastate, | ||
529 | stl_cd1400eiointr | ||
530 | }; | ||
531 | |||
532 | /* | ||
533 | * Define the offsets within the register bank of a cd1400 based panel. | ||
534 | * These io address offsets are common to the EasyIO board as well. | ||
535 | */ | ||
536 | #define EREG_ADDR 0 | ||
537 | #define EREG_DATA 4 | ||
538 | #define EREG_RXACK 5 | ||
539 | #define EREG_TXACK 6 | ||
540 | #define EREG_MDACK 7 | ||
541 | |||
542 | #define EREG_BANKSIZE 8 | ||
543 | |||
544 | #define CD1400_CLK 25000000 | ||
545 | #define CD1400_CLK8M 20000000 | ||
546 | |||
547 | /* | ||
548 | * Define the cd1400 baud rate clocks. These are used when calculating | ||
549 | * what clock and divisor to use for the required baud rate. Also | ||
550 | * define the maximum baud rate allowed, and the default base baud. | ||
551 | */ | ||
552 | static int stl_cd1400clkdivs[] = { | ||
553 | CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4 | ||
554 | }; | ||
555 | |||
556 | /*****************************************************************************/ | ||
557 | |||
558 | /* | ||
559 | * SC26198 UART specific data initization. | ||
560 | */ | ||
561 | static uart_t stl_sc26198uart = { | ||
562 | stl_sc26198panelinit, | ||
563 | stl_sc26198portinit, | ||
564 | stl_sc26198setport, | ||
565 | stl_sc26198getsignals, | ||
566 | stl_sc26198setsignals, | ||
567 | stl_sc26198enablerxtx, | ||
568 | stl_sc26198startrxtx, | ||
569 | stl_sc26198disableintrs, | ||
570 | stl_sc26198sendbreak, | ||
571 | stl_sc26198flowctrl, | ||
572 | stl_sc26198sendflow, | ||
573 | stl_sc26198flush, | ||
574 | stl_sc26198datastate, | ||
575 | stl_sc26198intr | ||
576 | }; | ||
577 | |||
578 | /* | ||
579 | * Define the offsets within the register bank of a sc26198 based panel. | ||
580 | */ | ||
581 | #define XP_DATA 0 | ||
582 | #define XP_ADDR 1 | ||
583 | #define XP_MODID 2 | ||
584 | #define XP_STATUS 2 | ||
585 | #define XP_IACK 3 | ||
586 | |||
587 | #define XP_BANKSIZE 4 | ||
588 | |||
589 | /* | ||
590 | * Define the sc26198 baud rate table. Offsets within the table | ||
591 | * represent the actual baud rate selector of sc26198 registers. | ||
592 | */ | ||
593 | static unsigned int sc26198_baudtable[] = { | ||
594 | 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600, | ||
595 | 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, | ||
596 | 230400, 460800, 921600 | ||
597 | }; | ||
598 | |||
599 | #define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable) | ||
600 | |||
601 | /*****************************************************************************/ | ||
602 | |||
603 | /* | ||
604 | * Define the driver info for a user level control device. Used mainly | ||
605 | * to get at port stats - only not using the port device itself. | ||
606 | */ | ||
607 | static const struct file_operations stl_fsiomem = { | ||
608 | .owner = THIS_MODULE, | ||
609 | .unlocked_ioctl = stl_memioctl, | ||
610 | .llseek = noop_llseek, | ||
611 | }; | ||
612 | |||
613 | static struct class *stallion_class; | ||
614 | |||
615 | static void stl_cd_change(struct stlport *portp) | ||
616 | { | ||
617 | unsigned int oldsigs = portp->sigs; | ||
618 | struct tty_struct *tty = tty_port_tty_get(&portp->port); | ||
619 | |||
620 | if (!tty) | ||
621 | return; | ||
622 | |||
623 | portp->sigs = stl_getsignals(portp); | ||
624 | |||
625 | if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0)) | ||
626 | wake_up_interruptible(&portp->port.open_wait); | ||
627 | |||
628 | if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) | ||
629 | if (portp->port.flags & ASYNC_CHECK_CD) | ||
630 | tty_hangup(tty); | ||
631 | tty_kref_put(tty); | ||
632 | } | ||
633 | |||
634 | /* | ||
635 | * Check for any arguments passed in on the module load command line. | ||
636 | */ | ||
637 | |||
638 | /*****************************************************************************/ | ||
639 | |||
640 | /* | ||
641 | * Parse the supplied argument string, into the board conf struct. | ||
642 | */ | ||
643 | |||
644 | static int __init stl_parsebrd(struct stlconf *confp, char **argp) | ||
645 | { | ||
646 | char *sp; | ||
647 | unsigned int i; | ||
648 | |||
649 | pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp); | ||
650 | |||
651 | if ((argp[0] == NULL) || (*argp[0] == 0)) | ||
652 | return 0; | ||
653 | |||
654 | for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++) | ||
655 | *sp = tolower(*sp); | ||
656 | |||
657 | for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) | ||
658 | if (strcmp(stl_brdstr[i].name, argp[0]) == 0) | ||
659 | break; | ||
660 | |||
661 | if (i == ARRAY_SIZE(stl_brdstr)) { | ||
662 | printk("STALLION: unknown board name, %s?\n", argp[0]); | ||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | confp->brdtype = stl_brdstr[i].type; | ||
667 | |||
668 | i = 1; | ||
669 | if ((argp[i] != NULL) && (*argp[i] != 0)) | ||
670 | confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0); | ||
671 | i++; | ||
672 | if (confp->brdtype == BRD_ECH) { | ||
673 | if ((argp[i] != NULL) && (*argp[i] != 0)) | ||
674 | confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0); | ||
675 | i++; | ||
676 | } | ||
677 | if ((argp[i] != NULL) && (*argp[i] != 0)) | ||
678 | confp->irq = simple_strtoul(argp[i], NULL, 0); | ||
679 | return 1; | ||
680 | } | ||
681 | |||
682 | /*****************************************************************************/ | ||
683 | |||
684 | /* | ||
685 | * Allocate a new board structure. Fill out the basic info in it. | ||
686 | */ | ||
687 | |||
688 | static struct stlbrd *stl_allocbrd(void) | ||
689 | { | ||
690 | struct stlbrd *brdp; | ||
691 | |||
692 | brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL); | ||
693 | if (!brdp) { | ||
694 | printk("STALLION: failed to allocate memory (size=%Zd)\n", | ||
695 | sizeof(struct stlbrd)); | ||
696 | return NULL; | ||
697 | } | ||
698 | |||
699 | brdp->magic = STL_BOARDMAGIC; | ||
700 | return brdp; | ||
701 | } | ||
702 | |||
703 | /*****************************************************************************/ | ||
704 | |||
705 | static int stl_activate(struct tty_port *port, struct tty_struct *tty) | ||
706 | { | ||
707 | struct stlport *portp = container_of(port, struct stlport, port); | ||
708 | if (!portp->tx.buf) { | ||
709 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | ||
710 | if (!portp->tx.buf) | ||
711 | return -ENOMEM; | ||
712 | portp->tx.head = portp->tx.buf; | ||
713 | portp->tx.tail = portp->tx.buf; | ||
714 | } | ||
715 | stl_setport(portp, tty->termios); | ||
716 | portp->sigs = stl_getsignals(portp); | ||
717 | stl_setsignals(portp, 1, 1); | ||
718 | stl_enablerxtx(portp, 1, 1); | ||
719 | stl_startrxtx(portp, 1, 0); | ||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static int stl_open(struct tty_struct *tty, struct file *filp) | ||
724 | { | ||
725 | struct stlport *portp; | ||
726 | struct stlbrd *brdp; | ||
727 | unsigned int minordev, brdnr, panelnr; | ||
728 | int portnr; | ||
729 | |||
730 | pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); | ||
731 | |||
732 | minordev = tty->index; | ||
733 | brdnr = MINOR2BRD(minordev); | ||
734 | if (brdnr >= stl_nrbrds) | ||
735 | return -ENODEV; | ||
736 | brdp = stl_brds[brdnr]; | ||
737 | if (brdp == NULL) | ||
738 | return -ENODEV; | ||
739 | |||
740 | minordev = MINOR2PORT(minordev); | ||
741 | for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { | ||
742 | if (brdp->panels[panelnr] == NULL) | ||
743 | break; | ||
744 | if (minordev < brdp->panels[panelnr]->nrports) { | ||
745 | portnr = minordev; | ||
746 | break; | ||
747 | } | ||
748 | minordev -= brdp->panels[panelnr]->nrports; | ||
749 | } | ||
750 | if (portnr < 0) | ||
751 | return -ENODEV; | ||
752 | |||
753 | portp = brdp->panels[panelnr]->ports[portnr]; | ||
754 | if (portp == NULL) | ||
755 | return -ENODEV; | ||
756 | |||
757 | tty->driver_data = portp; | ||
758 | return tty_port_open(&portp->port, tty, filp); | ||
759 | |||
760 | } | ||
761 | |||
762 | /*****************************************************************************/ | ||
763 | |||
764 | static int stl_carrier_raised(struct tty_port *port) | ||
765 | { | ||
766 | struct stlport *portp = container_of(port, struct stlport, port); | ||
767 | return (portp->sigs & TIOCM_CD) ? 1 : 0; | ||
768 | } | ||
769 | |||
770 | static void stl_dtr_rts(struct tty_port *port, int on) | ||
771 | { | ||
772 | struct stlport *portp = container_of(port, struct stlport, port); | ||
773 | /* Takes brd_lock internally */ | ||
774 | stl_setsignals(portp, on, on); | ||
775 | } | ||
776 | |||
777 | /*****************************************************************************/ | ||
778 | |||
779 | static void stl_flushbuffer(struct tty_struct *tty) | ||
780 | { | ||
781 | struct stlport *portp; | ||
782 | |||
783 | pr_debug("stl_flushbuffer(tty=%p)\n", tty); | ||
784 | |||
785 | portp = tty->driver_data; | ||
786 | if (portp == NULL) | ||
787 | return; | ||
788 | |||
789 | stl_flush(portp); | ||
790 | tty_wakeup(tty); | ||
791 | } | ||
792 | |||
793 | /*****************************************************************************/ | ||
794 | |||
795 | static void stl_waituntilsent(struct tty_struct *tty, int timeout) | ||
796 | { | ||
797 | struct stlport *portp; | ||
798 | unsigned long tend; | ||
799 | |||
800 | pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout); | ||
801 | |||
802 | portp = tty->driver_data; | ||
803 | if (portp == NULL) | ||
804 | return; | ||
805 | |||
806 | if (timeout == 0) | ||
807 | timeout = HZ; | ||
808 | tend = jiffies + timeout; | ||
809 | |||
810 | while (stl_datastate(portp)) { | ||
811 | if (signal_pending(current)) | ||
812 | break; | ||
813 | msleep_interruptible(20); | ||
814 | if (time_after_eq(jiffies, tend)) | ||
815 | break; | ||
816 | } | ||
817 | } | ||
818 | |||
819 | /*****************************************************************************/ | ||
820 | |||
821 | static void stl_shutdown(struct tty_port *port) | ||
822 | { | ||
823 | struct stlport *portp = container_of(port, struct stlport, port); | ||
824 | stl_disableintrs(portp); | ||
825 | stl_enablerxtx(portp, 0, 0); | ||
826 | stl_flush(portp); | ||
827 | portp->istate = 0; | ||
828 | if (portp->tx.buf != NULL) { | ||
829 | kfree(portp->tx.buf); | ||
830 | portp->tx.buf = NULL; | ||
831 | portp->tx.head = NULL; | ||
832 | portp->tx.tail = NULL; | ||
833 | } | ||
834 | } | ||
835 | |||
836 | static void stl_close(struct tty_struct *tty, struct file *filp) | ||
837 | { | ||
838 | struct stlport*portp; | ||
839 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | ||
840 | |||
841 | portp = tty->driver_data; | ||
842 | if(portp == NULL) | ||
843 | return; | ||
844 | tty_port_close(&portp->port, tty, filp); | ||
845 | } | ||
846 | |||
847 | /*****************************************************************************/ | ||
848 | |||
849 | /* | ||
850 | * Write routine. Take data and stuff it in to the TX ring queue. | ||
851 | * If transmit interrupts are not running then start them. | ||
852 | */ | ||
853 | |||
854 | static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count) | ||
855 | { | ||
856 | struct stlport *portp; | ||
857 | unsigned int len, stlen; | ||
858 | unsigned char *chbuf; | ||
859 | char *head, *tail; | ||
860 | |||
861 | pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count); | ||
862 | |||
863 | portp = tty->driver_data; | ||
864 | if (portp == NULL) | ||
865 | return 0; | ||
866 | if (portp->tx.buf == NULL) | ||
867 | return 0; | ||
868 | |||
869 | /* | ||
870 | * If copying direct from user space we must cater for page faults, | ||
871 | * causing us to "sleep" here for a while. To handle this copy in all | ||
872 | * the data we need now, into a local buffer. Then when we got it all | ||
873 | * copy it into the TX buffer. | ||
874 | */ | ||
875 | chbuf = (unsigned char *) buf; | ||
876 | |||
877 | head = portp->tx.head; | ||
878 | tail = portp->tx.tail; | ||
879 | if (head >= tail) { | ||
880 | len = STL_TXBUFSIZE - (head - tail) - 1; | ||
881 | stlen = STL_TXBUFSIZE - (head - portp->tx.buf); | ||
882 | } else { | ||
883 | len = tail - head - 1; | ||
884 | stlen = len; | ||
885 | } | ||
886 | |||
887 | len = min(len, (unsigned int)count); | ||
888 | count = 0; | ||
889 | while (len > 0) { | ||
890 | stlen = min(len, stlen); | ||
891 | memcpy(head, chbuf, stlen); | ||
892 | len -= stlen; | ||
893 | chbuf += stlen; | ||
894 | count += stlen; | ||
895 | head += stlen; | ||
896 | if (head >= (portp->tx.buf + STL_TXBUFSIZE)) { | ||
897 | head = portp->tx.buf; | ||
898 | stlen = tail - head; | ||
899 | } | ||
900 | } | ||
901 | portp->tx.head = head; | ||
902 | |||
903 | clear_bit(ASYI_TXLOW, &portp->istate); | ||
904 | stl_startrxtx(portp, -1, 1); | ||
905 | |||
906 | return count; | ||
907 | } | ||
908 | |||
909 | /*****************************************************************************/ | ||
910 | |||
911 | static int stl_putchar(struct tty_struct *tty, unsigned char ch) | ||
912 | { | ||
913 | struct stlport *portp; | ||
914 | unsigned int len; | ||
915 | char *head, *tail; | ||
916 | |||
917 | pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); | ||
918 | |||
919 | portp = tty->driver_data; | ||
920 | if (portp == NULL) | ||
921 | return -EINVAL; | ||
922 | if (portp->tx.buf == NULL) | ||
923 | return -EINVAL; | ||
924 | |||
925 | head = portp->tx.head; | ||
926 | tail = portp->tx.tail; | ||
927 | |||
928 | len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head); | ||
929 | len--; | ||
930 | |||
931 | if (len > 0) { | ||
932 | *head++ = ch; | ||
933 | if (head >= (portp->tx.buf + STL_TXBUFSIZE)) | ||
934 | head = portp->tx.buf; | ||
935 | } | ||
936 | portp->tx.head = head; | ||
937 | return 0; | ||
938 | } | ||
939 | |||
940 | /*****************************************************************************/ | ||
941 | |||
942 | /* | ||
943 | * If there are any characters in the buffer then make sure that TX | ||
944 | * interrupts are on and get'em out. Normally used after the putchar | ||
945 | * routine has been called. | ||
946 | */ | ||
947 | |||
948 | static void stl_flushchars(struct tty_struct *tty) | ||
949 | { | ||
950 | struct stlport *portp; | ||
951 | |||
952 | pr_debug("stl_flushchars(tty=%p)\n", tty); | ||
953 | |||
954 | portp = tty->driver_data; | ||
955 | if (portp == NULL) | ||
956 | return; | ||
957 | if (portp->tx.buf == NULL) | ||
958 | return; | ||
959 | |||
960 | stl_startrxtx(portp, -1, 1); | ||
961 | } | ||
962 | |||
963 | /*****************************************************************************/ | ||
964 | |||
965 | static int stl_writeroom(struct tty_struct *tty) | ||
966 | { | ||
967 | struct stlport *portp; | ||
968 | char *head, *tail; | ||
969 | |||
970 | pr_debug("stl_writeroom(tty=%p)\n", tty); | ||
971 | |||
972 | portp = tty->driver_data; | ||
973 | if (portp == NULL) | ||
974 | return 0; | ||
975 | if (portp->tx.buf == NULL) | ||
976 | return 0; | ||
977 | |||
978 | head = portp->tx.head; | ||
979 | tail = portp->tx.tail; | ||
980 | return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1); | ||
981 | } | ||
982 | |||
983 | /*****************************************************************************/ | ||
984 | |||
985 | /* | ||
986 | * Return number of chars in the TX buffer. Normally we would just | ||
987 | * calculate the number of chars in the buffer and return that, but if | ||
988 | * the buffer is empty and TX interrupts are still on then we return | ||
989 | * that the buffer still has 1 char in it. This way whoever called us | ||
990 | * will not think that ALL chars have drained - since the UART still | ||
991 | * must have some chars in it (we are busy after all). | ||
992 | */ | ||
993 | |||
994 | static int stl_charsinbuffer(struct tty_struct *tty) | ||
995 | { | ||
996 | struct stlport *portp; | ||
997 | unsigned int size; | ||
998 | char *head, *tail; | ||
999 | |||
1000 | pr_debug("stl_charsinbuffer(tty=%p)\n", tty); | ||
1001 | |||
1002 | portp = tty->driver_data; | ||
1003 | if (portp == NULL) | ||
1004 | return 0; | ||
1005 | if (portp->tx.buf == NULL) | ||
1006 | return 0; | ||
1007 | |||
1008 | head = portp->tx.head; | ||
1009 | tail = portp->tx.tail; | ||
1010 | size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); | ||
1011 | if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate)) | ||
1012 | size = 1; | ||
1013 | return size; | ||
1014 | } | ||
1015 | |||
1016 | /*****************************************************************************/ | ||
1017 | |||
1018 | /* | ||
1019 | * Generate the serial struct info. | ||
1020 | */ | ||
1021 | |||
1022 | static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) | ||
1023 | { | ||
1024 | struct serial_struct sio; | ||
1025 | struct stlbrd *brdp; | ||
1026 | |||
1027 | pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); | ||
1028 | |||
1029 | memset(&sio, 0, sizeof(struct serial_struct)); | ||
1030 | |||
1031 | mutex_lock(&portp->port.mutex); | ||
1032 | sio.line = portp->portnr; | ||
1033 | sio.port = portp->ioaddr; | ||
1034 | sio.flags = portp->port.flags; | ||
1035 | sio.baud_base = portp->baud_base; | ||
1036 | sio.close_delay = portp->close_delay; | ||
1037 | sio.closing_wait = portp->closing_wait; | ||
1038 | sio.custom_divisor = portp->custom_divisor; | ||
1039 | sio.hub6 = 0; | ||
1040 | if (portp->uartp == &stl_cd1400uart) { | ||
1041 | sio.type = PORT_CIRRUS; | ||
1042 | sio.xmit_fifo_size = CD1400_TXFIFOSIZE; | ||
1043 | } else { | ||
1044 | sio.type = PORT_UNKNOWN; | ||
1045 | sio.xmit_fifo_size = SC26198_TXFIFOSIZE; | ||
1046 | } | ||
1047 | |||
1048 | brdp = stl_brds[portp->brdnr]; | ||
1049 | if (brdp != NULL) | ||
1050 | sio.irq = brdp->irq; | ||
1051 | mutex_unlock(&portp->port.mutex); | ||
1052 | |||
1053 | return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; | ||
1054 | } | ||
1055 | |||
1056 | /*****************************************************************************/ | ||
1057 | |||
1058 | /* | ||
1059 | * Set port according to the serial struct info. | ||
1060 | * At this point we do not do any auto-configure stuff, so we will | ||
1061 | * just quietly ignore any requests to change irq, etc. | ||
1062 | */ | ||
1063 | |||
1064 | static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp) | ||
1065 | { | ||
1066 | struct stlport * portp = tty->driver_data; | ||
1067 | struct serial_struct sio; | ||
1068 | |||
1069 | pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp); | ||
1070 | |||
1071 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) | ||
1072 | return -EFAULT; | ||
1073 | mutex_lock(&portp->port.mutex); | ||
1074 | if (!capable(CAP_SYS_ADMIN)) { | ||
1075 | if ((sio.baud_base != portp->baud_base) || | ||
1076 | (sio.close_delay != portp->close_delay) || | ||
1077 | ((sio.flags & ~ASYNC_USR_MASK) != | ||
1078 | (portp->port.flags & ~ASYNC_USR_MASK))) { | ||
1079 | mutex_unlock(&portp->port.mutex); | ||
1080 | return -EPERM; | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | | ||
1085 | (sio.flags & ASYNC_USR_MASK); | ||
1086 | portp->baud_base = sio.baud_base; | ||
1087 | portp->close_delay = sio.close_delay; | ||
1088 | portp->closing_wait = sio.closing_wait; | ||
1089 | portp->custom_divisor = sio.custom_divisor; | ||
1090 | mutex_unlock(&portp->port.mutex); | ||
1091 | stl_setport(portp, tty->termios); | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | /*****************************************************************************/ | ||
1096 | |||
1097 | static int stl_tiocmget(struct tty_struct *tty) | ||
1098 | { | ||
1099 | struct stlport *portp; | ||
1100 | |||
1101 | portp = tty->driver_data; | ||
1102 | if (portp == NULL) | ||
1103 | return -ENODEV; | ||
1104 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1105 | return -EIO; | ||
1106 | |||
1107 | return stl_getsignals(portp); | ||
1108 | } | ||
1109 | |||
1110 | static int stl_tiocmset(struct tty_struct *tty, | ||
1111 | unsigned int set, unsigned int clear) | ||
1112 | { | ||
1113 | struct stlport *portp; | ||
1114 | int rts = -1, dtr = -1; | ||
1115 | |||
1116 | portp = tty->driver_data; | ||
1117 | if (portp == NULL) | ||
1118 | return -ENODEV; | ||
1119 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1120 | return -EIO; | ||
1121 | |||
1122 | if (set & TIOCM_RTS) | ||
1123 | rts = 1; | ||
1124 | if (set & TIOCM_DTR) | ||
1125 | dtr = 1; | ||
1126 | if (clear & TIOCM_RTS) | ||
1127 | rts = 0; | ||
1128 | if (clear & TIOCM_DTR) | ||
1129 | dtr = 0; | ||
1130 | |||
1131 | stl_setsignals(portp, dtr, rts); | ||
1132 | return 0; | ||
1133 | } | ||
1134 | |||
1135 | static int stl_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) | ||
1136 | { | ||
1137 | struct stlport *portp; | ||
1138 | int rc; | ||
1139 | void __user *argp = (void __user *)arg; | ||
1140 | |||
1141 | pr_debug("stl_ioctl(tty=%p,cmd=%x,arg=%lx)\n", tty, cmd, arg); | ||
1142 | |||
1143 | portp = tty->driver_data; | ||
1144 | if (portp == NULL) | ||
1145 | return -ENODEV; | ||
1146 | |||
1147 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | ||
1148 | (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) | ||
1149 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1150 | return -EIO; | ||
1151 | |||
1152 | rc = 0; | ||
1153 | |||
1154 | switch (cmd) { | ||
1155 | case TIOCGSERIAL: | ||
1156 | rc = stl_getserial(portp, argp); | ||
1157 | break; | ||
1158 | case TIOCSSERIAL: | ||
1159 | rc = stl_setserial(tty, argp); | ||
1160 | break; | ||
1161 | case COM_GETPORTSTATS: | ||
1162 | rc = stl_getportstats(tty, portp, argp); | ||
1163 | break; | ||
1164 | case COM_CLRPORTSTATS: | ||
1165 | rc = stl_clrportstats(portp, argp); | ||
1166 | break; | ||
1167 | case TIOCSERCONFIG: | ||
1168 | case TIOCSERGWILD: | ||
1169 | case TIOCSERSWILD: | ||
1170 | case TIOCSERGETLSR: | ||
1171 | case TIOCSERGSTRUCT: | ||
1172 | case TIOCSERGETMULTI: | ||
1173 | case TIOCSERSETMULTI: | ||
1174 | default: | ||
1175 | rc = -ENOIOCTLCMD; | ||
1176 | break; | ||
1177 | } | ||
1178 | return rc; | ||
1179 | } | ||
1180 | |||
1181 | /*****************************************************************************/ | ||
1182 | |||
1183 | /* | ||
1184 | * Start the transmitter again. Just turn TX interrupts back on. | ||
1185 | */ | ||
1186 | |||
1187 | static void stl_start(struct tty_struct *tty) | ||
1188 | { | ||
1189 | struct stlport *portp; | ||
1190 | |||
1191 | pr_debug("stl_start(tty=%p)\n", tty); | ||
1192 | |||
1193 | portp = tty->driver_data; | ||
1194 | if (portp == NULL) | ||
1195 | return; | ||
1196 | stl_startrxtx(portp, -1, 1); | ||
1197 | } | ||
1198 | |||
1199 | /*****************************************************************************/ | ||
1200 | |||
1201 | static void stl_settermios(struct tty_struct *tty, struct ktermios *old) | ||
1202 | { | ||
1203 | struct stlport *portp; | ||
1204 | struct ktermios *tiosp; | ||
1205 | |||
1206 | pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old); | ||
1207 | |||
1208 | portp = tty->driver_data; | ||
1209 | if (portp == NULL) | ||
1210 | return; | ||
1211 | |||
1212 | tiosp = tty->termios; | ||
1213 | if ((tiosp->c_cflag == old->c_cflag) && | ||
1214 | (tiosp->c_iflag == old->c_iflag)) | ||
1215 | return; | ||
1216 | |||
1217 | stl_setport(portp, tiosp); | ||
1218 | stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0), | ||
1219 | -1); | ||
1220 | if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) { | ||
1221 | tty->hw_stopped = 0; | ||
1222 | stl_start(tty); | ||
1223 | } | ||
1224 | if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL)) | ||
1225 | wake_up_interruptible(&portp->port.open_wait); | ||
1226 | } | ||
1227 | |||
1228 | /*****************************************************************************/ | ||
1229 | |||
1230 | /* | ||
1231 | * Attempt to flow control who ever is sending us data. Based on termios | ||
1232 | * settings use software or/and hardware flow control. | ||
1233 | */ | ||
1234 | |||
1235 | static void stl_throttle(struct tty_struct *tty) | ||
1236 | { | ||
1237 | struct stlport *portp; | ||
1238 | |||
1239 | pr_debug("stl_throttle(tty=%p)\n", tty); | ||
1240 | |||
1241 | portp = tty->driver_data; | ||
1242 | if (portp == NULL) | ||
1243 | return; | ||
1244 | stl_flowctrl(portp, 0); | ||
1245 | } | ||
1246 | |||
1247 | /*****************************************************************************/ | ||
1248 | |||
1249 | /* | ||
1250 | * Unflow control the device sending us data... | ||
1251 | */ | ||
1252 | |||
1253 | static void stl_unthrottle(struct tty_struct *tty) | ||
1254 | { | ||
1255 | struct stlport *portp; | ||
1256 | |||
1257 | pr_debug("stl_unthrottle(tty=%p)\n", tty); | ||
1258 | |||
1259 | portp = tty->driver_data; | ||
1260 | if (portp == NULL) | ||
1261 | return; | ||
1262 | stl_flowctrl(portp, 1); | ||
1263 | } | ||
1264 | |||
1265 | /*****************************************************************************/ | ||
1266 | |||
1267 | /* | ||
1268 | * Stop the transmitter. Basically to do this we will just turn TX | ||
1269 | * interrupts off. | ||
1270 | */ | ||
1271 | |||
1272 | static void stl_stop(struct tty_struct *tty) | ||
1273 | { | ||
1274 | struct stlport *portp; | ||
1275 | |||
1276 | pr_debug("stl_stop(tty=%p)\n", tty); | ||
1277 | |||
1278 | portp = tty->driver_data; | ||
1279 | if (portp == NULL) | ||
1280 | return; | ||
1281 | stl_startrxtx(portp, -1, 0); | ||
1282 | } | ||
1283 | |||
1284 | /*****************************************************************************/ | ||
1285 | |||
1286 | /* | ||
1287 | * Hangup this port. This is pretty much like closing the port, only | ||
1288 | * a little more brutal. No waiting for data to drain. Shutdown the | ||
1289 | * port and maybe drop signals. | ||
1290 | */ | ||
1291 | |||
1292 | static void stl_hangup(struct tty_struct *tty) | ||
1293 | { | ||
1294 | struct stlport *portp = tty->driver_data; | ||
1295 | pr_debug("stl_hangup(tty=%p)\n", tty); | ||
1296 | |||
1297 | if (portp == NULL) | ||
1298 | return; | ||
1299 | tty_port_hangup(&portp->port); | ||
1300 | } | ||
1301 | |||
1302 | /*****************************************************************************/ | ||
1303 | |||
1304 | static int stl_breakctl(struct tty_struct *tty, int state) | ||
1305 | { | ||
1306 | struct stlport *portp; | ||
1307 | |||
1308 | pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); | ||
1309 | |||
1310 | portp = tty->driver_data; | ||
1311 | if (portp == NULL) | ||
1312 | return -EINVAL; | ||
1313 | |||
1314 | stl_sendbreak(portp, ((state == -1) ? 1 : 2)); | ||
1315 | return 0; | ||
1316 | } | ||
1317 | |||
1318 | /*****************************************************************************/ | ||
1319 | |||
1320 | static void stl_sendxchar(struct tty_struct *tty, char ch) | ||
1321 | { | ||
1322 | struct stlport *portp; | ||
1323 | |||
1324 | pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch); | ||
1325 | |||
1326 | portp = tty->driver_data; | ||
1327 | if (portp == NULL) | ||
1328 | return; | ||
1329 | |||
1330 | if (ch == STOP_CHAR(tty)) | ||
1331 | stl_sendflow(portp, 0); | ||
1332 | else if (ch == START_CHAR(tty)) | ||
1333 | stl_sendflow(portp, 1); | ||
1334 | else | ||
1335 | stl_putchar(tty, ch); | ||
1336 | } | ||
1337 | |||
1338 | static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr) | ||
1339 | { | ||
1340 | int sigs; | ||
1341 | char sep; | ||
1342 | |||
1343 | seq_printf(m, "%d: uart:%s tx:%d rx:%d", | ||
1344 | portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", | ||
1345 | (int) portp->stats.txtotal, (int) portp->stats.rxtotal); | ||
1346 | |||
1347 | if (portp->stats.rxframing) | ||
1348 | seq_printf(m, " fe:%d", (int) portp->stats.rxframing); | ||
1349 | if (portp->stats.rxparity) | ||
1350 | seq_printf(m, " pe:%d", (int) portp->stats.rxparity); | ||
1351 | if (portp->stats.rxbreaks) | ||
1352 | seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks); | ||
1353 | if (portp->stats.rxoverrun) | ||
1354 | seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun); | ||
1355 | |||
1356 | sigs = stl_getsignals(portp); | ||
1357 | sep = ' '; | ||
1358 | if (sigs & TIOCM_RTS) { | ||
1359 | seq_printf(m, "%c%s", sep, "RTS"); | ||
1360 | sep = '|'; | ||
1361 | } | ||
1362 | if (sigs & TIOCM_CTS) { | ||
1363 | seq_printf(m, "%c%s", sep, "CTS"); | ||
1364 | sep = '|'; | ||
1365 | } | ||
1366 | if (sigs & TIOCM_DTR) { | ||
1367 | seq_printf(m, "%c%s", sep, "DTR"); | ||
1368 | sep = '|'; | ||
1369 | } | ||
1370 | if (sigs & TIOCM_CD) { | ||
1371 | seq_printf(m, "%c%s", sep, "DCD"); | ||
1372 | sep = '|'; | ||
1373 | } | ||
1374 | if (sigs & TIOCM_DSR) { | ||
1375 | seq_printf(m, "%c%s", sep, "DSR"); | ||
1376 | sep = '|'; | ||
1377 | } | ||
1378 | seq_putc(m, '\n'); | ||
1379 | } | ||
1380 | |||
1381 | /*****************************************************************************/ | ||
1382 | |||
1383 | /* | ||
1384 | * Port info, read from the /proc file system. | ||
1385 | */ | ||
1386 | |||
1387 | static int stl_proc_show(struct seq_file *m, void *v) | ||
1388 | { | ||
1389 | struct stlbrd *brdp; | ||
1390 | struct stlpanel *panelp; | ||
1391 | struct stlport *portp; | ||
1392 | unsigned int brdnr, panelnr, portnr; | ||
1393 | int totalport; | ||
1394 | |||
1395 | totalport = 0; | ||
1396 | |||
1397 | seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion); | ||
1398 | |||
1399 | /* | ||
1400 | * We scan through for each board, panel and port. The offset is | ||
1401 | * calculated on the fly, and irrelevant ports are skipped. | ||
1402 | */ | ||
1403 | for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) { | ||
1404 | brdp = stl_brds[brdnr]; | ||
1405 | if (brdp == NULL) | ||
1406 | continue; | ||
1407 | if (brdp->state == 0) | ||
1408 | continue; | ||
1409 | |||
1410 | totalport = brdnr * STL_MAXPORTS; | ||
1411 | for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { | ||
1412 | panelp = brdp->panels[panelnr]; | ||
1413 | if (panelp == NULL) | ||
1414 | continue; | ||
1415 | |||
1416 | for (portnr = 0; portnr < panelp->nrports; portnr++, | ||
1417 | totalport++) { | ||
1418 | portp = panelp->ports[portnr]; | ||
1419 | if (portp == NULL) | ||
1420 | continue; | ||
1421 | stl_portinfo(m, portp, totalport); | ||
1422 | } | ||
1423 | } | ||
1424 | } | ||
1425 | return 0; | ||
1426 | } | ||
1427 | |||
1428 | static int stl_proc_open(struct inode *inode, struct file *file) | ||
1429 | { | ||
1430 | return single_open(file, stl_proc_show, NULL); | ||
1431 | } | ||
1432 | |||
1433 | static const struct file_operations stl_proc_fops = { | ||
1434 | .owner = THIS_MODULE, | ||
1435 | .open = stl_proc_open, | ||
1436 | .read = seq_read, | ||
1437 | .llseek = seq_lseek, | ||
1438 | .release = single_release, | ||
1439 | }; | ||
1440 | |||
1441 | /*****************************************************************************/ | ||
1442 | |||
1443 | /* | ||
1444 | * All board interrupts are vectored through here first. This code then | ||
1445 | * calls off to the approrpriate board interrupt handlers. | ||
1446 | */ | ||
1447 | |||
1448 | static irqreturn_t stl_intr(int irq, void *dev_id) | ||
1449 | { | ||
1450 | struct stlbrd *brdp = dev_id; | ||
1451 | |||
1452 | pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq); | ||
1453 | |||
1454 | return IRQ_RETVAL((* brdp->isr)(brdp)); | ||
1455 | } | ||
1456 | |||
1457 | /*****************************************************************************/ | ||
1458 | |||
1459 | /* | ||
1460 | * Interrupt service routine for EasyIO board types. | ||
1461 | */ | ||
1462 | |||
1463 | static int stl_eiointr(struct stlbrd *brdp) | ||
1464 | { | ||
1465 | struct stlpanel *panelp; | ||
1466 | unsigned int iobase; | ||
1467 | int handled = 0; | ||
1468 | |||
1469 | spin_lock(&brd_lock); | ||
1470 | panelp = brdp->panels[0]; | ||
1471 | iobase = panelp->iobase; | ||
1472 | while (inb(brdp->iostatus) & EIO_INTRPEND) { | ||
1473 | handled = 1; | ||
1474 | (* panelp->isr)(panelp, iobase); | ||
1475 | } | ||
1476 | spin_unlock(&brd_lock); | ||
1477 | return handled; | ||
1478 | } | ||
1479 | |||
1480 | /*****************************************************************************/ | ||
1481 | |||
1482 | /* | ||
1483 | * Interrupt service routine for ECH-AT board types. | ||
1484 | */ | ||
1485 | |||
1486 | static int stl_echatintr(struct stlbrd *brdp) | ||
1487 | { | ||
1488 | struct stlpanel *panelp; | ||
1489 | unsigned int ioaddr, bnknr; | ||
1490 | int handled = 0; | ||
1491 | |||
1492 | outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); | ||
1493 | |||
1494 | while (inb(brdp->iostatus) & ECH_INTRPEND) { | ||
1495 | handled = 1; | ||
1496 | for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { | ||
1497 | ioaddr = brdp->bnkstataddr[bnknr]; | ||
1498 | if (inb(ioaddr) & ECH_PNLINTRPEND) { | ||
1499 | panelp = brdp->bnk2panel[bnknr]; | ||
1500 | (* panelp->isr)(panelp, (ioaddr & 0xfffc)); | ||
1501 | } | ||
1502 | } | ||
1503 | } | ||
1504 | |||
1505 | outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl); | ||
1506 | |||
1507 | return handled; | ||
1508 | } | ||
1509 | |||
1510 | /*****************************************************************************/ | ||
1511 | |||
1512 | /* | ||
1513 | * Interrupt service routine for ECH-MCA board types. | ||
1514 | */ | ||
1515 | |||
1516 | static int stl_echmcaintr(struct stlbrd *brdp) | ||
1517 | { | ||
1518 | struct stlpanel *panelp; | ||
1519 | unsigned int ioaddr, bnknr; | ||
1520 | int handled = 0; | ||
1521 | |||
1522 | while (inb(brdp->iostatus) & ECH_INTRPEND) { | ||
1523 | handled = 1; | ||
1524 | for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { | ||
1525 | ioaddr = brdp->bnkstataddr[bnknr]; | ||
1526 | if (inb(ioaddr) & ECH_PNLINTRPEND) { | ||
1527 | panelp = brdp->bnk2panel[bnknr]; | ||
1528 | (* panelp->isr)(panelp, (ioaddr & 0xfffc)); | ||
1529 | } | ||
1530 | } | ||
1531 | } | ||
1532 | return handled; | ||
1533 | } | ||
1534 | |||
1535 | /*****************************************************************************/ | ||
1536 | |||
1537 | /* | ||
1538 | * Interrupt service routine for ECH-PCI board types. | ||
1539 | */ | ||
1540 | |||
1541 | static int stl_echpciintr(struct stlbrd *brdp) | ||
1542 | { | ||
1543 | struct stlpanel *panelp; | ||
1544 | unsigned int ioaddr, bnknr, recheck; | ||
1545 | int handled = 0; | ||
1546 | |||
1547 | while (1) { | ||
1548 | recheck = 0; | ||
1549 | for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { | ||
1550 | outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl); | ||
1551 | ioaddr = brdp->bnkstataddr[bnknr]; | ||
1552 | if (inb(ioaddr) & ECH_PNLINTRPEND) { | ||
1553 | panelp = brdp->bnk2panel[bnknr]; | ||
1554 | (* panelp->isr)(panelp, (ioaddr & 0xfffc)); | ||
1555 | recheck++; | ||
1556 | handled = 1; | ||
1557 | } | ||
1558 | } | ||
1559 | if (! recheck) | ||
1560 | break; | ||
1561 | } | ||
1562 | return handled; | ||
1563 | } | ||
1564 | |||
1565 | /*****************************************************************************/ | ||
1566 | |||
1567 | /* | ||
1568 | * Interrupt service routine for ECH-8/64-PCI board types. | ||
1569 | */ | ||
1570 | |||
1571 | static int stl_echpci64intr(struct stlbrd *brdp) | ||
1572 | { | ||
1573 | struct stlpanel *panelp; | ||
1574 | unsigned int ioaddr, bnknr; | ||
1575 | int handled = 0; | ||
1576 | |||
1577 | while (inb(brdp->ioctrl) & 0x1) { | ||
1578 | handled = 1; | ||
1579 | for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { | ||
1580 | ioaddr = brdp->bnkstataddr[bnknr]; | ||
1581 | if (inb(ioaddr) & ECH_PNLINTRPEND) { | ||
1582 | panelp = brdp->bnk2panel[bnknr]; | ||
1583 | (* panelp->isr)(panelp, (ioaddr & 0xfffc)); | ||
1584 | } | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | return handled; | ||
1589 | } | ||
1590 | |||
1591 | /*****************************************************************************/ | ||
1592 | |||
1593 | /* | ||
1594 | * Initialize all the ports on a panel. | ||
1595 | */ | ||
1596 | |||
1597 | static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) | ||
1598 | { | ||
1599 | struct stlport *portp; | ||
1600 | unsigned int i; | ||
1601 | int chipmask; | ||
1602 | |||
1603 | pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp); | ||
1604 | |||
1605 | chipmask = stl_panelinit(brdp, panelp); | ||
1606 | |||
1607 | /* | ||
1608 | * All UART's are initialized (if found!). Now go through and setup | ||
1609 | * each ports data structures. | ||
1610 | */ | ||
1611 | for (i = 0; i < panelp->nrports; i++) { | ||
1612 | portp = kzalloc(sizeof(struct stlport), GFP_KERNEL); | ||
1613 | if (!portp) { | ||
1614 | printk("STALLION: failed to allocate memory " | ||
1615 | "(size=%Zd)\n", sizeof(struct stlport)); | ||
1616 | break; | ||
1617 | } | ||
1618 | tty_port_init(&portp->port); | ||
1619 | portp->port.ops = &stl_port_ops; | ||
1620 | portp->magic = STL_PORTMAGIC; | ||
1621 | portp->portnr = i; | ||
1622 | portp->brdnr = panelp->brdnr; | ||
1623 | portp->panelnr = panelp->panelnr; | ||
1624 | portp->uartp = panelp->uartp; | ||
1625 | portp->clk = brdp->clk; | ||
1626 | portp->baud_base = STL_BAUDBASE; | ||
1627 | portp->close_delay = STL_CLOSEDELAY; | ||
1628 | portp->closing_wait = 30 * HZ; | ||
1629 | init_waitqueue_head(&portp->port.open_wait); | ||
1630 | init_waitqueue_head(&portp->port.close_wait); | ||
1631 | portp->stats.brd = portp->brdnr; | ||
1632 | portp->stats.panel = portp->panelnr; | ||
1633 | portp->stats.port = portp->portnr; | ||
1634 | panelp->ports[i] = portp; | ||
1635 | stl_portinit(brdp, panelp, portp); | ||
1636 | } | ||
1637 | |||
1638 | return 0; | ||
1639 | } | ||
1640 | |||
1641 | static void stl_cleanup_panels(struct stlbrd *brdp) | ||
1642 | { | ||
1643 | struct stlpanel *panelp; | ||
1644 | struct stlport *portp; | ||
1645 | unsigned int j, k; | ||
1646 | struct tty_struct *tty; | ||
1647 | |||
1648 | for (j = 0; j < STL_MAXPANELS; j++) { | ||
1649 | panelp = brdp->panels[j]; | ||
1650 | if (panelp == NULL) | ||
1651 | continue; | ||
1652 | for (k = 0; k < STL_PORTSPERPANEL; k++) { | ||
1653 | portp = panelp->ports[k]; | ||
1654 | if (portp == NULL) | ||
1655 | continue; | ||
1656 | tty = tty_port_tty_get(&portp->port); | ||
1657 | if (tty != NULL) { | ||
1658 | stl_hangup(tty); | ||
1659 | tty_kref_put(tty); | ||
1660 | } | ||
1661 | kfree(portp->tx.buf); | ||
1662 | kfree(portp); | ||
1663 | } | ||
1664 | kfree(panelp); | ||
1665 | } | ||
1666 | } | ||
1667 | |||
1668 | /*****************************************************************************/ | ||
1669 | |||
1670 | /* | ||
1671 | * Try to find and initialize an EasyIO board. | ||
1672 | */ | ||
1673 | |||
1674 | static int __devinit stl_initeio(struct stlbrd *brdp) | ||
1675 | { | ||
1676 | struct stlpanel *panelp; | ||
1677 | unsigned int status; | ||
1678 | char *name; | ||
1679 | int retval; | ||
1680 | |||
1681 | pr_debug("stl_initeio(brdp=%p)\n", brdp); | ||
1682 | |||
1683 | brdp->ioctrl = brdp->ioaddr1 + 1; | ||
1684 | brdp->iostatus = brdp->ioaddr1 + 2; | ||
1685 | |||
1686 | status = inb(brdp->iostatus); | ||
1687 | if ((status & EIO_IDBITMASK) == EIO_MK3) | ||
1688 | brdp->ioctrl++; | ||
1689 | |||
1690 | /* | ||
1691 | * Handle board specific stuff now. The real difference is PCI | ||
1692 | * or not PCI. | ||
1693 | */ | ||
1694 | if (brdp->brdtype == BRD_EASYIOPCI) { | ||
1695 | brdp->iosize1 = 0x80; | ||
1696 | brdp->iosize2 = 0x80; | ||
1697 | name = "serial(EIO-PCI)"; | ||
1698 | outb(0x41, (brdp->ioaddr2 + 0x4c)); | ||
1699 | } else { | ||
1700 | brdp->iosize1 = 8; | ||
1701 | name = "serial(EIO)"; | ||
1702 | if ((brdp->irq < 0) || (brdp->irq > 15) || | ||
1703 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { | ||
1704 | printk("STALLION: invalid irq=%d for brd=%d\n", | ||
1705 | brdp->irq, brdp->brdnr); | ||
1706 | retval = -EINVAL; | ||
1707 | goto err; | ||
1708 | } | ||
1709 | outb((stl_vecmap[brdp->irq] | EIO_0WS | | ||
1710 | ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)), | ||
1711 | brdp->ioctrl); | ||
1712 | } | ||
1713 | |||
1714 | retval = -EBUSY; | ||
1715 | if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { | ||
1716 | printk(KERN_WARNING "STALLION: Warning, board %d I/O address " | ||
1717 | "%x conflicts with another device\n", brdp->brdnr, | ||
1718 | brdp->ioaddr1); | ||
1719 | goto err; | ||
1720 | } | ||
1721 | |||
1722 | if (brdp->iosize2 > 0) | ||
1723 | if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) { | ||
1724 | printk(KERN_WARNING "STALLION: Warning, board %d I/O " | ||
1725 | "address %x conflicts with another device\n", | ||
1726 | brdp->brdnr, brdp->ioaddr2); | ||
1727 | printk(KERN_WARNING "STALLION: Warning, also " | ||
1728 | "releasing board %d I/O address %x \n", | ||
1729 | brdp->brdnr, brdp->ioaddr1); | ||
1730 | goto err_rel1; | ||
1731 | } | ||
1732 | |||
1733 | /* | ||
1734 | * Everything looks OK, so let's go ahead and probe for the hardware. | ||
1735 | */ | ||
1736 | brdp->clk = CD1400_CLK; | ||
1737 | brdp->isr = stl_eiointr; | ||
1738 | |||
1739 | retval = -ENODEV; | ||
1740 | switch (status & EIO_IDBITMASK) { | ||
1741 | case EIO_8PORTM: | ||
1742 | brdp->clk = CD1400_CLK8M; | ||
1743 | /* fall thru */ | ||
1744 | case EIO_8PORTRS: | ||
1745 | case EIO_8PORTDI: | ||
1746 | brdp->nrports = 8; | ||
1747 | break; | ||
1748 | case EIO_4PORTRS: | ||
1749 | brdp->nrports = 4; | ||
1750 | break; | ||
1751 | case EIO_MK3: | ||
1752 | switch (status & EIO_BRDMASK) { | ||
1753 | case ID_BRD4: | ||
1754 | brdp->nrports = 4; | ||
1755 | break; | ||
1756 | case ID_BRD8: | ||
1757 | brdp->nrports = 8; | ||
1758 | break; | ||
1759 | case ID_BRD16: | ||
1760 | brdp->nrports = 16; | ||
1761 | break; | ||
1762 | default: | ||
1763 | goto err_rel2; | ||
1764 | } | ||
1765 | break; | ||
1766 | default: | ||
1767 | goto err_rel2; | ||
1768 | } | ||
1769 | |||
1770 | /* | ||
1771 | * We have verified that the board is actually present, so now we | ||
1772 | * can complete the setup. | ||
1773 | */ | ||
1774 | |||
1775 | panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); | ||
1776 | if (!panelp) { | ||
1777 | printk(KERN_WARNING "STALLION: failed to allocate memory " | ||
1778 | "(size=%Zd)\n", sizeof(struct stlpanel)); | ||
1779 | retval = -ENOMEM; | ||
1780 | goto err_rel2; | ||
1781 | } | ||
1782 | |||
1783 | panelp->magic = STL_PANELMAGIC; | ||
1784 | panelp->brdnr = brdp->brdnr; | ||
1785 | panelp->panelnr = 0; | ||
1786 | panelp->nrports = brdp->nrports; | ||
1787 | panelp->iobase = brdp->ioaddr1; | ||
1788 | panelp->hwid = status; | ||
1789 | if ((status & EIO_IDBITMASK) == EIO_MK3) { | ||
1790 | panelp->uartp = &stl_sc26198uart; | ||
1791 | panelp->isr = stl_sc26198intr; | ||
1792 | } else { | ||
1793 | panelp->uartp = &stl_cd1400uart; | ||
1794 | panelp->isr = stl_cd1400eiointr; | ||
1795 | } | ||
1796 | |||
1797 | brdp->panels[0] = panelp; | ||
1798 | brdp->nrpanels = 1; | ||
1799 | brdp->state |= BRD_FOUND; | ||
1800 | brdp->hwid = status; | ||
1801 | if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { | ||
1802 | printk("STALLION: failed to register interrupt " | ||
1803 | "routine for %s irq=%d\n", name, brdp->irq); | ||
1804 | retval = -ENODEV; | ||
1805 | goto err_fr; | ||
1806 | } | ||
1807 | |||
1808 | return 0; | ||
1809 | err_fr: | ||
1810 | stl_cleanup_panels(brdp); | ||
1811 | err_rel2: | ||
1812 | if (brdp->iosize2 > 0) | ||
1813 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
1814 | err_rel1: | ||
1815 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
1816 | err: | ||
1817 | return retval; | ||
1818 | } | ||
1819 | |||
1820 | /*****************************************************************************/ | ||
1821 | |||
1822 | /* | ||
1823 | * Try to find an ECH board and initialize it. This code is capable of | ||
1824 | * dealing with all types of ECH board. | ||
1825 | */ | ||
1826 | |||
1827 | static int __devinit stl_initech(struct stlbrd *brdp) | ||
1828 | { | ||
1829 | struct stlpanel *panelp; | ||
1830 | unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i; | ||
1831 | int retval; | ||
1832 | char *name; | ||
1833 | |||
1834 | pr_debug("stl_initech(brdp=%p)\n", brdp); | ||
1835 | |||
1836 | status = 0; | ||
1837 | conflict = 0; | ||
1838 | |||
1839 | /* | ||
1840 | * Set up the initial board register contents for boards. This varies a | ||
1841 | * bit between the different board types. So we need to handle each | ||
1842 | * separately. Also do a check that the supplied IRQ is good. | ||
1843 | */ | ||
1844 | switch (brdp->brdtype) { | ||
1845 | |||
1846 | case BRD_ECH: | ||
1847 | brdp->isr = stl_echatintr; | ||
1848 | brdp->ioctrl = brdp->ioaddr1 + 1; | ||
1849 | brdp->iostatus = brdp->ioaddr1 + 1; | ||
1850 | status = inb(brdp->iostatus); | ||
1851 | if ((status & ECH_IDBITMASK) != ECH_ID) { | ||
1852 | retval = -ENODEV; | ||
1853 | goto err; | ||
1854 | } | ||
1855 | if ((brdp->irq < 0) || (brdp->irq > 15) || | ||
1856 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { | ||
1857 | printk("STALLION: invalid irq=%d for brd=%d\n", | ||
1858 | brdp->irq, brdp->brdnr); | ||
1859 | retval = -EINVAL; | ||
1860 | goto err; | ||
1861 | } | ||
1862 | status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1); | ||
1863 | status |= (stl_vecmap[brdp->irq] << 1); | ||
1864 | outb((status | ECH_BRDRESET), brdp->ioaddr1); | ||
1865 | brdp->ioctrlval = ECH_INTENABLE | | ||
1866 | ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE); | ||
1867 | for (i = 0; i < 10; i++) | ||
1868 | outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); | ||
1869 | brdp->iosize1 = 2; | ||
1870 | brdp->iosize2 = 32; | ||
1871 | name = "serial(EC8/32)"; | ||
1872 | outb(status, brdp->ioaddr1); | ||
1873 | break; | ||
1874 | |||
1875 | case BRD_ECHMC: | ||
1876 | brdp->isr = stl_echmcaintr; | ||
1877 | brdp->ioctrl = brdp->ioaddr1 + 0x20; | ||
1878 | brdp->iostatus = brdp->ioctrl; | ||
1879 | status = inb(brdp->iostatus); | ||
1880 | if ((status & ECH_IDBITMASK) != ECH_ID) { | ||
1881 | retval = -ENODEV; | ||
1882 | goto err; | ||
1883 | } | ||
1884 | if ((brdp->irq < 0) || (brdp->irq > 15) || | ||
1885 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { | ||
1886 | printk("STALLION: invalid irq=%d for brd=%d\n", | ||
1887 | brdp->irq, brdp->brdnr); | ||
1888 | retval = -EINVAL; | ||
1889 | goto err; | ||
1890 | } | ||
1891 | outb(ECHMC_BRDRESET, brdp->ioctrl); | ||
1892 | outb(ECHMC_INTENABLE, brdp->ioctrl); | ||
1893 | brdp->iosize1 = 64; | ||
1894 | name = "serial(EC8/32-MC)"; | ||
1895 | break; | ||
1896 | |||
1897 | case BRD_ECHPCI: | ||
1898 | brdp->isr = stl_echpciintr; | ||
1899 | brdp->ioctrl = brdp->ioaddr1 + 2; | ||
1900 | brdp->iosize1 = 4; | ||
1901 | brdp->iosize2 = 8; | ||
1902 | name = "serial(EC8/32-PCI)"; | ||
1903 | break; | ||
1904 | |||
1905 | case BRD_ECH64PCI: | ||
1906 | brdp->isr = stl_echpci64intr; | ||
1907 | brdp->ioctrl = brdp->ioaddr2 + 0x40; | ||
1908 | outb(0x43, (brdp->ioaddr1 + 0x4c)); | ||
1909 | brdp->iosize1 = 0x80; | ||
1910 | brdp->iosize2 = 0x80; | ||
1911 | name = "serial(EC8/64-PCI)"; | ||
1912 | break; | ||
1913 | |||
1914 | default: | ||
1915 | printk("STALLION: unknown board type=%d\n", brdp->brdtype); | ||
1916 | retval = -EINVAL; | ||
1917 | goto err; | ||
1918 | } | ||
1919 | |||
1920 | /* | ||
1921 | * Check boards for possible IO address conflicts and return fail status | ||
1922 | * if an IO conflict found. | ||
1923 | */ | ||
1924 | retval = -EBUSY; | ||
1925 | if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { | ||
1926 | printk(KERN_WARNING "STALLION: Warning, board %d I/O address " | ||
1927 | "%x conflicts with another device\n", brdp->brdnr, | ||
1928 | brdp->ioaddr1); | ||
1929 | goto err; | ||
1930 | } | ||
1931 | |||
1932 | if (brdp->iosize2 > 0) | ||
1933 | if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) { | ||
1934 | printk(KERN_WARNING "STALLION: Warning, board %d I/O " | ||
1935 | "address %x conflicts with another device\n", | ||
1936 | brdp->brdnr, brdp->ioaddr2); | ||
1937 | printk(KERN_WARNING "STALLION: Warning, also " | ||
1938 | "releasing board %d I/O address %x \n", | ||
1939 | brdp->brdnr, brdp->ioaddr1); | ||
1940 | goto err_rel1; | ||
1941 | } | ||
1942 | |||
1943 | /* | ||
1944 | * Scan through the secondary io address space looking for panels. | ||
1945 | * As we find'em allocate and initialize panel structures for each. | ||
1946 | */ | ||
1947 | brdp->clk = CD1400_CLK; | ||
1948 | brdp->hwid = status; | ||
1949 | |||
1950 | ioaddr = brdp->ioaddr2; | ||
1951 | banknr = 0; | ||
1952 | panelnr = 0; | ||
1953 | nxtid = 0; | ||
1954 | |||
1955 | for (i = 0; i < STL_MAXPANELS; i++) { | ||
1956 | if (brdp->brdtype == BRD_ECHPCI) { | ||
1957 | outb(nxtid, brdp->ioctrl); | ||
1958 | ioaddr = brdp->ioaddr2; | ||
1959 | } | ||
1960 | status = inb(ioaddr + ECH_PNLSTATUS); | ||
1961 | if ((status & ECH_PNLIDMASK) != nxtid) | ||
1962 | break; | ||
1963 | panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); | ||
1964 | if (!panelp) { | ||
1965 | printk("STALLION: failed to allocate memory " | ||
1966 | "(size=%Zd)\n", sizeof(struct stlpanel)); | ||
1967 | retval = -ENOMEM; | ||
1968 | goto err_fr; | ||
1969 | } | ||
1970 | panelp->magic = STL_PANELMAGIC; | ||
1971 | panelp->brdnr = brdp->brdnr; | ||
1972 | panelp->panelnr = panelnr; | ||
1973 | panelp->iobase = ioaddr; | ||
1974 | panelp->pagenr = nxtid; | ||
1975 | panelp->hwid = status; | ||
1976 | brdp->bnk2panel[banknr] = panelp; | ||
1977 | brdp->bnkpageaddr[banknr] = nxtid; | ||
1978 | brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS; | ||
1979 | |||
1980 | if (status & ECH_PNLXPID) { | ||
1981 | panelp->uartp = &stl_sc26198uart; | ||
1982 | panelp->isr = stl_sc26198intr; | ||
1983 | if (status & ECH_PNL16PORT) { | ||
1984 | panelp->nrports = 16; | ||
1985 | brdp->bnk2panel[banknr] = panelp; | ||
1986 | brdp->bnkpageaddr[banknr] = nxtid; | ||
1987 | brdp->bnkstataddr[banknr++] = ioaddr + 4 + | ||
1988 | ECH_PNLSTATUS; | ||
1989 | } else | ||
1990 | panelp->nrports = 8; | ||
1991 | } else { | ||
1992 | panelp->uartp = &stl_cd1400uart; | ||
1993 | panelp->isr = stl_cd1400echintr; | ||
1994 | if (status & ECH_PNL16PORT) { | ||
1995 | panelp->nrports = 16; | ||
1996 | panelp->ackmask = 0x80; | ||
1997 | if (brdp->brdtype != BRD_ECHPCI) | ||
1998 | ioaddr += EREG_BANKSIZE; | ||
1999 | brdp->bnk2panel[banknr] = panelp; | ||
2000 | brdp->bnkpageaddr[banknr] = ++nxtid; | ||
2001 | brdp->bnkstataddr[banknr++] = ioaddr + | ||
2002 | ECH_PNLSTATUS; | ||
2003 | } else { | ||
2004 | panelp->nrports = 8; | ||
2005 | panelp->ackmask = 0xc0; | ||
2006 | } | ||
2007 | } | ||
2008 | |||
2009 | nxtid++; | ||
2010 | ioaddr += EREG_BANKSIZE; | ||
2011 | brdp->nrports += panelp->nrports; | ||
2012 | brdp->panels[panelnr++] = panelp; | ||
2013 | if ((brdp->brdtype != BRD_ECHPCI) && | ||
2014 | (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) { | ||
2015 | retval = -EINVAL; | ||
2016 | goto err_fr; | ||
2017 | } | ||
2018 | } | ||
2019 | |||
2020 | brdp->nrpanels = panelnr; | ||
2021 | brdp->nrbnks = banknr; | ||
2022 | if (brdp->brdtype == BRD_ECH) | ||
2023 | outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl); | ||
2024 | |||
2025 | brdp->state |= BRD_FOUND; | ||
2026 | if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { | ||
2027 | printk("STALLION: failed to register interrupt " | ||
2028 | "routine for %s irq=%d\n", name, brdp->irq); | ||
2029 | retval = -ENODEV; | ||
2030 | goto err_fr; | ||
2031 | } | ||
2032 | |||
2033 | return 0; | ||
2034 | err_fr: | ||
2035 | stl_cleanup_panels(brdp); | ||
2036 | if (brdp->iosize2 > 0) | ||
2037 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
2038 | err_rel1: | ||
2039 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
2040 | err: | ||
2041 | return retval; | ||
2042 | } | ||
2043 | |||
2044 | /*****************************************************************************/ | ||
2045 | |||
2046 | /* | ||
2047 | * Initialize and configure the specified board. | ||
2048 | * Scan through all the boards in the configuration and see what we | ||
2049 | * can find. Handle EIO and the ECH boards a little differently here | ||
2050 | * since the initial search and setup is very different. | ||
2051 | */ | ||
2052 | |||
2053 | static int __devinit stl_brdinit(struct stlbrd *brdp) | ||
2054 | { | ||
2055 | int i, retval; | ||
2056 | |||
2057 | pr_debug("stl_brdinit(brdp=%p)\n", brdp); | ||
2058 | |||
2059 | switch (brdp->brdtype) { | ||
2060 | case BRD_EASYIO: | ||
2061 | case BRD_EASYIOPCI: | ||
2062 | retval = stl_initeio(brdp); | ||
2063 | if (retval) | ||
2064 | goto err; | ||
2065 | break; | ||
2066 | case BRD_ECH: | ||
2067 | case BRD_ECHMC: | ||
2068 | case BRD_ECHPCI: | ||
2069 | case BRD_ECH64PCI: | ||
2070 | retval = stl_initech(brdp); | ||
2071 | if (retval) | ||
2072 | goto err; | ||
2073 | break; | ||
2074 | default: | ||
2075 | printk("STALLION: board=%d is unknown board type=%d\n", | ||
2076 | brdp->brdnr, brdp->brdtype); | ||
2077 | retval = -ENODEV; | ||
2078 | goto err; | ||
2079 | } | ||
2080 | |||
2081 | if ((brdp->state & BRD_FOUND) == 0) { | ||
2082 | printk("STALLION: %s board not found, board=%d io=%x irq=%d\n", | ||
2083 | stl_brdnames[brdp->brdtype], brdp->brdnr, | ||
2084 | brdp->ioaddr1, brdp->irq); | ||
2085 | goto err_free; | ||
2086 | } | ||
2087 | |||
2088 | for (i = 0; i < STL_MAXPANELS; i++) | ||
2089 | if (brdp->panels[i] != NULL) | ||
2090 | stl_initports(brdp, brdp->panels[i]); | ||
2091 | |||
2092 | printk("STALLION: %s found, board=%d io=%x irq=%d " | ||
2093 | "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype], | ||
2094 | brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels, | ||
2095 | brdp->nrports); | ||
2096 | |||
2097 | return 0; | ||
2098 | err_free: | ||
2099 | free_irq(brdp->irq, brdp); | ||
2100 | |||
2101 | stl_cleanup_panels(brdp); | ||
2102 | |||
2103 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
2104 | if (brdp->iosize2 > 0) | ||
2105 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
2106 | err: | ||
2107 | return retval; | ||
2108 | } | ||
2109 | |||
2110 | /*****************************************************************************/ | ||
2111 | |||
2112 | /* | ||
2113 | * Find the next available board number that is free. | ||
2114 | */ | ||
2115 | |||
2116 | static int __devinit stl_getbrdnr(void) | ||
2117 | { | ||
2118 | unsigned int i; | ||
2119 | |||
2120 | for (i = 0; i < STL_MAXBRDS; i++) | ||
2121 | if (stl_brds[i] == NULL) { | ||
2122 | if (i >= stl_nrbrds) | ||
2123 | stl_nrbrds = i + 1; | ||
2124 | return i; | ||
2125 | } | ||
2126 | |||
2127 | return -1; | ||
2128 | } | ||
2129 | |||
2130 | /*****************************************************************************/ | ||
2131 | /* | ||
2132 | * We have a Stallion board. Allocate a board structure and | ||
2133 | * initialize it. Read its IO and IRQ resources from PCI | ||
2134 | * configuration space. | ||
2135 | */ | ||
2136 | |||
2137 | static int __devinit stl_pciprobe(struct pci_dev *pdev, | ||
2138 | const struct pci_device_id *ent) | ||
2139 | { | ||
2140 | struct stlbrd *brdp; | ||
2141 | unsigned int i, brdtype = ent->driver_data; | ||
2142 | int brdnr, retval = -ENODEV; | ||
2143 | |||
2144 | if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) | ||
2145 | goto err; | ||
2146 | |||
2147 | retval = pci_enable_device(pdev); | ||
2148 | if (retval) | ||
2149 | goto err; | ||
2150 | brdp = stl_allocbrd(); | ||
2151 | if (brdp == NULL) { | ||
2152 | retval = -ENOMEM; | ||
2153 | goto err; | ||
2154 | } | ||
2155 | mutex_lock(&stl_brdslock); | ||
2156 | brdnr = stl_getbrdnr(); | ||
2157 | if (brdnr < 0) { | ||
2158 | dev_err(&pdev->dev, "too many boards found, " | ||
2159 | "maximum supported %d\n", STL_MAXBRDS); | ||
2160 | mutex_unlock(&stl_brdslock); | ||
2161 | retval = -ENODEV; | ||
2162 | goto err_fr; | ||
2163 | } | ||
2164 | brdp->brdnr = (unsigned int)brdnr; | ||
2165 | stl_brds[brdp->brdnr] = brdp; | ||
2166 | mutex_unlock(&stl_brdslock); | ||
2167 | |||
2168 | brdp->brdtype = brdtype; | ||
2169 | brdp->state |= STL_PROBED; | ||
2170 | |||
2171 | /* | ||
2172 | * We have all resources from the board, so let's setup the actual | ||
2173 | * board structure now. | ||
2174 | */ | ||
2175 | switch (brdtype) { | ||
2176 | case BRD_ECHPCI: | ||
2177 | brdp->ioaddr2 = pci_resource_start(pdev, 0); | ||
2178 | brdp->ioaddr1 = pci_resource_start(pdev, 1); | ||
2179 | break; | ||
2180 | case BRD_ECH64PCI: | ||
2181 | brdp->ioaddr2 = pci_resource_start(pdev, 2); | ||
2182 | brdp->ioaddr1 = pci_resource_start(pdev, 1); | ||
2183 | break; | ||
2184 | case BRD_EASYIOPCI: | ||
2185 | brdp->ioaddr1 = pci_resource_start(pdev, 2); | ||
2186 | brdp->ioaddr2 = pci_resource_start(pdev, 1); | ||
2187 | break; | ||
2188 | default: | ||
2189 | dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype); | ||
2190 | break; | ||
2191 | } | ||
2192 | |||
2193 | brdp->irq = pdev->irq; | ||
2194 | retval = stl_brdinit(brdp); | ||
2195 | if (retval) | ||
2196 | goto err_null; | ||
2197 | |||
2198 | pci_set_drvdata(pdev, brdp); | ||
2199 | |||
2200 | for (i = 0; i < brdp->nrports; i++) | ||
2201 | tty_register_device(stl_serial, | ||
2202 | brdp->brdnr * STL_MAXPORTS + i, &pdev->dev); | ||
2203 | |||
2204 | return 0; | ||
2205 | err_null: | ||
2206 | stl_brds[brdp->brdnr] = NULL; | ||
2207 | err_fr: | ||
2208 | kfree(brdp); | ||
2209 | err: | ||
2210 | return retval; | ||
2211 | } | ||
2212 | |||
2213 | static void __devexit stl_pciremove(struct pci_dev *pdev) | ||
2214 | { | ||
2215 | struct stlbrd *brdp = pci_get_drvdata(pdev); | ||
2216 | unsigned int i; | ||
2217 | |||
2218 | free_irq(brdp->irq, brdp); | ||
2219 | |||
2220 | stl_cleanup_panels(brdp); | ||
2221 | |||
2222 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
2223 | if (brdp->iosize2 > 0) | ||
2224 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
2225 | |||
2226 | for (i = 0; i < brdp->nrports; i++) | ||
2227 | tty_unregister_device(stl_serial, | ||
2228 | brdp->brdnr * STL_MAXPORTS + i); | ||
2229 | |||
2230 | stl_brds[brdp->brdnr] = NULL; | ||
2231 | kfree(brdp); | ||
2232 | } | ||
2233 | |||
2234 | static struct pci_driver stl_pcidriver = { | ||
2235 | .name = "stallion", | ||
2236 | .id_table = stl_pcibrds, | ||
2237 | .probe = stl_pciprobe, | ||
2238 | .remove = __devexit_p(stl_pciremove) | ||
2239 | }; | ||
2240 | |||
2241 | /*****************************************************************************/ | ||
2242 | |||
2243 | /* | ||
2244 | * Return the board stats structure to user app. | ||
2245 | */ | ||
2246 | |||
2247 | static int stl_getbrdstats(combrd_t __user *bp) | ||
2248 | { | ||
2249 | combrd_t stl_brdstats; | ||
2250 | struct stlbrd *brdp; | ||
2251 | struct stlpanel *panelp; | ||
2252 | unsigned int i; | ||
2253 | |||
2254 | if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t))) | ||
2255 | return -EFAULT; | ||
2256 | if (stl_brdstats.brd >= STL_MAXBRDS) | ||
2257 | return -ENODEV; | ||
2258 | brdp = stl_brds[stl_brdstats.brd]; | ||
2259 | if (brdp == NULL) | ||
2260 | return -ENODEV; | ||
2261 | |||
2262 | memset(&stl_brdstats, 0, sizeof(combrd_t)); | ||
2263 | stl_brdstats.brd = brdp->brdnr; | ||
2264 | stl_brdstats.type = brdp->brdtype; | ||
2265 | stl_brdstats.hwid = brdp->hwid; | ||
2266 | stl_brdstats.state = brdp->state; | ||
2267 | stl_brdstats.ioaddr = brdp->ioaddr1; | ||
2268 | stl_brdstats.ioaddr2 = brdp->ioaddr2; | ||
2269 | stl_brdstats.irq = brdp->irq; | ||
2270 | stl_brdstats.nrpanels = brdp->nrpanels; | ||
2271 | stl_brdstats.nrports = brdp->nrports; | ||
2272 | for (i = 0; i < brdp->nrpanels; i++) { | ||
2273 | panelp = brdp->panels[i]; | ||
2274 | stl_brdstats.panels[i].panel = i; | ||
2275 | stl_brdstats.panels[i].hwid = panelp->hwid; | ||
2276 | stl_brdstats.panels[i].nrports = panelp->nrports; | ||
2277 | } | ||
2278 | |||
2279 | return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0; | ||
2280 | } | ||
2281 | |||
2282 | /*****************************************************************************/ | ||
2283 | |||
2284 | /* | ||
2285 | * Resolve the referenced port number into a port struct pointer. | ||
2286 | */ | ||
2287 | |||
2288 | static struct stlport *stl_getport(int brdnr, int panelnr, int portnr) | ||
2289 | { | ||
2290 | struct stlbrd *brdp; | ||
2291 | struct stlpanel *panelp; | ||
2292 | |||
2293 | if (brdnr < 0 || brdnr >= STL_MAXBRDS) | ||
2294 | return NULL; | ||
2295 | brdp = stl_brds[brdnr]; | ||
2296 | if (brdp == NULL) | ||
2297 | return NULL; | ||
2298 | if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels) | ||
2299 | return NULL; | ||
2300 | panelp = brdp->panels[panelnr]; | ||
2301 | if (panelp == NULL) | ||
2302 | return NULL; | ||
2303 | if (portnr < 0 || (unsigned int)portnr >= panelp->nrports) | ||
2304 | return NULL; | ||
2305 | return panelp->ports[portnr]; | ||
2306 | } | ||
2307 | |||
2308 | /*****************************************************************************/ | ||
2309 | |||
2310 | /* | ||
2311 | * Return the port stats structure to user app. A NULL port struct | ||
2312 | * pointer passed in means that we need to find out from the app | ||
2313 | * what port to get stats for (used through board control device). | ||
2314 | */ | ||
2315 | |||
2316 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp) | ||
2317 | { | ||
2318 | comstats_t stl_comstats; | ||
2319 | unsigned char *head, *tail; | ||
2320 | unsigned long flags; | ||
2321 | |||
2322 | if (!portp) { | ||
2323 | if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t))) | ||
2324 | return -EFAULT; | ||
2325 | portp = stl_getport(stl_comstats.brd, stl_comstats.panel, | ||
2326 | stl_comstats.port); | ||
2327 | if (portp == NULL) | ||
2328 | return -ENODEV; | ||
2329 | } | ||
2330 | |||
2331 | mutex_lock(&portp->port.mutex); | ||
2332 | portp->stats.state = portp->istate; | ||
2333 | portp->stats.flags = portp->port.flags; | ||
2334 | portp->stats.hwid = portp->hwid; | ||
2335 | |||
2336 | portp->stats.ttystate = 0; | ||
2337 | portp->stats.cflags = 0; | ||
2338 | portp->stats.iflags = 0; | ||
2339 | portp->stats.oflags = 0; | ||
2340 | portp->stats.lflags = 0; | ||
2341 | portp->stats.rxbuffered = 0; | ||
2342 | |||
2343 | spin_lock_irqsave(&stallion_lock, flags); | ||
2344 | if (tty != NULL && portp->port.tty == tty) { | ||
2345 | portp->stats.ttystate = tty->flags; | ||
2346 | /* No longer available as a statistic */ | ||
2347 | portp->stats.rxbuffered = 1; /*tty->flip.count; */ | ||
2348 | if (tty->termios != NULL) { | ||
2349 | portp->stats.cflags = tty->termios->c_cflag; | ||
2350 | portp->stats.iflags = tty->termios->c_iflag; | ||
2351 | portp->stats.oflags = tty->termios->c_oflag; | ||
2352 | portp->stats.lflags = tty->termios->c_lflag; | ||
2353 | } | ||
2354 | } | ||
2355 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
2356 | |||
2357 | head = portp->tx.head; | ||
2358 | tail = portp->tx.tail; | ||
2359 | portp->stats.txbuffered = (head >= tail) ? (head - tail) : | ||
2360 | (STL_TXBUFSIZE - (tail - head)); | ||
2361 | |||
2362 | portp->stats.signals = (unsigned long) stl_getsignals(portp); | ||
2363 | mutex_unlock(&portp->port.mutex); | ||
2364 | |||
2365 | return copy_to_user(cp, &portp->stats, | ||
2366 | sizeof(comstats_t)) ? -EFAULT : 0; | ||
2367 | } | ||
2368 | |||
2369 | /*****************************************************************************/ | ||
2370 | |||
2371 | /* | ||
2372 | * Clear the port stats structure. We also return it zeroed out... | ||
2373 | */ | ||
2374 | |||
2375 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp) | ||
2376 | { | ||
2377 | comstats_t stl_comstats; | ||
2378 | |||
2379 | if (!portp) { | ||
2380 | if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t))) | ||
2381 | return -EFAULT; | ||
2382 | portp = stl_getport(stl_comstats.brd, stl_comstats.panel, | ||
2383 | stl_comstats.port); | ||
2384 | if (portp == NULL) | ||
2385 | return -ENODEV; | ||
2386 | } | ||
2387 | |||
2388 | mutex_lock(&portp->port.mutex); | ||
2389 | memset(&portp->stats, 0, sizeof(comstats_t)); | ||
2390 | portp->stats.brd = portp->brdnr; | ||
2391 | portp->stats.panel = portp->panelnr; | ||
2392 | portp->stats.port = portp->portnr; | ||
2393 | mutex_unlock(&portp->port.mutex); | ||
2394 | return copy_to_user(cp, &portp->stats, | ||
2395 | sizeof(comstats_t)) ? -EFAULT : 0; | ||
2396 | } | ||
2397 | |||
2398 | /*****************************************************************************/ | ||
2399 | |||
2400 | /* | ||
2401 | * Return the entire driver ports structure to a user app. | ||
2402 | */ | ||
2403 | |||
2404 | static int stl_getportstruct(struct stlport __user *arg) | ||
2405 | { | ||
2406 | struct stlport stl_dummyport; | ||
2407 | struct stlport *portp; | ||
2408 | |||
2409 | if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport))) | ||
2410 | return -EFAULT; | ||
2411 | portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr, | ||
2412 | stl_dummyport.portnr); | ||
2413 | if (!portp) | ||
2414 | return -ENODEV; | ||
2415 | return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0; | ||
2416 | } | ||
2417 | |||
2418 | /*****************************************************************************/ | ||
2419 | |||
2420 | /* | ||
2421 | * Return the entire driver board structure to a user app. | ||
2422 | */ | ||
2423 | |||
2424 | static int stl_getbrdstruct(struct stlbrd __user *arg) | ||
2425 | { | ||
2426 | struct stlbrd stl_dummybrd; | ||
2427 | struct stlbrd *brdp; | ||
2428 | |||
2429 | if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd))) | ||
2430 | return -EFAULT; | ||
2431 | if (stl_dummybrd.brdnr >= STL_MAXBRDS) | ||
2432 | return -ENODEV; | ||
2433 | brdp = stl_brds[stl_dummybrd.brdnr]; | ||
2434 | if (!brdp) | ||
2435 | return -ENODEV; | ||
2436 | return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0; | ||
2437 | } | ||
2438 | |||
2439 | /*****************************************************************************/ | ||
2440 | |||
2441 | /* | ||
2442 | * The "staliomem" device is also required to do some special operations | ||
2443 | * on the board and/or ports. In this driver it is mostly used for stats | ||
2444 | * collection. | ||
2445 | */ | ||
2446 | |||
2447 | static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | ||
2448 | { | ||
2449 | int brdnr, rc; | ||
2450 | void __user *argp = (void __user *)arg; | ||
2451 | |||
2452 | pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg); | ||
2453 | |||
2454 | brdnr = iminor(fp->f_dentry->d_inode); | ||
2455 | if (brdnr >= STL_MAXBRDS) | ||
2456 | return -ENODEV; | ||
2457 | rc = 0; | ||
2458 | |||
2459 | switch (cmd) { | ||
2460 | case COM_GETPORTSTATS: | ||
2461 | rc = stl_getportstats(NULL, NULL, argp); | ||
2462 | break; | ||
2463 | case COM_CLRPORTSTATS: | ||
2464 | rc = stl_clrportstats(NULL, argp); | ||
2465 | break; | ||
2466 | case COM_GETBRDSTATS: | ||
2467 | rc = stl_getbrdstats(argp); | ||
2468 | break; | ||
2469 | case COM_READPORT: | ||
2470 | rc = stl_getportstruct(argp); | ||
2471 | break; | ||
2472 | case COM_READBOARD: | ||
2473 | rc = stl_getbrdstruct(argp); | ||
2474 | break; | ||
2475 | default: | ||
2476 | rc = -ENOIOCTLCMD; | ||
2477 | break; | ||
2478 | } | ||
2479 | return rc; | ||
2480 | } | ||
2481 | |||
2482 | static const struct tty_operations stl_ops = { | ||
2483 | .open = stl_open, | ||
2484 | .close = stl_close, | ||
2485 | .write = stl_write, | ||
2486 | .put_char = stl_putchar, | ||
2487 | .flush_chars = stl_flushchars, | ||
2488 | .write_room = stl_writeroom, | ||
2489 | .chars_in_buffer = stl_charsinbuffer, | ||
2490 | .ioctl = stl_ioctl, | ||
2491 | .set_termios = stl_settermios, | ||
2492 | .throttle = stl_throttle, | ||
2493 | .unthrottle = stl_unthrottle, | ||
2494 | .stop = stl_stop, | ||
2495 | .start = stl_start, | ||
2496 | .hangup = stl_hangup, | ||
2497 | .flush_buffer = stl_flushbuffer, | ||
2498 | .break_ctl = stl_breakctl, | ||
2499 | .wait_until_sent = stl_waituntilsent, | ||
2500 | .send_xchar = stl_sendxchar, | ||
2501 | .tiocmget = stl_tiocmget, | ||
2502 | .tiocmset = stl_tiocmset, | ||
2503 | .proc_fops = &stl_proc_fops, | ||
2504 | }; | ||
2505 | |||
2506 | static const struct tty_port_operations stl_port_ops = { | ||
2507 | .carrier_raised = stl_carrier_raised, | ||
2508 | .dtr_rts = stl_dtr_rts, | ||
2509 | .activate = stl_activate, | ||
2510 | .shutdown = stl_shutdown, | ||
2511 | }; | ||
2512 | |||
2513 | /*****************************************************************************/ | ||
2514 | /* CD1400 HARDWARE FUNCTIONS */ | ||
2515 | /*****************************************************************************/ | ||
2516 | |||
2517 | /* | ||
2518 | * These functions get/set/update the registers of the cd1400 UARTs. | ||
2519 | * Access to the cd1400 registers is via an address/data io port pair. | ||
2520 | * (Maybe should make this inline...) | ||
2521 | */ | ||
2522 | |||
2523 | static int stl_cd1400getreg(struct stlport *portp, int regnr) | ||
2524 | { | ||
2525 | outb((regnr + portp->uartaddr), portp->ioaddr); | ||
2526 | return inb(portp->ioaddr + EREG_DATA); | ||
2527 | } | ||
2528 | |||
2529 | static void stl_cd1400setreg(struct stlport *portp, int regnr, int value) | ||
2530 | { | ||
2531 | outb(regnr + portp->uartaddr, portp->ioaddr); | ||
2532 | outb(value, portp->ioaddr + EREG_DATA); | ||
2533 | } | ||
2534 | |||
2535 | static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value) | ||
2536 | { | ||
2537 | outb(regnr + portp->uartaddr, portp->ioaddr); | ||
2538 | if (inb(portp->ioaddr + EREG_DATA) != value) { | ||
2539 | outb(value, portp->ioaddr + EREG_DATA); | ||
2540 | return 1; | ||
2541 | } | ||
2542 | return 0; | ||
2543 | } | ||
2544 | |||
2545 | /*****************************************************************************/ | ||
2546 | |||
2547 | /* | ||
2548 | * Inbitialize the UARTs in a panel. We don't care what sort of board | ||
2549 | * these ports are on - since the port io registers are almost | ||
2550 | * identical when dealing with ports. | ||
2551 | */ | ||
2552 | |||
2553 | static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp) | ||
2554 | { | ||
2555 | unsigned int gfrcr; | ||
2556 | int chipmask, i, j; | ||
2557 | int nrchips, uartaddr, ioaddr; | ||
2558 | unsigned long flags; | ||
2559 | |||
2560 | pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); | ||
2561 | |||
2562 | spin_lock_irqsave(&brd_lock, flags); | ||
2563 | BRDENABLE(panelp->brdnr, panelp->pagenr); | ||
2564 | |||
2565 | /* | ||
2566 | * Check that each chip is present and started up OK. | ||
2567 | */ | ||
2568 | chipmask = 0; | ||
2569 | nrchips = panelp->nrports / CD1400_PORTS; | ||
2570 | for (i = 0; i < nrchips; i++) { | ||
2571 | if (brdp->brdtype == BRD_ECHPCI) { | ||
2572 | outb((panelp->pagenr + (i >> 1)), brdp->ioctrl); | ||
2573 | ioaddr = panelp->iobase; | ||
2574 | } else | ||
2575 | ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1)); | ||
2576 | uartaddr = (i & 0x01) ? 0x080 : 0; | ||
2577 | outb((GFRCR + uartaddr), ioaddr); | ||
2578 | outb(0, (ioaddr + EREG_DATA)); | ||
2579 | outb((CCR + uartaddr), ioaddr); | ||
2580 | outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); | ||
2581 | outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); | ||
2582 | outb((GFRCR + uartaddr), ioaddr); | ||
2583 | for (j = 0; j < CCR_MAXWAIT; j++) | ||
2584 | if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0) | ||
2585 | break; | ||
2586 | |||
2587 | if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) { | ||
2588 | printk("STALLION: cd1400 not responding, " | ||
2589 | "brd=%d panel=%d chip=%d\n", | ||
2590 | panelp->brdnr, panelp->panelnr, i); | ||
2591 | continue; | ||
2592 | } | ||
2593 | chipmask |= (0x1 << i); | ||
2594 | outb((PPR + uartaddr), ioaddr); | ||
2595 | outb(PPR_SCALAR, (ioaddr + EREG_DATA)); | ||
2596 | } | ||
2597 | |||
2598 | BRDDISABLE(panelp->brdnr); | ||
2599 | spin_unlock_irqrestore(&brd_lock, flags); | ||
2600 | return chipmask; | ||
2601 | } | ||
2602 | |||
2603 | /*****************************************************************************/ | ||
2604 | |||
2605 | /* | ||
2606 | * Initialize hardware specific port registers. | ||
2607 | */ | ||
2608 | |||
2609 | static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) | ||
2610 | { | ||
2611 | unsigned long flags; | ||
2612 | pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, | ||
2613 | panelp, portp); | ||
2614 | |||
2615 | if ((brdp == NULL) || (panelp == NULL) || | ||
2616 | (portp == NULL)) | ||
2617 | return; | ||
2618 | |||
2619 | spin_lock_irqsave(&brd_lock, flags); | ||
2620 | portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) || | ||
2621 | (portp->portnr < 8)) ? 0 : EREG_BANKSIZE); | ||
2622 | portp->uartaddr = (portp->portnr & 0x04) << 5; | ||
2623 | portp->pagenr = panelp->pagenr + (portp->portnr >> 3); | ||
2624 | |||
2625 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
2626 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
2627 | stl_cd1400setreg(portp, LIVR, (portp->portnr << 3)); | ||
2628 | portp->hwid = stl_cd1400getreg(portp, GFRCR); | ||
2629 | BRDDISABLE(portp->brdnr); | ||
2630 | spin_unlock_irqrestore(&brd_lock, flags); | ||
2631 | } | ||
2632 | |||
2633 | /*****************************************************************************/ | ||
2634 | |||
2635 | /* | ||
2636 | * Wait for the command register to be ready. We will poll this, | ||
2637 | * since it won't usually take too long to be ready. | ||
2638 | */ | ||
2639 | |||
2640 | static void stl_cd1400ccrwait(struct stlport *portp) | ||
2641 | { | ||
2642 | int i; | ||
2643 | |||
2644 | for (i = 0; i < CCR_MAXWAIT; i++) | ||
2645 | if (stl_cd1400getreg(portp, CCR) == 0) | ||
2646 | return; | ||
2647 | |||
2648 | printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n", | ||
2649 | portp->portnr, portp->panelnr, portp->brdnr); | ||
2650 | } | ||
2651 | |||
2652 | /*****************************************************************************/ | ||
2653 | |||
2654 | /* | ||
2655 | * Set up the cd1400 registers for a port based on the termios port | ||
2656 | * settings. | ||
2657 | */ | ||
2658 | |||
2659 | static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp) | ||
2660 | { | ||
2661 | struct stlbrd *brdp; | ||
2662 | unsigned long flags; | ||
2663 | unsigned int clkdiv, baudrate; | ||
2664 | unsigned char cor1, cor2, cor3; | ||
2665 | unsigned char cor4, cor5, ccr; | ||
2666 | unsigned char srer, sreron, sreroff; | ||
2667 | unsigned char mcor1, mcor2, rtpr; | ||
2668 | unsigned char clk, div; | ||
2669 | |||
2670 | cor1 = 0; | ||
2671 | cor2 = 0; | ||
2672 | cor3 = 0; | ||
2673 | cor4 = 0; | ||
2674 | cor5 = 0; | ||
2675 | ccr = 0; | ||
2676 | rtpr = 0; | ||
2677 | clk = 0; | ||
2678 | div = 0; | ||
2679 | mcor1 = 0; | ||
2680 | mcor2 = 0; | ||
2681 | sreron = 0; | ||
2682 | sreroff = 0; | ||
2683 | |||
2684 | brdp = stl_brds[portp->brdnr]; | ||
2685 | if (brdp == NULL) | ||
2686 | return; | ||
2687 | |||
2688 | /* | ||
2689 | * Set up the RX char ignore mask with those RX error types we | ||
2690 | * can ignore. We can get the cd1400 to help us out a little here, | ||
2691 | * it will ignore parity errors and breaks for us. | ||
2692 | */ | ||
2693 | portp->rxignoremsk = 0; | ||
2694 | if (tiosp->c_iflag & IGNPAR) { | ||
2695 | portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN); | ||
2696 | cor1 |= COR1_PARIGNORE; | ||
2697 | } | ||
2698 | if (tiosp->c_iflag & IGNBRK) { | ||
2699 | portp->rxignoremsk |= ST_BREAK; | ||
2700 | cor4 |= COR4_IGNBRK; | ||
2701 | } | ||
2702 | |||
2703 | portp->rxmarkmsk = ST_OVERRUN; | ||
2704 | if (tiosp->c_iflag & (INPCK | PARMRK)) | ||
2705 | portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING); | ||
2706 | if (tiosp->c_iflag & BRKINT) | ||
2707 | portp->rxmarkmsk |= ST_BREAK; | ||
2708 | |||
2709 | /* | ||
2710 | * Go through the char size, parity and stop bits and set all the | ||
2711 | * option register appropriately. | ||
2712 | */ | ||
2713 | switch (tiosp->c_cflag & CSIZE) { | ||
2714 | case CS5: | ||
2715 | cor1 |= COR1_CHL5; | ||
2716 | break; | ||
2717 | case CS6: | ||
2718 | cor1 |= COR1_CHL6; | ||
2719 | break; | ||
2720 | case CS7: | ||
2721 | cor1 |= COR1_CHL7; | ||
2722 | break; | ||
2723 | default: | ||
2724 | cor1 |= COR1_CHL8; | ||
2725 | break; | ||
2726 | } | ||
2727 | |||
2728 | if (tiosp->c_cflag & CSTOPB) | ||
2729 | cor1 |= COR1_STOP2; | ||
2730 | else | ||
2731 | cor1 |= COR1_STOP1; | ||
2732 | |||
2733 | if (tiosp->c_cflag & PARENB) { | ||
2734 | if (tiosp->c_cflag & PARODD) | ||
2735 | cor1 |= (COR1_PARENB | COR1_PARODD); | ||
2736 | else | ||
2737 | cor1 |= (COR1_PARENB | COR1_PAREVEN); | ||
2738 | } else { | ||
2739 | cor1 |= COR1_PARNONE; | ||
2740 | } | ||
2741 | |||
2742 | /* | ||
2743 | * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing | ||
2744 | * space for hardware flow control and the like. This should be set to | ||
2745 | * VMIN. Also here we will set the RX data timeout to 10ms - this should | ||
2746 | * really be based on VTIME. | ||
2747 | */ | ||
2748 | cor3 |= FIFO_RXTHRESHOLD; | ||
2749 | rtpr = 2; | ||
2750 | |||
2751 | /* | ||
2752 | * Calculate the baud rate timers. For now we will just assume that | ||
2753 | * the input and output baud are the same. Could have used a baud | ||
2754 | * table here, but this way we can generate virtually any baud rate | ||
2755 | * we like! | ||
2756 | */ | ||
2757 | baudrate = tiosp->c_cflag & CBAUD; | ||
2758 | if (baudrate & CBAUDEX) { | ||
2759 | baudrate &= ~CBAUDEX; | ||
2760 | if ((baudrate < 1) || (baudrate > 4)) | ||
2761 | tiosp->c_cflag &= ~CBAUDEX; | ||
2762 | else | ||
2763 | baudrate += 15; | ||
2764 | } | ||
2765 | baudrate = stl_baudrates[baudrate]; | ||
2766 | if ((tiosp->c_cflag & CBAUD) == B38400) { | ||
2767 | if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
2768 | baudrate = 57600; | ||
2769 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
2770 | baudrate = 115200; | ||
2771 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
2772 | baudrate = 230400; | ||
2773 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
2774 | baudrate = 460800; | ||
2775 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) | ||
2776 | baudrate = (portp->baud_base / portp->custom_divisor); | ||
2777 | } | ||
2778 | if (baudrate > STL_CD1400MAXBAUD) | ||
2779 | baudrate = STL_CD1400MAXBAUD; | ||
2780 | |||
2781 | if (baudrate > 0) { | ||
2782 | for (clk = 0; clk < CD1400_NUMCLKS; clk++) { | ||
2783 | clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate; | ||
2784 | if (clkdiv < 0x100) | ||
2785 | break; | ||
2786 | } | ||
2787 | div = (unsigned char) clkdiv; | ||
2788 | } | ||
2789 | |||
2790 | /* | ||
2791 | * Check what form of modem signaling is required and set it up. | ||
2792 | */ | ||
2793 | if ((tiosp->c_cflag & CLOCAL) == 0) { | ||
2794 | mcor1 |= MCOR1_DCD; | ||
2795 | mcor2 |= MCOR2_DCD; | ||
2796 | sreron |= SRER_MODEM; | ||
2797 | portp->port.flags |= ASYNC_CHECK_CD; | ||
2798 | } else | ||
2799 | portp->port.flags &= ~ASYNC_CHECK_CD; | ||
2800 | |||
2801 | /* | ||
2802 | * Setup cd1400 enhanced modes if we can. In particular we want to | ||
2803 | * handle as much of the flow control as possible automatically. As | ||
2804 | * well as saving a few CPU cycles it will also greatly improve flow | ||
2805 | * control reliability. | ||
2806 | */ | ||
2807 | if (tiosp->c_iflag & IXON) { | ||
2808 | cor2 |= COR2_TXIBE; | ||
2809 | cor3 |= COR3_SCD12; | ||
2810 | if (tiosp->c_iflag & IXANY) | ||
2811 | cor2 |= COR2_IXM; | ||
2812 | } | ||
2813 | |||
2814 | if (tiosp->c_cflag & CRTSCTS) { | ||
2815 | cor2 |= COR2_CTSAE; | ||
2816 | mcor1 |= FIFO_RTSTHRESHOLD; | ||
2817 | } | ||
2818 | |||
2819 | /* | ||
2820 | * All cd1400 register values calculated so go through and set | ||
2821 | * them all up. | ||
2822 | */ | ||
2823 | |||
2824 | pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", | ||
2825 | portp->portnr, portp->panelnr, portp->brdnr); | ||
2826 | pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", | ||
2827 | cor1, cor2, cor3, cor4, cor5); | ||
2828 | pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", | ||
2829 | mcor1, mcor2, rtpr, sreron, sreroff); | ||
2830 | pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); | ||
2831 | pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", | ||
2832 | tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], | ||
2833 | tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); | ||
2834 | |||
2835 | spin_lock_irqsave(&brd_lock, flags); | ||
2836 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
2837 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); | ||
2838 | srer = stl_cd1400getreg(portp, SRER); | ||
2839 | stl_cd1400setreg(portp, SRER, 0); | ||
2840 | if (stl_cd1400updatereg(portp, COR1, cor1)) | ||
2841 | ccr = 1; | ||
2842 | if (stl_cd1400updatereg(portp, COR2, cor2)) | ||
2843 | ccr = 1; | ||
2844 | if (stl_cd1400updatereg(portp, COR3, cor3)) | ||
2845 | ccr = 1; | ||
2846 | if (ccr) { | ||
2847 | stl_cd1400ccrwait(portp); | ||
2848 | stl_cd1400setreg(portp, CCR, CCR_CORCHANGE); | ||
2849 | } | ||
2850 | stl_cd1400setreg(portp, COR4, cor4); | ||
2851 | stl_cd1400setreg(portp, COR5, cor5); | ||
2852 | stl_cd1400setreg(portp, MCOR1, mcor1); | ||
2853 | stl_cd1400setreg(portp, MCOR2, mcor2); | ||
2854 | if (baudrate > 0) { | ||
2855 | stl_cd1400setreg(portp, TCOR, clk); | ||
2856 | stl_cd1400setreg(portp, TBPR, div); | ||
2857 | stl_cd1400setreg(portp, RCOR, clk); | ||
2858 | stl_cd1400setreg(portp, RBPR, div); | ||
2859 | } | ||
2860 | stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]); | ||
2861 | stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]); | ||
2862 | stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]); | ||
2863 | stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]); | ||
2864 | stl_cd1400setreg(portp, RTPR, rtpr); | ||
2865 | mcor1 = stl_cd1400getreg(portp, MSVR1); | ||
2866 | if (mcor1 & MSVR1_DCD) | ||
2867 | portp->sigs |= TIOCM_CD; | ||
2868 | else | ||
2869 | portp->sigs &= ~TIOCM_CD; | ||
2870 | stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron)); | ||
2871 | BRDDISABLE(portp->brdnr); | ||
2872 | spin_unlock_irqrestore(&brd_lock, flags); | ||
2873 | } | ||
2874 | |||
2875 | /*****************************************************************************/ | ||
2876 | |||
2877 | /* | ||
2878 | * Set the state of the DTR and RTS signals. | ||
2879 | */ | ||
2880 | |||
2881 | static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts) | ||
2882 | { | ||
2883 | unsigned char msvr1, msvr2; | ||
2884 | unsigned long flags; | ||
2885 | |||
2886 | pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n", | ||
2887 | portp, dtr, rts); | ||
2888 | |||
2889 | msvr1 = 0; | ||
2890 | msvr2 = 0; | ||
2891 | if (dtr > 0) | ||
2892 | msvr1 = MSVR1_DTR; | ||
2893 | if (rts > 0) | ||
2894 | msvr2 = MSVR2_RTS; | ||
2895 | |||
2896 | spin_lock_irqsave(&brd_lock, flags); | ||
2897 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
2898 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
2899 | if (rts >= 0) | ||
2900 | stl_cd1400setreg(portp, MSVR2, msvr2); | ||
2901 | if (dtr >= 0) | ||
2902 | stl_cd1400setreg(portp, MSVR1, msvr1); | ||
2903 | BRDDISABLE(portp->brdnr); | ||
2904 | spin_unlock_irqrestore(&brd_lock, flags); | ||
2905 | } | ||
2906 | |||
2907 | /*****************************************************************************/ | ||
2908 | |||
2909 | /* | ||
2910 | * Return the state of the signals. | ||
2911 | */ | ||
2912 | |||
2913 | static int stl_cd1400getsignals(struct stlport *portp) | ||
2914 | { | ||
2915 | unsigned char msvr1, msvr2; | ||
2916 | unsigned long flags; | ||
2917 | int sigs; | ||
2918 | |||
2919 | pr_debug("stl_cd1400getsignals(portp=%p)\n", portp); | ||
2920 | |||
2921 | spin_lock_irqsave(&brd_lock, flags); | ||
2922 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
2923 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
2924 | msvr1 = stl_cd1400getreg(portp, MSVR1); | ||
2925 | msvr2 = stl_cd1400getreg(portp, MSVR2); | ||
2926 | BRDDISABLE(portp->brdnr); | ||
2927 | spin_unlock_irqrestore(&brd_lock, flags); | ||
2928 | |||
2929 | sigs = 0; | ||
2930 | sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0; | ||
2931 | sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0; | ||
2932 | sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0; | ||
2933 | sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0; | ||
2934 | #if 0 | ||
2935 | sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0; | ||
2936 | sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0; | ||
2937 | #else | ||
2938 | sigs |= TIOCM_DSR; | ||
2939 | #endif | ||
2940 | return sigs; | ||
2941 | } | ||
2942 | |||
2943 | /*****************************************************************************/ | ||
2944 | |||
2945 | /* | ||
2946 | * Enable/Disable the Transmitter and/or Receiver. | ||
2947 | */ | ||
2948 | |||
2949 | static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx) | ||
2950 | { | ||
2951 | unsigned char ccr; | ||
2952 | unsigned long flags; | ||
2953 | |||
2954 | pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); | ||
2955 | |||
2956 | ccr = 0; | ||
2957 | |||
2958 | if (tx == 0) | ||
2959 | ccr |= CCR_TXDISABLE; | ||
2960 | else if (tx > 0) | ||
2961 | ccr |= CCR_TXENABLE; | ||
2962 | if (rx == 0) | ||
2963 | ccr |= CCR_RXDISABLE; | ||
2964 | else if (rx > 0) | ||
2965 | ccr |= CCR_RXENABLE; | ||
2966 | |||
2967 | spin_lock_irqsave(&brd_lock, flags); | ||
2968 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
2969 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
2970 | stl_cd1400ccrwait(portp); | ||
2971 | stl_cd1400setreg(portp, CCR, ccr); | ||
2972 | stl_cd1400ccrwait(portp); | ||
2973 | BRDDISABLE(portp->brdnr); | ||
2974 | spin_unlock_irqrestore(&brd_lock, flags); | ||
2975 | } | ||
2976 | |||
2977 | /*****************************************************************************/ | ||
2978 | |||
2979 | /* | ||
2980 | * Start/stop the Transmitter and/or Receiver. | ||
2981 | */ | ||
2982 | |||
2983 | static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx) | ||
2984 | { | ||
2985 | unsigned char sreron, sreroff; | ||
2986 | unsigned long flags; | ||
2987 | |||
2988 | pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); | ||
2989 | |||
2990 | sreron = 0; | ||
2991 | sreroff = 0; | ||
2992 | if (tx == 0) | ||
2993 | sreroff |= (SRER_TXDATA | SRER_TXEMPTY); | ||
2994 | else if (tx == 1) | ||
2995 | sreron |= SRER_TXDATA; | ||
2996 | else if (tx >= 2) | ||
2997 | sreron |= SRER_TXEMPTY; | ||
2998 | if (rx == 0) | ||
2999 | sreroff |= SRER_RXDATA; | ||
3000 | else if (rx > 0) | ||
3001 | sreron |= SRER_RXDATA; | ||
3002 | |||
3003 | spin_lock_irqsave(&brd_lock, flags); | ||
3004 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3005 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
3006 | stl_cd1400setreg(portp, SRER, | ||
3007 | ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron)); | ||
3008 | BRDDISABLE(portp->brdnr); | ||
3009 | if (tx > 0) | ||
3010 | set_bit(ASYI_TXBUSY, &portp->istate); | ||
3011 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3012 | } | ||
3013 | |||
3014 | /*****************************************************************************/ | ||
3015 | |||
3016 | /* | ||
3017 | * Disable all interrupts from this port. | ||
3018 | */ | ||
3019 | |||
3020 | static void stl_cd1400disableintrs(struct stlport *portp) | ||
3021 | { | ||
3022 | unsigned long flags; | ||
3023 | |||
3024 | pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp); | ||
3025 | |||
3026 | spin_lock_irqsave(&brd_lock, flags); | ||
3027 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3028 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
3029 | stl_cd1400setreg(portp, SRER, 0); | ||
3030 | BRDDISABLE(portp->brdnr); | ||
3031 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3032 | } | ||
3033 | |||
3034 | /*****************************************************************************/ | ||
3035 | |||
3036 | static void stl_cd1400sendbreak(struct stlport *portp, int len) | ||
3037 | { | ||
3038 | unsigned long flags; | ||
3039 | |||
3040 | pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len); | ||
3041 | |||
3042 | spin_lock_irqsave(&brd_lock, flags); | ||
3043 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3044 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
3045 | stl_cd1400setreg(portp, SRER, | ||
3046 | ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) | | ||
3047 | SRER_TXEMPTY)); | ||
3048 | BRDDISABLE(portp->brdnr); | ||
3049 | portp->brklen = len; | ||
3050 | if (len == 1) | ||
3051 | portp->stats.txbreaks++; | ||
3052 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3053 | } | ||
3054 | |||
3055 | /*****************************************************************************/ | ||
3056 | |||
3057 | /* | ||
3058 | * Take flow control actions... | ||
3059 | */ | ||
3060 | |||
3061 | static void stl_cd1400flowctrl(struct stlport *portp, int state) | ||
3062 | { | ||
3063 | struct tty_struct *tty; | ||
3064 | unsigned long flags; | ||
3065 | |||
3066 | pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state); | ||
3067 | |||
3068 | if (portp == NULL) | ||
3069 | return; | ||
3070 | tty = tty_port_tty_get(&portp->port); | ||
3071 | if (tty == NULL) | ||
3072 | return; | ||
3073 | |||
3074 | spin_lock_irqsave(&brd_lock, flags); | ||
3075 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3076 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
3077 | |||
3078 | if (state) { | ||
3079 | if (tty->termios->c_iflag & IXOFF) { | ||
3080 | stl_cd1400ccrwait(portp); | ||
3081 | stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); | ||
3082 | portp->stats.rxxon++; | ||
3083 | stl_cd1400ccrwait(portp); | ||
3084 | } | ||
3085 | /* | ||
3086 | * Question: should we return RTS to what it was before? It may | ||
3087 | * have been set by an ioctl... Suppose not, since if you have | ||
3088 | * hardware flow control set then it is pretty silly to go and | ||
3089 | * set the RTS line by hand. | ||
3090 | */ | ||
3091 | if (tty->termios->c_cflag & CRTSCTS) { | ||
3092 | stl_cd1400setreg(portp, MCOR1, | ||
3093 | (stl_cd1400getreg(portp, MCOR1) | | ||
3094 | FIFO_RTSTHRESHOLD)); | ||
3095 | stl_cd1400setreg(portp, MSVR2, MSVR2_RTS); | ||
3096 | portp->stats.rxrtson++; | ||
3097 | } | ||
3098 | } else { | ||
3099 | if (tty->termios->c_iflag & IXOFF) { | ||
3100 | stl_cd1400ccrwait(portp); | ||
3101 | stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); | ||
3102 | portp->stats.rxxoff++; | ||
3103 | stl_cd1400ccrwait(portp); | ||
3104 | } | ||
3105 | if (tty->termios->c_cflag & CRTSCTS) { | ||
3106 | stl_cd1400setreg(portp, MCOR1, | ||
3107 | (stl_cd1400getreg(portp, MCOR1) & 0xf0)); | ||
3108 | stl_cd1400setreg(portp, MSVR2, 0); | ||
3109 | portp->stats.rxrtsoff++; | ||
3110 | } | ||
3111 | } | ||
3112 | |||
3113 | BRDDISABLE(portp->brdnr); | ||
3114 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3115 | tty_kref_put(tty); | ||
3116 | } | ||
3117 | |||
3118 | /*****************************************************************************/ | ||
3119 | |||
3120 | /* | ||
3121 | * Send a flow control character... | ||
3122 | */ | ||
3123 | |||
3124 | static void stl_cd1400sendflow(struct stlport *portp, int state) | ||
3125 | { | ||
3126 | struct tty_struct *tty; | ||
3127 | unsigned long flags; | ||
3128 | |||
3129 | pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state); | ||
3130 | |||
3131 | if (portp == NULL) | ||
3132 | return; | ||
3133 | tty = tty_port_tty_get(&portp->port); | ||
3134 | if (tty == NULL) | ||
3135 | return; | ||
3136 | |||
3137 | spin_lock_irqsave(&brd_lock, flags); | ||
3138 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3139 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
3140 | if (state) { | ||
3141 | stl_cd1400ccrwait(portp); | ||
3142 | stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); | ||
3143 | portp->stats.rxxon++; | ||
3144 | stl_cd1400ccrwait(portp); | ||
3145 | } else { | ||
3146 | stl_cd1400ccrwait(portp); | ||
3147 | stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); | ||
3148 | portp->stats.rxxoff++; | ||
3149 | stl_cd1400ccrwait(portp); | ||
3150 | } | ||
3151 | BRDDISABLE(portp->brdnr); | ||
3152 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3153 | tty_kref_put(tty); | ||
3154 | } | ||
3155 | |||
3156 | /*****************************************************************************/ | ||
3157 | |||
3158 | static void stl_cd1400flush(struct stlport *portp) | ||
3159 | { | ||
3160 | unsigned long flags; | ||
3161 | |||
3162 | pr_debug("stl_cd1400flush(portp=%p)\n", portp); | ||
3163 | |||
3164 | if (portp == NULL) | ||
3165 | return; | ||
3166 | |||
3167 | spin_lock_irqsave(&brd_lock, flags); | ||
3168 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3169 | stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); | ||
3170 | stl_cd1400ccrwait(portp); | ||
3171 | stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO); | ||
3172 | stl_cd1400ccrwait(portp); | ||
3173 | portp->tx.tail = portp->tx.head; | ||
3174 | BRDDISABLE(portp->brdnr); | ||
3175 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3176 | } | ||
3177 | |||
3178 | /*****************************************************************************/ | ||
3179 | |||
3180 | /* | ||
3181 | * Return the current state of data flow on this port. This is only | ||
3182 | * really interesting when determining if data has fully completed | ||
3183 | * transmission or not... This is easy for the cd1400, it accurately | ||
3184 | * maintains the busy port flag. | ||
3185 | */ | ||
3186 | |||
3187 | static int stl_cd1400datastate(struct stlport *portp) | ||
3188 | { | ||
3189 | pr_debug("stl_cd1400datastate(portp=%p)\n", portp); | ||
3190 | |||
3191 | if (portp == NULL) | ||
3192 | return 0; | ||
3193 | |||
3194 | return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0; | ||
3195 | } | ||
3196 | |||
3197 | /*****************************************************************************/ | ||
3198 | |||
3199 | /* | ||
3200 | * Interrupt service routine for cd1400 EasyIO boards. | ||
3201 | */ | ||
3202 | |||
3203 | static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase) | ||
3204 | { | ||
3205 | unsigned char svrtype; | ||
3206 | |||
3207 | pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase); | ||
3208 | |||
3209 | spin_lock(&brd_lock); | ||
3210 | outb(SVRR, iobase); | ||
3211 | svrtype = inb(iobase + EREG_DATA); | ||
3212 | if (panelp->nrports > 4) { | ||
3213 | outb((SVRR + 0x80), iobase); | ||
3214 | svrtype |= inb(iobase + EREG_DATA); | ||
3215 | } | ||
3216 | |||
3217 | if (svrtype & SVRR_RX) | ||
3218 | stl_cd1400rxisr(panelp, iobase); | ||
3219 | else if (svrtype & SVRR_TX) | ||
3220 | stl_cd1400txisr(panelp, iobase); | ||
3221 | else if (svrtype & SVRR_MDM) | ||
3222 | stl_cd1400mdmisr(panelp, iobase); | ||
3223 | |||
3224 | spin_unlock(&brd_lock); | ||
3225 | } | ||
3226 | |||
3227 | /*****************************************************************************/ | ||
3228 | |||
3229 | /* | ||
3230 | * Interrupt service routine for cd1400 panels. | ||
3231 | */ | ||
3232 | |||
3233 | static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase) | ||
3234 | { | ||
3235 | unsigned char svrtype; | ||
3236 | |||
3237 | pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase); | ||
3238 | |||
3239 | outb(SVRR, iobase); | ||
3240 | svrtype = inb(iobase + EREG_DATA); | ||
3241 | outb((SVRR + 0x80), iobase); | ||
3242 | svrtype |= inb(iobase + EREG_DATA); | ||
3243 | if (svrtype & SVRR_RX) | ||
3244 | stl_cd1400rxisr(panelp, iobase); | ||
3245 | else if (svrtype & SVRR_TX) | ||
3246 | stl_cd1400txisr(panelp, iobase); | ||
3247 | else if (svrtype & SVRR_MDM) | ||
3248 | stl_cd1400mdmisr(panelp, iobase); | ||
3249 | } | ||
3250 | |||
3251 | |||
3252 | /*****************************************************************************/ | ||
3253 | |||
3254 | /* | ||
3255 | * Unfortunately we need to handle breaks in the TX data stream, since | ||
3256 | * this is the only way to generate them on the cd1400. | ||
3257 | */ | ||
3258 | |||
3259 | static int stl_cd1400breakisr(struct stlport *portp, int ioaddr) | ||
3260 | { | ||
3261 | if (portp->brklen == 1) { | ||
3262 | outb((COR2 + portp->uartaddr), ioaddr); | ||
3263 | outb((inb(ioaddr + EREG_DATA) | COR2_ETC), | ||
3264 | (ioaddr + EREG_DATA)); | ||
3265 | outb((TDR + portp->uartaddr), ioaddr); | ||
3266 | outb(ETC_CMD, (ioaddr + EREG_DATA)); | ||
3267 | outb(ETC_STARTBREAK, (ioaddr + EREG_DATA)); | ||
3268 | outb((SRER + portp->uartaddr), ioaddr); | ||
3269 | outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)), | ||
3270 | (ioaddr + EREG_DATA)); | ||
3271 | return 1; | ||
3272 | } else if (portp->brklen > 1) { | ||
3273 | outb((TDR + portp->uartaddr), ioaddr); | ||
3274 | outb(ETC_CMD, (ioaddr + EREG_DATA)); | ||
3275 | outb(ETC_STOPBREAK, (ioaddr + EREG_DATA)); | ||
3276 | portp->brklen = -1; | ||
3277 | return 1; | ||
3278 | } else { | ||
3279 | outb((COR2 + portp->uartaddr), ioaddr); | ||
3280 | outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC), | ||
3281 | (ioaddr + EREG_DATA)); | ||
3282 | portp->brklen = 0; | ||
3283 | } | ||
3284 | return 0; | ||
3285 | } | ||
3286 | |||
3287 | /*****************************************************************************/ | ||
3288 | |||
3289 | /* | ||
3290 | * Transmit interrupt handler. This has gotta be fast! Handling TX | ||
3291 | * chars is pretty simple, stuff as many as possible from the TX buffer | ||
3292 | * into the cd1400 FIFO. Must also handle TX breaks here, since they | ||
3293 | * are embedded as commands in the data stream. Oh no, had to use a goto! | ||
3294 | * This could be optimized more, will do when I get time... | ||
3295 | * In practice it is possible that interrupts are enabled but that the | ||
3296 | * port has been hung up. Need to handle not having any TX buffer here, | ||
3297 | * this is done by using the side effect that head and tail will also | ||
3298 | * be NULL if the buffer has been freed. | ||
3299 | */ | ||
3300 | |||
3301 | static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) | ||
3302 | { | ||
3303 | struct stlport *portp; | ||
3304 | int len, stlen; | ||
3305 | char *head, *tail; | ||
3306 | unsigned char ioack, srer; | ||
3307 | struct tty_struct *tty; | ||
3308 | |||
3309 | pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); | ||
3310 | |||
3311 | ioack = inb(ioaddr + EREG_TXACK); | ||
3312 | if (((ioack & panelp->ackmask) != 0) || | ||
3313 | ((ioack & ACK_TYPMASK) != ACK_TYPTX)) { | ||
3314 | printk("STALLION: bad TX interrupt ack value=%x\n", ioack); | ||
3315 | return; | ||
3316 | } | ||
3317 | portp = panelp->ports[(ioack >> 3)]; | ||
3318 | |||
3319 | /* | ||
3320 | * Unfortunately we need to handle breaks in the data stream, since | ||
3321 | * this is the only way to generate them on the cd1400. Do it now if | ||
3322 | * a break is to be sent. | ||
3323 | */ | ||
3324 | if (portp->brklen != 0) | ||
3325 | if (stl_cd1400breakisr(portp, ioaddr)) | ||
3326 | goto stl_txalldone; | ||
3327 | |||
3328 | head = portp->tx.head; | ||
3329 | tail = portp->tx.tail; | ||
3330 | len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); | ||
3331 | if ((len == 0) || ((len < STL_TXBUFLOW) && | ||
3332 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { | ||
3333 | set_bit(ASYI_TXLOW, &portp->istate); | ||
3334 | tty = tty_port_tty_get(&portp->port); | ||
3335 | if (tty) { | ||
3336 | tty_wakeup(tty); | ||
3337 | tty_kref_put(tty); | ||
3338 | } | ||
3339 | } | ||
3340 | |||
3341 | if (len == 0) { | ||
3342 | outb((SRER + portp->uartaddr), ioaddr); | ||
3343 | srer = inb(ioaddr + EREG_DATA); | ||
3344 | if (srer & SRER_TXDATA) { | ||
3345 | srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY; | ||
3346 | } else { | ||
3347 | srer &= ~(SRER_TXDATA | SRER_TXEMPTY); | ||
3348 | clear_bit(ASYI_TXBUSY, &portp->istate); | ||
3349 | } | ||
3350 | outb(srer, (ioaddr + EREG_DATA)); | ||
3351 | } else { | ||
3352 | len = min(len, CD1400_TXFIFOSIZE); | ||
3353 | portp->stats.txtotal += len; | ||
3354 | stlen = min_t(unsigned int, len, | ||
3355 | (portp->tx.buf + STL_TXBUFSIZE) - tail); | ||
3356 | outb((TDR + portp->uartaddr), ioaddr); | ||
3357 | outsb((ioaddr + EREG_DATA), tail, stlen); | ||
3358 | len -= stlen; | ||
3359 | tail += stlen; | ||
3360 | if (tail >= (portp->tx.buf + STL_TXBUFSIZE)) | ||
3361 | tail = portp->tx.buf; | ||
3362 | if (len > 0) { | ||
3363 | outsb((ioaddr + EREG_DATA), tail, len); | ||
3364 | tail += len; | ||
3365 | } | ||
3366 | portp->tx.tail = tail; | ||
3367 | } | ||
3368 | |||
3369 | stl_txalldone: | ||
3370 | outb((EOSRR + portp->uartaddr), ioaddr); | ||
3371 | outb(0, (ioaddr + EREG_DATA)); | ||
3372 | } | ||
3373 | |||
3374 | /*****************************************************************************/ | ||
3375 | |||
3376 | /* | ||
3377 | * Receive character interrupt handler. Determine if we have good chars | ||
3378 | * or bad chars and then process appropriately. Good chars are easy | ||
3379 | * just shove the lot into the RX buffer and set all status byte to 0. | ||
3380 | * If a bad RX char then process as required. This routine needs to be | ||
3381 | * fast! In practice it is possible that we get an interrupt on a port | ||
3382 | * that is closed. This can happen on hangups - since they completely | ||
3383 | * shutdown a port not in user context. Need to handle this case. | ||
3384 | */ | ||
3385 | |||
3386 | static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr) | ||
3387 | { | ||
3388 | struct stlport *portp; | ||
3389 | struct tty_struct *tty; | ||
3390 | unsigned int ioack, len, buflen; | ||
3391 | unsigned char status; | ||
3392 | char ch; | ||
3393 | |||
3394 | pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); | ||
3395 | |||
3396 | ioack = inb(ioaddr + EREG_RXACK); | ||
3397 | if ((ioack & panelp->ackmask) != 0) { | ||
3398 | printk("STALLION: bad RX interrupt ack value=%x\n", ioack); | ||
3399 | return; | ||
3400 | } | ||
3401 | portp = panelp->ports[(ioack >> 3)]; | ||
3402 | tty = tty_port_tty_get(&portp->port); | ||
3403 | |||
3404 | if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) { | ||
3405 | outb((RDCR + portp->uartaddr), ioaddr); | ||
3406 | len = inb(ioaddr + EREG_DATA); | ||
3407 | if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { | ||
3408 | len = min_t(unsigned int, len, sizeof(stl_unwanted)); | ||
3409 | outb((RDSR + portp->uartaddr), ioaddr); | ||
3410 | insb((ioaddr + EREG_DATA), &stl_unwanted[0], len); | ||
3411 | portp->stats.rxlost += len; | ||
3412 | portp->stats.rxtotal += len; | ||
3413 | } else { | ||
3414 | len = min(len, buflen); | ||
3415 | if (len > 0) { | ||
3416 | unsigned char *ptr; | ||
3417 | outb((RDSR + portp->uartaddr), ioaddr); | ||
3418 | tty_prepare_flip_string(tty, &ptr, len); | ||
3419 | insb((ioaddr + EREG_DATA), ptr, len); | ||
3420 | tty_schedule_flip(tty); | ||
3421 | portp->stats.rxtotal += len; | ||
3422 | } | ||
3423 | } | ||
3424 | } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) { | ||
3425 | outb((RDSR + portp->uartaddr), ioaddr); | ||
3426 | status = inb(ioaddr + EREG_DATA); | ||
3427 | ch = inb(ioaddr + EREG_DATA); | ||
3428 | if (status & ST_PARITY) | ||
3429 | portp->stats.rxparity++; | ||
3430 | if (status & ST_FRAMING) | ||
3431 | portp->stats.rxframing++; | ||
3432 | if (status & ST_OVERRUN) | ||
3433 | portp->stats.rxoverrun++; | ||
3434 | if (status & ST_BREAK) | ||
3435 | portp->stats.rxbreaks++; | ||
3436 | if (status & ST_SCHARMASK) { | ||
3437 | if ((status & ST_SCHARMASK) == ST_SCHAR1) | ||
3438 | portp->stats.txxon++; | ||
3439 | if ((status & ST_SCHARMASK) == ST_SCHAR2) | ||
3440 | portp->stats.txxoff++; | ||
3441 | goto stl_rxalldone; | ||
3442 | } | ||
3443 | if (tty != NULL && (portp->rxignoremsk & status) == 0) { | ||
3444 | if (portp->rxmarkmsk & status) { | ||
3445 | if (status & ST_BREAK) { | ||
3446 | status = TTY_BREAK; | ||
3447 | if (portp->port.flags & ASYNC_SAK) { | ||
3448 | do_SAK(tty); | ||
3449 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3450 | } | ||
3451 | } else if (status & ST_PARITY) | ||
3452 | status = TTY_PARITY; | ||
3453 | else if (status & ST_FRAMING) | ||
3454 | status = TTY_FRAME; | ||
3455 | else if(status & ST_OVERRUN) | ||
3456 | status = TTY_OVERRUN; | ||
3457 | else | ||
3458 | status = 0; | ||
3459 | } else | ||
3460 | status = 0; | ||
3461 | tty_insert_flip_char(tty, ch, status); | ||
3462 | tty_schedule_flip(tty); | ||
3463 | } | ||
3464 | } else { | ||
3465 | printk("STALLION: bad RX interrupt ack value=%x\n", ioack); | ||
3466 | tty_kref_put(tty); | ||
3467 | return; | ||
3468 | } | ||
3469 | |||
3470 | stl_rxalldone: | ||
3471 | tty_kref_put(tty); | ||
3472 | outb((EOSRR + portp->uartaddr), ioaddr); | ||
3473 | outb(0, (ioaddr + EREG_DATA)); | ||
3474 | } | ||
3475 | |||
3476 | /*****************************************************************************/ | ||
3477 | |||
3478 | /* | ||
3479 | * Modem interrupt handler. The is called when the modem signal line | ||
3480 | * (DCD) has changed state. Leave most of the work to the off-level | ||
3481 | * processing routine. | ||
3482 | */ | ||
3483 | |||
3484 | static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr) | ||
3485 | { | ||
3486 | struct stlport *portp; | ||
3487 | unsigned int ioack; | ||
3488 | unsigned char misr; | ||
3489 | |||
3490 | pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp); | ||
3491 | |||
3492 | ioack = inb(ioaddr + EREG_MDACK); | ||
3493 | if (((ioack & panelp->ackmask) != 0) || | ||
3494 | ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) { | ||
3495 | printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack); | ||
3496 | return; | ||
3497 | } | ||
3498 | portp = panelp->ports[(ioack >> 3)]; | ||
3499 | |||
3500 | outb((MISR + portp->uartaddr), ioaddr); | ||
3501 | misr = inb(ioaddr + EREG_DATA); | ||
3502 | if (misr & MISR_DCD) { | ||
3503 | stl_cd_change(portp); | ||
3504 | portp->stats.modem++; | ||
3505 | } | ||
3506 | |||
3507 | outb((EOSRR + portp->uartaddr), ioaddr); | ||
3508 | outb(0, (ioaddr + EREG_DATA)); | ||
3509 | } | ||
3510 | |||
3511 | /*****************************************************************************/ | ||
3512 | /* SC26198 HARDWARE FUNCTIONS */ | ||
3513 | /*****************************************************************************/ | ||
3514 | |||
3515 | /* | ||
3516 | * These functions get/set/update the registers of the sc26198 UARTs. | ||
3517 | * Access to the sc26198 registers is via an address/data io port pair. | ||
3518 | * (Maybe should make this inline...) | ||
3519 | */ | ||
3520 | |||
3521 | static int stl_sc26198getreg(struct stlport *portp, int regnr) | ||
3522 | { | ||
3523 | outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); | ||
3524 | return inb(portp->ioaddr + XP_DATA); | ||
3525 | } | ||
3526 | |||
3527 | static void stl_sc26198setreg(struct stlport *portp, int regnr, int value) | ||
3528 | { | ||
3529 | outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); | ||
3530 | outb(value, (portp->ioaddr + XP_DATA)); | ||
3531 | } | ||
3532 | |||
3533 | static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value) | ||
3534 | { | ||
3535 | outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); | ||
3536 | if (inb(portp->ioaddr + XP_DATA) != value) { | ||
3537 | outb(value, (portp->ioaddr + XP_DATA)); | ||
3538 | return 1; | ||
3539 | } | ||
3540 | return 0; | ||
3541 | } | ||
3542 | |||
3543 | /*****************************************************************************/ | ||
3544 | |||
3545 | /* | ||
3546 | * Functions to get and set the sc26198 global registers. | ||
3547 | */ | ||
3548 | |||
3549 | static int stl_sc26198getglobreg(struct stlport *portp, int regnr) | ||
3550 | { | ||
3551 | outb(regnr, (portp->ioaddr + XP_ADDR)); | ||
3552 | return inb(portp->ioaddr + XP_DATA); | ||
3553 | } | ||
3554 | |||
3555 | #if 0 | ||
3556 | static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value) | ||
3557 | { | ||
3558 | outb(regnr, (portp->ioaddr + XP_ADDR)); | ||
3559 | outb(value, (portp->ioaddr + XP_DATA)); | ||
3560 | } | ||
3561 | #endif | ||
3562 | |||
3563 | /*****************************************************************************/ | ||
3564 | |||
3565 | /* | ||
3566 | * Inbitialize the UARTs in a panel. We don't care what sort of board | ||
3567 | * these ports are on - since the port io registers are almost | ||
3568 | * identical when dealing with ports. | ||
3569 | */ | ||
3570 | |||
3571 | static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp) | ||
3572 | { | ||
3573 | int chipmask, i; | ||
3574 | int nrchips, ioaddr; | ||
3575 | |||
3576 | pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); | ||
3577 | |||
3578 | BRDENABLE(panelp->brdnr, panelp->pagenr); | ||
3579 | |||
3580 | /* | ||
3581 | * Check that each chip is present and started up OK. | ||
3582 | */ | ||
3583 | chipmask = 0; | ||
3584 | nrchips = (panelp->nrports + 4) / SC26198_PORTS; | ||
3585 | if (brdp->brdtype == BRD_ECHPCI) | ||
3586 | outb(panelp->pagenr, brdp->ioctrl); | ||
3587 | |||
3588 | for (i = 0; i < nrchips; i++) { | ||
3589 | ioaddr = panelp->iobase + (i * 4); | ||
3590 | outb(SCCR, (ioaddr + XP_ADDR)); | ||
3591 | outb(CR_RESETALL, (ioaddr + XP_DATA)); | ||
3592 | outb(TSTR, (ioaddr + XP_ADDR)); | ||
3593 | if (inb(ioaddr + XP_DATA) != 0) { | ||
3594 | printk("STALLION: sc26198 not responding, " | ||
3595 | "brd=%d panel=%d chip=%d\n", | ||
3596 | panelp->brdnr, panelp->panelnr, i); | ||
3597 | continue; | ||
3598 | } | ||
3599 | chipmask |= (0x1 << i); | ||
3600 | outb(GCCR, (ioaddr + XP_ADDR)); | ||
3601 | outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA)); | ||
3602 | outb(WDTRCR, (ioaddr + XP_ADDR)); | ||
3603 | outb(0xff, (ioaddr + XP_DATA)); | ||
3604 | } | ||
3605 | |||
3606 | BRDDISABLE(panelp->brdnr); | ||
3607 | return chipmask; | ||
3608 | } | ||
3609 | |||
3610 | /*****************************************************************************/ | ||
3611 | |||
3612 | /* | ||
3613 | * Initialize hardware specific port registers. | ||
3614 | */ | ||
3615 | |||
3616 | static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) | ||
3617 | { | ||
3618 | pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, | ||
3619 | panelp, portp); | ||
3620 | |||
3621 | if ((brdp == NULL) || (panelp == NULL) || | ||
3622 | (portp == NULL)) | ||
3623 | return; | ||
3624 | |||
3625 | portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4); | ||
3626 | portp->uartaddr = (portp->portnr & 0x07) << 4; | ||
3627 | portp->pagenr = panelp->pagenr; | ||
3628 | portp->hwid = 0x1; | ||
3629 | |||
3630 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3631 | stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS); | ||
3632 | BRDDISABLE(portp->brdnr); | ||
3633 | } | ||
3634 | |||
3635 | /*****************************************************************************/ | ||
3636 | |||
3637 | /* | ||
3638 | * Set up the sc26198 registers for a port based on the termios port | ||
3639 | * settings. | ||
3640 | */ | ||
3641 | |||
3642 | static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp) | ||
3643 | { | ||
3644 | struct stlbrd *brdp; | ||
3645 | unsigned long flags; | ||
3646 | unsigned int baudrate; | ||
3647 | unsigned char mr0, mr1, mr2, clk; | ||
3648 | unsigned char imron, imroff, iopr, ipr; | ||
3649 | |||
3650 | mr0 = 0; | ||
3651 | mr1 = 0; | ||
3652 | mr2 = 0; | ||
3653 | clk = 0; | ||
3654 | iopr = 0; | ||
3655 | imron = 0; | ||
3656 | imroff = 0; | ||
3657 | |||
3658 | brdp = stl_brds[portp->brdnr]; | ||
3659 | if (brdp == NULL) | ||
3660 | return; | ||
3661 | |||
3662 | /* | ||
3663 | * Set up the RX char ignore mask with those RX error types we | ||
3664 | * can ignore. | ||
3665 | */ | ||
3666 | portp->rxignoremsk = 0; | ||
3667 | if (tiosp->c_iflag & IGNPAR) | ||
3668 | portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING | | ||
3669 | SR_RXOVERRUN); | ||
3670 | if (tiosp->c_iflag & IGNBRK) | ||
3671 | portp->rxignoremsk |= SR_RXBREAK; | ||
3672 | |||
3673 | portp->rxmarkmsk = SR_RXOVERRUN; | ||
3674 | if (tiosp->c_iflag & (INPCK | PARMRK)) | ||
3675 | portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING); | ||
3676 | if (tiosp->c_iflag & BRKINT) | ||
3677 | portp->rxmarkmsk |= SR_RXBREAK; | ||
3678 | |||
3679 | /* | ||
3680 | * Go through the char size, parity and stop bits and set all the | ||
3681 | * option register appropriately. | ||
3682 | */ | ||
3683 | switch (tiosp->c_cflag & CSIZE) { | ||
3684 | case CS5: | ||
3685 | mr1 |= MR1_CS5; | ||
3686 | break; | ||
3687 | case CS6: | ||
3688 | mr1 |= MR1_CS6; | ||
3689 | break; | ||
3690 | case CS7: | ||
3691 | mr1 |= MR1_CS7; | ||
3692 | break; | ||
3693 | default: | ||
3694 | mr1 |= MR1_CS8; | ||
3695 | break; | ||
3696 | } | ||
3697 | |||
3698 | if (tiosp->c_cflag & CSTOPB) | ||
3699 | mr2 |= MR2_STOP2; | ||
3700 | else | ||
3701 | mr2 |= MR2_STOP1; | ||
3702 | |||
3703 | if (tiosp->c_cflag & PARENB) { | ||
3704 | if (tiosp->c_cflag & PARODD) | ||
3705 | mr1 |= (MR1_PARENB | MR1_PARODD); | ||
3706 | else | ||
3707 | mr1 |= (MR1_PARENB | MR1_PAREVEN); | ||
3708 | } else | ||
3709 | mr1 |= MR1_PARNONE; | ||
3710 | |||
3711 | mr1 |= MR1_ERRBLOCK; | ||
3712 | |||
3713 | /* | ||
3714 | * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing | ||
3715 | * space for hardware flow control and the like. This should be set to | ||
3716 | * VMIN. | ||
3717 | */ | ||
3718 | mr2 |= MR2_RXFIFOHALF; | ||
3719 | |||
3720 | /* | ||
3721 | * Calculate the baud rate timers. For now we will just assume that | ||
3722 | * the input and output baud are the same. The sc26198 has a fixed | ||
3723 | * baud rate table, so only discrete baud rates possible. | ||
3724 | */ | ||
3725 | baudrate = tiosp->c_cflag & CBAUD; | ||
3726 | if (baudrate & CBAUDEX) { | ||
3727 | baudrate &= ~CBAUDEX; | ||
3728 | if ((baudrate < 1) || (baudrate > 4)) | ||
3729 | tiosp->c_cflag &= ~CBAUDEX; | ||
3730 | else | ||
3731 | baudrate += 15; | ||
3732 | } | ||
3733 | baudrate = stl_baudrates[baudrate]; | ||
3734 | if ((tiosp->c_cflag & CBAUD) == B38400) { | ||
3735 | if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
3736 | baudrate = 57600; | ||
3737 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
3738 | baudrate = 115200; | ||
3739 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
3740 | baudrate = 230400; | ||
3741 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
3742 | baudrate = 460800; | ||
3743 | else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) | ||
3744 | baudrate = (portp->baud_base / portp->custom_divisor); | ||
3745 | } | ||
3746 | if (baudrate > STL_SC26198MAXBAUD) | ||
3747 | baudrate = STL_SC26198MAXBAUD; | ||
3748 | |||
3749 | if (baudrate > 0) | ||
3750 | for (clk = 0; clk < SC26198_NRBAUDS; clk++) | ||
3751 | if (baudrate <= sc26198_baudtable[clk]) | ||
3752 | break; | ||
3753 | |||
3754 | /* | ||
3755 | * Check what form of modem signaling is required and set it up. | ||
3756 | */ | ||
3757 | if (tiosp->c_cflag & CLOCAL) { | ||
3758 | portp->port.flags &= ~ASYNC_CHECK_CD; | ||
3759 | } else { | ||
3760 | iopr |= IOPR_DCDCOS; | ||
3761 | imron |= IR_IOPORT; | ||
3762 | portp->port.flags |= ASYNC_CHECK_CD; | ||
3763 | } | ||
3764 | |||
3765 | /* | ||
3766 | * Setup sc26198 enhanced modes if we can. In particular we want to | ||
3767 | * handle as much of the flow control as possible automatically. As | ||
3768 | * well as saving a few CPU cycles it will also greatly improve flow | ||
3769 | * control reliability. | ||
3770 | */ | ||
3771 | if (tiosp->c_iflag & IXON) { | ||
3772 | mr0 |= MR0_SWFTX | MR0_SWFT; | ||
3773 | imron |= IR_XONXOFF; | ||
3774 | } else | ||
3775 | imroff |= IR_XONXOFF; | ||
3776 | |||
3777 | if (tiosp->c_iflag & IXOFF) | ||
3778 | mr0 |= MR0_SWFRX; | ||
3779 | |||
3780 | if (tiosp->c_cflag & CRTSCTS) { | ||
3781 | mr2 |= MR2_AUTOCTS; | ||
3782 | mr1 |= MR1_AUTORTS; | ||
3783 | } | ||
3784 | |||
3785 | /* | ||
3786 | * All sc26198 register values calculated so go through and set | ||
3787 | * them all up. | ||
3788 | */ | ||
3789 | |||
3790 | pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", | ||
3791 | portp->portnr, portp->panelnr, portp->brdnr); | ||
3792 | pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); | ||
3793 | pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); | ||
3794 | pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", | ||
3795 | tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], | ||
3796 | tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); | ||
3797 | |||
3798 | spin_lock_irqsave(&brd_lock, flags); | ||
3799 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3800 | stl_sc26198setreg(portp, IMR, 0); | ||
3801 | stl_sc26198updatereg(portp, MR0, mr0); | ||
3802 | stl_sc26198updatereg(portp, MR1, mr1); | ||
3803 | stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK); | ||
3804 | stl_sc26198updatereg(portp, MR2, mr2); | ||
3805 | stl_sc26198updatereg(portp, IOPIOR, | ||
3806 | ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr)); | ||
3807 | |||
3808 | if (baudrate > 0) { | ||
3809 | stl_sc26198setreg(portp, TXCSR, clk); | ||
3810 | stl_sc26198setreg(portp, RXCSR, clk); | ||
3811 | } | ||
3812 | |||
3813 | stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]); | ||
3814 | stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]); | ||
3815 | |||
3816 | ipr = stl_sc26198getreg(portp, IPR); | ||
3817 | if (ipr & IPR_DCD) | ||
3818 | portp->sigs &= ~TIOCM_CD; | ||
3819 | else | ||
3820 | portp->sigs |= TIOCM_CD; | ||
3821 | |||
3822 | portp->imr = (portp->imr & ~imroff) | imron; | ||
3823 | stl_sc26198setreg(portp, IMR, portp->imr); | ||
3824 | BRDDISABLE(portp->brdnr); | ||
3825 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3826 | } | ||
3827 | |||
3828 | /*****************************************************************************/ | ||
3829 | |||
3830 | /* | ||
3831 | * Set the state of the DTR and RTS signals. | ||
3832 | */ | ||
3833 | |||
3834 | static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts) | ||
3835 | { | ||
3836 | unsigned char iopioron, iopioroff; | ||
3837 | unsigned long flags; | ||
3838 | |||
3839 | pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp, | ||
3840 | dtr, rts); | ||
3841 | |||
3842 | iopioron = 0; | ||
3843 | iopioroff = 0; | ||
3844 | if (dtr == 0) | ||
3845 | iopioroff |= IPR_DTR; | ||
3846 | else if (dtr > 0) | ||
3847 | iopioron |= IPR_DTR; | ||
3848 | if (rts == 0) | ||
3849 | iopioroff |= IPR_RTS; | ||
3850 | else if (rts > 0) | ||
3851 | iopioron |= IPR_RTS; | ||
3852 | |||
3853 | spin_lock_irqsave(&brd_lock, flags); | ||
3854 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3855 | stl_sc26198setreg(portp, IOPIOR, | ||
3856 | ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron)); | ||
3857 | BRDDISABLE(portp->brdnr); | ||
3858 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3859 | } | ||
3860 | |||
3861 | /*****************************************************************************/ | ||
3862 | |||
3863 | /* | ||
3864 | * Return the state of the signals. | ||
3865 | */ | ||
3866 | |||
3867 | static int stl_sc26198getsignals(struct stlport *portp) | ||
3868 | { | ||
3869 | unsigned char ipr; | ||
3870 | unsigned long flags; | ||
3871 | int sigs; | ||
3872 | |||
3873 | pr_debug("stl_sc26198getsignals(portp=%p)\n", portp); | ||
3874 | |||
3875 | spin_lock_irqsave(&brd_lock, flags); | ||
3876 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3877 | ipr = stl_sc26198getreg(portp, IPR); | ||
3878 | BRDDISABLE(portp->brdnr); | ||
3879 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3880 | |||
3881 | sigs = 0; | ||
3882 | sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD; | ||
3883 | sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS; | ||
3884 | sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR; | ||
3885 | sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS; | ||
3886 | sigs |= TIOCM_DSR; | ||
3887 | return sigs; | ||
3888 | } | ||
3889 | |||
3890 | /*****************************************************************************/ | ||
3891 | |||
3892 | /* | ||
3893 | * Enable/Disable the Transmitter and/or Receiver. | ||
3894 | */ | ||
3895 | |||
3896 | static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx) | ||
3897 | { | ||
3898 | unsigned char ccr; | ||
3899 | unsigned long flags; | ||
3900 | |||
3901 | pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx); | ||
3902 | |||
3903 | ccr = portp->crenable; | ||
3904 | if (tx == 0) | ||
3905 | ccr &= ~CR_TXENABLE; | ||
3906 | else if (tx > 0) | ||
3907 | ccr |= CR_TXENABLE; | ||
3908 | if (rx == 0) | ||
3909 | ccr &= ~CR_RXENABLE; | ||
3910 | else if (rx > 0) | ||
3911 | ccr |= CR_RXENABLE; | ||
3912 | |||
3913 | spin_lock_irqsave(&brd_lock, flags); | ||
3914 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3915 | stl_sc26198setreg(portp, SCCR, ccr); | ||
3916 | BRDDISABLE(portp->brdnr); | ||
3917 | portp->crenable = ccr; | ||
3918 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3919 | } | ||
3920 | |||
3921 | /*****************************************************************************/ | ||
3922 | |||
3923 | /* | ||
3924 | * Start/stop the Transmitter and/or Receiver. | ||
3925 | */ | ||
3926 | |||
3927 | static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx) | ||
3928 | { | ||
3929 | unsigned char imr; | ||
3930 | unsigned long flags; | ||
3931 | |||
3932 | pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); | ||
3933 | |||
3934 | imr = portp->imr; | ||
3935 | if (tx == 0) | ||
3936 | imr &= ~IR_TXRDY; | ||
3937 | else if (tx == 1) | ||
3938 | imr |= IR_TXRDY; | ||
3939 | if (rx == 0) | ||
3940 | imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG); | ||
3941 | else if (rx > 0) | ||
3942 | imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG; | ||
3943 | |||
3944 | spin_lock_irqsave(&brd_lock, flags); | ||
3945 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3946 | stl_sc26198setreg(portp, IMR, imr); | ||
3947 | BRDDISABLE(portp->brdnr); | ||
3948 | portp->imr = imr; | ||
3949 | if (tx > 0) | ||
3950 | set_bit(ASYI_TXBUSY, &portp->istate); | ||
3951 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3952 | } | ||
3953 | |||
3954 | /*****************************************************************************/ | ||
3955 | |||
3956 | /* | ||
3957 | * Disable all interrupts from this port. | ||
3958 | */ | ||
3959 | |||
3960 | static void stl_sc26198disableintrs(struct stlport *portp) | ||
3961 | { | ||
3962 | unsigned long flags; | ||
3963 | |||
3964 | pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp); | ||
3965 | |||
3966 | spin_lock_irqsave(&brd_lock, flags); | ||
3967 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3968 | portp->imr = 0; | ||
3969 | stl_sc26198setreg(portp, IMR, 0); | ||
3970 | BRDDISABLE(portp->brdnr); | ||
3971 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3972 | } | ||
3973 | |||
3974 | /*****************************************************************************/ | ||
3975 | |||
3976 | static void stl_sc26198sendbreak(struct stlport *portp, int len) | ||
3977 | { | ||
3978 | unsigned long flags; | ||
3979 | |||
3980 | pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len); | ||
3981 | |||
3982 | spin_lock_irqsave(&brd_lock, flags); | ||
3983 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
3984 | if (len == 1) { | ||
3985 | stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK); | ||
3986 | portp->stats.txbreaks++; | ||
3987 | } else | ||
3988 | stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK); | ||
3989 | |||
3990 | BRDDISABLE(portp->brdnr); | ||
3991 | spin_unlock_irqrestore(&brd_lock, flags); | ||
3992 | } | ||
3993 | |||
3994 | /*****************************************************************************/ | ||
3995 | |||
3996 | /* | ||
3997 | * Take flow control actions... | ||
3998 | */ | ||
3999 | |||
4000 | static void stl_sc26198flowctrl(struct stlport *portp, int state) | ||
4001 | { | ||
4002 | struct tty_struct *tty; | ||
4003 | unsigned long flags; | ||
4004 | unsigned char mr0; | ||
4005 | |||
4006 | pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state); | ||
4007 | |||
4008 | if (portp == NULL) | ||
4009 | return; | ||
4010 | tty = tty_port_tty_get(&portp->port); | ||
4011 | if (tty == NULL) | ||
4012 | return; | ||
4013 | |||
4014 | spin_lock_irqsave(&brd_lock, flags); | ||
4015 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
4016 | |||
4017 | if (state) { | ||
4018 | if (tty->termios->c_iflag & IXOFF) { | ||
4019 | mr0 = stl_sc26198getreg(portp, MR0); | ||
4020 | stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); | ||
4021 | stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); | ||
4022 | mr0 |= MR0_SWFRX; | ||
4023 | portp->stats.rxxon++; | ||
4024 | stl_sc26198wait(portp); | ||
4025 | stl_sc26198setreg(portp, MR0, mr0); | ||
4026 | } | ||
4027 | /* | ||
4028 | * Question: should we return RTS to what it was before? It may | ||
4029 | * have been set by an ioctl... Suppose not, since if you have | ||
4030 | * hardware flow control set then it is pretty silly to go and | ||
4031 | * set the RTS line by hand. | ||
4032 | */ | ||
4033 | if (tty->termios->c_cflag & CRTSCTS) { | ||
4034 | stl_sc26198setreg(portp, MR1, | ||
4035 | (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS)); | ||
4036 | stl_sc26198setreg(portp, IOPIOR, | ||
4037 | (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS)); | ||
4038 | portp->stats.rxrtson++; | ||
4039 | } | ||
4040 | } else { | ||
4041 | if (tty->termios->c_iflag & IXOFF) { | ||
4042 | mr0 = stl_sc26198getreg(portp, MR0); | ||
4043 | stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); | ||
4044 | stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); | ||
4045 | mr0 &= ~MR0_SWFRX; | ||
4046 | portp->stats.rxxoff++; | ||
4047 | stl_sc26198wait(portp); | ||
4048 | stl_sc26198setreg(portp, MR0, mr0); | ||
4049 | } | ||
4050 | if (tty->termios->c_cflag & CRTSCTS) { | ||
4051 | stl_sc26198setreg(portp, MR1, | ||
4052 | (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS)); | ||
4053 | stl_sc26198setreg(portp, IOPIOR, | ||
4054 | (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS)); | ||
4055 | portp->stats.rxrtsoff++; | ||
4056 | } | ||
4057 | } | ||
4058 | |||
4059 | BRDDISABLE(portp->brdnr); | ||
4060 | spin_unlock_irqrestore(&brd_lock, flags); | ||
4061 | tty_kref_put(tty); | ||
4062 | } | ||
4063 | |||
4064 | /*****************************************************************************/ | ||
4065 | |||
4066 | /* | ||
4067 | * Send a flow control character. | ||
4068 | */ | ||
4069 | |||
4070 | static void stl_sc26198sendflow(struct stlport *portp, int state) | ||
4071 | { | ||
4072 | struct tty_struct *tty; | ||
4073 | unsigned long flags; | ||
4074 | unsigned char mr0; | ||
4075 | |||
4076 | pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state); | ||
4077 | |||
4078 | if (portp == NULL) | ||
4079 | return; | ||
4080 | tty = tty_port_tty_get(&portp->port); | ||
4081 | if (tty == NULL) | ||
4082 | return; | ||
4083 | |||
4084 | spin_lock_irqsave(&brd_lock, flags); | ||
4085 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
4086 | if (state) { | ||
4087 | mr0 = stl_sc26198getreg(portp, MR0); | ||
4088 | stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); | ||
4089 | stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); | ||
4090 | mr0 |= MR0_SWFRX; | ||
4091 | portp->stats.rxxon++; | ||
4092 | stl_sc26198wait(portp); | ||
4093 | stl_sc26198setreg(portp, MR0, mr0); | ||
4094 | } else { | ||
4095 | mr0 = stl_sc26198getreg(portp, MR0); | ||
4096 | stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); | ||
4097 | stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); | ||
4098 | mr0 &= ~MR0_SWFRX; | ||
4099 | portp->stats.rxxoff++; | ||
4100 | stl_sc26198wait(portp); | ||
4101 | stl_sc26198setreg(portp, MR0, mr0); | ||
4102 | } | ||
4103 | BRDDISABLE(portp->brdnr); | ||
4104 | spin_unlock_irqrestore(&brd_lock, flags); | ||
4105 | tty_kref_put(tty); | ||
4106 | } | ||
4107 | |||
4108 | /*****************************************************************************/ | ||
4109 | |||
4110 | static void stl_sc26198flush(struct stlport *portp) | ||
4111 | { | ||
4112 | unsigned long flags; | ||
4113 | |||
4114 | pr_debug("stl_sc26198flush(portp=%p)\n", portp); | ||
4115 | |||
4116 | if (portp == NULL) | ||
4117 | return; | ||
4118 | |||
4119 | spin_lock_irqsave(&brd_lock, flags); | ||
4120 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
4121 | stl_sc26198setreg(portp, SCCR, CR_TXRESET); | ||
4122 | stl_sc26198setreg(portp, SCCR, portp->crenable); | ||
4123 | BRDDISABLE(portp->brdnr); | ||
4124 | portp->tx.tail = portp->tx.head; | ||
4125 | spin_unlock_irqrestore(&brd_lock, flags); | ||
4126 | } | ||
4127 | |||
4128 | /*****************************************************************************/ | ||
4129 | |||
4130 | /* | ||
4131 | * Return the current state of data flow on this port. This is only | ||
4132 | * really interesting when determining if data has fully completed | ||
4133 | * transmission or not... The sc26198 interrupt scheme cannot | ||
4134 | * determine when all data has actually drained, so we need to | ||
4135 | * check the port statusy register to be sure. | ||
4136 | */ | ||
4137 | |||
4138 | static int stl_sc26198datastate(struct stlport *portp) | ||
4139 | { | ||
4140 | unsigned long flags; | ||
4141 | unsigned char sr; | ||
4142 | |||
4143 | pr_debug("stl_sc26198datastate(portp=%p)\n", portp); | ||
4144 | |||
4145 | if (portp == NULL) | ||
4146 | return 0; | ||
4147 | if (test_bit(ASYI_TXBUSY, &portp->istate)) | ||
4148 | return 1; | ||
4149 | |||
4150 | spin_lock_irqsave(&brd_lock, flags); | ||
4151 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
4152 | sr = stl_sc26198getreg(portp, SR); | ||
4153 | BRDDISABLE(portp->brdnr); | ||
4154 | spin_unlock_irqrestore(&brd_lock, flags); | ||
4155 | |||
4156 | return (sr & SR_TXEMPTY) ? 0 : 1; | ||
4157 | } | ||
4158 | |||
4159 | /*****************************************************************************/ | ||
4160 | |||
4161 | /* | ||
4162 | * Delay for a small amount of time, to give the sc26198 a chance | ||
4163 | * to process a command... | ||
4164 | */ | ||
4165 | |||
4166 | static void stl_sc26198wait(struct stlport *portp) | ||
4167 | { | ||
4168 | int i; | ||
4169 | |||
4170 | pr_debug("stl_sc26198wait(portp=%p)\n", portp); | ||
4171 | |||
4172 | if (portp == NULL) | ||
4173 | return; | ||
4174 | |||
4175 | for (i = 0; i < 20; i++) | ||
4176 | stl_sc26198getglobreg(portp, TSTR); | ||
4177 | } | ||
4178 | |||
4179 | /*****************************************************************************/ | ||
4180 | |||
4181 | /* | ||
4182 | * If we are TX flow controlled and in IXANY mode then we may | ||
4183 | * need to unflow control here. We gotta do this because of the | ||
4184 | * automatic flow control modes of the sc26198. | ||
4185 | */ | ||
4186 | |||
4187 | static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty) | ||
4188 | { | ||
4189 | unsigned char mr0; | ||
4190 | |||
4191 | mr0 = stl_sc26198getreg(portp, MR0); | ||
4192 | stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); | ||
4193 | stl_sc26198setreg(portp, SCCR, CR_HOSTXON); | ||
4194 | stl_sc26198wait(portp); | ||
4195 | stl_sc26198setreg(portp, MR0, mr0); | ||
4196 | clear_bit(ASYI_TXFLOWED, &portp->istate); | ||
4197 | } | ||
4198 | |||
4199 | /*****************************************************************************/ | ||
4200 | |||
4201 | /* | ||
4202 | * Interrupt service routine for sc26198 panels. | ||
4203 | */ | ||
4204 | |||
4205 | static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase) | ||
4206 | { | ||
4207 | struct stlport *portp; | ||
4208 | unsigned int iack; | ||
4209 | |||
4210 | spin_lock(&brd_lock); | ||
4211 | |||
4212 | /* | ||
4213 | * Work around bug in sc26198 chip... Cannot have A6 address | ||
4214 | * line of UART high, else iack will be returned as 0. | ||
4215 | */ | ||
4216 | outb(0, (iobase + 1)); | ||
4217 | |||
4218 | iack = inb(iobase + XP_IACK); | ||
4219 | portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)]; | ||
4220 | |||
4221 | if (iack & IVR_RXDATA) | ||
4222 | stl_sc26198rxisr(portp, iack); | ||
4223 | else if (iack & IVR_TXDATA) | ||
4224 | stl_sc26198txisr(portp); | ||
4225 | else | ||
4226 | stl_sc26198otherisr(portp, iack); | ||
4227 | |||
4228 | spin_unlock(&brd_lock); | ||
4229 | } | ||
4230 | |||
4231 | /*****************************************************************************/ | ||
4232 | |||
4233 | /* | ||
4234 | * Transmit interrupt handler. This has gotta be fast! Handling TX | ||
4235 | * chars is pretty simple, stuff as many as possible from the TX buffer | ||
4236 | * into the sc26198 FIFO. | ||
4237 | * In practice it is possible that interrupts are enabled but that the | ||
4238 | * port has been hung up. Need to handle not having any TX buffer here, | ||
4239 | * this is done by using the side effect that head and tail will also | ||
4240 | * be NULL if the buffer has been freed. | ||
4241 | */ | ||
4242 | |||
4243 | static void stl_sc26198txisr(struct stlport *portp) | ||
4244 | { | ||
4245 | struct tty_struct *tty; | ||
4246 | unsigned int ioaddr; | ||
4247 | unsigned char mr0; | ||
4248 | int len, stlen; | ||
4249 | char *head, *tail; | ||
4250 | |||
4251 | pr_debug("stl_sc26198txisr(portp=%p)\n", portp); | ||
4252 | |||
4253 | ioaddr = portp->ioaddr; | ||
4254 | head = portp->tx.head; | ||
4255 | tail = portp->tx.tail; | ||
4256 | len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); | ||
4257 | if ((len == 0) || ((len < STL_TXBUFLOW) && | ||
4258 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { | ||
4259 | set_bit(ASYI_TXLOW, &portp->istate); | ||
4260 | tty = tty_port_tty_get(&portp->port); | ||
4261 | if (tty) { | ||
4262 | tty_wakeup(tty); | ||
4263 | tty_kref_put(tty); | ||
4264 | } | ||
4265 | } | ||
4266 | |||
4267 | if (len == 0) { | ||
4268 | outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR)); | ||
4269 | mr0 = inb(ioaddr + XP_DATA); | ||
4270 | if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) { | ||
4271 | portp->imr &= ~IR_TXRDY; | ||
4272 | outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR)); | ||
4273 | outb(portp->imr, (ioaddr + XP_DATA)); | ||
4274 | clear_bit(ASYI_TXBUSY, &portp->istate); | ||
4275 | } else { | ||
4276 | mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY); | ||
4277 | outb(mr0, (ioaddr + XP_DATA)); | ||
4278 | } | ||
4279 | } else { | ||
4280 | len = min(len, SC26198_TXFIFOSIZE); | ||
4281 | portp->stats.txtotal += len; | ||
4282 | stlen = min_t(unsigned int, len, | ||
4283 | (portp->tx.buf + STL_TXBUFSIZE) - tail); | ||
4284 | outb(GTXFIFO, (ioaddr + XP_ADDR)); | ||
4285 | outsb((ioaddr + XP_DATA), tail, stlen); | ||
4286 | len -= stlen; | ||
4287 | tail += stlen; | ||
4288 | if (tail >= (portp->tx.buf + STL_TXBUFSIZE)) | ||
4289 | tail = portp->tx.buf; | ||
4290 | if (len > 0) { | ||
4291 | outsb((ioaddr + XP_DATA), tail, len); | ||
4292 | tail += len; | ||
4293 | } | ||
4294 | portp->tx.tail = tail; | ||
4295 | } | ||
4296 | } | ||
4297 | |||
4298 | /*****************************************************************************/ | ||
4299 | |||
4300 | /* | ||
4301 | * Receive character interrupt handler. Determine if we have good chars | ||
4302 | * or bad chars and then process appropriately. Good chars are easy | ||
4303 | * just shove the lot into the RX buffer and set all status byte to 0. | ||
4304 | * If a bad RX char then process as required. This routine needs to be | ||
4305 | * fast! In practice it is possible that we get an interrupt on a port | ||
4306 | * that is closed. This can happen on hangups - since they completely | ||
4307 | * shutdown a port not in user context. Need to handle this case. | ||
4308 | */ | ||
4309 | |||
4310 | static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack) | ||
4311 | { | ||
4312 | struct tty_struct *tty; | ||
4313 | unsigned int len, buflen, ioaddr; | ||
4314 | |||
4315 | pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack); | ||
4316 | |||
4317 | tty = tty_port_tty_get(&portp->port); | ||
4318 | ioaddr = portp->ioaddr; | ||
4319 | outb(GIBCR, (ioaddr + XP_ADDR)); | ||
4320 | len = inb(ioaddr + XP_DATA) + 1; | ||
4321 | |||
4322 | if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { | ||
4323 | if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { | ||
4324 | len = min_t(unsigned int, len, sizeof(stl_unwanted)); | ||
4325 | outb(GRXFIFO, (ioaddr + XP_ADDR)); | ||
4326 | insb((ioaddr + XP_DATA), &stl_unwanted[0], len); | ||
4327 | portp->stats.rxlost += len; | ||
4328 | portp->stats.rxtotal += len; | ||
4329 | } else { | ||
4330 | len = min(len, buflen); | ||
4331 | if (len > 0) { | ||
4332 | unsigned char *ptr; | ||
4333 | outb(GRXFIFO, (ioaddr + XP_ADDR)); | ||
4334 | tty_prepare_flip_string(tty, &ptr, len); | ||
4335 | insb((ioaddr + XP_DATA), ptr, len); | ||
4336 | tty_schedule_flip(tty); | ||
4337 | portp->stats.rxtotal += len; | ||
4338 | } | ||
4339 | } | ||
4340 | } else { | ||
4341 | stl_sc26198rxbadchars(portp); | ||
4342 | } | ||
4343 | |||
4344 | /* | ||
4345 | * If we are TX flow controlled and in IXANY mode then we may need | ||
4346 | * to unflow control here. We gotta do this because of the automatic | ||
4347 | * flow control modes of the sc26198. | ||
4348 | */ | ||
4349 | if (test_bit(ASYI_TXFLOWED, &portp->istate)) { | ||
4350 | if ((tty != NULL) && | ||
4351 | (tty->termios != NULL) && | ||
4352 | (tty->termios->c_iflag & IXANY)) { | ||
4353 | stl_sc26198txunflow(portp, tty); | ||
4354 | } | ||
4355 | } | ||
4356 | tty_kref_put(tty); | ||
4357 | } | ||
4358 | |||
4359 | /*****************************************************************************/ | ||
4360 | |||
4361 | /* | ||
4362 | * Process an RX bad character. | ||
4363 | */ | ||
4364 | |||
4365 | static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch) | ||
4366 | { | ||
4367 | struct tty_struct *tty; | ||
4368 | unsigned int ioaddr; | ||
4369 | |||
4370 | tty = tty_port_tty_get(&portp->port); | ||
4371 | ioaddr = portp->ioaddr; | ||
4372 | |||
4373 | if (status & SR_RXPARITY) | ||
4374 | portp->stats.rxparity++; | ||
4375 | if (status & SR_RXFRAMING) | ||
4376 | portp->stats.rxframing++; | ||
4377 | if (status & SR_RXOVERRUN) | ||
4378 | portp->stats.rxoverrun++; | ||
4379 | if (status & SR_RXBREAK) | ||
4380 | portp->stats.rxbreaks++; | ||
4381 | |||
4382 | if ((tty != NULL) && | ||
4383 | ((portp->rxignoremsk & status) == 0)) { | ||
4384 | if (portp->rxmarkmsk & status) { | ||
4385 | if (status & SR_RXBREAK) { | ||
4386 | status = TTY_BREAK; | ||
4387 | if (portp->port.flags & ASYNC_SAK) { | ||
4388 | do_SAK(tty); | ||
4389 | BRDENABLE(portp->brdnr, portp->pagenr); | ||
4390 | } | ||
4391 | } else if (status & SR_RXPARITY) | ||
4392 | status = TTY_PARITY; | ||
4393 | else if (status & SR_RXFRAMING) | ||
4394 | status = TTY_FRAME; | ||
4395 | else if(status & SR_RXOVERRUN) | ||
4396 | status = TTY_OVERRUN; | ||
4397 | else | ||
4398 | status = 0; | ||
4399 | } else | ||
4400 | status = 0; | ||
4401 | |||
4402 | tty_insert_flip_char(tty, ch, status); | ||
4403 | tty_schedule_flip(tty); | ||
4404 | |||
4405 | if (status == 0) | ||
4406 | portp->stats.rxtotal++; | ||
4407 | } | ||
4408 | tty_kref_put(tty); | ||
4409 | } | ||
4410 | |||
4411 | /*****************************************************************************/ | ||
4412 | |||
4413 | /* | ||
4414 | * Process all characters in the RX FIFO of the UART. Check all char | ||
4415 | * status bytes as well, and process as required. We need to check | ||
4416 | * all bytes in the FIFO, in case some more enter the FIFO while we | ||
4417 | * are here. To get the exact character error type we need to switch | ||
4418 | * into CHAR error mode (that is why we need to make sure we empty | ||
4419 | * the FIFO). | ||
4420 | */ | ||
4421 | |||
4422 | static void stl_sc26198rxbadchars(struct stlport *portp) | ||
4423 | { | ||
4424 | unsigned char status, mr1; | ||
4425 | char ch; | ||
4426 | |||
4427 | /* | ||
4428 | * To get the precise error type for each character we must switch | ||
4429 | * back into CHAR error mode. | ||
4430 | */ | ||
4431 | mr1 = stl_sc26198getreg(portp, MR1); | ||
4432 | stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK)); | ||
4433 | |||
4434 | while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) { | ||
4435 | stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR); | ||
4436 | ch = stl_sc26198getreg(portp, RXFIFO); | ||
4437 | stl_sc26198rxbadch(portp, status, ch); | ||
4438 | } | ||
4439 | |||
4440 | /* | ||
4441 | * To get correct interrupt class we must switch back into BLOCK | ||
4442 | * error mode. | ||
4443 | */ | ||
4444 | stl_sc26198setreg(portp, MR1, mr1); | ||
4445 | } | ||
4446 | |||
4447 | /*****************************************************************************/ | ||
4448 | |||
4449 | /* | ||
4450 | * Other interrupt handler. This includes modem signals, flow | ||
4451 | * control actions, etc. Most stuff is left to off-level interrupt | ||
4452 | * processing time. | ||
4453 | */ | ||
4454 | |||
4455 | static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack) | ||
4456 | { | ||
4457 | unsigned char cir, ipr, xisr; | ||
4458 | |||
4459 | pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack); | ||
4460 | |||
4461 | cir = stl_sc26198getglobreg(portp, CIR); | ||
4462 | |||
4463 | switch (cir & CIR_SUBTYPEMASK) { | ||
4464 | case CIR_SUBCOS: | ||
4465 | ipr = stl_sc26198getreg(portp, IPR); | ||
4466 | if (ipr & IPR_DCDCHANGE) { | ||
4467 | stl_cd_change(portp); | ||
4468 | portp->stats.modem++; | ||
4469 | } | ||
4470 | break; | ||
4471 | case CIR_SUBXONXOFF: | ||
4472 | xisr = stl_sc26198getreg(portp, XISR); | ||
4473 | if (xisr & XISR_RXXONGOT) { | ||
4474 | set_bit(ASYI_TXFLOWED, &portp->istate); | ||
4475 | portp->stats.txxoff++; | ||
4476 | } | ||
4477 | if (xisr & XISR_RXXOFFGOT) { | ||
4478 | clear_bit(ASYI_TXFLOWED, &portp->istate); | ||
4479 | portp->stats.txxon++; | ||
4480 | } | ||
4481 | break; | ||
4482 | case CIR_SUBBREAK: | ||
4483 | stl_sc26198setreg(portp, SCCR, CR_BREAKRESET); | ||
4484 | stl_sc26198rxbadchars(portp); | ||
4485 | break; | ||
4486 | default: | ||
4487 | break; | ||
4488 | } | ||
4489 | } | ||
4490 | |||
4491 | static void stl_free_isabrds(void) | ||
4492 | { | ||
4493 | struct stlbrd *brdp; | ||
4494 | unsigned int i; | ||
4495 | |||
4496 | for (i = 0; i < stl_nrbrds; i++) { | ||
4497 | if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) | ||
4498 | continue; | ||
4499 | |||
4500 | free_irq(brdp->irq, brdp); | ||
4501 | |||
4502 | stl_cleanup_panels(brdp); | ||
4503 | |||
4504 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
4505 | if (brdp->iosize2 > 0) | ||
4506 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
4507 | |||
4508 | kfree(brdp); | ||
4509 | stl_brds[i] = NULL; | ||
4510 | } | ||
4511 | } | ||
4512 | |||
4513 | /* | ||
4514 | * Loadable module initialization stuff. | ||
4515 | */ | ||
4516 | static int __init stallion_module_init(void) | ||
4517 | { | ||
4518 | struct stlbrd *brdp; | ||
4519 | struct stlconf conf; | ||
4520 | unsigned int i, j; | ||
4521 | int retval; | ||
4522 | |||
4523 | printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); | ||
4524 | |||
4525 | spin_lock_init(&stallion_lock); | ||
4526 | spin_lock_init(&brd_lock); | ||
4527 | |||
4528 | stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); | ||
4529 | if (!stl_serial) { | ||
4530 | retval = -ENOMEM; | ||
4531 | goto err; | ||
4532 | } | ||
4533 | |||
4534 | stl_serial->owner = THIS_MODULE; | ||
4535 | stl_serial->driver_name = stl_drvname; | ||
4536 | stl_serial->name = "ttyE"; | ||
4537 | stl_serial->major = STL_SERIALMAJOR; | ||
4538 | stl_serial->minor_start = 0; | ||
4539 | stl_serial->type = TTY_DRIVER_TYPE_SERIAL; | ||
4540 | stl_serial->subtype = SERIAL_TYPE_NORMAL; | ||
4541 | stl_serial->init_termios = stl_deftermios; | ||
4542 | stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
4543 | tty_set_operations(stl_serial, &stl_ops); | ||
4544 | |||
4545 | retval = tty_register_driver(stl_serial); | ||
4546 | if (retval) { | ||
4547 | printk("STALLION: failed to register serial driver\n"); | ||
4548 | goto err_frtty; | ||
4549 | } | ||
4550 | |||
4551 | /* | ||
4552 | * Find any dynamically supported boards. That is via module load | ||
4553 | * line options. | ||
4554 | */ | ||
4555 | for (i = stl_nrbrds; i < stl_nargs; i++) { | ||
4556 | memset(&conf, 0, sizeof(conf)); | ||
4557 | if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) | ||
4558 | continue; | ||
4559 | if ((brdp = stl_allocbrd()) == NULL) | ||
4560 | continue; | ||
4561 | brdp->brdnr = i; | ||
4562 | brdp->brdtype = conf.brdtype; | ||
4563 | brdp->ioaddr1 = conf.ioaddr1; | ||
4564 | brdp->ioaddr2 = conf.ioaddr2; | ||
4565 | brdp->irq = conf.irq; | ||
4566 | brdp->irqtype = conf.irqtype; | ||
4567 | stl_brds[brdp->brdnr] = brdp; | ||
4568 | if (stl_brdinit(brdp)) { | ||
4569 | stl_brds[brdp->brdnr] = NULL; | ||
4570 | kfree(brdp); | ||
4571 | } else { | ||
4572 | for (j = 0; j < brdp->nrports; j++) | ||
4573 | tty_register_device(stl_serial, | ||
4574 | brdp->brdnr * STL_MAXPORTS + j, NULL); | ||
4575 | stl_nrbrds = i + 1; | ||
4576 | } | ||
4577 | } | ||
4578 | |||
4579 | /* this has to be _after_ isa finding because of locking */ | ||
4580 | retval = pci_register_driver(&stl_pcidriver); | ||
4581 | if (retval && stl_nrbrds == 0) { | ||
4582 | printk(KERN_ERR "STALLION: can't register pci driver\n"); | ||
4583 | goto err_unrtty; | ||
4584 | } | ||
4585 | |||
4586 | /* | ||
4587 | * Set up a character driver for per board stuff. This is mainly used | ||
4588 | * to do stats ioctls on the ports. | ||
4589 | */ | ||
4590 | if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) | ||
4591 | printk("STALLION: failed to register serial board device\n"); | ||
4592 | |||
4593 | stallion_class = class_create(THIS_MODULE, "staliomem"); | ||
4594 | if (IS_ERR(stallion_class)) | ||
4595 | printk("STALLION: failed to create class\n"); | ||
4596 | for (i = 0; i < 4; i++) | ||
4597 | device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), | ||
4598 | NULL, "staliomem%d", i); | ||
4599 | |||
4600 | return 0; | ||
4601 | err_unrtty: | ||
4602 | tty_unregister_driver(stl_serial); | ||
4603 | err_frtty: | ||
4604 | put_tty_driver(stl_serial); | ||
4605 | err: | ||
4606 | return retval; | ||
4607 | } | ||
4608 | |||
4609 | static void __exit stallion_module_exit(void) | ||
4610 | { | ||
4611 | struct stlbrd *brdp; | ||
4612 | unsigned int i, j; | ||
4613 | |||
4614 | pr_debug("cleanup_module()\n"); | ||
4615 | |||
4616 | printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, | ||
4617 | stl_drvversion); | ||
4618 | |||
4619 | /* | ||
4620 | * Free up all allocated resources used by the ports. This includes | ||
4621 | * memory and interrupts. As part of this process we will also do | ||
4622 | * a hangup on every open port - to try to flush out any processes | ||
4623 | * hanging onto ports. | ||
4624 | */ | ||
4625 | for (i = 0; i < stl_nrbrds; i++) { | ||
4626 | if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) | ||
4627 | continue; | ||
4628 | for (j = 0; j < brdp->nrports; j++) | ||
4629 | tty_unregister_device(stl_serial, | ||
4630 | brdp->brdnr * STL_MAXPORTS + j); | ||
4631 | } | ||
4632 | |||
4633 | for (i = 0; i < 4; i++) | ||
4634 | device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); | ||
4635 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); | ||
4636 | class_destroy(stallion_class); | ||
4637 | |||
4638 | pci_unregister_driver(&stl_pcidriver); | ||
4639 | |||
4640 | stl_free_isabrds(); | ||
4641 | |||
4642 | tty_unregister_driver(stl_serial); | ||
4643 | put_tty_driver(stl_serial); | ||
4644 | } | ||
4645 | |||
4646 | module_init(stallion_module_init); | ||
4647 | module_exit(stallion_module_exit); | ||
4648 | |||
4649 | MODULE_AUTHOR("Greg Ungerer"); | ||
4650 | MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); | ||
4651 | MODULE_LICENSE("GPL"); | ||