blob: bc2911396b7e638b1ba84a33db6be056ec8d6eb2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*****************************************************************************/
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/interrupt.h>
32#include <linux/tty.h>
33#include <linux/tty_flip.h>
34#include <linux/serial.h>
35#include <linux/cd1400.h>
36#include <linux/sc26198.h>
37#include <linux/comstats.h>
38#include <linux/stallion.h>
39#include <linux/ioport.h>
40#include <linux/init.h>
41#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/device.h>
43#include <linux/delay.h>
44
45#include <asm/io.h>
46#include <asm/uaccess.h>
47
48#ifdef CONFIG_PCI
49#include <linux/pci.h>
50#endif
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/*
67 * Define a configuration structure to hold the board configuration.
68 * Need to set this up in the code (for now) with the boards that are
69 * to be configured into the system. This is what needs to be modified
70 * when adding/removing/modifying boards. Each line entry in the
71 * stl_brdconf[] array is a board. Each line contains io/irq/memory
72 * ranges for that board (as well as what type of board it is).
73 * Some examples:
74 * { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
75 * This line would configure an EasyIO board (4 or 8, no difference),
76 * at io address 2a0 and irq 10.
77 * Another example:
78 * { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 },
79 * This line will configure an EasyConnection 8/32 board at primary io
80 * address 2a8, secondary io address 280 and irq 12.
81 * Enter as many lines into this array as you want (only the first 4
82 * will actually be used!). Any combination of EasyIO and EasyConnection
83 * boards can be specified. EasyConnection 8/32 boards can share their
84 * secondary io addresses between each other.
85 *
86 * NOTE: there is no need to put any entries in this table for PCI
87 * boards. They will be found automatically by the driver - provided
88 * PCI BIOS32 support is compiled into the kernel.
89 */
90
Jiri Slabyca7ed0f2006-12-08 02:38:39 -080091static struct stlconf {
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 int brdtype;
93 int ioaddr1;
94 int ioaddr2;
95 unsigned long memaddr;
96 int irq;
97 int irqtype;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -080098} stl_brdconf[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
100};
101
Tobias Klauserfe971072006-01-09 20:54:02 -0800102static int stl_nrbrds = ARRAY_SIZE(stl_brdconf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104/*****************************************************************************/
105
106/*
107 * Define some important driver characteristics. Device major numbers
108 * allocated as per Linux Device Registry.
109 */
110#ifndef STL_SIOMEMMAJOR
111#define STL_SIOMEMMAJOR 28
112#endif
113#ifndef STL_SERIALMAJOR
114#define STL_SERIALMAJOR 24
115#endif
116#ifndef STL_CALLOUTMAJOR
117#define STL_CALLOUTMAJOR 25
118#endif
119
120/*
121 * Set the TX buffer size. Bigger is better, but we don't want
122 * to chew too much memory with buffers!
123 */
124#define STL_TXBUFLOW 512
125#define STL_TXBUFSIZE 4096
126
127/*****************************************************************************/
128
129/*
130 * Define our local driver identity first. Set up stuff to deal with
131 * all the local structures required by a serial tty driver.
132 */
133static char *stl_drvtitle = "Stallion Multiport Serial Driver";
134static char *stl_drvname = "stallion";
135static char *stl_drvversion = "5.6.0";
136
137static struct tty_driver *stl_serial;
138
139/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 * Define a local default termios struct. All ports will be created
141 * with this termios initially. Basically all it defines is a raw port
142 * at 9600, 8 data bits, 1 stop bit.
143 */
Alan Cox606d0992006-12-08 02:38:45 -0800144static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
146 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800147 .c_ispeed = 9600,
148 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149};
150
151/*
152 * Define global stats structures. Not used often, and can be
153 * re-used for each stats call.
154 */
155static comstats_t stl_comstats;
156static combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800157static struct stlbrd stl_dummybrd;
158static struct stlport stl_dummyport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160/*
161 * Define global place to put buffer overflow characters.
162 */
163static char stl_unwanted[SC26198_RXFIFOSIZE];
164
165/*****************************************************************************/
166
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800167static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
169/*
170 * Per board state flags. Used with the state field of the board struct.
171 * Not really much here!
172 */
173#define BRD_FOUND 0x1
174
175/*
176 * Define the port structure istate flags. These set of flags are
177 * modified at interrupt time - so setting and reseting them needs
178 * to be atomic. Use the bit clear/setting routines for this.
179 */
180#define ASYI_TXBUSY 1
181#define ASYI_TXLOW 2
182#define ASYI_DCDCHANGE 3
183#define ASYI_TXFLOWED 4
184
185/*
186 * Define an array of board names as printable strings. Handy for
187 * referencing boards when printing trace and stuff.
188 */
189static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800190 NULL,
191 NULL,
192 NULL,
193 NULL,
194 NULL,
195 NULL,
196 NULL,
197 NULL,
198 NULL,
199 NULL,
200 NULL,
201 NULL,
202 NULL,
203 NULL,
204 NULL,
205 NULL,
206 NULL,
207 NULL,
208 NULL,
209 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 "EasyIO",
211 "EC8/32-AT",
212 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800213 NULL,
214 NULL,
215 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 "EC8/32-PCI",
217 "EC8/64-PCI",
218 "EasyIO-PCI",
219};
220
221/*****************************************************************************/
222
223/*
224 * Define some string labels for arguments passed from the module
225 * load line. These allow for easy board definitions, and easy
226 * modification of the io, memory and irq resoucres.
227 */
228static int stl_nargs = 0;
229static char *board0[4];
230static char *board1[4];
231static char *board2[4];
232static char *board3[4];
233
234static char **stl_brdsp[] = {
235 (char **) &board0,
236 (char **) &board1,
237 (char **) &board2,
238 (char **) &board3
239};
240
241/*
242 * Define a set of common board names, and types. This is used to
243 * parse any module arguments.
244 */
245
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800246static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 char *name;
248 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800249} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 { "easyio", BRD_EASYIO },
251 { "eio", BRD_EASYIO },
252 { "20", BRD_EASYIO },
253 { "ec8/32", BRD_ECH },
254 { "ec8/32-at", BRD_ECH },
255 { "ec8/32-isa", BRD_ECH },
256 { "ech", BRD_ECH },
257 { "echat", BRD_ECH },
258 { "21", BRD_ECH },
259 { "ec8/32-mc", BRD_ECHMC },
260 { "ec8/32-mca", BRD_ECHMC },
261 { "echmc", BRD_ECHMC },
262 { "echmca", BRD_ECHMC },
263 { "22", BRD_ECHMC },
264 { "ec8/32-pc", BRD_ECHPCI },
265 { "ec8/32-pci", BRD_ECHPCI },
266 { "26", BRD_ECHPCI },
267 { "ec8/64-pc", BRD_ECH64PCI },
268 { "ec8/64-pci", BRD_ECH64PCI },
269 { "ech-pci", BRD_ECH64PCI },
270 { "echpci", BRD_ECH64PCI },
271 { "echpc", BRD_ECH64PCI },
272 { "27", BRD_ECH64PCI },
273 { "easyio-pc", BRD_EASYIOPCI },
274 { "easyio-pci", BRD_EASYIOPCI },
275 { "eio-pci", BRD_EASYIOPCI },
276 { "eiopci", BRD_EASYIOPCI },
277 { "28", BRD_EASYIOPCI },
278};
279
280/*
281 * Define the module agruments.
282 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284module_param_array(board0, charp, &stl_nargs, 0);
285MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
286module_param_array(board1, charp, &stl_nargs, 0);
287MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
288module_param_array(board2, charp, &stl_nargs, 0);
289MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
290module_param_array(board3, charp, &stl_nargs, 0);
291MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
292
293/*****************************************************************************/
294
295/*
296 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
297 * to the directly accessible io ports of these boards (not the uarts -
298 * they are in cd1400.h and sc26198.h).
299 */
300#define EIO_8PORTRS 0x04
301#define EIO_4PORTRS 0x05
302#define EIO_8PORTDI 0x00
303#define EIO_8PORTM 0x06
304#define EIO_MK3 0x03
305#define EIO_IDBITMASK 0x07
306
307#define EIO_BRDMASK 0xf0
308#define ID_BRD4 0x10
309#define ID_BRD8 0x20
310#define ID_BRD16 0x30
311
312#define EIO_INTRPEND 0x08
313#define EIO_INTEDGE 0x00
314#define EIO_INTLEVEL 0x08
315#define EIO_0WS 0x10
316
317#define ECH_ID 0xa0
318#define ECH_IDBITMASK 0xe0
319#define ECH_BRDENABLE 0x08
320#define ECH_BRDDISABLE 0x00
321#define ECH_INTENABLE 0x01
322#define ECH_INTDISABLE 0x00
323#define ECH_INTLEVEL 0x02
324#define ECH_INTEDGE 0x00
325#define ECH_INTRPEND 0x01
326#define ECH_BRDRESET 0x01
327
328#define ECHMC_INTENABLE 0x01
329#define ECHMC_BRDRESET 0x02
330
331#define ECH_PNLSTATUS 2
332#define ECH_PNL16PORT 0x20
333#define ECH_PNLIDMASK 0x07
334#define ECH_PNLXPID 0x40
335#define ECH_PNLINTRPEND 0x80
336
337#define ECH_ADDR2MASK 0x1e0
338
339/*
340 * Define the vector mapping bits for the programmable interrupt board
341 * hardware. These bits encode the interrupt for the board to use - it
342 * is software selectable (except the EIO-8M).
343 */
344static unsigned char stl_vecmap[] = {
345 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
346 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
347};
348
349/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700350 * Lock ordering is that you may not take stallion_lock holding
351 * brd_lock.
352 */
353
354static spinlock_t brd_lock; /* Guard the board mapping */
355static spinlock_t stallion_lock; /* Guard the tty driver */
356
357/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 * Set up enable and disable macros for the ECH boards. They require
359 * the secondary io address space to be activated and deactivated.
360 * This way all ECH boards can share their secondary io region.
361 * If this is an ECH-PCI board then also need to set the page pointer
362 * to point to the correct page.
363 */
364#define BRDENABLE(brdnr,pagenr) \
365 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
366 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
367 stl_brds[(brdnr)]->ioctrl); \
368 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
369 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
370
371#define BRDDISABLE(brdnr) \
372 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
373 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
374 stl_brds[(brdnr)]->ioctrl);
375
376#define STL_CD1400MAXBAUD 230400
377#define STL_SC26198MAXBAUD 460800
378
379#define STL_BAUDBASE 115200
380#define STL_CLOSEDELAY (5 * HZ / 10)
381
382/*****************************************************************************/
383
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384/*
385 * Define the Stallion PCI vendor and device IDs.
386 */
387#ifndef PCI_VENDOR_ID_STALLION
388#define PCI_VENDOR_ID_STALLION 0x124d
389#endif
390#ifndef PCI_DEVICE_ID_ECHPCI832
391#define PCI_DEVICE_ID_ECHPCI832 0x0000
392#endif
393#ifndef PCI_DEVICE_ID_ECHPCI864
394#define PCI_DEVICE_ID_ECHPCI864 0x0002
395#endif
396#ifndef PCI_DEVICE_ID_EIOPCI
397#define PCI_DEVICE_ID_EIOPCI 0x0003
398#endif
399
400/*
401 * Define structure to hold all Stallion PCI boards.
402 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800404static struct pci_device_id stl_pcibrds[] = {
405 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
406 .driver_data = BRD_ECH64PCI },
407 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
408 .driver_data = BRD_EASYIOPCI },
409 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
410 .driver_data = BRD_ECHPCI },
411 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
412 .driver_data = BRD_ECHPCI },
413 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800415MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
417/*****************************************************************************/
418
419/*
420 * Define macros to extract a brd/port number from a minor number.
421 */
422#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
423#define MINOR2PORT(min) ((min) & 0x3f)
424
425/*
426 * Define a baud rate table that converts termios baud rate selector
427 * into the actual baud rate value. All baud rate calculations are
428 * based on the actual baud rate required.
429 */
430static unsigned int stl_baudrates[] = {
431 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
432 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
433};
434
435/*
436 * Define some handy local macros...
437 */
438#undef MIN
439#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
440
441#undef TOLOWER
442#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
443
444/*****************************************************************************/
445
446/*
447 * Declare all those functions in this driver!
448 */
449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800451static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800452static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
453static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800454static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456/*
457 * CD1400 uart specific handling functions.
458 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800459static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
460static int stl_cd1400getreg(struct stlport *portp, int regnr);
461static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
462static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
463static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800464static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800465static int stl_cd1400getsignals(struct stlport *portp);
466static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
467static void stl_cd1400ccrwait(struct stlport *portp);
468static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
469static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
470static void stl_cd1400disableintrs(struct stlport *portp);
471static void stl_cd1400sendbreak(struct stlport *portp, int len);
472static void stl_cd1400flowctrl(struct stlport *portp, int state);
473static void stl_cd1400sendflow(struct stlport *portp, int state);
474static void stl_cd1400flush(struct stlport *portp);
475static int stl_cd1400datastate(struct stlport *portp);
476static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
477static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
478static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
479static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
480static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800482static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484/*
485 * SC26198 uart specific handling functions.
486 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800487static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
488static int stl_sc26198getreg(struct stlport *portp, int regnr);
489static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
490static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
491static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
492static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800493static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800494static int stl_sc26198getsignals(struct stlport *portp);
495static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
496static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
497static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
498static void stl_sc26198disableintrs(struct stlport *portp);
499static void stl_sc26198sendbreak(struct stlport *portp, int len);
500static void stl_sc26198flowctrl(struct stlport *portp, int state);
501static void stl_sc26198sendflow(struct stlport *portp, int state);
502static void stl_sc26198flush(struct stlport *portp);
503static int stl_sc26198datastate(struct stlport *portp);
504static void stl_sc26198wait(struct stlport *portp);
505static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
506static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
507static void stl_sc26198txisr(struct stlport *port);
508static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
509static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
510static void stl_sc26198rxbadchars(struct stlport *portp);
511static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513/*****************************************************************************/
514
515/*
516 * Generic UART support structure.
517 */
518typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800519 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
520 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800521 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800522 int (*getsignals)(struct stlport *portp);
523 void (*setsignals)(struct stlport *portp, int dtr, int rts);
524 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
525 void (*startrxtx)(struct stlport *portp, int rx, int tx);
526 void (*disableintrs)(struct stlport *portp);
527 void (*sendbreak)(struct stlport *portp, int len);
528 void (*flowctrl)(struct stlport *portp, int state);
529 void (*sendflow)(struct stlport *portp, int state);
530 void (*flush)(struct stlport *portp);
531 int (*datastate)(struct stlport *portp);
532 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533} uart_t;
534
535/*
536 * Define some macros to make calling these functions nice and clean.
537 */
538#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
539#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
540#define stl_setport (* ((uart_t *) portp->uartp)->setport)
541#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
542#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
543#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
544#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
545#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
546#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
547#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
548#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
549#define stl_flush (* ((uart_t *) portp->uartp)->flush)
550#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
551
552/*****************************************************************************/
553
554/*
555 * CD1400 UART specific data initialization.
556 */
557static uart_t stl_cd1400uart = {
558 stl_cd1400panelinit,
559 stl_cd1400portinit,
560 stl_cd1400setport,
561 stl_cd1400getsignals,
562 stl_cd1400setsignals,
563 stl_cd1400enablerxtx,
564 stl_cd1400startrxtx,
565 stl_cd1400disableintrs,
566 stl_cd1400sendbreak,
567 stl_cd1400flowctrl,
568 stl_cd1400sendflow,
569 stl_cd1400flush,
570 stl_cd1400datastate,
571 stl_cd1400eiointr
572};
573
574/*
575 * Define the offsets within the register bank of a cd1400 based panel.
576 * These io address offsets are common to the EasyIO board as well.
577 */
578#define EREG_ADDR 0
579#define EREG_DATA 4
580#define EREG_RXACK 5
581#define EREG_TXACK 6
582#define EREG_MDACK 7
583
584#define EREG_BANKSIZE 8
585
586#define CD1400_CLK 25000000
587#define CD1400_CLK8M 20000000
588
589/*
590 * Define the cd1400 baud rate clocks. These are used when calculating
591 * what clock and divisor to use for the required baud rate. Also
592 * define the maximum baud rate allowed, and the default base baud.
593 */
594static int stl_cd1400clkdivs[] = {
595 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
596};
597
598/*****************************************************************************/
599
600/*
601 * SC26198 UART specific data initization.
602 */
603static uart_t stl_sc26198uart = {
604 stl_sc26198panelinit,
605 stl_sc26198portinit,
606 stl_sc26198setport,
607 stl_sc26198getsignals,
608 stl_sc26198setsignals,
609 stl_sc26198enablerxtx,
610 stl_sc26198startrxtx,
611 stl_sc26198disableintrs,
612 stl_sc26198sendbreak,
613 stl_sc26198flowctrl,
614 stl_sc26198sendflow,
615 stl_sc26198flush,
616 stl_sc26198datastate,
617 stl_sc26198intr
618};
619
620/*
621 * Define the offsets within the register bank of a sc26198 based panel.
622 */
623#define XP_DATA 0
624#define XP_ADDR 1
625#define XP_MODID 2
626#define XP_STATUS 2
627#define XP_IACK 3
628
629#define XP_BANKSIZE 4
630
631/*
632 * Define the sc26198 baud rate table. Offsets within the table
633 * represent the actual baud rate selector of sc26198 registers.
634 */
635static unsigned int sc26198_baudtable[] = {
636 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
637 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
638 230400, 460800, 921600
639};
640
Tobias Klauserfe971072006-01-09 20:54:02 -0800641#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
643/*****************************************************************************/
644
645/*
646 * Define the driver info for a user level control device. Used mainly
647 * to get at port stats - only not using the port device itself.
648 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700649static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 .owner = THIS_MODULE,
651 .ioctl = stl_memioctl,
652};
653
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800654static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
656/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 * Check for any arguments passed in on the module load command line.
658 */
659
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660/*****************************************************************************/
661
662/*
663 * Convert an ascii string number into an unsigned long.
664 */
665
666static unsigned long stl_atol(char *str)
667{
668 unsigned long val;
669 int base, c;
670 char *sp;
671
672 val = 0;
673 sp = str;
674 if ((*sp == '0') && (*(sp+1) == 'x')) {
675 base = 16;
676 sp += 2;
677 } else if (*sp == '0') {
678 base = 8;
679 sp++;
680 } else {
681 base = 10;
682 }
683
684 for (; (*sp != 0); sp++) {
685 c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
686 if ((c < 0) || (c >= base)) {
687 printk("STALLION: invalid argument %s\n", str);
688 val = 0;
689 break;
690 }
691 val = (val * base) + c;
692 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100693 return val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694}
695
696/*****************************************************************************/
697
698/*
699 * Parse the supplied argument string, into the board conf struct.
700 */
701
Jiri Slaby40e82652006-12-08 02:38:41 -0800702static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
704 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800705 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Jiri Slabya0564e12006-12-08 02:38:37 -0800707 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Jiri Slaby615e4a72006-12-08 02:38:38 -0800709 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100710 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
713 *sp = TOLOWER(*sp);
714
Tobias Klauserfe971072006-01-09 20:54:02 -0800715 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
717 break;
718 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800719 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800721 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 }
723
724 confp->brdtype = stl_brdstr[i].type;
725
726 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800727 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 confp->ioaddr1 = stl_atol(argp[i]);
729 i++;
730 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800731 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 confp->ioaddr2 = stl_atol(argp[i]);
733 i++;
734 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800735 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 confp->irq = stl_atol(argp[i]);
Jesper Juhl014c2542006-01-15 02:37:08 +0100737 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738}
739
740/*****************************************************************************/
741
742/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 * Allocate a new board structure. Fill out the basic info in it.
744 */
745
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800746static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800748 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800750 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800751 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700752 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800753 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800754 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 }
756
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100758 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759}
760
Jiri Slaby96b066b2006-12-08 02:38:42 -0800761static void __init stl_argbrds(void)
762{
763 struct stlconf conf;
764 struct stlbrd *brdp;
765 int i;
766
767 pr_debug("stl_argbrds()\n");
768
769 for (i = stl_nrbrds; (i < stl_nargs); i++) {
770 memset(&conf, 0, sizeof(conf));
771 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
772 continue;
773 if ((brdp = stl_allocbrd()) == NULL)
774 continue;
775 stl_nrbrds = i + 1;
776 brdp->brdnr = i;
777 brdp->brdtype = conf.brdtype;
778 brdp->ioaddr1 = conf.ioaddr1;
779 brdp->ioaddr2 = conf.ioaddr2;
780 brdp->irq = conf.irq;
781 brdp->irqtype = conf.irqtype;
782 stl_brdinit(brdp);
783 }
784}
785
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786/*****************************************************************************/
787
788static int stl_open(struct tty_struct *tty, struct file *filp)
789{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800790 struct stlport *portp;
791 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 unsigned int minordev;
793 int brdnr, panelnr, portnr, rc;
794
Jiri Slabya0564e12006-12-08 02:38:37 -0800795 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797 minordev = tty->index;
798 brdnr = MINOR2BRD(minordev);
799 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100800 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800802 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100803 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 minordev = MINOR2PORT(minordev);
805 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800806 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 break;
808 if (minordev < brdp->panels[panelnr]->nrports) {
809 portnr = minordev;
810 break;
811 }
812 minordev -= brdp->panels[panelnr]->nrports;
813 }
814 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100815 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
817 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800818 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100819 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821/*
822 * On the first open of the device setup the port hardware, and
823 * initialize the per port data structure.
824 */
825 portp->tty = tty;
826 tty->driver_data = portp;
827 portp->refcount++;
828
829 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800830 if (!portp->tx.buf) {
831 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
832 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100833 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 portp->tx.head = portp->tx.buf;
835 portp->tx.tail = portp->tx.buf;
836 }
837 stl_setport(portp, tty->termios);
838 portp->sigs = stl_getsignals(portp);
839 stl_setsignals(portp, 1, 1);
840 stl_enablerxtx(portp, 1, 1);
841 stl_startrxtx(portp, 1, 0);
842 clear_bit(TTY_IO_ERROR, &tty->flags);
843 portp->flags |= ASYNC_INITIALIZED;
844 }
845
846/*
847 * Check if this port is in the middle of closing. If so then wait
848 * until it is closed then return error status, based on flag settings.
849 * The sleep here does not need interrupt protection since the wakeup
850 * for it is done with the same context.
851 */
852 if (portp->flags & ASYNC_CLOSING) {
853 interruptible_sleep_on(&portp->close_wait);
854 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100855 return -EAGAIN;
856 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 }
858
859/*
860 * Based on type of open being done check if it can overlap with any
861 * previous opens still in effect. If we are a normal serial device
862 * then also we might have to wait for carrier.
863 */
864 if (!(filp->f_flags & O_NONBLOCK)) {
865 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100866 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 }
868 portp->flags |= ASYNC_NORMAL_ACTIVE;
869
Jesper Juhl014c2542006-01-15 02:37:08 +0100870 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871}
872
873/*****************************************************************************/
874
875/*
876 * Possibly need to wait for carrier (DCD signal) to come high. Say
877 * maybe because if we are clocal then we don't need to wait...
878 */
879
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800880static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881{
882 unsigned long flags;
883 int rc, doclocal;
884
Jiri Slabya0564e12006-12-08 02:38:37 -0800885 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 rc = 0;
888 doclocal = 0;
889
Alan Coxb65b5b52006-06-27 02:54:05 -0700890 spin_lock_irqsave(&stallion_lock, flags);
891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 if (portp->tty->termios->c_cflag & CLOCAL)
893 doclocal++;
894
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 portp->openwaitcnt++;
896 if (! tty_hung_up_p(filp))
897 portp->refcount--;
898
899 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700900 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 stl_setsignals(portp, 1, 1);
902 if (tty_hung_up_p(filp) ||
903 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
904 if (portp->flags & ASYNC_HUP_NOTIFY)
905 rc = -EBUSY;
906 else
907 rc = -ERESTARTSYS;
908 break;
909 }
910 if (((portp->flags & ASYNC_CLOSING) == 0) &&
911 (doclocal || (portp->sigs & TIOCM_CD))) {
912 break;
913 }
914 if (signal_pending(current)) {
915 rc = -ERESTARTSYS;
916 break;
917 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700918 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 interruptible_sleep_on(&portp->open_wait);
920 }
921
922 if (! tty_hung_up_p(filp))
923 portp->refcount++;
924 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700925 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Jesper Juhl014c2542006-01-15 02:37:08 +0100927 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928}
929
930/*****************************************************************************/
931
Jiri Slaby96b066b2006-12-08 02:38:42 -0800932static void stl_flushbuffer(struct tty_struct *tty)
933{
934 struct stlport *portp;
935
936 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
937
938 if (tty == NULL)
939 return;
940 portp = tty->driver_data;
941 if (portp == NULL)
942 return;
943
944 stl_flush(portp);
945 tty_wakeup(tty);
946}
947
948/*****************************************************************************/
949
950static void stl_waituntilsent(struct tty_struct *tty, int timeout)
951{
952 struct stlport *portp;
953 unsigned long tend;
954
955 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
956
957 if (tty == NULL)
958 return;
959 portp = tty->driver_data;
960 if (portp == NULL)
961 return;
962
963 if (timeout == 0)
964 timeout = HZ;
965 tend = jiffies + timeout;
966
967 while (stl_datastate(portp)) {
968 if (signal_pending(current))
969 break;
970 msleep_interruptible(20);
971 if (time_after_eq(jiffies, tend))
972 break;
973 }
974}
975
976/*****************************************************************************/
977
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978static void stl_close(struct tty_struct *tty, struct file *filp)
979{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800980 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 unsigned long flags;
982
Jiri Slabya0564e12006-12-08 02:38:37 -0800983 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
985 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800986 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 return;
988
Alan Coxb65b5b52006-06-27 02:54:05 -0700989 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700991 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 return;
993 }
994 if ((tty->count == 1) && (portp->refcount != 1))
995 portp->refcount = 1;
996 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700997 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 return;
999 }
1000
1001 portp->refcount = 0;
1002 portp->flags |= ASYNC_CLOSING;
1003
1004/*
1005 * May want to wait for any data to drain before closing. The BUSY
1006 * flag keeps track of whether we are still sending or not - it is
1007 * very accurate for the cd1400, not quite so for the sc26198.
1008 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
1009 */
1010 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -07001011
1012 spin_unlock_irqrestore(&stallion_lock, flags);
1013
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1015 tty_wait_until_sent(tty, portp->closing_wait);
1016 stl_waituntilsent(tty, (HZ / 2));
1017
Alan Coxb65b5b52006-06-27 02:54:05 -07001018
1019 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -07001021 spin_unlock_irqrestore(&stallion_lock, flags);
1022
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 stl_disableintrs(portp);
1024 if (tty->termios->c_cflag & HUPCL)
1025 stl_setsignals(portp, 0, 0);
1026 stl_enablerxtx(portp, 0, 0);
1027 stl_flushbuffer(tty);
1028 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001029 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001031 portp->tx.buf = NULL;
1032 portp->tx.head = NULL;
1033 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 }
1035 set_bit(TTY_IO_ERROR, &tty->flags);
1036 tty_ldisc_flush(tty);
1037
1038 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001039 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
1041 if (portp->openwaitcnt) {
1042 if (portp->close_delay)
1043 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
1044 wake_up_interruptible(&portp->open_wait);
1045 }
1046
1047 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1048 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049}
1050
1051/*****************************************************************************/
1052
1053/*
1054 * Write routine. Take data and stuff it in to the TX ring queue.
1055 * If transmit interrupts are not running then start them.
1056 */
1057
1058static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
1059{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001060 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 unsigned int len, stlen;
1062 unsigned char *chbuf;
1063 char *head, *tail;
1064
Jiri Slabya0564e12006-12-08 02:38:37 -08001065 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001068 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001069 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001070 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001071 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
1073/*
1074 * If copying direct from user space we must cater for page faults,
1075 * causing us to "sleep" here for a while. To handle this copy in all
1076 * the data we need now, into a local buffer. Then when we got it all
1077 * copy it into the TX buffer.
1078 */
1079 chbuf = (unsigned char *) buf;
1080
1081 head = portp->tx.head;
1082 tail = portp->tx.tail;
1083 if (head >= tail) {
1084 len = STL_TXBUFSIZE - (head - tail) - 1;
1085 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1086 } else {
1087 len = tail - head - 1;
1088 stlen = len;
1089 }
1090
1091 len = MIN(len, count);
1092 count = 0;
1093 while (len > 0) {
1094 stlen = MIN(len, stlen);
1095 memcpy(head, chbuf, stlen);
1096 len -= stlen;
1097 chbuf += stlen;
1098 count += stlen;
1099 head += stlen;
1100 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1101 head = portp->tx.buf;
1102 stlen = tail - head;
1103 }
1104 }
1105 portp->tx.head = head;
1106
1107 clear_bit(ASYI_TXLOW, &portp->istate);
1108 stl_startrxtx(portp, -1, 1);
1109
Jesper Juhl014c2542006-01-15 02:37:08 +01001110 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111}
1112
1113/*****************************************************************************/
1114
1115static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1116{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001117 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 unsigned int len;
1119 char *head, *tail;
1120
Jiri Slabya0564e12006-12-08 02:38:37 -08001121 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
Jiri Slaby615e4a72006-12-08 02:38:38 -08001123 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 return;
1125 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001126 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001128 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 return;
1130
1131 head = portp->tx.head;
1132 tail = portp->tx.tail;
1133
1134 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1135 len--;
1136
1137 if (len > 0) {
1138 *head++ = ch;
1139 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1140 head = portp->tx.buf;
1141 }
1142 portp->tx.head = head;
1143}
1144
1145/*****************************************************************************/
1146
1147/*
1148 * If there are any characters in the buffer then make sure that TX
1149 * interrupts are on and get'em out. Normally used after the putchar
1150 * routine has been called.
1151 */
1152
1153static void stl_flushchars(struct tty_struct *tty)
1154{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001155 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
Jiri Slabya0564e12006-12-08 02:38:37 -08001157 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Jiri Slaby615e4a72006-12-08 02:38:38 -08001159 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 return;
1161 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001162 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001164 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 return;
1166
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 stl_startrxtx(portp, -1, 1);
1168}
1169
1170/*****************************************************************************/
1171
1172static int stl_writeroom(struct tty_struct *tty)
1173{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001174 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 char *head, *tail;
1176
Jiri Slabya0564e12006-12-08 02:38:37 -08001177 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
Jiri Slaby615e4a72006-12-08 02:38:38 -08001179 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001180 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001182 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001183 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001184 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001185 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
1187 head = portp->tx.head;
1188 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001189 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190}
1191
1192/*****************************************************************************/
1193
1194/*
1195 * Return number of chars in the TX buffer. Normally we would just
1196 * calculate the number of chars in the buffer and return that, but if
1197 * the buffer is empty and TX interrupts are still on then we return
1198 * that the buffer still has 1 char in it. This way whoever called us
1199 * will not think that ALL chars have drained - since the UART still
1200 * must have some chars in it (we are busy after all).
1201 */
1202
1203static int stl_charsinbuffer(struct tty_struct *tty)
1204{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001205 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 unsigned int size;
1207 char *head, *tail;
1208
Jiri Slabya0564e12006-12-08 02:38:37 -08001209 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
Jiri Slaby615e4a72006-12-08 02:38:38 -08001211 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001212 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001214 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001215 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001216 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001217 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
1219 head = portp->tx.head;
1220 tail = portp->tx.tail;
1221 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1222 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1223 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001224 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225}
1226
1227/*****************************************************************************/
1228
1229/*
1230 * Generate the serial struct info.
1231 */
1232
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001233static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234{
1235 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001236 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Jiri Slabya0564e12006-12-08 02:38:37 -08001238 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
1240 memset(&sio, 0, sizeof(struct serial_struct));
1241 sio.line = portp->portnr;
1242 sio.port = portp->ioaddr;
1243 sio.flags = portp->flags;
1244 sio.baud_base = portp->baud_base;
1245 sio.close_delay = portp->close_delay;
1246 sio.closing_wait = portp->closing_wait;
1247 sio.custom_divisor = portp->custom_divisor;
1248 sio.hub6 = 0;
1249 if (portp->uartp == &stl_cd1400uart) {
1250 sio.type = PORT_CIRRUS;
1251 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1252 } else {
1253 sio.type = PORT_UNKNOWN;
1254 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1255 }
1256
1257 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001258 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 sio.irq = brdp->irq;
1260
1261 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1262}
1263
1264/*****************************************************************************/
1265
1266/*
1267 * Set port according to the serial struct info.
1268 * At this point we do not do any auto-configure stuff, so we will
1269 * just quietly ignore any requests to change irq, etc.
1270 */
1271
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001272static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273{
1274 struct serial_struct sio;
1275
Jiri Slabya0564e12006-12-08 02:38:37 -08001276 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
1278 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1279 return -EFAULT;
1280 if (!capable(CAP_SYS_ADMIN)) {
1281 if ((sio.baud_base != portp->baud_base) ||
1282 (sio.close_delay != portp->close_delay) ||
1283 ((sio.flags & ~ASYNC_USR_MASK) !=
1284 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001285 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 }
1287
1288 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1289 (sio.flags & ASYNC_USR_MASK);
1290 portp->baud_base = sio.baud_base;
1291 portp->close_delay = sio.close_delay;
1292 portp->closing_wait = sio.closing_wait;
1293 portp->custom_divisor = sio.custom_divisor;
1294 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001295 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296}
1297
1298/*****************************************************************************/
1299
1300static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1301{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001302 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Jiri Slaby615e4a72006-12-08 02:38:38 -08001304 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001305 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001307 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001308 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001310 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
1312 return stl_getsignals(portp);
1313}
1314
1315static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1316 unsigned int set, unsigned int clear)
1317{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001318 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 int rts = -1, dtr = -1;
1320
Jiri Slaby615e4a72006-12-08 02:38:38 -08001321 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001322 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001324 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001325 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001327 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
1329 if (set & TIOCM_RTS)
1330 rts = 1;
1331 if (set & TIOCM_DTR)
1332 dtr = 1;
1333 if (clear & TIOCM_RTS)
1334 rts = 0;
1335 if (clear & TIOCM_DTR)
1336 dtr = 0;
1337
1338 stl_setsignals(portp, dtr, rts);
1339 return 0;
1340}
1341
1342static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1343{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001344 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 unsigned int ival;
1346 int rc;
1347 void __user *argp = (void __user *)arg;
1348
Jiri Slabya0564e12006-12-08 02:38:37 -08001349 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1350 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Jiri Slaby615e4a72006-12-08 02:38:38 -08001352 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001353 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001355 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001356 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
1358 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1359 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1360 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001361 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 }
1363
1364 rc = 0;
1365
1366 switch (cmd) {
1367 case TIOCGSOFTCAR:
1368 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1369 (unsigned __user *) argp);
1370 break;
1371 case TIOCSSOFTCAR:
1372 if (get_user(ival, (unsigned int __user *) arg))
1373 return -EFAULT;
1374 tty->termios->c_cflag =
1375 (tty->termios->c_cflag & ~CLOCAL) |
1376 (ival ? CLOCAL : 0);
1377 break;
1378 case TIOCGSERIAL:
1379 rc = stl_getserial(portp, argp);
1380 break;
1381 case TIOCSSERIAL:
1382 rc = stl_setserial(portp, argp);
1383 break;
1384 case COM_GETPORTSTATS:
1385 rc = stl_getportstats(portp, argp);
1386 break;
1387 case COM_CLRPORTSTATS:
1388 rc = stl_clrportstats(portp, argp);
1389 break;
1390 case TIOCSERCONFIG:
1391 case TIOCSERGWILD:
1392 case TIOCSERSWILD:
1393 case TIOCSERGETLSR:
1394 case TIOCSERGSTRUCT:
1395 case TIOCSERGETMULTI:
1396 case TIOCSERSETMULTI:
1397 default:
1398 rc = -ENOIOCTLCMD;
1399 break;
1400 }
1401
Jesper Juhl014c2542006-01-15 02:37:08 +01001402 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403}
1404
1405/*****************************************************************************/
1406
Jiri Slaby96b066b2006-12-08 02:38:42 -08001407/*
1408 * Start the transmitter again. Just turn TX interrupts back on.
1409 */
1410
1411static void stl_start(struct tty_struct *tty)
1412{
1413 struct stlport *portp;
1414
1415 pr_debug("stl_start(tty=%p)\n", tty);
1416
1417 if (tty == NULL)
1418 return;
1419 portp = tty->driver_data;
1420 if (portp == NULL)
1421 return;
1422 stl_startrxtx(portp, -1, 1);
1423}
1424
1425/*****************************************************************************/
1426
Alan Cox606d0992006-12-08 02:38:45 -08001427static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001429 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001430 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
Jiri Slabya0564e12006-12-08 02:38:37 -08001432 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Jiri Slaby615e4a72006-12-08 02:38:38 -08001434 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 return;
1436 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001437 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 return;
1439
1440 tiosp = tty->termios;
1441 if ((tiosp->c_cflag == old->c_cflag) &&
1442 (tiosp->c_iflag == old->c_iflag))
1443 return;
1444
1445 stl_setport(portp, tiosp);
1446 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1447 -1);
1448 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1449 tty->hw_stopped = 0;
1450 stl_start(tty);
1451 }
1452 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1453 wake_up_interruptible(&portp->open_wait);
1454}
1455
1456/*****************************************************************************/
1457
1458/*
1459 * Attempt to flow control who ever is sending us data. Based on termios
1460 * settings use software or/and hardware flow control.
1461 */
1462
1463static void stl_throttle(struct tty_struct *tty)
1464{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001465 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Jiri Slabya0564e12006-12-08 02:38:37 -08001467 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Jiri Slaby615e4a72006-12-08 02:38:38 -08001469 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 return;
1471 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001472 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 return;
1474 stl_flowctrl(portp, 0);
1475}
1476
1477/*****************************************************************************/
1478
1479/*
1480 * Unflow control the device sending us data...
1481 */
1482
1483static void stl_unthrottle(struct tty_struct *tty)
1484{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001485 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
Jiri Slabya0564e12006-12-08 02:38:37 -08001487 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Jiri Slaby615e4a72006-12-08 02:38:38 -08001489 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 return;
1491 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001492 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 return;
1494 stl_flowctrl(portp, 1);
1495}
1496
1497/*****************************************************************************/
1498
1499/*
1500 * Stop the transmitter. Basically to do this we will just turn TX
1501 * interrupts off.
1502 */
1503
1504static void stl_stop(struct tty_struct *tty)
1505{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001506 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
Jiri Slabya0564e12006-12-08 02:38:37 -08001508 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
Jiri Slaby615e4a72006-12-08 02:38:38 -08001510 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 return;
1512 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001513 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 return;
1515 stl_startrxtx(portp, -1, 0);
1516}
1517
1518/*****************************************************************************/
1519
1520/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 * Hangup this port. This is pretty much like closing the port, only
1522 * a little more brutal. No waiting for data to drain. Shutdown the
1523 * port and maybe drop signals.
1524 */
1525
1526static void stl_hangup(struct tty_struct *tty)
1527{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001528 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
Jiri Slabya0564e12006-12-08 02:38:37 -08001530 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
Jiri Slaby615e4a72006-12-08 02:38:38 -08001532 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 return;
1534 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001535 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 return;
1537
1538 portp->flags &= ~ASYNC_INITIALIZED;
1539 stl_disableintrs(portp);
1540 if (tty->termios->c_cflag & HUPCL)
1541 stl_setsignals(portp, 0, 0);
1542 stl_enablerxtx(portp, 0, 0);
1543 stl_flushbuffer(tty);
1544 portp->istate = 0;
1545 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001546 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001548 portp->tx.buf = NULL;
1549 portp->tx.head = NULL;
1550 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001552 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1554 portp->refcount = 0;
1555 wake_up_interruptible(&portp->open_wait);
1556}
1557
1558/*****************************************************************************/
1559
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560static void stl_breakctl(struct tty_struct *tty, int state)
1561{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001562 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Jiri Slabya0564e12006-12-08 02:38:37 -08001564 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
Jiri Slaby615e4a72006-12-08 02:38:38 -08001566 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 return;
1568 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001569 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 return;
1571
1572 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1573}
1574
1575/*****************************************************************************/
1576
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577static void stl_sendxchar(struct tty_struct *tty, char ch)
1578{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001579 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Jiri Slabya0564e12006-12-08 02:38:37 -08001581 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582
Jiri Slaby615e4a72006-12-08 02:38:38 -08001583 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 return;
1585 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001586 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 return;
1588
1589 if (ch == STOP_CHAR(tty))
1590 stl_sendflow(portp, 0);
1591 else if (ch == START_CHAR(tty))
1592 stl_sendflow(portp, 1);
1593 else
1594 stl_putchar(tty, ch);
1595}
1596
1597/*****************************************************************************/
1598
1599#define MAXLINE 80
1600
1601/*
1602 * Format info for a specified port. The line is deliberately limited
1603 * to 80 characters. (If it is too long it will be truncated, if too
1604 * short then padded with spaces).
1605 */
1606
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001607static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608{
1609 char *sp;
1610 int sigs, cnt;
1611
1612 sp = pos;
1613 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1614 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1615 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1616
1617 if (portp->stats.rxframing)
1618 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1619 if (portp->stats.rxparity)
1620 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1621 if (portp->stats.rxbreaks)
1622 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1623 if (portp->stats.rxoverrun)
1624 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1625
1626 sigs = stl_getsignals(portp);
1627 cnt = sprintf(sp, "%s%s%s%s%s ",
1628 (sigs & TIOCM_RTS) ? "|RTS" : "",
1629 (sigs & TIOCM_CTS) ? "|CTS" : "",
1630 (sigs & TIOCM_DTR) ? "|DTR" : "",
1631 (sigs & TIOCM_CD) ? "|DCD" : "",
1632 (sigs & TIOCM_DSR) ? "|DSR" : "");
1633 *sp = ' ';
1634 sp += cnt;
1635
1636 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1637 *sp++ = ' ';
1638 if (cnt >= MAXLINE)
1639 pos[(MAXLINE - 2)] = '+';
1640 pos[(MAXLINE - 1)] = '\n';
1641
Jesper Juhl014c2542006-01-15 02:37:08 +01001642 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643}
1644
1645/*****************************************************************************/
1646
1647/*
1648 * Port info, read from the /proc file system.
1649 */
1650
1651static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1652{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001653 struct stlbrd *brdp;
1654 struct stlpanel *panelp;
1655 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 int brdnr, panelnr, portnr, totalport;
1657 int curoff, maxoff;
1658 char *pos;
1659
Jiri Slabya0564e12006-12-08 02:38:37 -08001660 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1661 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
1663 pos = page;
1664 totalport = 0;
1665 curoff = 0;
1666
1667 if (off == 0) {
1668 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1669 stl_drvversion);
1670 while (pos < (page + MAXLINE - 1))
1671 *pos++ = ' ';
1672 *pos++ = '\n';
1673 }
1674 curoff = MAXLINE;
1675
1676/*
1677 * We scan through for each board, panel and port. The offset is
1678 * calculated on the fly, and irrelevant ports are skipped.
1679 */
1680 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1681 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001682 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 continue;
1684 if (brdp->state == 0)
1685 continue;
1686
1687 maxoff = curoff + (brdp->nrports * MAXLINE);
1688 if (off >= maxoff) {
1689 curoff = maxoff;
1690 continue;
1691 }
1692
1693 totalport = brdnr * STL_MAXPORTS;
1694 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1695 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001696 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 continue;
1698
1699 maxoff = curoff + (panelp->nrports * MAXLINE);
1700 if (off >= maxoff) {
1701 curoff = maxoff;
1702 totalport += panelp->nrports;
1703 continue;
1704 }
1705
1706 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1707 totalport++) {
1708 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001709 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 continue;
1711 if (off >= (curoff += MAXLINE))
1712 continue;
1713 if ((pos - page + MAXLINE) > count)
1714 goto stl_readdone;
1715 pos += stl_portinfo(portp, totalport, pos);
1716 }
1717 }
1718 }
1719
1720 *eof = 1;
1721
1722stl_readdone:
1723 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001724 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725}
1726
1727/*****************************************************************************/
1728
1729/*
1730 * All board interrupts are vectored through here first. This code then
1731 * calls off to the approrpriate board interrupt handlers.
1732 */
1733
David Howells7d12e782006-10-05 14:55:46 +01001734static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001736 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
Jiri Slabya0564e12006-12-08 02:38:37 -08001738 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
1740 return IRQ_RETVAL((* brdp->isr)(brdp));
1741}
1742
1743/*****************************************************************************/
1744
1745/*
1746 * Interrupt service routine for EasyIO board types.
1747 */
1748
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001749static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001751 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 unsigned int iobase;
1753 int handled = 0;
1754
Alan Coxb65b5b52006-06-27 02:54:05 -07001755 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 panelp = brdp->panels[0];
1757 iobase = panelp->iobase;
1758 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1759 handled = 1;
1760 (* panelp->isr)(panelp, iobase);
1761 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001762 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 return handled;
1764}
1765
1766/*****************************************************************************/
1767
1768/*
1769 * Interrupt service routine for ECH-AT board types.
1770 */
1771
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001772static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001774 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 unsigned int ioaddr;
1776 int bnknr;
1777 int handled = 0;
1778
1779 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1780
1781 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1782 handled = 1;
1783 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1784 ioaddr = brdp->bnkstataddr[bnknr];
1785 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1786 panelp = brdp->bnk2panel[bnknr];
1787 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1788 }
1789 }
1790 }
1791
1792 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1793
1794 return handled;
1795}
1796
1797/*****************************************************************************/
1798
1799/*
1800 * Interrupt service routine for ECH-MCA board types.
1801 */
1802
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001803static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001805 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 unsigned int ioaddr;
1807 int bnknr;
1808 int handled = 0;
1809
1810 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1811 handled = 1;
1812 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1813 ioaddr = brdp->bnkstataddr[bnknr];
1814 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1815 panelp = brdp->bnk2panel[bnknr];
1816 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1817 }
1818 }
1819 }
1820 return handled;
1821}
1822
1823/*****************************************************************************/
1824
1825/*
1826 * Interrupt service routine for ECH-PCI board types.
1827 */
1828
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001829static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001831 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 unsigned int ioaddr;
1833 int bnknr, recheck;
1834 int handled = 0;
1835
1836 while (1) {
1837 recheck = 0;
1838 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1839 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1840 ioaddr = brdp->bnkstataddr[bnknr];
1841 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1842 panelp = brdp->bnk2panel[bnknr];
1843 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1844 recheck++;
1845 handled = 1;
1846 }
1847 }
1848 if (! recheck)
1849 break;
1850 }
1851 return handled;
1852}
1853
1854/*****************************************************************************/
1855
1856/*
1857 * Interrupt service routine for ECH-8/64-PCI board types.
1858 */
1859
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001860static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001862 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 unsigned int ioaddr;
1864 int bnknr;
1865 int handled = 0;
1866
1867 while (inb(brdp->ioctrl) & 0x1) {
1868 handled = 1;
1869 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1870 ioaddr = brdp->bnkstataddr[bnknr];
1871 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1872 panelp = brdp->bnk2panel[bnknr];
1873 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1874 }
1875 }
1876 }
1877
1878 return handled;
1879}
1880
1881/*****************************************************************************/
1882
1883/*
1884 * Service an off-level request for some channel.
1885 */
Al Viro3e577a82006-12-06 18:41:45 +00001886static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001888 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 struct tty_struct *tty;
1890 unsigned int oldsigs;
1891
Jiri Slabya0564e12006-12-08 02:38:37 -08001892 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
Jiri Slaby615e4a72006-12-08 02:38:38 -08001894 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 return;
1896
1897 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001898 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 return;
1900
1901 lock_kernel();
1902 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1903 tty_wakeup(tty);
1904 }
1905 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1906 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1907 oldsigs = portp->sigs;
1908 portp->sigs = stl_getsignals(portp);
1909 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1910 wake_up_interruptible(&portp->open_wait);
1911 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1912 if (portp->flags & ASYNC_CHECK_CD)
1913 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1914 }
1915 }
1916 unlock_kernel();
1917}
1918
1919/*****************************************************************************/
1920
1921/*
1922 * Initialize all the ports on a panel.
1923 */
1924
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001925static int __init stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001927 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 int chipmask, i;
1929
Jiri Slabya0564e12006-12-08 02:38:37 -08001930 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931
1932 chipmask = stl_panelinit(brdp, panelp);
1933
1934/*
1935 * All UART's are initialized (if found!). Now go through and setup
1936 * each ports data structures.
1937 */
1938 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001939 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001940 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001942 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 break;
1944 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945
1946 portp->magic = STL_PORTMAGIC;
1947 portp->portnr = i;
1948 portp->brdnr = panelp->brdnr;
1949 portp->panelnr = panelp->panelnr;
1950 portp->uartp = panelp->uartp;
1951 portp->clk = brdp->clk;
1952 portp->baud_base = STL_BAUDBASE;
1953 portp->close_delay = STL_CLOSEDELAY;
1954 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001955 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 init_waitqueue_head(&portp->open_wait);
1957 init_waitqueue_head(&portp->close_wait);
1958 portp->stats.brd = portp->brdnr;
1959 portp->stats.panel = portp->panelnr;
1960 portp->stats.port = portp->portnr;
1961 panelp->ports[i] = portp;
1962 stl_portinit(brdp, panelp, portp);
1963 }
1964
1965 return(0);
1966}
1967
1968/*****************************************************************************/
1969
1970/*
1971 * Try to find and initialize an EasyIO board.
1972 */
1973
Jiri Slaby40e82652006-12-08 02:38:41 -08001974static int __init stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001976 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 unsigned int status;
1978 char *name;
1979 int rc;
1980
Jiri Slabya0564e12006-12-08 02:38:37 -08001981 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
1983 brdp->ioctrl = brdp->ioaddr1 + 1;
1984 brdp->iostatus = brdp->ioaddr1 + 2;
1985
1986 status = inb(brdp->iostatus);
1987 if ((status & EIO_IDBITMASK) == EIO_MK3)
1988 brdp->ioctrl++;
1989
1990/*
1991 * Handle board specific stuff now. The real difference is PCI
1992 * or not PCI.
1993 */
1994 if (brdp->brdtype == BRD_EASYIOPCI) {
1995 brdp->iosize1 = 0x80;
1996 brdp->iosize2 = 0x80;
1997 name = "serial(EIO-PCI)";
1998 outb(0x41, (brdp->ioaddr2 + 0x4c));
1999 } else {
2000 brdp->iosize1 = 8;
2001 name = "serial(EIO)";
2002 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2003 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2004 printk("STALLION: invalid irq=%d for brd=%d\n",
2005 brdp->irq, brdp->brdnr);
2006 return(-EINVAL);
2007 }
2008 outb((stl_vecmap[brdp->irq] | EIO_0WS |
2009 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
2010 brdp->ioctrl);
2011 }
2012
2013 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2014 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2015 "%x conflicts with another device\n", brdp->brdnr,
2016 brdp->ioaddr1);
2017 return(-EBUSY);
2018 }
2019
2020 if (brdp->iosize2 > 0)
2021 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2022 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2023 "address %x conflicts with another device\n",
2024 brdp->brdnr, brdp->ioaddr2);
2025 printk(KERN_WARNING "STALLION: Warning, also "
2026 "releasing board %d I/O address %x \n",
2027 brdp->brdnr, brdp->ioaddr1);
2028 release_region(brdp->ioaddr1, brdp->iosize1);
2029 return(-EBUSY);
2030 }
2031
2032/*
2033 * Everything looks OK, so let's go ahead and probe for the hardware.
2034 */
2035 brdp->clk = CD1400_CLK;
2036 brdp->isr = stl_eiointr;
2037
2038 switch (status & EIO_IDBITMASK) {
2039 case EIO_8PORTM:
2040 brdp->clk = CD1400_CLK8M;
2041 /* fall thru */
2042 case EIO_8PORTRS:
2043 case EIO_8PORTDI:
2044 brdp->nrports = 8;
2045 break;
2046 case EIO_4PORTRS:
2047 brdp->nrports = 4;
2048 break;
2049 case EIO_MK3:
2050 switch (status & EIO_BRDMASK) {
2051 case ID_BRD4:
2052 brdp->nrports = 4;
2053 break;
2054 case ID_BRD8:
2055 brdp->nrports = 8;
2056 break;
2057 case ID_BRD16:
2058 brdp->nrports = 16;
2059 break;
2060 default:
2061 return(-ENODEV);
2062 }
2063 break;
2064 default:
2065 return(-ENODEV);
2066 }
2067
2068/*
2069 * We have verified that the board is actually present, so now we
2070 * can complete the setup.
2071 */
2072
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002073 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002074 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002076 "(size=%Zd)\n", sizeof(struct stlpanel));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002077 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079
2080 panelp->magic = STL_PANELMAGIC;
2081 panelp->brdnr = brdp->brdnr;
2082 panelp->panelnr = 0;
2083 panelp->nrports = brdp->nrports;
2084 panelp->iobase = brdp->ioaddr1;
2085 panelp->hwid = status;
2086 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002087 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 panelp->isr = stl_sc26198intr;
2089 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002090 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 panelp->isr = stl_cd1400eiointr;
2092 }
2093
2094 brdp->panels[0] = panelp;
2095 brdp->nrpanels = 1;
2096 brdp->state |= BRD_FOUND;
2097 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002098 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 printk("STALLION: failed to register interrupt "
2100 "routine for %s irq=%d\n", name, brdp->irq);
2101 rc = -ENODEV;
2102 } else {
2103 rc = 0;
2104 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002105 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106}
2107
2108/*****************************************************************************/
2109
2110/*
2111 * Try to find an ECH board and initialize it. This code is capable of
2112 * dealing with all types of ECH board.
2113 */
2114
Jiri Slaby40e82652006-12-08 02:38:41 -08002115static int __init stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002117 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 unsigned int status, nxtid, ioaddr, conflict;
2119 int panelnr, banknr, i;
2120 char *name;
2121
Jiri Slabya0564e12006-12-08 02:38:37 -08002122 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
2124 status = 0;
2125 conflict = 0;
2126
2127/*
2128 * Set up the initial board register contents for boards. This varies a
2129 * bit between the different board types. So we need to handle each
2130 * separately. Also do a check that the supplied IRQ is good.
2131 */
2132 switch (brdp->brdtype) {
2133
2134 case BRD_ECH:
2135 brdp->isr = stl_echatintr;
2136 brdp->ioctrl = brdp->ioaddr1 + 1;
2137 brdp->iostatus = brdp->ioaddr1 + 1;
2138 status = inb(brdp->iostatus);
2139 if ((status & ECH_IDBITMASK) != ECH_ID)
2140 return(-ENODEV);
2141 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2142 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2143 printk("STALLION: invalid irq=%d for brd=%d\n",
2144 brdp->irq, brdp->brdnr);
2145 return(-EINVAL);
2146 }
2147 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2148 status |= (stl_vecmap[brdp->irq] << 1);
2149 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2150 brdp->ioctrlval = ECH_INTENABLE |
2151 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2152 for (i = 0; (i < 10); i++)
2153 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2154 brdp->iosize1 = 2;
2155 brdp->iosize2 = 32;
2156 name = "serial(EC8/32)";
2157 outb(status, brdp->ioaddr1);
2158 break;
2159
2160 case BRD_ECHMC:
2161 brdp->isr = stl_echmcaintr;
2162 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2163 brdp->iostatus = brdp->ioctrl;
2164 status = inb(brdp->iostatus);
2165 if ((status & ECH_IDBITMASK) != ECH_ID)
2166 return(-ENODEV);
2167 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2168 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2169 printk("STALLION: invalid irq=%d for brd=%d\n",
2170 brdp->irq, brdp->brdnr);
2171 return(-EINVAL);
2172 }
2173 outb(ECHMC_BRDRESET, brdp->ioctrl);
2174 outb(ECHMC_INTENABLE, brdp->ioctrl);
2175 brdp->iosize1 = 64;
2176 name = "serial(EC8/32-MC)";
2177 break;
2178
2179 case BRD_ECHPCI:
2180 brdp->isr = stl_echpciintr;
2181 brdp->ioctrl = brdp->ioaddr1 + 2;
2182 brdp->iosize1 = 4;
2183 brdp->iosize2 = 8;
2184 name = "serial(EC8/32-PCI)";
2185 break;
2186
2187 case BRD_ECH64PCI:
2188 brdp->isr = stl_echpci64intr;
2189 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2190 outb(0x43, (brdp->ioaddr1 + 0x4c));
2191 brdp->iosize1 = 0x80;
2192 brdp->iosize2 = 0x80;
2193 name = "serial(EC8/64-PCI)";
2194 break;
2195
2196 default:
2197 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
2198 return(-EINVAL);
2199 break;
2200 }
2201
2202/*
2203 * Check boards for possible IO address conflicts and return fail status
2204 * if an IO conflict found.
2205 */
2206 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2207 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2208 "%x conflicts with another device\n", brdp->brdnr,
2209 brdp->ioaddr1);
2210 return(-EBUSY);
2211 }
2212
2213 if (brdp->iosize2 > 0)
2214 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2215 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2216 "address %x conflicts with another device\n",
2217 brdp->brdnr, brdp->ioaddr2);
2218 printk(KERN_WARNING "STALLION: Warning, also "
2219 "releasing board %d I/O address %x \n",
2220 brdp->brdnr, brdp->ioaddr1);
2221 release_region(brdp->ioaddr1, brdp->iosize1);
2222 return(-EBUSY);
2223 }
2224
2225/*
2226 * Scan through the secondary io address space looking for panels.
2227 * As we find'em allocate and initialize panel structures for each.
2228 */
2229 brdp->clk = CD1400_CLK;
2230 brdp->hwid = status;
2231
2232 ioaddr = brdp->ioaddr2;
2233 banknr = 0;
2234 panelnr = 0;
2235 nxtid = 0;
2236
2237 for (i = 0; (i < STL_MAXPANELS); i++) {
2238 if (brdp->brdtype == BRD_ECHPCI) {
2239 outb(nxtid, brdp->ioctrl);
2240 ioaddr = brdp->ioaddr2;
2241 }
2242 status = inb(ioaddr + ECH_PNLSTATUS);
2243 if ((status & ECH_PNLIDMASK) != nxtid)
2244 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002245 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002246 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002248 "(size=%Zd)\n", sizeof(struct stlpanel));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 break;
2250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 panelp->magic = STL_PANELMAGIC;
2252 panelp->brdnr = brdp->brdnr;
2253 panelp->panelnr = panelnr;
2254 panelp->iobase = ioaddr;
2255 panelp->pagenr = nxtid;
2256 panelp->hwid = status;
2257 brdp->bnk2panel[banknr] = panelp;
2258 brdp->bnkpageaddr[banknr] = nxtid;
2259 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2260
2261 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002262 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 panelp->isr = stl_sc26198intr;
2264 if (status & ECH_PNL16PORT) {
2265 panelp->nrports = 16;
2266 brdp->bnk2panel[banknr] = panelp;
2267 brdp->bnkpageaddr[banknr] = nxtid;
2268 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2269 ECH_PNLSTATUS;
2270 } else {
2271 panelp->nrports = 8;
2272 }
2273 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002274 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 panelp->isr = stl_cd1400echintr;
2276 if (status & ECH_PNL16PORT) {
2277 panelp->nrports = 16;
2278 panelp->ackmask = 0x80;
2279 if (brdp->brdtype != BRD_ECHPCI)
2280 ioaddr += EREG_BANKSIZE;
2281 brdp->bnk2panel[banknr] = panelp;
2282 brdp->bnkpageaddr[banknr] = ++nxtid;
2283 brdp->bnkstataddr[banknr++] = ioaddr +
2284 ECH_PNLSTATUS;
2285 } else {
2286 panelp->nrports = 8;
2287 panelp->ackmask = 0xc0;
2288 }
2289 }
2290
2291 nxtid++;
2292 ioaddr += EREG_BANKSIZE;
2293 brdp->nrports += panelp->nrports;
2294 brdp->panels[panelnr++] = panelp;
2295 if ((brdp->brdtype != BRD_ECHPCI) &&
2296 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
2297 break;
2298 }
2299
2300 brdp->nrpanels = panelnr;
2301 brdp->nrbnks = banknr;
2302 if (brdp->brdtype == BRD_ECH)
2303 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2304
2305 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002306 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 printk("STALLION: failed to register interrupt "
2308 "routine for %s irq=%d\n", name, brdp->irq);
2309 i = -ENODEV;
2310 } else {
2311 i = 0;
2312 }
2313
2314 return(i);
2315}
2316
2317/*****************************************************************************/
2318
2319/*
2320 * Initialize and configure the specified board.
2321 * Scan through all the boards in the configuration and see what we
2322 * can find. Handle EIO and the ECH boards a little differently here
2323 * since the initial search and setup is very different.
2324 */
2325
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002326static int __init stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327{
2328 int i;
2329
Jiri Slabya0564e12006-12-08 02:38:37 -08002330 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
2332 switch (brdp->brdtype) {
2333 case BRD_EASYIO:
2334 case BRD_EASYIOPCI:
2335 stl_initeio(brdp);
2336 break;
2337 case BRD_ECH:
2338 case BRD_ECHMC:
2339 case BRD_ECHPCI:
2340 case BRD_ECH64PCI:
2341 stl_initech(brdp);
2342 break;
2343 default:
2344 printk("STALLION: board=%d is unknown board type=%d\n",
2345 brdp->brdnr, brdp->brdtype);
2346 return(ENODEV);
2347 }
2348
2349 stl_brds[brdp->brdnr] = brdp;
2350 if ((brdp->state & BRD_FOUND) == 0) {
2351 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2352 stl_brdnames[brdp->brdtype], brdp->brdnr,
2353 brdp->ioaddr1, brdp->irq);
2354 return(ENODEV);
2355 }
2356
2357 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002358 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 stl_initports(brdp, brdp->panels[i]);
2360
2361 printk("STALLION: %s found, board=%d io=%x irq=%d "
2362 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2363 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2364 brdp->nrports);
2365 return(0);
2366}
2367
2368/*****************************************************************************/
2369
2370/*
2371 * Find the next available board number that is free.
2372 */
2373
Jiri Slaby40e82652006-12-08 02:38:41 -08002374static int __init stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375{
2376 int i;
2377
2378 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002379 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 if (i >= stl_nrbrds)
2381 stl_nrbrds = i + 1;
2382 return(i);
2383 }
2384 }
2385 return(-1);
2386}
2387
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002388static void stl_cleanup_panels(struct stlbrd *brdp)
2389{
2390 struct stlpanel *panelp;
2391 struct stlport *portp;
2392 unsigned int j, k;
2393
2394 for (j = 0; j < STL_MAXPANELS; j++) {
2395 panelp = brdp->panels[j];
2396 if (panelp == NULL)
2397 continue;
2398 for (k = 0; k < STL_PORTSPERPANEL; k++) {
2399 portp = panelp->ports[k];
2400 if (portp == NULL)
2401 continue;
2402 if (portp->tty != NULL)
2403 stl_hangup(portp->tty);
2404 kfree(portp->tx.buf);
2405 kfree(portp);
2406 }
2407 kfree(panelp);
2408 }
2409}
2410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412/*
2413 * We have a Stallion board. Allocate a board structure and
2414 * initialize it. Read its IO and IRQ resources from PCI
2415 * configuration space.
2416 */
2417
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002418static int __devinit stl_pciprobe(struct pci_dev *pdev,
2419 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002421 struct stlbrd *brdp;
2422 unsigned int brdtype = ent->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002424 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
2425 return -ENODEV;
2426
2427 dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
2428 pdev->vendor, pdev->device, pdev->class);
2429
2430 if (pci_enable_device(pdev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 return(-EIO);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002432 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 return(-ENOMEM);
2434 if ((brdp->brdnr = stl_getbrdnr()) < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002435 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 "maximum supported %d\n", STL_MAXBRDS);
2437 return(0);
2438 }
2439 brdp->brdtype = brdtype;
2440
2441/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 * We have all resources from the board, so let's setup the actual
2443 * board structure now.
2444 */
2445 switch (brdtype) {
2446 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002447 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2448 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 break;
2450 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002451 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2452 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 break;
2454 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002455 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2456 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 break;
2458 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002459 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 break;
2461 }
2462
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002463 brdp->irq = pdev->irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 stl_brdinit(brdp);
2465
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002466 pci_set_drvdata(pdev, brdp);
2467
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 return(0);
2469}
2470
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002471static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002473 struct stlbrd *brdp = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002475 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002477 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002479 release_region(brdp->ioaddr1, brdp->iosize1);
2480 if (brdp->iosize2 > 0)
2481 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002483 stl_brds[brdp->brdnr] = NULL;
2484 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485}
2486
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002487static struct pci_driver stl_pcidriver = {
2488 .name = "stallion",
2489 .id_table = stl_pcibrds,
2490 .probe = stl_pciprobe,
2491 .remove = __devexit_p(stl_pciremove)
2492};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
2494/*****************************************************************************/
2495
2496/*
2497 * Scan through all the boards in the configuration and see what we
2498 * can find. Handle EIO and the ECH boards a little differently here
2499 * since the initial search and setup is too different.
2500 */
2501
Jiri Slaby40e82652006-12-08 02:38:41 -08002502static int __init stl_initbrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002504 struct stlbrd *brdp;
2505 struct stlconf *confp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 int i;
2507
Jiri Slabya0564e12006-12-08 02:38:37 -08002508 pr_debug("stl_initbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
2510 if (stl_nrbrds > STL_MAXBRDS) {
2511 printk("STALLION: too many boards in configuration table, "
2512 "truncating to %d\n", STL_MAXBRDS);
2513 stl_nrbrds = STL_MAXBRDS;
2514 }
2515
2516/*
2517 * Firstly scan the list of static boards configured. Allocate
2518 * resources and initialize the boards as found.
2519 */
2520 for (i = 0; (i < stl_nrbrds); i++) {
2521 confp = &stl_brdconf[i];
2522 stl_parsebrd(confp, stl_brdsp[i]);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002523 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 return(-ENOMEM);
2525 brdp->brdnr = i;
2526 brdp->brdtype = confp->brdtype;
2527 brdp->ioaddr1 = confp->ioaddr1;
2528 brdp->ioaddr2 = confp->ioaddr2;
2529 brdp->irq = confp->irq;
2530 brdp->irqtype = confp->irqtype;
2531 stl_brdinit(brdp);
2532 }
2533
2534/*
2535 * Find any dynamically supported boards. That is via module load
2536 * line options or auto-detected on the PCI bus.
2537 */
2538 stl_argbrds();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
2540 return(0);
2541}
2542
2543/*****************************************************************************/
2544
2545/*
2546 * Return the board stats structure to user app.
2547 */
2548
2549static int stl_getbrdstats(combrd_t __user *bp)
2550{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002551 struct stlbrd *brdp;
2552 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 int i;
2554
2555 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2556 return -EFAULT;
2557 if (stl_brdstats.brd >= STL_MAXBRDS)
2558 return(-ENODEV);
2559 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002560 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 return(-ENODEV);
2562
2563 memset(&stl_brdstats, 0, sizeof(combrd_t));
2564 stl_brdstats.brd = brdp->brdnr;
2565 stl_brdstats.type = brdp->brdtype;
2566 stl_brdstats.hwid = brdp->hwid;
2567 stl_brdstats.state = brdp->state;
2568 stl_brdstats.ioaddr = brdp->ioaddr1;
2569 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2570 stl_brdstats.irq = brdp->irq;
2571 stl_brdstats.nrpanels = brdp->nrpanels;
2572 stl_brdstats.nrports = brdp->nrports;
2573 for (i = 0; (i < brdp->nrpanels); i++) {
2574 panelp = brdp->panels[i];
2575 stl_brdstats.panels[i].panel = i;
2576 stl_brdstats.panels[i].hwid = panelp->hwid;
2577 stl_brdstats.panels[i].nrports = panelp->nrports;
2578 }
2579
2580 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2581}
2582
2583/*****************************************************************************/
2584
2585/*
2586 * Resolve the referenced port number into a port struct pointer.
2587 */
2588
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002589static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002591 struct stlbrd *brdp;
2592 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593
2594 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002595 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002597 if (brdp == NULL)
2598 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002600 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002602 if (panelp == NULL)
2603 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002605 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 return(panelp->ports[portnr]);
2607}
2608
2609/*****************************************************************************/
2610
2611/*
2612 * Return the port stats structure to user app. A NULL port struct
2613 * pointer passed in means that we need to find out from the app
2614 * what port to get stats for (used through board control device).
2615 */
2616
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002617static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618{
2619 unsigned char *head, *tail;
2620 unsigned long flags;
2621
2622 if (!portp) {
2623 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2624 return -EFAULT;
2625 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2626 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002627 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 return(-ENODEV);
2629 }
2630
2631 portp->stats.state = portp->istate;
2632 portp->stats.flags = portp->flags;
2633 portp->stats.hwid = portp->hwid;
2634
2635 portp->stats.ttystate = 0;
2636 portp->stats.cflags = 0;
2637 portp->stats.iflags = 0;
2638 portp->stats.oflags = 0;
2639 portp->stats.lflags = 0;
2640 portp->stats.rxbuffered = 0;
2641
Alan Coxb65b5b52006-06-27 02:54:05 -07002642 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002643 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 if (portp->tty->driver_data == portp) {
2645 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002646 /* No longer available as a statistic */
2647 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002648 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 portp->stats.cflags = portp->tty->termios->c_cflag;
2650 portp->stats.iflags = portp->tty->termios->c_iflag;
2651 portp->stats.oflags = portp->tty->termios->c_oflag;
2652 portp->stats.lflags = portp->tty->termios->c_lflag;
2653 }
2654 }
2655 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002656 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657
2658 head = portp->tx.head;
2659 tail = portp->tx.tail;
2660 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2661 (STL_TXBUFSIZE - (tail - head)));
2662
2663 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2664
2665 return copy_to_user(cp, &portp->stats,
2666 sizeof(comstats_t)) ? -EFAULT : 0;
2667}
2668
2669/*****************************************************************************/
2670
2671/*
2672 * Clear the port stats structure. We also return it zeroed out...
2673 */
2674
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002675static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676{
2677 if (!portp) {
2678 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2679 return -EFAULT;
2680 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2681 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002682 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 return(-ENODEV);
2684 }
2685
2686 memset(&portp->stats, 0, sizeof(comstats_t));
2687 portp->stats.brd = portp->brdnr;
2688 portp->stats.panel = portp->panelnr;
2689 portp->stats.port = portp->portnr;
2690 return copy_to_user(cp, &portp->stats,
2691 sizeof(comstats_t)) ? -EFAULT : 0;
2692}
2693
2694/*****************************************************************************/
2695
2696/*
2697 * Return the entire driver ports structure to a user app.
2698 */
2699
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002700static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002702 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002704 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 return -EFAULT;
2706 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2707 stl_dummyport.portnr);
2708 if (!portp)
2709 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002710 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711}
2712
2713/*****************************************************************************/
2714
2715/*
2716 * Return the entire driver board structure to a user app.
2717 */
2718
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002719static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002721 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002723 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 return -EFAULT;
2725 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2726 return -ENODEV;
2727 brdp = stl_brds[stl_dummybrd.brdnr];
2728 if (!brdp)
2729 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002730 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731}
2732
2733/*****************************************************************************/
2734
2735/*
2736 * The "staliomem" device is also required to do some special operations
2737 * on the board and/or ports. In this driver it is mostly used for stats
2738 * collection.
2739 */
2740
2741static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2742{
2743 int brdnr, rc;
2744 void __user *argp = (void __user *)arg;
2745
Jiri Slabya0564e12006-12-08 02:38:37 -08002746 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747
2748 brdnr = iminor(ip);
2749 if (brdnr >= STL_MAXBRDS)
2750 return(-ENODEV);
2751 rc = 0;
2752
2753 switch (cmd) {
2754 case COM_GETPORTSTATS:
2755 rc = stl_getportstats(NULL, argp);
2756 break;
2757 case COM_CLRPORTSTATS:
2758 rc = stl_clrportstats(NULL, argp);
2759 break;
2760 case COM_GETBRDSTATS:
2761 rc = stl_getbrdstats(argp);
2762 break;
2763 case COM_READPORT:
2764 rc = stl_getportstruct(argp);
2765 break;
2766 case COM_READBOARD:
2767 rc = stl_getbrdstruct(argp);
2768 break;
2769 default:
2770 rc = -ENOIOCTLCMD;
2771 break;
2772 }
2773
2774 return(rc);
2775}
2776
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002777static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 .open = stl_open,
2779 .close = stl_close,
2780 .write = stl_write,
2781 .put_char = stl_putchar,
2782 .flush_chars = stl_flushchars,
2783 .write_room = stl_writeroom,
2784 .chars_in_buffer = stl_charsinbuffer,
2785 .ioctl = stl_ioctl,
2786 .set_termios = stl_settermios,
2787 .throttle = stl_throttle,
2788 .unthrottle = stl_unthrottle,
2789 .stop = stl_stop,
2790 .start = stl_start,
2791 .hangup = stl_hangup,
2792 .flush_buffer = stl_flushbuffer,
2793 .break_ctl = stl_breakctl,
2794 .wait_until_sent = stl_waituntilsent,
2795 .send_xchar = stl_sendxchar,
2796 .read_proc = stl_readproc,
2797 .tiocmget = stl_tiocmget,
2798 .tiocmset = stl_tiocmset,
2799};
2800
2801/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802/* CD1400 HARDWARE FUNCTIONS */
2803/*****************************************************************************/
2804
2805/*
2806 * These functions get/set/update the registers of the cd1400 UARTs.
2807 * Access to the cd1400 registers is via an address/data io port pair.
2808 * (Maybe should make this inline...)
2809 */
2810
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002811static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812{
2813 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002814 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815}
2816
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002817static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818{
2819 outb((regnr + portp->uartaddr), portp->ioaddr);
2820 outb(value, portp->ioaddr + EREG_DATA);
2821}
2822
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002823static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824{
2825 outb((regnr + portp->uartaddr), portp->ioaddr);
2826 if (inb(portp->ioaddr + EREG_DATA) != value) {
2827 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002828 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002830 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831}
2832
2833/*****************************************************************************/
2834
2835/*
2836 * Inbitialize the UARTs in a panel. We don't care what sort of board
2837 * these ports are on - since the port io registers are almost
2838 * identical when dealing with ports.
2839 */
2840
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002841static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842{
2843 unsigned int gfrcr;
2844 int chipmask, i, j;
2845 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002846 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847
Jiri Slabya0564e12006-12-08 02:38:37 -08002848 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849
Alan Coxb65b5b52006-06-27 02:54:05 -07002850 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 BRDENABLE(panelp->brdnr, panelp->pagenr);
2852
2853/*
2854 * Check that each chip is present and started up OK.
2855 */
2856 chipmask = 0;
2857 nrchips = panelp->nrports / CD1400_PORTS;
2858 for (i = 0; (i < nrchips); i++) {
2859 if (brdp->brdtype == BRD_ECHPCI) {
2860 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2861 ioaddr = panelp->iobase;
2862 } else {
2863 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2864 }
2865 uartaddr = (i & 0x01) ? 0x080 : 0;
2866 outb((GFRCR + uartaddr), ioaddr);
2867 outb(0, (ioaddr + EREG_DATA));
2868 outb((CCR + uartaddr), ioaddr);
2869 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2870 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2871 outb((GFRCR + uartaddr), ioaddr);
2872 for (j = 0; (j < CCR_MAXWAIT); j++) {
2873 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2874 break;
2875 }
2876 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2877 printk("STALLION: cd1400 not responding, "
2878 "brd=%d panel=%d chip=%d\n",
2879 panelp->brdnr, panelp->panelnr, i);
2880 continue;
2881 }
2882 chipmask |= (0x1 << i);
2883 outb((PPR + uartaddr), ioaddr);
2884 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2885 }
2886
2887 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002888 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002889 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890}
2891
2892/*****************************************************************************/
2893
2894/*
2895 * Initialize hardware specific port registers.
2896 */
2897
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002898static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899{
Alan Coxb65b5b52006-06-27 02:54:05 -07002900 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002901 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2902 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903
Jiri Slaby615e4a72006-12-08 02:38:38 -08002904 if ((brdp == NULL) || (panelp == NULL) ||
2905 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 return;
2907
Alan Coxb65b5b52006-06-27 02:54:05 -07002908 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2910 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2911 portp->uartaddr = (portp->portnr & 0x04) << 5;
2912 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2913
2914 BRDENABLE(portp->brdnr, portp->pagenr);
2915 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2916 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2917 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2918 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002919 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920}
2921
2922/*****************************************************************************/
2923
2924/*
2925 * Wait for the command register to be ready. We will poll this,
2926 * since it won't usually take too long to be ready.
2927 */
2928
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002929static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930{
2931 int i;
2932
2933 for (i = 0; (i < CCR_MAXWAIT); i++) {
2934 if (stl_cd1400getreg(portp, CCR) == 0) {
2935 return;
2936 }
2937 }
2938
2939 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2940 portp->portnr, portp->panelnr, portp->brdnr);
2941}
2942
2943/*****************************************************************************/
2944
2945/*
2946 * Set up the cd1400 registers for a port based on the termios port
2947 * settings.
2948 */
2949
Alan Cox606d0992006-12-08 02:38:45 -08002950static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002952 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 unsigned long flags;
2954 unsigned int clkdiv, baudrate;
2955 unsigned char cor1, cor2, cor3;
2956 unsigned char cor4, cor5, ccr;
2957 unsigned char srer, sreron, sreroff;
2958 unsigned char mcor1, mcor2, rtpr;
2959 unsigned char clk, div;
2960
2961 cor1 = 0;
2962 cor2 = 0;
2963 cor3 = 0;
2964 cor4 = 0;
2965 cor5 = 0;
2966 ccr = 0;
2967 rtpr = 0;
2968 clk = 0;
2969 div = 0;
2970 mcor1 = 0;
2971 mcor2 = 0;
2972 sreron = 0;
2973 sreroff = 0;
2974
2975 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002976 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 return;
2978
2979/*
2980 * Set up the RX char ignore mask with those RX error types we
2981 * can ignore. We can get the cd1400 to help us out a little here,
2982 * it will ignore parity errors and breaks for us.
2983 */
2984 portp->rxignoremsk = 0;
2985 if (tiosp->c_iflag & IGNPAR) {
2986 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2987 cor1 |= COR1_PARIGNORE;
2988 }
2989 if (tiosp->c_iflag & IGNBRK) {
2990 portp->rxignoremsk |= ST_BREAK;
2991 cor4 |= COR4_IGNBRK;
2992 }
2993
2994 portp->rxmarkmsk = ST_OVERRUN;
2995 if (tiosp->c_iflag & (INPCK | PARMRK))
2996 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2997 if (tiosp->c_iflag & BRKINT)
2998 portp->rxmarkmsk |= ST_BREAK;
2999
3000/*
3001 * Go through the char size, parity and stop bits and set all the
3002 * option register appropriately.
3003 */
3004 switch (tiosp->c_cflag & CSIZE) {
3005 case CS5:
3006 cor1 |= COR1_CHL5;
3007 break;
3008 case CS6:
3009 cor1 |= COR1_CHL6;
3010 break;
3011 case CS7:
3012 cor1 |= COR1_CHL7;
3013 break;
3014 default:
3015 cor1 |= COR1_CHL8;
3016 break;
3017 }
3018
3019 if (tiosp->c_cflag & CSTOPB)
3020 cor1 |= COR1_STOP2;
3021 else
3022 cor1 |= COR1_STOP1;
3023
3024 if (tiosp->c_cflag & PARENB) {
3025 if (tiosp->c_cflag & PARODD)
3026 cor1 |= (COR1_PARENB | COR1_PARODD);
3027 else
3028 cor1 |= (COR1_PARENB | COR1_PAREVEN);
3029 } else {
3030 cor1 |= COR1_PARNONE;
3031 }
3032
3033/*
3034 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
3035 * space for hardware flow control and the like. This should be set to
3036 * VMIN. Also here we will set the RX data timeout to 10ms - this should
3037 * really be based on VTIME.
3038 */
3039 cor3 |= FIFO_RXTHRESHOLD;
3040 rtpr = 2;
3041
3042/*
3043 * Calculate the baud rate timers. For now we will just assume that
3044 * the input and output baud are the same. Could have used a baud
3045 * table here, but this way we can generate virtually any baud rate
3046 * we like!
3047 */
3048 baudrate = tiosp->c_cflag & CBAUD;
3049 if (baudrate & CBAUDEX) {
3050 baudrate &= ~CBAUDEX;
3051 if ((baudrate < 1) || (baudrate > 4))
3052 tiosp->c_cflag &= ~CBAUDEX;
3053 else
3054 baudrate += 15;
3055 }
3056 baudrate = stl_baudrates[baudrate];
3057 if ((tiosp->c_cflag & CBAUD) == B38400) {
3058 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3059 baudrate = 57600;
3060 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3061 baudrate = 115200;
3062 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3063 baudrate = 230400;
3064 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3065 baudrate = 460800;
3066 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3067 baudrate = (portp->baud_base / portp->custom_divisor);
3068 }
3069 if (baudrate > STL_CD1400MAXBAUD)
3070 baudrate = STL_CD1400MAXBAUD;
3071
3072 if (baudrate > 0) {
3073 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
3074 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
3075 if (clkdiv < 0x100)
3076 break;
3077 }
3078 div = (unsigned char) clkdiv;
3079 }
3080
3081/*
3082 * Check what form of modem signaling is required and set it up.
3083 */
3084 if ((tiosp->c_cflag & CLOCAL) == 0) {
3085 mcor1 |= MCOR1_DCD;
3086 mcor2 |= MCOR2_DCD;
3087 sreron |= SRER_MODEM;
3088 portp->flags |= ASYNC_CHECK_CD;
3089 } else {
3090 portp->flags &= ~ASYNC_CHECK_CD;
3091 }
3092
3093/*
3094 * Setup cd1400 enhanced modes if we can. In particular we want to
3095 * handle as much of the flow control as possible automatically. As
3096 * well as saving a few CPU cycles it will also greatly improve flow
3097 * control reliability.
3098 */
3099 if (tiosp->c_iflag & IXON) {
3100 cor2 |= COR2_TXIBE;
3101 cor3 |= COR3_SCD12;
3102 if (tiosp->c_iflag & IXANY)
3103 cor2 |= COR2_IXM;
3104 }
3105
3106 if (tiosp->c_cflag & CRTSCTS) {
3107 cor2 |= COR2_CTSAE;
3108 mcor1 |= FIFO_RTSTHRESHOLD;
3109 }
3110
3111/*
3112 * All cd1400 register values calculated so go through and set
3113 * them all up.
3114 */
3115
Jiri Slabya0564e12006-12-08 02:38:37 -08003116 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003118 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003120 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003122 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3123 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3125 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
Alan Coxb65b5b52006-06-27 02:54:05 -07003127 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 BRDENABLE(portp->brdnr, portp->pagenr);
3129 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3130 srer = stl_cd1400getreg(portp, SRER);
3131 stl_cd1400setreg(portp, SRER, 0);
3132 if (stl_cd1400updatereg(portp, COR1, cor1))
3133 ccr = 1;
3134 if (stl_cd1400updatereg(portp, COR2, cor2))
3135 ccr = 1;
3136 if (stl_cd1400updatereg(portp, COR3, cor3))
3137 ccr = 1;
3138 if (ccr) {
3139 stl_cd1400ccrwait(portp);
3140 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3141 }
3142 stl_cd1400setreg(portp, COR4, cor4);
3143 stl_cd1400setreg(portp, COR5, cor5);
3144 stl_cd1400setreg(portp, MCOR1, mcor1);
3145 stl_cd1400setreg(portp, MCOR2, mcor2);
3146 if (baudrate > 0) {
3147 stl_cd1400setreg(portp, TCOR, clk);
3148 stl_cd1400setreg(portp, TBPR, div);
3149 stl_cd1400setreg(portp, RCOR, clk);
3150 stl_cd1400setreg(portp, RBPR, div);
3151 }
3152 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3153 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3154 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3155 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3156 stl_cd1400setreg(portp, RTPR, rtpr);
3157 mcor1 = stl_cd1400getreg(portp, MSVR1);
3158 if (mcor1 & MSVR1_DCD)
3159 portp->sigs |= TIOCM_CD;
3160 else
3161 portp->sigs &= ~TIOCM_CD;
3162 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3163 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003164 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165}
3166
3167/*****************************************************************************/
3168
3169/*
3170 * Set the state of the DTR and RTS signals.
3171 */
3172
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003173static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174{
3175 unsigned char msvr1, msvr2;
3176 unsigned long flags;
3177
Jiri Slabya0564e12006-12-08 02:38:37 -08003178 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3179 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180
3181 msvr1 = 0;
3182 msvr2 = 0;
3183 if (dtr > 0)
3184 msvr1 = MSVR1_DTR;
3185 if (rts > 0)
3186 msvr2 = MSVR2_RTS;
3187
Alan Coxb65b5b52006-06-27 02:54:05 -07003188 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189 BRDENABLE(portp->brdnr, portp->pagenr);
3190 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3191 if (rts >= 0)
3192 stl_cd1400setreg(portp, MSVR2, msvr2);
3193 if (dtr >= 0)
3194 stl_cd1400setreg(portp, MSVR1, msvr1);
3195 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003196 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197}
3198
3199/*****************************************************************************/
3200
3201/*
3202 * Return the state of the signals.
3203 */
3204
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003205static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206{
3207 unsigned char msvr1, msvr2;
3208 unsigned long flags;
3209 int sigs;
3210
Jiri Slabya0564e12006-12-08 02:38:37 -08003211 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212
Alan Coxb65b5b52006-06-27 02:54:05 -07003213 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214 BRDENABLE(portp->brdnr, portp->pagenr);
3215 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3216 msvr1 = stl_cd1400getreg(portp, MSVR1);
3217 msvr2 = stl_cd1400getreg(portp, MSVR2);
3218 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003219 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220
3221 sigs = 0;
3222 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3223 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3224 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3225 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3226#if 0
3227 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3228 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3229#else
3230 sigs |= TIOCM_DSR;
3231#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003232 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233}
3234
3235/*****************************************************************************/
3236
3237/*
3238 * Enable/Disable the Transmitter and/or Receiver.
3239 */
3240
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003241static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242{
3243 unsigned char ccr;
3244 unsigned long flags;
3245
Jiri Slabya0564e12006-12-08 02:38:37 -08003246 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3247
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 ccr = 0;
3249
3250 if (tx == 0)
3251 ccr |= CCR_TXDISABLE;
3252 else if (tx > 0)
3253 ccr |= CCR_TXENABLE;
3254 if (rx == 0)
3255 ccr |= CCR_RXDISABLE;
3256 else if (rx > 0)
3257 ccr |= CCR_RXENABLE;
3258
Alan Coxb65b5b52006-06-27 02:54:05 -07003259 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 BRDENABLE(portp->brdnr, portp->pagenr);
3261 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3262 stl_cd1400ccrwait(portp);
3263 stl_cd1400setreg(portp, CCR, ccr);
3264 stl_cd1400ccrwait(portp);
3265 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003266 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267}
3268
3269/*****************************************************************************/
3270
3271/*
3272 * Start/stop the Transmitter and/or Receiver.
3273 */
3274
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003275static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276{
3277 unsigned char sreron, sreroff;
3278 unsigned long flags;
3279
Jiri Slabya0564e12006-12-08 02:38:37 -08003280 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
3282 sreron = 0;
3283 sreroff = 0;
3284 if (tx == 0)
3285 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3286 else if (tx == 1)
3287 sreron |= SRER_TXDATA;
3288 else if (tx >= 2)
3289 sreron |= SRER_TXEMPTY;
3290 if (rx == 0)
3291 sreroff |= SRER_RXDATA;
3292 else if (rx > 0)
3293 sreron |= SRER_RXDATA;
3294
Alan Coxb65b5b52006-06-27 02:54:05 -07003295 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 BRDENABLE(portp->brdnr, portp->pagenr);
3297 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3298 stl_cd1400setreg(portp, SRER,
3299 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3300 BRDDISABLE(portp->brdnr);
3301 if (tx > 0)
3302 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003303 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304}
3305
3306/*****************************************************************************/
3307
3308/*
3309 * Disable all interrupts from this port.
3310 */
3311
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003312static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313{
3314 unsigned long flags;
3315
Jiri Slabya0564e12006-12-08 02:38:37 -08003316 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3317
Alan Coxb65b5b52006-06-27 02:54:05 -07003318 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319 BRDENABLE(portp->brdnr, portp->pagenr);
3320 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3321 stl_cd1400setreg(portp, SRER, 0);
3322 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003323 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324}
3325
3326/*****************************************************************************/
3327
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003328static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329{
3330 unsigned long flags;
3331
Jiri Slabya0564e12006-12-08 02:38:37 -08003332 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333
Alan Coxb65b5b52006-06-27 02:54:05 -07003334 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 BRDENABLE(portp->brdnr, portp->pagenr);
3336 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3337 stl_cd1400setreg(portp, SRER,
3338 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3339 SRER_TXEMPTY));
3340 BRDDISABLE(portp->brdnr);
3341 portp->brklen = len;
3342 if (len == 1)
3343 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003344 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345}
3346
3347/*****************************************************************************/
3348
3349/*
3350 * Take flow control actions...
3351 */
3352
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003353static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354{
3355 struct tty_struct *tty;
3356 unsigned long flags;
3357
Jiri Slabya0564e12006-12-08 02:38:37 -08003358 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359
Jiri Slaby615e4a72006-12-08 02:38:38 -08003360 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 return;
3362 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003363 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 return;
3365
Alan Coxb65b5b52006-06-27 02:54:05 -07003366 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 BRDENABLE(portp->brdnr, portp->pagenr);
3368 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3369
3370 if (state) {
3371 if (tty->termios->c_iflag & IXOFF) {
3372 stl_cd1400ccrwait(portp);
3373 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3374 portp->stats.rxxon++;
3375 stl_cd1400ccrwait(portp);
3376 }
3377/*
3378 * Question: should we return RTS to what it was before? It may
3379 * have been set by an ioctl... Suppose not, since if you have
3380 * hardware flow control set then it is pretty silly to go and
3381 * set the RTS line by hand.
3382 */
3383 if (tty->termios->c_cflag & CRTSCTS) {
3384 stl_cd1400setreg(portp, MCOR1,
3385 (stl_cd1400getreg(portp, MCOR1) |
3386 FIFO_RTSTHRESHOLD));
3387 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3388 portp->stats.rxrtson++;
3389 }
3390 } else {
3391 if (tty->termios->c_iflag & IXOFF) {
3392 stl_cd1400ccrwait(portp);
3393 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3394 portp->stats.rxxoff++;
3395 stl_cd1400ccrwait(portp);
3396 }
3397 if (tty->termios->c_cflag & CRTSCTS) {
3398 stl_cd1400setreg(portp, MCOR1,
3399 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3400 stl_cd1400setreg(portp, MSVR2, 0);
3401 portp->stats.rxrtsoff++;
3402 }
3403 }
3404
3405 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003406 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407}
3408
3409/*****************************************************************************/
3410
3411/*
3412 * Send a flow control character...
3413 */
3414
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003415static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416{
3417 struct tty_struct *tty;
3418 unsigned long flags;
3419
Jiri Slabya0564e12006-12-08 02:38:37 -08003420 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421
Jiri Slaby615e4a72006-12-08 02:38:38 -08003422 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423 return;
3424 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003425 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426 return;
3427
Alan Coxb65b5b52006-06-27 02:54:05 -07003428 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 BRDENABLE(portp->brdnr, portp->pagenr);
3430 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3431 if (state) {
3432 stl_cd1400ccrwait(portp);
3433 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3434 portp->stats.rxxon++;
3435 stl_cd1400ccrwait(portp);
3436 } else {
3437 stl_cd1400ccrwait(portp);
3438 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3439 portp->stats.rxxoff++;
3440 stl_cd1400ccrwait(portp);
3441 }
3442 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003443 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444}
3445
3446/*****************************************************************************/
3447
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003448static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449{
3450 unsigned long flags;
3451
Jiri Slabya0564e12006-12-08 02:38:37 -08003452 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453
Jiri Slaby615e4a72006-12-08 02:38:38 -08003454 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 return;
3456
Alan Coxb65b5b52006-06-27 02:54:05 -07003457 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 BRDENABLE(portp->brdnr, portp->pagenr);
3459 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3460 stl_cd1400ccrwait(portp);
3461 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3462 stl_cd1400ccrwait(portp);
3463 portp->tx.tail = portp->tx.head;
3464 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003465 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466}
3467
3468/*****************************************************************************/
3469
3470/*
3471 * Return the current state of data flow on this port. This is only
3472 * really interresting when determining if data has fully completed
3473 * transmission or not... This is easy for the cd1400, it accurately
3474 * maintains the busy port flag.
3475 */
3476
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003477static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478{
Jiri Slabya0564e12006-12-08 02:38:37 -08003479 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480
Jiri Slaby615e4a72006-12-08 02:38:38 -08003481 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003482 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483
Jesper Juhl014c2542006-01-15 02:37:08 +01003484 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485}
3486
3487/*****************************************************************************/
3488
3489/*
3490 * Interrupt service routine for cd1400 EasyIO boards.
3491 */
3492
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003493static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494{
3495 unsigned char svrtype;
3496
Jiri Slabya0564e12006-12-08 02:38:37 -08003497 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498
Alan Coxb65b5b52006-06-27 02:54:05 -07003499 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 outb(SVRR, iobase);
3501 svrtype = inb(iobase + EREG_DATA);
3502 if (panelp->nrports > 4) {
3503 outb((SVRR + 0x80), iobase);
3504 svrtype |= inb(iobase + EREG_DATA);
3505 }
3506
3507 if (svrtype & SVRR_RX)
3508 stl_cd1400rxisr(panelp, iobase);
3509 else if (svrtype & SVRR_TX)
3510 stl_cd1400txisr(panelp, iobase);
3511 else if (svrtype & SVRR_MDM)
3512 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003513
3514 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515}
3516
3517/*****************************************************************************/
3518
3519/*
3520 * Interrupt service routine for cd1400 panels.
3521 */
3522
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003523static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524{
3525 unsigned char svrtype;
3526
Jiri Slabya0564e12006-12-08 02:38:37 -08003527 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528
3529 outb(SVRR, iobase);
3530 svrtype = inb(iobase + EREG_DATA);
3531 outb((SVRR + 0x80), iobase);
3532 svrtype |= inb(iobase + EREG_DATA);
3533 if (svrtype & SVRR_RX)
3534 stl_cd1400rxisr(panelp, iobase);
3535 else if (svrtype & SVRR_TX)
3536 stl_cd1400txisr(panelp, iobase);
3537 else if (svrtype & SVRR_MDM)
3538 stl_cd1400mdmisr(panelp, iobase);
3539}
3540
3541
3542/*****************************************************************************/
3543
3544/*
3545 * Unfortunately we need to handle breaks in the TX data stream, since
3546 * this is the only way to generate them on the cd1400.
3547 */
3548
Jiri Slaby60be4812006-12-08 02:38:40 -08003549static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550{
3551 if (portp->brklen == 1) {
3552 outb((COR2 + portp->uartaddr), ioaddr);
3553 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3554 (ioaddr + EREG_DATA));
3555 outb((TDR + portp->uartaddr), ioaddr);
3556 outb(ETC_CMD, (ioaddr + EREG_DATA));
3557 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3558 outb((SRER + portp->uartaddr), ioaddr);
3559 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3560 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003561 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562 } else if (portp->brklen > 1) {
3563 outb((TDR + portp->uartaddr), ioaddr);
3564 outb(ETC_CMD, (ioaddr + EREG_DATA));
3565 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3566 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003567 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 } else {
3569 outb((COR2 + portp->uartaddr), ioaddr);
3570 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3571 (ioaddr + EREG_DATA));
3572 portp->brklen = 0;
3573 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003574 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575}
3576
3577/*****************************************************************************/
3578
3579/*
3580 * Transmit interrupt handler. This has gotta be fast! Handling TX
3581 * chars is pretty simple, stuff as many as possible from the TX buffer
3582 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3583 * are embedded as commands in the data stream. Oh no, had to use a goto!
3584 * This could be optimized more, will do when I get time...
3585 * In practice it is possible that interrupts are enabled but that the
3586 * port has been hung up. Need to handle not having any TX buffer here,
3587 * this is done by using the side effect that head and tail will also
3588 * be NULL if the buffer has been freed.
3589 */
3590
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003591static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003593 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594 int len, stlen;
3595 char *head, *tail;
3596 unsigned char ioack, srer;
3597
Jiri Slabya0564e12006-12-08 02:38:37 -08003598 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599
3600 ioack = inb(ioaddr + EREG_TXACK);
3601 if (((ioack & panelp->ackmask) != 0) ||
3602 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3603 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3604 return;
3605 }
3606 portp = panelp->ports[(ioack >> 3)];
3607
3608/*
3609 * Unfortunately we need to handle breaks in the data stream, since
3610 * this is the only way to generate them on the cd1400. Do it now if
3611 * a break is to be sent.
3612 */
3613 if (portp->brklen != 0)
3614 if (stl_cd1400breakisr(portp, ioaddr))
3615 goto stl_txalldone;
3616
3617 head = portp->tx.head;
3618 tail = portp->tx.tail;
3619 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3620 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3621 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3622 set_bit(ASYI_TXLOW, &portp->istate);
3623 schedule_work(&portp->tqueue);
3624 }
3625
3626 if (len == 0) {
3627 outb((SRER + portp->uartaddr), ioaddr);
3628 srer = inb(ioaddr + EREG_DATA);
3629 if (srer & SRER_TXDATA) {
3630 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3631 } else {
3632 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3633 clear_bit(ASYI_TXBUSY, &portp->istate);
3634 }
3635 outb(srer, (ioaddr + EREG_DATA));
3636 } else {
3637 len = MIN(len, CD1400_TXFIFOSIZE);
3638 portp->stats.txtotal += len;
3639 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
3640 outb((TDR + portp->uartaddr), ioaddr);
3641 outsb((ioaddr + EREG_DATA), tail, stlen);
3642 len -= stlen;
3643 tail += stlen;
3644 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3645 tail = portp->tx.buf;
3646 if (len > 0) {
3647 outsb((ioaddr + EREG_DATA), tail, len);
3648 tail += len;
3649 }
3650 portp->tx.tail = tail;
3651 }
3652
3653stl_txalldone:
3654 outb((EOSRR + portp->uartaddr), ioaddr);
3655 outb(0, (ioaddr + EREG_DATA));
3656}
3657
3658/*****************************************************************************/
3659
3660/*
3661 * Receive character interrupt handler. Determine if we have good chars
3662 * or bad chars and then process appropriately. Good chars are easy
3663 * just shove the lot into the RX buffer and set all status byte to 0.
3664 * If a bad RX char then process as required. This routine needs to be
3665 * fast! In practice it is possible that we get an interrupt on a port
3666 * that is closed. This can happen on hangups - since they completely
3667 * shutdown a port not in user context. Need to handle this case.
3668 */
3669
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003670static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003672 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 struct tty_struct *tty;
3674 unsigned int ioack, len, buflen;
3675 unsigned char status;
3676 char ch;
3677
Jiri Slabya0564e12006-12-08 02:38:37 -08003678 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679
3680 ioack = inb(ioaddr + EREG_RXACK);
3681 if ((ioack & panelp->ackmask) != 0) {
3682 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3683 return;
3684 }
3685 portp = panelp->ports[(ioack >> 3)];
3686 tty = portp->tty;
3687
3688 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3689 outb((RDCR + portp->uartaddr), ioaddr);
3690 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003691 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 len = MIN(len, sizeof(stl_unwanted));
3693 outb((RDSR + portp->uartaddr), ioaddr);
3694 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3695 portp->stats.rxlost += len;
3696 portp->stats.rxtotal += len;
3697 } else {
3698 len = MIN(len, buflen);
3699 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003700 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003702 tty_prepare_flip_string(tty, &ptr, len);
3703 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 tty_schedule_flip(tty);
3705 portp->stats.rxtotal += len;
3706 }
3707 }
3708 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3709 outb((RDSR + portp->uartaddr), ioaddr);
3710 status = inb(ioaddr + EREG_DATA);
3711 ch = inb(ioaddr + EREG_DATA);
3712 if (status & ST_PARITY)
3713 portp->stats.rxparity++;
3714 if (status & ST_FRAMING)
3715 portp->stats.rxframing++;
3716 if (status & ST_OVERRUN)
3717 portp->stats.rxoverrun++;
3718 if (status & ST_BREAK)
3719 portp->stats.rxbreaks++;
3720 if (status & ST_SCHARMASK) {
3721 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3722 portp->stats.txxon++;
3723 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3724 portp->stats.txxoff++;
3725 goto stl_rxalldone;
3726 }
Alan Cox33f0f882006-01-09 20:54:13 -08003727 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 if (portp->rxmarkmsk & status) {
3729 if (status & ST_BREAK) {
3730 status = TTY_BREAK;
3731 if (portp->flags & ASYNC_SAK) {
3732 do_SAK(tty);
3733 BRDENABLE(portp->brdnr, portp->pagenr);
3734 }
3735 } else if (status & ST_PARITY) {
3736 status = TTY_PARITY;
3737 } else if (status & ST_FRAMING) {
3738 status = TTY_FRAME;
3739 } else if(status & ST_OVERRUN) {
3740 status = TTY_OVERRUN;
3741 } else {
3742 status = 0;
3743 }
3744 } else {
3745 status = 0;
3746 }
Alan Cox33f0f882006-01-09 20:54:13 -08003747 tty_insert_flip_char(tty, ch, status);
3748 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 }
3750 } else {
3751 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3752 return;
3753 }
3754
3755stl_rxalldone:
3756 outb((EOSRR + portp->uartaddr), ioaddr);
3757 outb(0, (ioaddr + EREG_DATA));
3758}
3759
3760/*****************************************************************************/
3761
3762/*
3763 * Modem interrupt handler. The is called when the modem signal line
3764 * (DCD) has changed state. Leave most of the work to the off-level
3765 * processing routine.
3766 */
3767
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003768static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003770 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 unsigned int ioack;
3772 unsigned char misr;
3773
Jiri Slabya0564e12006-12-08 02:38:37 -08003774 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775
3776 ioack = inb(ioaddr + EREG_MDACK);
3777 if (((ioack & panelp->ackmask) != 0) ||
3778 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3779 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3780 return;
3781 }
3782 portp = panelp->ports[(ioack >> 3)];
3783
3784 outb((MISR + portp->uartaddr), ioaddr);
3785 misr = inb(ioaddr + EREG_DATA);
3786 if (misr & MISR_DCD) {
3787 set_bit(ASYI_DCDCHANGE, &portp->istate);
3788 schedule_work(&portp->tqueue);
3789 portp->stats.modem++;
3790 }
3791
3792 outb((EOSRR + portp->uartaddr), ioaddr);
3793 outb(0, (ioaddr + EREG_DATA));
3794}
3795
3796/*****************************************************************************/
3797/* SC26198 HARDWARE FUNCTIONS */
3798/*****************************************************************************/
3799
3800/*
3801 * These functions get/set/update the registers of the sc26198 UARTs.
3802 * Access to the sc26198 registers is via an address/data io port pair.
3803 * (Maybe should make this inline...)
3804 */
3805
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003806static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807{
3808 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003809 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810}
3811
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003812static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813{
3814 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3815 outb(value, (portp->ioaddr + XP_DATA));
3816}
3817
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003818static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819{
3820 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3821 if (inb(portp->ioaddr + XP_DATA) != value) {
3822 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003823 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003825 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826}
3827
3828/*****************************************************************************/
3829
3830/*
3831 * Functions to get and set the sc26198 global registers.
3832 */
3833
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003834static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835{
3836 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003837 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838}
3839
3840#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003841static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842{
3843 outb(regnr, (portp->ioaddr + XP_ADDR));
3844 outb(value, (portp->ioaddr + XP_DATA));
3845}
3846#endif
3847
3848/*****************************************************************************/
3849
3850/*
3851 * Inbitialize the UARTs in a panel. We don't care what sort of board
3852 * these ports are on - since the port io registers are almost
3853 * identical when dealing with ports.
3854 */
3855
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003856static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857{
3858 int chipmask, i;
3859 int nrchips, ioaddr;
3860
Jiri Slabya0564e12006-12-08 02:38:37 -08003861 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
3863 BRDENABLE(panelp->brdnr, panelp->pagenr);
3864
3865/*
3866 * Check that each chip is present and started up OK.
3867 */
3868 chipmask = 0;
3869 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3870 if (brdp->brdtype == BRD_ECHPCI)
3871 outb(panelp->pagenr, brdp->ioctrl);
3872
3873 for (i = 0; (i < nrchips); i++) {
3874 ioaddr = panelp->iobase + (i * 4);
3875 outb(SCCR, (ioaddr + XP_ADDR));
3876 outb(CR_RESETALL, (ioaddr + XP_DATA));
3877 outb(TSTR, (ioaddr + XP_ADDR));
3878 if (inb(ioaddr + XP_DATA) != 0) {
3879 printk("STALLION: sc26198 not responding, "
3880 "brd=%d panel=%d chip=%d\n",
3881 panelp->brdnr, panelp->panelnr, i);
3882 continue;
3883 }
3884 chipmask |= (0x1 << i);
3885 outb(GCCR, (ioaddr + XP_ADDR));
3886 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3887 outb(WDTRCR, (ioaddr + XP_ADDR));
3888 outb(0xff, (ioaddr + XP_DATA));
3889 }
3890
3891 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003892 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893}
3894
3895/*****************************************************************************/
3896
3897/*
3898 * Initialize hardware specific port registers.
3899 */
3900
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003901static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902{
Jiri Slabya0564e12006-12-08 02:38:37 -08003903 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3904 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Jiri Slaby615e4a72006-12-08 02:38:38 -08003906 if ((brdp == NULL) || (panelp == NULL) ||
3907 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 return;
3909
3910 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3911 portp->uartaddr = (portp->portnr & 0x07) << 4;
3912 portp->pagenr = panelp->pagenr;
3913 portp->hwid = 0x1;
3914
3915 BRDENABLE(portp->brdnr, portp->pagenr);
3916 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3917 BRDDISABLE(portp->brdnr);
3918}
3919
3920/*****************************************************************************/
3921
3922/*
3923 * Set up the sc26198 registers for a port based on the termios port
3924 * settings.
3925 */
3926
Alan Cox606d0992006-12-08 02:38:45 -08003927static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003929 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 unsigned long flags;
3931 unsigned int baudrate;
3932 unsigned char mr0, mr1, mr2, clk;
3933 unsigned char imron, imroff, iopr, ipr;
3934
3935 mr0 = 0;
3936 mr1 = 0;
3937 mr2 = 0;
3938 clk = 0;
3939 iopr = 0;
3940 imron = 0;
3941 imroff = 0;
3942
3943 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003944 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 return;
3946
3947/*
3948 * Set up the RX char ignore mask with those RX error types we
3949 * can ignore.
3950 */
3951 portp->rxignoremsk = 0;
3952 if (tiosp->c_iflag & IGNPAR)
3953 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3954 SR_RXOVERRUN);
3955 if (tiosp->c_iflag & IGNBRK)
3956 portp->rxignoremsk |= SR_RXBREAK;
3957
3958 portp->rxmarkmsk = SR_RXOVERRUN;
3959 if (tiosp->c_iflag & (INPCK | PARMRK))
3960 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3961 if (tiosp->c_iflag & BRKINT)
3962 portp->rxmarkmsk |= SR_RXBREAK;
3963
3964/*
3965 * Go through the char size, parity and stop bits and set all the
3966 * option register appropriately.
3967 */
3968 switch (tiosp->c_cflag & CSIZE) {
3969 case CS5:
3970 mr1 |= MR1_CS5;
3971 break;
3972 case CS6:
3973 mr1 |= MR1_CS6;
3974 break;
3975 case CS7:
3976 mr1 |= MR1_CS7;
3977 break;
3978 default:
3979 mr1 |= MR1_CS8;
3980 break;
3981 }
3982
3983 if (tiosp->c_cflag & CSTOPB)
3984 mr2 |= MR2_STOP2;
3985 else
3986 mr2 |= MR2_STOP1;
3987
3988 if (tiosp->c_cflag & PARENB) {
3989 if (tiosp->c_cflag & PARODD)
3990 mr1 |= (MR1_PARENB | MR1_PARODD);
3991 else
3992 mr1 |= (MR1_PARENB | MR1_PAREVEN);
3993 } else {
3994 mr1 |= MR1_PARNONE;
3995 }
3996
3997 mr1 |= MR1_ERRBLOCK;
3998
3999/*
4000 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
4001 * space for hardware flow control and the like. This should be set to
4002 * VMIN.
4003 */
4004 mr2 |= MR2_RXFIFOHALF;
4005
4006/*
4007 * Calculate the baud rate timers. For now we will just assume that
4008 * the input and output baud are the same. The sc26198 has a fixed
4009 * baud rate table, so only discrete baud rates possible.
4010 */
4011 baudrate = tiosp->c_cflag & CBAUD;
4012 if (baudrate & CBAUDEX) {
4013 baudrate &= ~CBAUDEX;
4014 if ((baudrate < 1) || (baudrate > 4))
4015 tiosp->c_cflag &= ~CBAUDEX;
4016 else
4017 baudrate += 15;
4018 }
4019 baudrate = stl_baudrates[baudrate];
4020 if ((tiosp->c_cflag & CBAUD) == B38400) {
4021 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
4022 baudrate = 57600;
4023 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
4024 baudrate = 115200;
4025 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
4026 baudrate = 230400;
4027 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
4028 baudrate = 460800;
4029 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
4030 baudrate = (portp->baud_base / portp->custom_divisor);
4031 }
4032 if (baudrate > STL_SC26198MAXBAUD)
4033 baudrate = STL_SC26198MAXBAUD;
4034
4035 if (baudrate > 0) {
4036 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
4037 if (baudrate <= sc26198_baudtable[clk])
4038 break;
4039 }
4040 }
4041
4042/*
4043 * Check what form of modem signaling is required and set it up.
4044 */
4045 if (tiosp->c_cflag & CLOCAL) {
4046 portp->flags &= ~ASYNC_CHECK_CD;
4047 } else {
4048 iopr |= IOPR_DCDCOS;
4049 imron |= IR_IOPORT;
4050 portp->flags |= ASYNC_CHECK_CD;
4051 }
4052
4053/*
4054 * Setup sc26198 enhanced modes if we can. In particular we want to
4055 * handle as much of the flow control as possible automatically. As
4056 * well as saving a few CPU cycles it will also greatly improve flow
4057 * control reliability.
4058 */
4059 if (tiosp->c_iflag & IXON) {
4060 mr0 |= MR0_SWFTX | MR0_SWFT;
4061 imron |= IR_XONXOFF;
4062 } else {
4063 imroff |= IR_XONXOFF;
4064 }
4065 if (tiosp->c_iflag & IXOFF)
4066 mr0 |= MR0_SWFRX;
4067
4068 if (tiosp->c_cflag & CRTSCTS) {
4069 mr2 |= MR2_AUTOCTS;
4070 mr1 |= MR1_AUTORTS;
4071 }
4072
4073/*
4074 * All sc26198 register values calculated so go through and set
4075 * them all up.
4076 */
4077
Jiri Slabya0564e12006-12-08 02:38:37 -08004078 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08004080 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
4081 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
4082 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4084 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085
Alan Coxb65b5b52006-06-27 02:54:05 -07004086 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 BRDENABLE(portp->brdnr, portp->pagenr);
4088 stl_sc26198setreg(portp, IMR, 0);
4089 stl_sc26198updatereg(portp, MR0, mr0);
4090 stl_sc26198updatereg(portp, MR1, mr1);
4091 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4092 stl_sc26198updatereg(portp, MR2, mr2);
4093 stl_sc26198updatereg(portp, IOPIOR,
4094 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4095
4096 if (baudrate > 0) {
4097 stl_sc26198setreg(portp, TXCSR, clk);
4098 stl_sc26198setreg(portp, RXCSR, clk);
4099 }
4100
4101 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4102 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4103
4104 ipr = stl_sc26198getreg(portp, IPR);
4105 if (ipr & IPR_DCD)
4106 portp->sigs &= ~TIOCM_CD;
4107 else
4108 portp->sigs |= TIOCM_CD;
4109
4110 portp->imr = (portp->imr & ~imroff) | imron;
4111 stl_sc26198setreg(portp, IMR, portp->imr);
4112 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004113 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114}
4115
4116/*****************************************************************************/
4117
4118/*
4119 * Set the state of the DTR and RTS signals.
4120 */
4121
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004122static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123{
4124 unsigned char iopioron, iopioroff;
4125 unsigned long flags;
4126
Jiri Slabya0564e12006-12-08 02:38:37 -08004127 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4128 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
4130 iopioron = 0;
4131 iopioroff = 0;
4132 if (dtr == 0)
4133 iopioroff |= IPR_DTR;
4134 else if (dtr > 0)
4135 iopioron |= IPR_DTR;
4136 if (rts == 0)
4137 iopioroff |= IPR_RTS;
4138 else if (rts > 0)
4139 iopioron |= IPR_RTS;
4140
Alan Coxb65b5b52006-06-27 02:54:05 -07004141 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 BRDENABLE(portp->brdnr, portp->pagenr);
4143 stl_sc26198setreg(portp, IOPIOR,
4144 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4145 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004146 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147}
4148
4149/*****************************************************************************/
4150
4151/*
4152 * Return the state of the signals.
4153 */
4154
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004155static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156{
4157 unsigned char ipr;
4158 unsigned long flags;
4159 int sigs;
4160
Jiri Slabya0564e12006-12-08 02:38:37 -08004161 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162
Alan Coxb65b5b52006-06-27 02:54:05 -07004163 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 BRDENABLE(portp->brdnr, portp->pagenr);
4165 ipr = stl_sc26198getreg(portp, IPR);
4166 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004167 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
4169 sigs = 0;
4170 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4171 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4172 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4173 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4174 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004175 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176}
4177
4178/*****************************************************************************/
4179
4180/*
4181 * Enable/Disable the Transmitter and/or Receiver.
4182 */
4183
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004184static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185{
4186 unsigned char ccr;
4187 unsigned long flags;
4188
Jiri Slabya0564e12006-12-08 02:38:37 -08004189 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190
4191 ccr = portp->crenable;
4192 if (tx == 0)
4193 ccr &= ~CR_TXENABLE;
4194 else if (tx > 0)
4195 ccr |= CR_TXENABLE;
4196 if (rx == 0)
4197 ccr &= ~CR_RXENABLE;
4198 else if (rx > 0)
4199 ccr |= CR_RXENABLE;
4200
Alan Coxb65b5b52006-06-27 02:54:05 -07004201 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 BRDENABLE(portp->brdnr, portp->pagenr);
4203 stl_sc26198setreg(portp, SCCR, ccr);
4204 BRDDISABLE(portp->brdnr);
4205 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004206 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207}
4208
4209/*****************************************************************************/
4210
4211/*
4212 * Start/stop the Transmitter and/or Receiver.
4213 */
4214
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004215static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216{
4217 unsigned char imr;
4218 unsigned long flags;
4219
Jiri Slabya0564e12006-12-08 02:38:37 -08004220 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221
4222 imr = portp->imr;
4223 if (tx == 0)
4224 imr &= ~IR_TXRDY;
4225 else if (tx == 1)
4226 imr |= IR_TXRDY;
4227 if (rx == 0)
4228 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4229 else if (rx > 0)
4230 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4231
Alan Coxb65b5b52006-06-27 02:54:05 -07004232 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233 BRDENABLE(portp->brdnr, portp->pagenr);
4234 stl_sc26198setreg(portp, IMR, imr);
4235 BRDDISABLE(portp->brdnr);
4236 portp->imr = imr;
4237 if (tx > 0)
4238 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004239 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240}
4241
4242/*****************************************************************************/
4243
4244/*
4245 * Disable all interrupts from this port.
4246 */
4247
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004248static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249{
4250 unsigned long flags;
4251
Jiri Slabya0564e12006-12-08 02:38:37 -08004252 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
Alan Coxb65b5b52006-06-27 02:54:05 -07004254 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255 BRDENABLE(portp->brdnr, portp->pagenr);
4256 portp->imr = 0;
4257 stl_sc26198setreg(portp, IMR, 0);
4258 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004259 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
4262/*****************************************************************************/
4263
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004264static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265{
4266 unsigned long flags;
4267
Jiri Slabya0564e12006-12-08 02:38:37 -08004268 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269
Alan Coxb65b5b52006-06-27 02:54:05 -07004270 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 BRDENABLE(portp->brdnr, portp->pagenr);
4272 if (len == 1) {
4273 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4274 portp->stats.txbreaks++;
4275 } else {
4276 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4277 }
4278 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004279 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280}
4281
4282/*****************************************************************************/
4283
4284/*
4285 * Take flow control actions...
4286 */
4287
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004288static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289{
4290 struct tty_struct *tty;
4291 unsigned long flags;
4292 unsigned char mr0;
4293
Jiri Slabya0564e12006-12-08 02:38:37 -08004294 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Jiri Slaby615e4a72006-12-08 02:38:38 -08004296 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 return;
4298 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004299 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 return;
4301
Alan Coxb65b5b52006-06-27 02:54:05 -07004302 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 BRDENABLE(portp->brdnr, portp->pagenr);
4304
4305 if (state) {
4306 if (tty->termios->c_iflag & IXOFF) {
4307 mr0 = stl_sc26198getreg(portp, MR0);
4308 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4309 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4310 mr0 |= MR0_SWFRX;
4311 portp->stats.rxxon++;
4312 stl_sc26198wait(portp);
4313 stl_sc26198setreg(portp, MR0, mr0);
4314 }
4315/*
4316 * Question: should we return RTS to what it was before? It may
4317 * have been set by an ioctl... Suppose not, since if you have
4318 * hardware flow control set then it is pretty silly to go and
4319 * set the RTS line by hand.
4320 */
4321 if (tty->termios->c_cflag & CRTSCTS) {
4322 stl_sc26198setreg(portp, MR1,
4323 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4324 stl_sc26198setreg(portp, IOPIOR,
4325 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4326 portp->stats.rxrtson++;
4327 }
4328 } else {
4329 if (tty->termios->c_iflag & IXOFF) {
4330 mr0 = stl_sc26198getreg(portp, MR0);
4331 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4332 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4333 mr0 &= ~MR0_SWFRX;
4334 portp->stats.rxxoff++;
4335 stl_sc26198wait(portp);
4336 stl_sc26198setreg(portp, MR0, mr0);
4337 }
4338 if (tty->termios->c_cflag & CRTSCTS) {
4339 stl_sc26198setreg(portp, MR1,
4340 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4341 stl_sc26198setreg(portp, IOPIOR,
4342 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4343 portp->stats.rxrtsoff++;
4344 }
4345 }
4346
4347 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004348 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349}
4350
4351/*****************************************************************************/
4352
4353/*
4354 * Send a flow control character.
4355 */
4356
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004357static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358{
4359 struct tty_struct *tty;
4360 unsigned long flags;
4361 unsigned char mr0;
4362
Jiri Slabya0564e12006-12-08 02:38:37 -08004363 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364
Jiri Slaby615e4a72006-12-08 02:38:38 -08004365 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366 return;
4367 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004368 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 return;
4370
Alan Coxb65b5b52006-06-27 02:54:05 -07004371 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372 BRDENABLE(portp->brdnr, portp->pagenr);
4373 if (state) {
4374 mr0 = stl_sc26198getreg(portp, MR0);
4375 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4376 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4377 mr0 |= MR0_SWFRX;
4378 portp->stats.rxxon++;
4379 stl_sc26198wait(portp);
4380 stl_sc26198setreg(portp, MR0, mr0);
4381 } else {
4382 mr0 = stl_sc26198getreg(portp, MR0);
4383 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4384 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4385 mr0 &= ~MR0_SWFRX;
4386 portp->stats.rxxoff++;
4387 stl_sc26198wait(portp);
4388 stl_sc26198setreg(portp, MR0, mr0);
4389 }
4390 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004391 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392}
4393
4394/*****************************************************************************/
4395
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004396static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397{
4398 unsigned long flags;
4399
Jiri Slabya0564e12006-12-08 02:38:37 -08004400 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Jiri Slaby615e4a72006-12-08 02:38:38 -08004402 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 return;
4404
Alan Coxb65b5b52006-06-27 02:54:05 -07004405 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 BRDENABLE(portp->brdnr, portp->pagenr);
4407 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4408 stl_sc26198setreg(portp, SCCR, portp->crenable);
4409 BRDDISABLE(portp->brdnr);
4410 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004411 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412}
4413
4414/*****************************************************************************/
4415
4416/*
4417 * Return the current state of data flow on this port. This is only
4418 * really interresting when determining if data has fully completed
4419 * transmission or not... The sc26198 interrupt scheme cannot
4420 * determine when all data has actually drained, so we need to
4421 * check the port statusy register to be sure.
4422 */
4423
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004424static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425{
4426 unsigned long flags;
4427 unsigned char sr;
4428
Jiri Slabya0564e12006-12-08 02:38:37 -08004429 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430
Jiri Slaby615e4a72006-12-08 02:38:38 -08004431 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004432 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004434 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
Alan Coxb65b5b52006-06-27 02:54:05 -07004436 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437 BRDENABLE(portp->brdnr, portp->pagenr);
4438 sr = stl_sc26198getreg(portp, SR);
4439 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004440 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
Jesper Juhl014c2542006-01-15 02:37:08 +01004442 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443}
4444
4445/*****************************************************************************/
4446
4447/*
4448 * Delay for a small amount of time, to give the sc26198 a chance
4449 * to process a command...
4450 */
4451
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004452static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453{
4454 int i;
4455
Jiri Slabya0564e12006-12-08 02:38:37 -08004456 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
Jiri Slaby615e4a72006-12-08 02:38:38 -08004458 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459 return;
4460
4461 for (i = 0; (i < 20); i++)
4462 stl_sc26198getglobreg(portp, TSTR);
4463}
4464
4465/*****************************************************************************/
4466
4467/*
4468 * If we are TX flow controlled and in IXANY mode then we may
4469 * need to unflow control here. We gotta do this because of the
4470 * automatic flow control modes of the sc26198.
4471 */
4472
Jiri Slaby60be4812006-12-08 02:38:40 -08004473static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474{
4475 unsigned char mr0;
4476
4477 mr0 = stl_sc26198getreg(portp, MR0);
4478 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4479 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4480 stl_sc26198wait(portp);
4481 stl_sc26198setreg(portp, MR0, mr0);
4482 clear_bit(ASYI_TXFLOWED, &portp->istate);
4483}
4484
4485/*****************************************************************************/
4486
4487/*
4488 * Interrupt service routine for sc26198 panels.
4489 */
4490
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004491static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004493 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 unsigned int iack;
4495
Alan Coxb65b5b52006-06-27 02:54:05 -07004496 spin_lock(&brd_lock);
4497
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498/*
4499 * Work around bug in sc26198 chip... Cannot have A6 address
4500 * line of UART high, else iack will be returned as 0.
4501 */
4502 outb(0, (iobase + 1));
4503
4504 iack = inb(iobase + XP_IACK);
4505 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4506
4507 if (iack & IVR_RXDATA)
4508 stl_sc26198rxisr(portp, iack);
4509 else if (iack & IVR_TXDATA)
4510 stl_sc26198txisr(portp);
4511 else
4512 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004513
4514 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515}
4516
4517/*****************************************************************************/
4518
4519/*
4520 * Transmit interrupt handler. This has gotta be fast! Handling TX
4521 * chars is pretty simple, stuff as many as possible from the TX buffer
4522 * into the sc26198 FIFO.
4523 * In practice it is possible that interrupts are enabled but that the
4524 * port has been hung up. Need to handle not having any TX buffer here,
4525 * this is done by using the side effect that head and tail will also
4526 * be NULL if the buffer has been freed.
4527 */
4528
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004529static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530{
4531 unsigned int ioaddr;
4532 unsigned char mr0;
4533 int len, stlen;
4534 char *head, *tail;
4535
Jiri Slabya0564e12006-12-08 02:38:37 -08004536 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537
4538 ioaddr = portp->ioaddr;
4539 head = portp->tx.head;
4540 tail = portp->tx.tail;
4541 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4542 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4543 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4544 set_bit(ASYI_TXLOW, &portp->istate);
4545 schedule_work(&portp->tqueue);
4546 }
4547
4548 if (len == 0) {
4549 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4550 mr0 = inb(ioaddr + XP_DATA);
4551 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4552 portp->imr &= ~IR_TXRDY;
4553 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4554 outb(portp->imr, (ioaddr + XP_DATA));
4555 clear_bit(ASYI_TXBUSY, &portp->istate);
4556 } else {
4557 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4558 outb(mr0, (ioaddr + XP_DATA));
4559 }
4560 } else {
4561 len = MIN(len, SC26198_TXFIFOSIZE);
4562 portp->stats.txtotal += len;
4563 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
4564 outb(GTXFIFO, (ioaddr + XP_ADDR));
4565 outsb((ioaddr + XP_DATA), tail, stlen);
4566 len -= stlen;
4567 tail += stlen;
4568 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4569 tail = portp->tx.buf;
4570 if (len > 0) {
4571 outsb((ioaddr + XP_DATA), tail, len);
4572 tail += len;
4573 }
4574 portp->tx.tail = tail;
4575 }
4576}
4577
4578/*****************************************************************************/
4579
4580/*
4581 * Receive character interrupt handler. Determine if we have good chars
4582 * or bad chars and then process appropriately. Good chars are easy
4583 * just shove the lot into the RX buffer and set all status byte to 0.
4584 * If a bad RX char then process as required. This routine needs to be
4585 * fast! In practice it is possible that we get an interrupt on a port
4586 * that is closed. This can happen on hangups - since they completely
4587 * shutdown a port not in user context. Need to handle this case.
4588 */
4589
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004590static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591{
4592 struct tty_struct *tty;
4593 unsigned int len, buflen, ioaddr;
4594
Jiri Slabya0564e12006-12-08 02:38:37 -08004595 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596
4597 tty = portp->tty;
4598 ioaddr = portp->ioaddr;
4599 outb(GIBCR, (ioaddr + XP_ADDR));
4600 len = inb(ioaddr + XP_DATA) + 1;
4601
4602 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004603 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604 len = MIN(len, sizeof(stl_unwanted));
4605 outb(GRXFIFO, (ioaddr + XP_ADDR));
4606 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4607 portp->stats.rxlost += len;
4608 portp->stats.rxtotal += len;
4609 } else {
4610 len = MIN(len, buflen);
4611 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004612 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004614 tty_prepare_flip_string(tty, &ptr, len);
4615 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 tty_schedule_flip(tty);
4617 portp->stats.rxtotal += len;
4618 }
4619 }
4620 } else {
4621 stl_sc26198rxbadchars(portp);
4622 }
4623
4624/*
4625 * If we are TX flow controlled and in IXANY mode then we may need
4626 * to unflow control here. We gotta do this because of the automatic
4627 * flow control modes of the sc26198.
4628 */
4629 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004630 if ((tty != NULL) &&
4631 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632 (tty->termios->c_iflag & IXANY)) {
4633 stl_sc26198txunflow(portp, tty);
4634 }
4635 }
4636}
4637
4638/*****************************************************************************/
4639
4640/*
4641 * Process an RX bad character.
4642 */
4643
Jiri Slaby60be4812006-12-08 02:38:40 -08004644static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645{
4646 struct tty_struct *tty;
4647 unsigned int ioaddr;
4648
4649 tty = portp->tty;
4650 ioaddr = portp->ioaddr;
4651
4652 if (status & SR_RXPARITY)
4653 portp->stats.rxparity++;
4654 if (status & SR_RXFRAMING)
4655 portp->stats.rxframing++;
4656 if (status & SR_RXOVERRUN)
4657 portp->stats.rxoverrun++;
4658 if (status & SR_RXBREAK)
4659 portp->stats.rxbreaks++;
4660
Jiri Slaby615e4a72006-12-08 02:38:38 -08004661 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662 ((portp->rxignoremsk & status) == 0)) {
4663 if (portp->rxmarkmsk & status) {
4664 if (status & SR_RXBREAK) {
4665 status = TTY_BREAK;
4666 if (portp->flags & ASYNC_SAK) {
4667 do_SAK(tty);
4668 BRDENABLE(portp->brdnr, portp->pagenr);
4669 }
4670 } else if (status & SR_RXPARITY) {
4671 status = TTY_PARITY;
4672 } else if (status & SR_RXFRAMING) {
4673 status = TTY_FRAME;
4674 } else if(status & SR_RXOVERRUN) {
4675 status = TTY_OVERRUN;
4676 } else {
4677 status = 0;
4678 }
4679 } else {
4680 status = 0;
4681 }
4682
Alan Cox33f0f882006-01-09 20:54:13 -08004683 tty_insert_flip_char(tty, ch, status);
4684 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685
4686 if (status == 0)
4687 portp->stats.rxtotal++;
4688 }
4689}
4690
4691/*****************************************************************************/
4692
4693/*
4694 * Process all characters in the RX FIFO of the UART. Check all char
4695 * status bytes as well, and process as required. We need to check
4696 * all bytes in the FIFO, in case some more enter the FIFO while we
4697 * are here. To get the exact character error type we need to switch
4698 * into CHAR error mode (that is why we need to make sure we empty
4699 * the FIFO).
4700 */
4701
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004702static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703{
4704 unsigned char status, mr1;
4705 char ch;
4706
4707/*
4708 * To get the precise error type for each character we must switch
4709 * back into CHAR error mode.
4710 */
4711 mr1 = stl_sc26198getreg(portp, MR1);
4712 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4713
4714 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4715 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4716 ch = stl_sc26198getreg(portp, RXFIFO);
4717 stl_sc26198rxbadch(portp, status, ch);
4718 }
4719
4720/*
4721 * To get correct interrupt class we must switch back into BLOCK
4722 * error mode.
4723 */
4724 stl_sc26198setreg(portp, MR1, mr1);
4725}
4726
4727/*****************************************************************************/
4728
4729/*
4730 * Other interrupt handler. This includes modem signals, flow
4731 * control actions, etc. Most stuff is left to off-level interrupt
4732 * processing time.
4733 */
4734
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004735static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736{
4737 unsigned char cir, ipr, xisr;
4738
Jiri Slabya0564e12006-12-08 02:38:37 -08004739 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740
4741 cir = stl_sc26198getglobreg(portp, CIR);
4742
4743 switch (cir & CIR_SUBTYPEMASK) {
4744 case CIR_SUBCOS:
4745 ipr = stl_sc26198getreg(portp, IPR);
4746 if (ipr & IPR_DCDCHANGE) {
4747 set_bit(ASYI_DCDCHANGE, &portp->istate);
4748 schedule_work(&portp->tqueue);
4749 portp->stats.modem++;
4750 }
4751 break;
4752 case CIR_SUBXONXOFF:
4753 xisr = stl_sc26198getreg(portp, XISR);
4754 if (xisr & XISR_RXXONGOT) {
4755 set_bit(ASYI_TXFLOWED, &portp->istate);
4756 portp->stats.txxoff++;
4757 }
4758 if (xisr & XISR_RXXOFFGOT) {
4759 clear_bit(ASYI_TXFLOWED, &portp->istate);
4760 portp->stats.txxon++;
4761 }
4762 break;
4763 case CIR_SUBBREAK:
4764 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4765 stl_sc26198rxbadchars(portp);
4766 break;
4767 default:
4768 break;
4769 }
4770}
4771
Jiri Slaby23b85a12006-12-08 02:38:40 -08004772/*
4773 * Loadable module initialization stuff.
4774 */
4775static int __init stallion_module_init(void)
4776{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004777 unsigned int i, retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004778
4779 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4780
4781 spin_lock_init(&stallion_lock);
4782 spin_lock_init(&brd_lock);
4783
4784 stl_initbrds();
4785
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004786 retval = pci_register_driver(&stl_pcidriver);
4787 if (retval)
4788 goto err;
4789
Jiri Slaby23b85a12006-12-08 02:38:40 -08004790 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4791 if (!stl_serial)
4792 return -1;
4793
4794/*
4795 * Set up a character driver for per board stuff. This is mainly used
4796 * to do stats ioctls on the ports.
4797 */
4798 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4799 printk("STALLION: failed to register serial board device\n");
4800
4801 stallion_class = class_create(THIS_MODULE, "staliomem");
4802 for (i = 0; i < 4; i++)
4803 class_device_create(stallion_class, NULL,
4804 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4805 "staliomem%d", i);
4806
4807 stl_serial->owner = THIS_MODULE;
4808 stl_serial->driver_name = stl_drvname;
4809 stl_serial->name = "ttyE";
4810 stl_serial->major = STL_SERIALMAJOR;
4811 stl_serial->minor_start = 0;
4812 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4813 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4814 stl_serial->init_termios = stl_deftermios;
4815 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4816 tty_set_operations(stl_serial, &stl_ops);
4817
4818 if (tty_register_driver(stl_serial)) {
4819 put_tty_driver(stl_serial);
4820 printk("STALLION: failed to register serial driver\n");
4821 return -1;
4822 }
4823
4824 return 0;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004825err:
4826 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004827}
4828
4829static void __exit stallion_module_exit(void)
4830{
4831 struct stlbrd *brdp;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004832 int i;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004833
4834 pr_debug("cleanup_module()\n");
4835
4836 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4837 stl_drvversion);
4838
4839/*
4840 * Free up all allocated resources used by the ports. This includes
4841 * memory and interrupts. As part of this process we will also do
4842 * a hangup on every open port - to try to flush out any processes
4843 * hanging onto ports.
4844 */
4845 i = tty_unregister_driver(stl_serial);
4846 put_tty_driver(stl_serial);
4847 if (i) {
4848 printk("STALLION: failed to un-register tty driver, "
4849 "errno=%d\n", -i);
4850 return;
4851 }
4852 for (i = 0; i < 4; i++)
4853 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4854 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4855 printk("STALLION: failed to un-register serial memory device, "
4856 "errno=%d\n", -i);
4857 class_destroy(stallion_class);
4858
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004859 pci_unregister_driver(&stl_pcidriver);
4860
Jiri Slaby23b85a12006-12-08 02:38:40 -08004861 for (i = 0; (i < stl_nrbrds); i++) {
4862 if ((brdp = stl_brds[i]) == NULL)
4863 continue;
4864
4865 free_irq(brdp->irq, brdp);
4866
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004867 stl_cleanup_panels(brdp);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004868
4869 release_region(brdp->ioaddr1, brdp->iosize1);
4870 if (brdp->iosize2 > 0)
4871 release_region(brdp->ioaddr2, brdp->iosize2);
4872
4873 kfree(brdp);
4874 stl_brds[i] = NULL;
4875 }
4876}
4877
4878module_init(stallion_module_init);
4879module_exit(stallion_module_exit);
4880
4881MODULE_AUTHOR("Greg Ungerer");
4882MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4883MODULE_LICENSE("GPL");