blob: 6a9feb69632df0523bea99eed1696883eb84d451 [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 Slabya0564e12006-12-08 02:38:37 -08002424 pr_debug("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002425 pdev->bus->number, pdev->devfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002427 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
2428 return -ENODEV;
2429
2430 dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
2431 pdev->vendor, pdev->device, pdev->class);
2432
2433 if (pci_enable_device(pdev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 return(-EIO);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002435 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 return(-ENOMEM);
2437 if ((brdp->brdnr = stl_getbrdnr()) < 0) {
2438 printk("STALLION: too many boards found, "
2439 "maximum supported %d\n", STL_MAXBRDS);
2440 return(0);
2441 }
2442 brdp->brdtype = brdtype;
2443
2444/*
2445 * Different Stallion boards use the BAR registers in different ways,
2446 * so set up io addresses based on board type.
2447 */
Jiri Slabya0564e12006-12-08 02:38:37 -08002448 pr_debug("%s(%d): BAR[]=%Lx,%Lx,%Lx,%Lx IRQ=%x\n", __FILE__, __LINE__,
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002449 pci_resource_start(pdev, 0), pci_resource_start(pdev, 1),
2450 pci_resource_start(pdev, 2), pci_resource_start(pdev, 3), pdev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
2452/*
2453 * We have all resources from the board, so let's setup the actual
2454 * board structure now.
2455 */
2456 switch (brdtype) {
2457 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002458 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2459 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 break;
2461 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002462 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2463 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 break;
2465 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002466 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2467 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 break;
2469 default:
2470 printk("STALLION: unknown PCI board type=%d\n", brdtype);
2471 break;
2472 }
2473
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002474 brdp->irq = pdev->irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 stl_brdinit(brdp);
2476
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002477 pci_set_drvdata(pdev, brdp);
2478
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 return(0);
2480}
2481
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002482static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002484 struct stlbrd *brdp = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002486 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002488 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002490 release_region(brdp->ioaddr1, brdp->iosize1);
2491 if (brdp->iosize2 > 0)
2492 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002494 stl_brds[brdp->brdnr] = NULL;
2495 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496}
2497
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002498static struct pci_driver stl_pcidriver = {
2499 .name = "stallion",
2500 .id_table = stl_pcibrds,
2501 .probe = stl_pciprobe,
2502 .remove = __devexit_p(stl_pciremove)
2503};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504
2505/*****************************************************************************/
2506
2507/*
2508 * Scan through all the boards in the configuration and see what we
2509 * can find. Handle EIO and the ECH boards a little differently here
2510 * since the initial search and setup is too different.
2511 */
2512
Jiri Slaby40e82652006-12-08 02:38:41 -08002513static int __init stl_initbrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002515 struct stlbrd *brdp;
2516 struct stlconf *confp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 int i;
2518
Jiri Slabya0564e12006-12-08 02:38:37 -08002519 pr_debug("stl_initbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520
2521 if (stl_nrbrds > STL_MAXBRDS) {
2522 printk("STALLION: too many boards in configuration table, "
2523 "truncating to %d\n", STL_MAXBRDS);
2524 stl_nrbrds = STL_MAXBRDS;
2525 }
2526
2527/*
2528 * Firstly scan the list of static boards configured. Allocate
2529 * resources and initialize the boards as found.
2530 */
2531 for (i = 0; (i < stl_nrbrds); i++) {
2532 confp = &stl_brdconf[i];
2533 stl_parsebrd(confp, stl_brdsp[i]);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002534 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 return(-ENOMEM);
2536 brdp->brdnr = i;
2537 brdp->brdtype = confp->brdtype;
2538 brdp->ioaddr1 = confp->ioaddr1;
2539 brdp->ioaddr2 = confp->ioaddr2;
2540 brdp->irq = confp->irq;
2541 brdp->irqtype = confp->irqtype;
2542 stl_brdinit(brdp);
2543 }
2544
2545/*
2546 * Find any dynamically supported boards. That is via module load
2547 * line options or auto-detected on the PCI bus.
2548 */
2549 stl_argbrds();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550
2551 return(0);
2552}
2553
2554/*****************************************************************************/
2555
2556/*
2557 * Return the board stats structure to user app.
2558 */
2559
2560static int stl_getbrdstats(combrd_t __user *bp)
2561{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002562 struct stlbrd *brdp;
2563 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 int i;
2565
2566 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2567 return -EFAULT;
2568 if (stl_brdstats.brd >= STL_MAXBRDS)
2569 return(-ENODEV);
2570 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002571 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 return(-ENODEV);
2573
2574 memset(&stl_brdstats, 0, sizeof(combrd_t));
2575 stl_brdstats.brd = brdp->brdnr;
2576 stl_brdstats.type = brdp->brdtype;
2577 stl_brdstats.hwid = brdp->hwid;
2578 stl_brdstats.state = brdp->state;
2579 stl_brdstats.ioaddr = brdp->ioaddr1;
2580 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2581 stl_brdstats.irq = brdp->irq;
2582 stl_brdstats.nrpanels = brdp->nrpanels;
2583 stl_brdstats.nrports = brdp->nrports;
2584 for (i = 0; (i < brdp->nrpanels); i++) {
2585 panelp = brdp->panels[i];
2586 stl_brdstats.panels[i].panel = i;
2587 stl_brdstats.panels[i].hwid = panelp->hwid;
2588 stl_brdstats.panels[i].nrports = panelp->nrports;
2589 }
2590
2591 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2592}
2593
2594/*****************************************************************************/
2595
2596/*
2597 * Resolve the referenced port number into a port struct pointer.
2598 */
2599
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002600static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002602 struct stlbrd *brdp;
2603 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604
2605 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002606 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002608 if (brdp == NULL)
2609 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002611 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002613 if (panelp == NULL)
2614 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002616 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 return(panelp->ports[portnr]);
2618}
2619
2620/*****************************************************************************/
2621
2622/*
2623 * Return the port stats structure to user app. A NULL port struct
2624 * pointer passed in means that we need to find out from the app
2625 * what port to get stats for (used through board control device).
2626 */
2627
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002628static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629{
2630 unsigned char *head, *tail;
2631 unsigned long flags;
2632
2633 if (!portp) {
2634 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2635 return -EFAULT;
2636 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2637 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002638 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 return(-ENODEV);
2640 }
2641
2642 portp->stats.state = portp->istate;
2643 portp->stats.flags = portp->flags;
2644 portp->stats.hwid = portp->hwid;
2645
2646 portp->stats.ttystate = 0;
2647 portp->stats.cflags = 0;
2648 portp->stats.iflags = 0;
2649 portp->stats.oflags = 0;
2650 portp->stats.lflags = 0;
2651 portp->stats.rxbuffered = 0;
2652
Alan Coxb65b5b52006-06-27 02:54:05 -07002653 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002654 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 if (portp->tty->driver_data == portp) {
2656 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002657 /* No longer available as a statistic */
2658 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002659 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 portp->stats.cflags = portp->tty->termios->c_cflag;
2661 portp->stats.iflags = portp->tty->termios->c_iflag;
2662 portp->stats.oflags = portp->tty->termios->c_oflag;
2663 portp->stats.lflags = portp->tty->termios->c_lflag;
2664 }
2665 }
2666 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002667 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
2669 head = portp->tx.head;
2670 tail = portp->tx.tail;
2671 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2672 (STL_TXBUFSIZE - (tail - head)));
2673
2674 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2675
2676 return copy_to_user(cp, &portp->stats,
2677 sizeof(comstats_t)) ? -EFAULT : 0;
2678}
2679
2680/*****************************************************************************/
2681
2682/*
2683 * Clear the port stats structure. We also return it zeroed out...
2684 */
2685
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002686static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687{
2688 if (!portp) {
2689 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2690 return -EFAULT;
2691 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2692 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002693 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 return(-ENODEV);
2695 }
2696
2697 memset(&portp->stats, 0, sizeof(comstats_t));
2698 portp->stats.brd = portp->brdnr;
2699 portp->stats.panel = portp->panelnr;
2700 portp->stats.port = portp->portnr;
2701 return copy_to_user(cp, &portp->stats,
2702 sizeof(comstats_t)) ? -EFAULT : 0;
2703}
2704
2705/*****************************************************************************/
2706
2707/*
2708 * Return the entire driver ports structure to a user app.
2709 */
2710
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002711static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002713 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002715 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 return -EFAULT;
2717 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2718 stl_dummyport.portnr);
2719 if (!portp)
2720 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002721 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722}
2723
2724/*****************************************************************************/
2725
2726/*
2727 * Return the entire driver board structure to a user app.
2728 */
2729
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002730static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002732 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002734 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 return -EFAULT;
2736 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2737 return -ENODEV;
2738 brdp = stl_brds[stl_dummybrd.brdnr];
2739 if (!brdp)
2740 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002741 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742}
2743
2744/*****************************************************************************/
2745
2746/*
2747 * The "staliomem" device is also required to do some special operations
2748 * on the board and/or ports. In this driver it is mostly used for stats
2749 * collection.
2750 */
2751
2752static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2753{
2754 int brdnr, rc;
2755 void __user *argp = (void __user *)arg;
2756
Jiri Slabya0564e12006-12-08 02:38:37 -08002757 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
2759 brdnr = iminor(ip);
2760 if (brdnr >= STL_MAXBRDS)
2761 return(-ENODEV);
2762 rc = 0;
2763
2764 switch (cmd) {
2765 case COM_GETPORTSTATS:
2766 rc = stl_getportstats(NULL, argp);
2767 break;
2768 case COM_CLRPORTSTATS:
2769 rc = stl_clrportstats(NULL, argp);
2770 break;
2771 case COM_GETBRDSTATS:
2772 rc = stl_getbrdstats(argp);
2773 break;
2774 case COM_READPORT:
2775 rc = stl_getportstruct(argp);
2776 break;
2777 case COM_READBOARD:
2778 rc = stl_getbrdstruct(argp);
2779 break;
2780 default:
2781 rc = -ENOIOCTLCMD;
2782 break;
2783 }
2784
2785 return(rc);
2786}
2787
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002788static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 .open = stl_open,
2790 .close = stl_close,
2791 .write = stl_write,
2792 .put_char = stl_putchar,
2793 .flush_chars = stl_flushchars,
2794 .write_room = stl_writeroom,
2795 .chars_in_buffer = stl_charsinbuffer,
2796 .ioctl = stl_ioctl,
2797 .set_termios = stl_settermios,
2798 .throttle = stl_throttle,
2799 .unthrottle = stl_unthrottle,
2800 .stop = stl_stop,
2801 .start = stl_start,
2802 .hangup = stl_hangup,
2803 .flush_buffer = stl_flushbuffer,
2804 .break_ctl = stl_breakctl,
2805 .wait_until_sent = stl_waituntilsent,
2806 .send_xchar = stl_sendxchar,
2807 .read_proc = stl_readproc,
2808 .tiocmget = stl_tiocmget,
2809 .tiocmset = stl_tiocmset,
2810};
2811
2812/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813/* CD1400 HARDWARE FUNCTIONS */
2814/*****************************************************************************/
2815
2816/*
2817 * These functions get/set/update the registers of the cd1400 UARTs.
2818 * Access to the cd1400 registers is via an address/data io port pair.
2819 * (Maybe should make this inline...)
2820 */
2821
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002822static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823{
2824 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002825 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826}
2827
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002828static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829{
2830 outb((regnr + portp->uartaddr), portp->ioaddr);
2831 outb(value, portp->ioaddr + EREG_DATA);
2832}
2833
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002834static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835{
2836 outb((regnr + portp->uartaddr), portp->ioaddr);
2837 if (inb(portp->ioaddr + EREG_DATA) != value) {
2838 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002839 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002841 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842}
2843
2844/*****************************************************************************/
2845
2846/*
2847 * Inbitialize the UARTs in a panel. We don't care what sort of board
2848 * these ports are on - since the port io registers are almost
2849 * identical when dealing with ports.
2850 */
2851
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002852static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853{
2854 unsigned int gfrcr;
2855 int chipmask, i, j;
2856 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002857 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858
Jiri Slabya0564e12006-12-08 02:38:37 -08002859 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860
Alan Coxb65b5b52006-06-27 02:54:05 -07002861 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 BRDENABLE(panelp->brdnr, panelp->pagenr);
2863
2864/*
2865 * Check that each chip is present and started up OK.
2866 */
2867 chipmask = 0;
2868 nrchips = panelp->nrports / CD1400_PORTS;
2869 for (i = 0; (i < nrchips); i++) {
2870 if (brdp->brdtype == BRD_ECHPCI) {
2871 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2872 ioaddr = panelp->iobase;
2873 } else {
2874 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2875 }
2876 uartaddr = (i & 0x01) ? 0x080 : 0;
2877 outb((GFRCR + uartaddr), ioaddr);
2878 outb(0, (ioaddr + EREG_DATA));
2879 outb((CCR + uartaddr), ioaddr);
2880 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2881 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2882 outb((GFRCR + uartaddr), ioaddr);
2883 for (j = 0; (j < CCR_MAXWAIT); j++) {
2884 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2885 break;
2886 }
2887 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2888 printk("STALLION: cd1400 not responding, "
2889 "brd=%d panel=%d chip=%d\n",
2890 panelp->brdnr, panelp->panelnr, i);
2891 continue;
2892 }
2893 chipmask |= (0x1 << i);
2894 outb((PPR + uartaddr), ioaddr);
2895 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2896 }
2897
2898 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002899 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002900 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901}
2902
2903/*****************************************************************************/
2904
2905/*
2906 * Initialize hardware specific port registers.
2907 */
2908
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002909static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910{
Alan Coxb65b5b52006-06-27 02:54:05 -07002911 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002912 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2913 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
Jiri Slaby615e4a72006-12-08 02:38:38 -08002915 if ((brdp == NULL) || (panelp == NULL) ||
2916 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 return;
2918
Alan Coxb65b5b52006-06-27 02:54:05 -07002919 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2921 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2922 portp->uartaddr = (portp->portnr & 0x04) << 5;
2923 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2924
2925 BRDENABLE(portp->brdnr, portp->pagenr);
2926 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2927 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2928 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2929 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002930 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931}
2932
2933/*****************************************************************************/
2934
2935/*
2936 * Wait for the command register to be ready. We will poll this,
2937 * since it won't usually take too long to be ready.
2938 */
2939
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002940static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941{
2942 int i;
2943
2944 for (i = 0; (i < CCR_MAXWAIT); i++) {
2945 if (stl_cd1400getreg(portp, CCR) == 0) {
2946 return;
2947 }
2948 }
2949
2950 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2951 portp->portnr, portp->panelnr, portp->brdnr);
2952}
2953
2954/*****************************************************************************/
2955
2956/*
2957 * Set up the cd1400 registers for a port based on the termios port
2958 * settings.
2959 */
2960
Alan Cox606d0992006-12-08 02:38:45 -08002961static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002963 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 unsigned long flags;
2965 unsigned int clkdiv, baudrate;
2966 unsigned char cor1, cor2, cor3;
2967 unsigned char cor4, cor5, ccr;
2968 unsigned char srer, sreron, sreroff;
2969 unsigned char mcor1, mcor2, rtpr;
2970 unsigned char clk, div;
2971
2972 cor1 = 0;
2973 cor2 = 0;
2974 cor3 = 0;
2975 cor4 = 0;
2976 cor5 = 0;
2977 ccr = 0;
2978 rtpr = 0;
2979 clk = 0;
2980 div = 0;
2981 mcor1 = 0;
2982 mcor2 = 0;
2983 sreron = 0;
2984 sreroff = 0;
2985
2986 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002987 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 return;
2989
2990/*
2991 * Set up the RX char ignore mask with those RX error types we
2992 * can ignore. We can get the cd1400 to help us out a little here,
2993 * it will ignore parity errors and breaks for us.
2994 */
2995 portp->rxignoremsk = 0;
2996 if (tiosp->c_iflag & IGNPAR) {
2997 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2998 cor1 |= COR1_PARIGNORE;
2999 }
3000 if (tiosp->c_iflag & IGNBRK) {
3001 portp->rxignoremsk |= ST_BREAK;
3002 cor4 |= COR4_IGNBRK;
3003 }
3004
3005 portp->rxmarkmsk = ST_OVERRUN;
3006 if (tiosp->c_iflag & (INPCK | PARMRK))
3007 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
3008 if (tiosp->c_iflag & BRKINT)
3009 portp->rxmarkmsk |= ST_BREAK;
3010
3011/*
3012 * Go through the char size, parity and stop bits and set all the
3013 * option register appropriately.
3014 */
3015 switch (tiosp->c_cflag & CSIZE) {
3016 case CS5:
3017 cor1 |= COR1_CHL5;
3018 break;
3019 case CS6:
3020 cor1 |= COR1_CHL6;
3021 break;
3022 case CS7:
3023 cor1 |= COR1_CHL7;
3024 break;
3025 default:
3026 cor1 |= COR1_CHL8;
3027 break;
3028 }
3029
3030 if (tiosp->c_cflag & CSTOPB)
3031 cor1 |= COR1_STOP2;
3032 else
3033 cor1 |= COR1_STOP1;
3034
3035 if (tiosp->c_cflag & PARENB) {
3036 if (tiosp->c_cflag & PARODD)
3037 cor1 |= (COR1_PARENB | COR1_PARODD);
3038 else
3039 cor1 |= (COR1_PARENB | COR1_PAREVEN);
3040 } else {
3041 cor1 |= COR1_PARNONE;
3042 }
3043
3044/*
3045 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
3046 * space for hardware flow control and the like. This should be set to
3047 * VMIN. Also here we will set the RX data timeout to 10ms - this should
3048 * really be based on VTIME.
3049 */
3050 cor3 |= FIFO_RXTHRESHOLD;
3051 rtpr = 2;
3052
3053/*
3054 * Calculate the baud rate timers. For now we will just assume that
3055 * the input and output baud are the same. Could have used a baud
3056 * table here, but this way we can generate virtually any baud rate
3057 * we like!
3058 */
3059 baudrate = tiosp->c_cflag & CBAUD;
3060 if (baudrate & CBAUDEX) {
3061 baudrate &= ~CBAUDEX;
3062 if ((baudrate < 1) || (baudrate > 4))
3063 tiosp->c_cflag &= ~CBAUDEX;
3064 else
3065 baudrate += 15;
3066 }
3067 baudrate = stl_baudrates[baudrate];
3068 if ((tiosp->c_cflag & CBAUD) == B38400) {
3069 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3070 baudrate = 57600;
3071 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3072 baudrate = 115200;
3073 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3074 baudrate = 230400;
3075 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3076 baudrate = 460800;
3077 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3078 baudrate = (portp->baud_base / portp->custom_divisor);
3079 }
3080 if (baudrate > STL_CD1400MAXBAUD)
3081 baudrate = STL_CD1400MAXBAUD;
3082
3083 if (baudrate > 0) {
3084 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
3085 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
3086 if (clkdiv < 0x100)
3087 break;
3088 }
3089 div = (unsigned char) clkdiv;
3090 }
3091
3092/*
3093 * Check what form of modem signaling is required and set it up.
3094 */
3095 if ((tiosp->c_cflag & CLOCAL) == 0) {
3096 mcor1 |= MCOR1_DCD;
3097 mcor2 |= MCOR2_DCD;
3098 sreron |= SRER_MODEM;
3099 portp->flags |= ASYNC_CHECK_CD;
3100 } else {
3101 portp->flags &= ~ASYNC_CHECK_CD;
3102 }
3103
3104/*
3105 * Setup cd1400 enhanced modes if we can. In particular we want to
3106 * handle as much of the flow control as possible automatically. As
3107 * well as saving a few CPU cycles it will also greatly improve flow
3108 * control reliability.
3109 */
3110 if (tiosp->c_iflag & IXON) {
3111 cor2 |= COR2_TXIBE;
3112 cor3 |= COR3_SCD12;
3113 if (tiosp->c_iflag & IXANY)
3114 cor2 |= COR2_IXM;
3115 }
3116
3117 if (tiosp->c_cflag & CRTSCTS) {
3118 cor2 |= COR2_CTSAE;
3119 mcor1 |= FIFO_RTSTHRESHOLD;
3120 }
3121
3122/*
3123 * All cd1400 register values calculated so go through and set
3124 * them all up.
3125 */
3126
Jiri Slabya0564e12006-12-08 02:38:37 -08003127 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003129 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003131 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003133 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3134 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3136 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137
Alan Coxb65b5b52006-06-27 02:54:05 -07003138 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 BRDENABLE(portp->brdnr, portp->pagenr);
3140 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3141 srer = stl_cd1400getreg(portp, SRER);
3142 stl_cd1400setreg(portp, SRER, 0);
3143 if (stl_cd1400updatereg(portp, COR1, cor1))
3144 ccr = 1;
3145 if (stl_cd1400updatereg(portp, COR2, cor2))
3146 ccr = 1;
3147 if (stl_cd1400updatereg(portp, COR3, cor3))
3148 ccr = 1;
3149 if (ccr) {
3150 stl_cd1400ccrwait(portp);
3151 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3152 }
3153 stl_cd1400setreg(portp, COR4, cor4);
3154 stl_cd1400setreg(portp, COR5, cor5);
3155 stl_cd1400setreg(portp, MCOR1, mcor1);
3156 stl_cd1400setreg(portp, MCOR2, mcor2);
3157 if (baudrate > 0) {
3158 stl_cd1400setreg(portp, TCOR, clk);
3159 stl_cd1400setreg(portp, TBPR, div);
3160 stl_cd1400setreg(portp, RCOR, clk);
3161 stl_cd1400setreg(portp, RBPR, div);
3162 }
3163 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3164 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3165 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3166 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3167 stl_cd1400setreg(portp, RTPR, rtpr);
3168 mcor1 = stl_cd1400getreg(portp, MSVR1);
3169 if (mcor1 & MSVR1_DCD)
3170 portp->sigs |= TIOCM_CD;
3171 else
3172 portp->sigs &= ~TIOCM_CD;
3173 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3174 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003175 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176}
3177
3178/*****************************************************************************/
3179
3180/*
3181 * Set the state of the DTR and RTS signals.
3182 */
3183
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003184static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185{
3186 unsigned char msvr1, msvr2;
3187 unsigned long flags;
3188
Jiri Slabya0564e12006-12-08 02:38:37 -08003189 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3190 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
3192 msvr1 = 0;
3193 msvr2 = 0;
3194 if (dtr > 0)
3195 msvr1 = MSVR1_DTR;
3196 if (rts > 0)
3197 msvr2 = MSVR2_RTS;
3198
Alan Coxb65b5b52006-06-27 02:54:05 -07003199 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 BRDENABLE(portp->brdnr, portp->pagenr);
3201 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3202 if (rts >= 0)
3203 stl_cd1400setreg(portp, MSVR2, msvr2);
3204 if (dtr >= 0)
3205 stl_cd1400setreg(portp, MSVR1, msvr1);
3206 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003207 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208}
3209
3210/*****************************************************************************/
3211
3212/*
3213 * Return the state of the signals.
3214 */
3215
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003216static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217{
3218 unsigned char msvr1, msvr2;
3219 unsigned long flags;
3220 int sigs;
3221
Jiri Slabya0564e12006-12-08 02:38:37 -08003222 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223
Alan Coxb65b5b52006-06-27 02:54:05 -07003224 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225 BRDENABLE(portp->brdnr, portp->pagenr);
3226 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3227 msvr1 = stl_cd1400getreg(portp, MSVR1);
3228 msvr2 = stl_cd1400getreg(portp, MSVR2);
3229 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003230 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231
3232 sigs = 0;
3233 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3234 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3235 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3236 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3237#if 0
3238 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3239 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3240#else
3241 sigs |= TIOCM_DSR;
3242#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003243 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244}
3245
3246/*****************************************************************************/
3247
3248/*
3249 * Enable/Disable the Transmitter and/or Receiver.
3250 */
3251
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003252static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253{
3254 unsigned char ccr;
3255 unsigned long flags;
3256
Jiri Slabya0564e12006-12-08 02:38:37 -08003257 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3258
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 ccr = 0;
3260
3261 if (tx == 0)
3262 ccr |= CCR_TXDISABLE;
3263 else if (tx > 0)
3264 ccr |= CCR_TXENABLE;
3265 if (rx == 0)
3266 ccr |= CCR_RXDISABLE;
3267 else if (rx > 0)
3268 ccr |= CCR_RXENABLE;
3269
Alan Coxb65b5b52006-06-27 02:54:05 -07003270 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271 BRDENABLE(portp->brdnr, portp->pagenr);
3272 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3273 stl_cd1400ccrwait(portp);
3274 stl_cd1400setreg(portp, CCR, ccr);
3275 stl_cd1400ccrwait(portp);
3276 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003277 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278}
3279
3280/*****************************************************************************/
3281
3282/*
3283 * Start/stop the Transmitter and/or Receiver.
3284 */
3285
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003286static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287{
3288 unsigned char sreron, sreroff;
3289 unsigned long flags;
3290
Jiri Slabya0564e12006-12-08 02:38:37 -08003291 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292
3293 sreron = 0;
3294 sreroff = 0;
3295 if (tx == 0)
3296 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3297 else if (tx == 1)
3298 sreron |= SRER_TXDATA;
3299 else if (tx >= 2)
3300 sreron |= SRER_TXEMPTY;
3301 if (rx == 0)
3302 sreroff |= SRER_RXDATA;
3303 else if (rx > 0)
3304 sreron |= SRER_RXDATA;
3305
Alan Coxb65b5b52006-06-27 02:54:05 -07003306 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 BRDENABLE(portp->brdnr, portp->pagenr);
3308 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3309 stl_cd1400setreg(portp, SRER,
3310 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3311 BRDDISABLE(portp->brdnr);
3312 if (tx > 0)
3313 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003314 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315}
3316
3317/*****************************************************************************/
3318
3319/*
3320 * Disable all interrupts from this port.
3321 */
3322
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003323static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324{
3325 unsigned long flags;
3326
Jiri Slabya0564e12006-12-08 02:38:37 -08003327 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3328
Alan Coxb65b5b52006-06-27 02:54:05 -07003329 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330 BRDENABLE(portp->brdnr, portp->pagenr);
3331 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3332 stl_cd1400setreg(portp, SRER, 0);
3333 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003334 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335}
3336
3337/*****************************************************************************/
3338
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003339static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340{
3341 unsigned long flags;
3342
Jiri Slabya0564e12006-12-08 02:38:37 -08003343 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344
Alan Coxb65b5b52006-06-27 02:54:05 -07003345 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 BRDENABLE(portp->brdnr, portp->pagenr);
3347 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3348 stl_cd1400setreg(portp, SRER,
3349 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3350 SRER_TXEMPTY));
3351 BRDDISABLE(portp->brdnr);
3352 portp->brklen = len;
3353 if (len == 1)
3354 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003355 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356}
3357
3358/*****************************************************************************/
3359
3360/*
3361 * Take flow control actions...
3362 */
3363
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003364static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365{
3366 struct tty_struct *tty;
3367 unsigned long flags;
3368
Jiri Slabya0564e12006-12-08 02:38:37 -08003369 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370
Jiri Slaby615e4a72006-12-08 02:38:38 -08003371 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 return;
3373 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003374 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 return;
3376
Alan Coxb65b5b52006-06-27 02:54:05 -07003377 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 BRDENABLE(portp->brdnr, portp->pagenr);
3379 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3380
3381 if (state) {
3382 if (tty->termios->c_iflag & IXOFF) {
3383 stl_cd1400ccrwait(portp);
3384 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3385 portp->stats.rxxon++;
3386 stl_cd1400ccrwait(portp);
3387 }
3388/*
3389 * Question: should we return RTS to what it was before? It may
3390 * have been set by an ioctl... Suppose not, since if you have
3391 * hardware flow control set then it is pretty silly to go and
3392 * set the RTS line by hand.
3393 */
3394 if (tty->termios->c_cflag & CRTSCTS) {
3395 stl_cd1400setreg(portp, MCOR1,
3396 (stl_cd1400getreg(portp, MCOR1) |
3397 FIFO_RTSTHRESHOLD));
3398 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3399 portp->stats.rxrtson++;
3400 }
3401 } else {
3402 if (tty->termios->c_iflag & IXOFF) {
3403 stl_cd1400ccrwait(portp);
3404 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3405 portp->stats.rxxoff++;
3406 stl_cd1400ccrwait(portp);
3407 }
3408 if (tty->termios->c_cflag & CRTSCTS) {
3409 stl_cd1400setreg(portp, MCOR1,
3410 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3411 stl_cd1400setreg(portp, MSVR2, 0);
3412 portp->stats.rxrtsoff++;
3413 }
3414 }
3415
3416 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003417 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418}
3419
3420/*****************************************************************************/
3421
3422/*
3423 * Send a flow control character...
3424 */
3425
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003426static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427{
3428 struct tty_struct *tty;
3429 unsigned long flags;
3430
Jiri Slabya0564e12006-12-08 02:38:37 -08003431 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432
Jiri Slaby615e4a72006-12-08 02:38:38 -08003433 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434 return;
3435 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003436 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437 return;
3438
Alan Coxb65b5b52006-06-27 02:54:05 -07003439 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440 BRDENABLE(portp->brdnr, portp->pagenr);
3441 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3442 if (state) {
3443 stl_cd1400ccrwait(portp);
3444 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3445 portp->stats.rxxon++;
3446 stl_cd1400ccrwait(portp);
3447 } else {
3448 stl_cd1400ccrwait(portp);
3449 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3450 portp->stats.rxxoff++;
3451 stl_cd1400ccrwait(portp);
3452 }
3453 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003454 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455}
3456
3457/*****************************************************************************/
3458
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003459static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460{
3461 unsigned long flags;
3462
Jiri Slabya0564e12006-12-08 02:38:37 -08003463 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464
Jiri Slaby615e4a72006-12-08 02:38:38 -08003465 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 return;
3467
Alan Coxb65b5b52006-06-27 02:54:05 -07003468 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 BRDENABLE(portp->brdnr, portp->pagenr);
3470 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3471 stl_cd1400ccrwait(portp);
3472 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3473 stl_cd1400ccrwait(portp);
3474 portp->tx.tail = portp->tx.head;
3475 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003476 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477}
3478
3479/*****************************************************************************/
3480
3481/*
3482 * Return the current state of data flow on this port. This is only
3483 * really interresting when determining if data has fully completed
3484 * transmission or not... This is easy for the cd1400, it accurately
3485 * maintains the busy port flag.
3486 */
3487
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003488static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489{
Jiri Slabya0564e12006-12-08 02:38:37 -08003490 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
Jiri Slaby615e4a72006-12-08 02:38:38 -08003492 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003493 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494
Jesper Juhl014c2542006-01-15 02:37:08 +01003495 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496}
3497
3498/*****************************************************************************/
3499
3500/*
3501 * Interrupt service routine for cd1400 EasyIO boards.
3502 */
3503
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003504static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505{
3506 unsigned char svrtype;
3507
Jiri Slabya0564e12006-12-08 02:38:37 -08003508 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509
Alan Coxb65b5b52006-06-27 02:54:05 -07003510 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 outb(SVRR, iobase);
3512 svrtype = inb(iobase + EREG_DATA);
3513 if (panelp->nrports > 4) {
3514 outb((SVRR + 0x80), iobase);
3515 svrtype |= inb(iobase + EREG_DATA);
3516 }
3517
3518 if (svrtype & SVRR_RX)
3519 stl_cd1400rxisr(panelp, iobase);
3520 else if (svrtype & SVRR_TX)
3521 stl_cd1400txisr(panelp, iobase);
3522 else if (svrtype & SVRR_MDM)
3523 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003524
3525 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526}
3527
3528/*****************************************************************************/
3529
3530/*
3531 * Interrupt service routine for cd1400 panels.
3532 */
3533
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003534static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535{
3536 unsigned char svrtype;
3537
Jiri Slabya0564e12006-12-08 02:38:37 -08003538 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539
3540 outb(SVRR, iobase);
3541 svrtype = inb(iobase + EREG_DATA);
3542 outb((SVRR + 0x80), iobase);
3543 svrtype |= inb(iobase + EREG_DATA);
3544 if (svrtype & SVRR_RX)
3545 stl_cd1400rxisr(panelp, iobase);
3546 else if (svrtype & SVRR_TX)
3547 stl_cd1400txisr(panelp, iobase);
3548 else if (svrtype & SVRR_MDM)
3549 stl_cd1400mdmisr(panelp, iobase);
3550}
3551
3552
3553/*****************************************************************************/
3554
3555/*
3556 * Unfortunately we need to handle breaks in the TX data stream, since
3557 * this is the only way to generate them on the cd1400.
3558 */
3559
Jiri Slaby60be4812006-12-08 02:38:40 -08003560static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561{
3562 if (portp->brklen == 1) {
3563 outb((COR2 + portp->uartaddr), ioaddr);
3564 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3565 (ioaddr + EREG_DATA));
3566 outb((TDR + portp->uartaddr), ioaddr);
3567 outb(ETC_CMD, (ioaddr + EREG_DATA));
3568 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3569 outb((SRER + portp->uartaddr), ioaddr);
3570 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3571 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003572 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 } else if (portp->brklen > 1) {
3574 outb((TDR + portp->uartaddr), ioaddr);
3575 outb(ETC_CMD, (ioaddr + EREG_DATA));
3576 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3577 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003578 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 } else {
3580 outb((COR2 + portp->uartaddr), ioaddr);
3581 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3582 (ioaddr + EREG_DATA));
3583 portp->brklen = 0;
3584 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003585 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586}
3587
3588/*****************************************************************************/
3589
3590/*
3591 * Transmit interrupt handler. This has gotta be fast! Handling TX
3592 * chars is pretty simple, stuff as many as possible from the TX buffer
3593 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3594 * are embedded as commands in the data stream. Oh no, had to use a goto!
3595 * This could be optimized more, will do when I get time...
3596 * In practice it is possible that interrupts are enabled but that the
3597 * port has been hung up. Need to handle not having any TX buffer here,
3598 * this is done by using the side effect that head and tail will also
3599 * be NULL if the buffer has been freed.
3600 */
3601
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003602static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003604 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 int len, stlen;
3606 char *head, *tail;
3607 unsigned char ioack, srer;
3608
Jiri Slabya0564e12006-12-08 02:38:37 -08003609 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610
3611 ioack = inb(ioaddr + EREG_TXACK);
3612 if (((ioack & panelp->ackmask) != 0) ||
3613 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3614 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3615 return;
3616 }
3617 portp = panelp->ports[(ioack >> 3)];
3618
3619/*
3620 * Unfortunately we need to handle breaks in the data stream, since
3621 * this is the only way to generate them on the cd1400. Do it now if
3622 * a break is to be sent.
3623 */
3624 if (portp->brklen != 0)
3625 if (stl_cd1400breakisr(portp, ioaddr))
3626 goto stl_txalldone;
3627
3628 head = portp->tx.head;
3629 tail = portp->tx.tail;
3630 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3631 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3632 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3633 set_bit(ASYI_TXLOW, &portp->istate);
3634 schedule_work(&portp->tqueue);
3635 }
3636
3637 if (len == 0) {
3638 outb((SRER + portp->uartaddr), ioaddr);
3639 srer = inb(ioaddr + EREG_DATA);
3640 if (srer & SRER_TXDATA) {
3641 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3642 } else {
3643 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3644 clear_bit(ASYI_TXBUSY, &portp->istate);
3645 }
3646 outb(srer, (ioaddr + EREG_DATA));
3647 } else {
3648 len = MIN(len, CD1400_TXFIFOSIZE);
3649 portp->stats.txtotal += len;
3650 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
3651 outb((TDR + portp->uartaddr), ioaddr);
3652 outsb((ioaddr + EREG_DATA), tail, stlen);
3653 len -= stlen;
3654 tail += stlen;
3655 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3656 tail = portp->tx.buf;
3657 if (len > 0) {
3658 outsb((ioaddr + EREG_DATA), tail, len);
3659 tail += len;
3660 }
3661 portp->tx.tail = tail;
3662 }
3663
3664stl_txalldone:
3665 outb((EOSRR + portp->uartaddr), ioaddr);
3666 outb(0, (ioaddr + EREG_DATA));
3667}
3668
3669/*****************************************************************************/
3670
3671/*
3672 * Receive character interrupt handler. Determine if we have good chars
3673 * or bad chars and then process appropriately. Good chars are easy
3674 * just shove the lot into the RX buffer and set all status byte to 0.
3675 * If a bad RX char then process as required. This routine needs to be
3676 * fast! In practice it is possible that we get an interrupt on a port
3677 * that is closed. This can happen on hangups - since they completely
3678 * shutdown a port not in user context. Need to handle this case.
3679 */
3680
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003681static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003683 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684 struct tty_struct *tty;
3685 unsigned int ioack, len, buflen;
3686 unsigned char status;
3687 char ch;
3688
Jiri Slabya0564e12006-12-08 02:38:37 -08003689 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690
3691 ioack = inb(ioaddr + EREG_RXACK);
3692 if ((ioack & panelp->ackmask) != 0) {
3693 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3694 return;
3695 }
3696 portp = panelp->ports[(ioack >> 3)];
3697 tty = portp->tty;
3698
3699 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3700 outb((RDCR + portp->uartaddr), ioaddr);
3701 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003702 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 len = MIN(len, sizeof(stl_unwanted));
3704 outb((RDSR + portp->uartaddr), ioaddr);
3705 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3706 portp->stats.rxlost += len;
3707 portp->stats.rxtotal += len;
3708 } else {
3709 len = MIN(len, buflen);
3710 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003711 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003713 tty_prepare_flip_string(tty, &ptr, len);
3714 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 tty_schedule_flip(tty);
3716 portp->stats.rxtotal += len;
3717 }
3718 }
3719 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3720 outb((RDSR + portp->uartaddr), ioaddr);
3721 status = inb(ioaddr + EREG_DATA);
3722 ch = inb(ioaddr + EREG_DATA);
3723 if (status & ST_PARITY)
3724 portp->stats.rxparity++;
3725 if (status & ST_FRAMING)
3726 portp->stats.rxframing++;
3727 if (status & ST_OVERRUN)
3728 portp->stats.rxoverrun++;
3729 if (status & ST_BREAK)
3730 portp->stats.rxbreaks++;
3731 if (status & ST_SCHARMASK) {
3732 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3733 portp->stats.txxon++;
3734 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3735 portp->stats.txxoff++;
3736 goto stl_rxalldone;
3737 }
Alan Cox33f0f882006-01-09 20:54:13 -08003738 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739 if (portp->rxmarkmsk & status) {
3740 if (status & ST_BREAK) {
3741 status = TTY_BREAK;
3742 if (portp->flags & ASYNC_SAK) {
3743 do_SAK(tty);
3744 BRDENABLE(portp->brdnr, portp->pagenr);
3745 }
3746 } else if (status & ST_PARITY) {
3747 status = TTY_PARITY;
3748 } else if (status & ST_FRAMING) {
3749 status = TTY_FRAME;
3750 } else if(status & ST_OVERRUN) {
3751 status = TTY_OVERRUN;
3752 } else {
3753 status = 0;
3754 }
3755 } else {
3756 status = 0;
3757 }
Alan Cox33f0f882006-01-09 20:54:13 -08003758 tty_insert_flip_char(tty, ch, status);
3759 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 }
3761 } else {
3762 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3763 return;
3764 }
3765
3766stl_rxalldone:
3767 outb((EOSRR + portp->uartaddr), ioaddr);
3768 outb(0, (ioaddr + EREG_DATA));
3769}
3770
3771/*****************************************************************************/
3772
3773/*
3774 * Modem interrupt handler. The is called when the modem signal line
3775 * (DCD) has changed state. Leave most of the work to the off-level
3776 * processing routine.
3777 */
3778
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003779static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003781 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 unsigned int ioack;
3783 unsigned char misr;
3784
Jiri Slabya0564e12006-12-08 02:38:37 -08003785 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786
3787 ioack = inb(ioaddr + EREG_MDACK);
3788 if (((ioack & panelp->ackmask) != 0) ||
3789 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3790 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3791 return;
3792 }
3793 portp = panelp->ports[(ioack >> 3)];
3794
3795 outb((MISR + portp->uartaddr), ioaddr);
3796 misr = inb(ioaddr + EREG_DATA);
3797 if (misr & MISR_DCD) {
3798 set_bit(ASYI_DCDCHANGE, &portp->istate);
3799 schedule_work(&portp->tqueue);
3800 portp->stats.modem++;
3801 }
3802
3803 outb((EOSRR + portp->uartaddr), ioaddr);
3804 outb(0, (ioaddr + EREG_DATA));
3805}
3806
3807/*****************************************************************************/
3808/* SC26198 HARDWARE FUNCTIONS */
3809/*****************************************************************************/
3810
3811/*
3812 * These functions get/set/update the registers of the sc26198 UARTs.
3813 * Access to the sc26198 registers is via an address/data io port pair.
3814 * (Maybe should make this inline...)
3815 */
3816
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003817static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818{
3819 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003820 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821}
3822
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003823static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824{
3825 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3826 outb(value, (portp->ioaddr + XP_DATA));
3827}
3828
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003829static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830{
3831 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3832 if (inb(portp->ioaddr + XP_DATA) != value) {
3833 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003834 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003836 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837}
3838
3839/*****************************************************************************/
3840
3841/*
3842 * Functions to get and set the sc26198 global registers.
3843 */
3844
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003845static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846{
3847 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003848 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849}
3850
3851#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003852static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853{
3854 outb(regnr, (portp->ioaddr + XP_ADDR));
3855 outb(value, (portp->ioaddr + XP_DATA));
3856}
3857#endif
3858
3859/*****************************************************************************/
3860
3861/*
3862 * Inbitialize the UARTs in a panel. We don't care what sort of board
3863 * these ports are on - since the port io registers are almost
3864 * identical when dealing with ports.
3865 */
3866
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003867static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868{
3869 int chipmask, i;
3870 int nrchips, ioaddr;
3871
Jiri Slabya0564e12006-12-08 02:38:37 -08003872 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873
3874 BRDENABLE(panelp->brdnr, panelp->pagenr);
3875
3876/*
3877 * Check that each chip is present and started up OK.
3878 */
3879 chipmask = 0;
3880 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3881 if (brdp->brdtype == BRD_ECHPCI)
3882 outb(panelp->pagenr, brdp->ioctrl);
3883
3884 for (i = 0; (i < nrchips); i++) {
3885 ioaddr = panelp->iobase + (i * 4);
3886 outb(SCCR, (ioaddr + XP_ADDR));
3887 outb(CR_RESETALL, (ioaddr + XP_DATA));
3888 outb(TSTR, (ioaddr + XP_ADDR));
3889 if (inb(ioaddr + XP_DATA) != 0) {
3890 printk("STALLION: sc26198 not responding, "
3891 "brd=%d panel=%d chip=%d\n",
3892 panelp->brdnr, panelp->panelnr, i);
3893 continue;
3894 }
3895 chipmask |= (0x1 << i);
3896 outb(GCCR, (ioaddr + XP_ADDR));
3897 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3898 outb(WDTRCR, (ioaddr + XP_ADDR));
3899 outb(0xff, (ioaddr + XP_DATA));
3900 }
3901
3902 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003903 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904}
3905
3906/*****************************************************************************/
3907
3908/*
3909 * Initialize hardware specific port registers.
3910 */
3911
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003912static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913{
Jiri Slabya0564e12006-12-08 02:38:37 -08003914 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3915 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916
Jiri Slaby615e4a72006-12-08 02:38:38 -08003917 if ((brdp == NULL) || (panelp == NULL) ||
3918 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 return;
3920
3921 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3922 portp->uartaddr = (portp->portnr & 0x07) << 4;
3923 portp->pagenr = panelp->pagenr;
3924 portp->hwid = 0x1;
3925
3926 BRDENABLE(portp->brdnr, portp->pagenr);
3927 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3928 BRDDISABLE(portp->brdnr);
3929}
3930
3931/*****************************************************************************/
3932
3933/*
3934 * Set up the sc26198 registers for a port based on the termios port
3935 * settings.
3936 */
3937
Alan Cox606d0992006-12-08 02:38:45 -08003938static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003940 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 unsigned long flags;
3942 unsigned int baudrate;
3943 unsigned char mr0, mr1, mr2, clk;
3944 unsigned char imron, imroff, iopr, ipr;
3945
3946 mr0 = 0;
3947 mr1 = 0;
3948 mr2 = 0;
3949 clk = 0;
3950 iopr = 0;
3951 imron = 0;
3952 imroff = 0;
3953
3954 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003955 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 return;
3957
3958/*
3959 * Set up the RX char ignore mask with those RX error types we
3960 * can ignore.
3961 */
3962 portp->rxignoremsk = 0;
3963 if (tiosp->c_iflag & IGNPAR)
3964 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3965 SR_RXOVERRUN);
3966 if (tiosp->c_iflag & IGNBRK)
3967 portp->rxignoremsk |= SR_RXBREAK;
3968
3969 portp->rxmarkmsk = SR_RXOVERRUN;
3970 if (tiosp->c_iflag & (INPCK | PARMRK))
3971 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3972 if (tiosp->c_iflag & BRKINT)
3973 portp->rxmarkmsk |= SR_RXBREAK;
3974
3975/*
3976 * Go through the char size, parity and stop bits and set all the
3977 * option register appropriately.
3978 */
3979 switch (tiosp->c_cflag & CSIZE) {
3980 case CS5:
3981 mr1 |= MR1_CS5;
3982 break;
3983 case CS6:
3984 mr1 |= MR1_CS6;
3985 break;
3986 case CS7:
3987 mr1 |= MR1_CS7;
3988 break;
3989 default:
3990 mr1 |= MR1_CS8;
3991 break;
3992 }
3993
3994 if (tiosp->c_cflag & CSTOPB)
3995 mr2 |= MR2_STOP2;
3996 else
3997 mr2 |= MR2_STOP1;
3998
3999 if (tiosp->c_cflag & PARENB) {
4000 if (tiosp->c_cflag & PARODD)
4001 mr1 |= (MR1_PARENB | MR1_PARODD);
4002 else
4003 mr1 |= (MR1_PARENB | MR1_PAREVEN);
4004 } else {
4005 mr1 |= MR1_PARNONE;
4006 }
4007
4008 mr1 |= MR1_ERRBLOCK;
4009
4010/*
4011 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
4012 * space for hardware flow control and the like. This should be set to
4013 * VMIN.
4014 */
4015 mr2 |= MR2_RXFIFOHALF;
4016
4017/*
4018 * Calculate the baud rate timers. For now we will just assume that
4019 * the input and output baud are the same. The sc26198 has a fixed
4020 * baud rate table, so only discrete baud rates possible.
4021 */
4022 baudrate = tiosp->c_cflag & CBAUD;
4023 if (baudrate & CBAUDEX) {
4024 baudrate &= ~CBAUDEX;
4025 if ((baudrate < 1) || (baudrate > 4))
4026 tiosp->c_cflag &= ~CBAUDEX;
4027 else
4028 baudrate += 15;
4029 }
4030 baudrate = stl_baudrates[baudrate];
4031 if ((tiosp->c_cflag & CBAUD) == B38400) {
4032 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
4033 baudrate = 57600;
4034 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
4035 baudrate = 115200;
4036 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
4037 baudrate = 230400;
4038 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
4039 baudrate = 460800;
4040 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
4041 baudrate = (portp->baud_base / portp->custom_divisor);
4042 }
4043 if (baudrate > STL_SC26198MAXBAUD)
4044 baudrate = STL_SC26198MAXBAUD;
4045
4046 if (baudrate > 0) {
4047 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
4048 if (baudrate <= sc26198_baudtable[clk])
4049 break;
4050 }
4051 }
4052
4053/*
4054 * Check what form of modem signaling is required and set it up.
4055 */
4056 if (tiosp->c_cflag & CLOCAL) {
4057 portp->flags &= ~ASYNC_CHECK_CD;
4058 } else {
4059 iopr |= IOPR_DCDCOS;
4060 imron |= IR_IOPORT;
4061 portp->flags |= ASYNC_CHECK_CD;
4062 }
4063
4064/*
4065 * Setup sc26198 enhanced modes if we can. In particular we want to
4066 * handle as much of the flow control as possible automatically. As
4067 * well as saving a few CPU cycles it will also greatly improve flow
4068 * control reliability.
4069 */
4070 if (tiosp->c_iflag & IXON) {
4071 mr0 |= MR0_SWFTX | MR0_SWFT;
4072 imron |= IR_XONXOFF;
4073 } else {
4074 imroff |= IR_XONXOFF;
4075 }
4076 if (tiosp->c_iflag & IXOFF)
4077 mr0 |= MR0_SWFRX;
4078
4079 if (tiosp->c_cflag & CRTSCTS) {
4080 mr2 |= MR2_AUTOCTS;
4081 mr1 |= MR1_AUTORTS;
4082 }
4083
4084/*
4085 * All sc26198 register values calculated so go through and set
4086 * them all up.
4087 */
4088
Jiri Slabya0564e12006-12-08 02:38:37 -08004089 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08004091 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
4092 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
4093 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4095 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
Alan Coxb65b5b52006-06-27 02:54:05 -07004097 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 BRDENABLE(portp->brdnr, portp->pagenr);
4099 stl_sc26198setreg(portp, IMR, 0);
4100 stl_sc26198updatereg(portp, MR0, mr0);
4101 stl_sc26198updatereg(portp, MR1, mr1);
4102 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4103 stl_sc26198updatereg(portp, MR2, mr2);
4104 stl_sc26198updatereg(portp, IOPIOR,
4105 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4106
4107 if (baudrate > 0) {
4108 stl_sc26198setreg(portp, TXCSR, clk);
4109 stl_sc26198setreg(portp, RXCSR, clk);
4110 }
4111
4112 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4113 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4114
4115 ipr = stl_sc26198getreg(portp, IPR);
4116 if (ipr & IPR_DCD)
4117 portp->sigs &= ~TIOCM_CD;
4118 else
4119 portp->sigs |= TIOCM_CD;
4120
4121 portp->imr = (portp->imr & ~imroff) | imron;
4122 stl_sc26198setreg(portp, IMR, portp->imr);
4123 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004124 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125}
4126
4127/*****************************************************************************/
4128
4129/*
4130 * Set the state of the DTR and RTS signals.
4131 */
4132
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004133static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134{
4135 unsigned char iopioron, iopioroff;
4136 unsigned long flags;
4137
Jiri Slabya0564e12006-12-08 02:38:37 -08004138 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4139 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
4141 iopioron = 0;
4142 iopioroff = 0;
4143 if (dtr == 0)
4144 iopioroff |= IPR_DTR;
4145 else if (dtr > 0)
4146 iopioron |= IPR_DTR;
4147 if (rts == 0)
4148 iopioroff |= IPR_RTS;
4149 else if (rts > 0)
4150 iopioron |= IPR_RTS;
4151
Alan Coxb65b5b52006-06-27 02:54:05 -07004152 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 BRDENABLE(portp->brdnr, portp->pagenr);
4154 stl_sc26198setreg(portp, IOPIOR,
4155 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4156 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004157 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158}
4159
4160/*****************************************************************************/
4161
4162/*
4163 * Return the state of the signals.
4164 */
4165
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004166static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167{
4168 unsigned char ipr;
4169 unsigned long flags;
4170 int sigs;
4171
Jiri Slabya0564e12006-12-08 02:38:37 -08004172 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173
Alan Coxb65b5b52006-06-27 02:54:05 -07004174 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 BRDENABLE(portp->brdnr, portp->pagenr);
4176 ipr = stl_sc26198getreg(portp, IPR);
4177 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004178 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
4180 sigs = 0;
4181 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4182 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4183 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4184 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4185 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004186 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187}
4188
4189/*****************************************************************************/
4190
4191/*
4192 * Enable/Disable the Transmitter and/or Receiver.
4193 */
4194
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004195static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196{
4197 unsigned char ccr;
4198 unsigned long flags;
4199
Jiri Slabya0564e12006-12-08 02:38:37 -08004200 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201
4202 ccr = portp->crenable;
4203 if (tx == 0)
4204 ccr &= ~CR_TXENABLE;
4205 else if (tx > 0)
4206 ccr |= CR_TXENABLE;
4207 if (rx == 0)
4208 ccr &= ~CR_RXENABLE;
4209 else if (rx > 0)
4210 ccr |= CR_RXENABLE;
4211
Alan Coxb65b5b52006-06-27 02:54:05 -07004212 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 BRDENABLE(portp->brdnr, portp->pagenr);
4214 stl_sc26198setreg(portp, SCCR, ccr);
4215 BRDDISABLE(portp->brdnr);
4216 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004217 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218}
4219
4220/*****************************************************************************/
4221
4222/*
4223 * Start/stop the Transmitter and/or Receiver.
4224 */
4225
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004226static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227{
4228 unsigned char imr;
4229 unsigned long flags;
4230
Jiri Slabya0564e12006-12-08 02:38:37 -08004231 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232
4233 imr = portp->imr;
4234 if (tx == 0)
4235 imr &= ~IR_TXRDY;
4236 else if (tx == 1)
4237 imr |= IR_TXRDY;
4238 if (rx == 0)
4239 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4240 else if (rx > 0)
4241 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4242
Alan Coxb65b5b52006-06-27 02:54:05 -07004243 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 BRDENABLE(portp->brdnr, portp->pagenr);
4245 stl_sc26198setreg(portp, IMR, imr);
4246 BRDDISABLE(portp->brdnr);
4247 portp->imr = imr;
4248 if (tx > 0)
4249 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004250 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251}
4252
4253/*****************************************************************************/
4254
4255/*
4256 * Disable all interrupts from this port.
4257 */
4258
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004259static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260{
4261 unsigned long flags;
4262
Jiri Slabya0564e12006-12-08 02:38:37 -08004263 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264
Alan Coxb65b5b52006-06-27 02:54:05 -07004265 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 BRDENABLE(portp->brdnr, portp->pagenr);
4267 portp->imr = 0;
4268 stl_sc26198setreg(portp, IMR, 0);
4269 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004270 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271}
4272
4273/*****************************************************************************/
4274
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004275static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276{
4277 unsigned long flags;
4278
Jiri Slabya0564e12006-12-08 02:38:37 -08004279 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280
Alan Coxb65b5b52006-06-27 02:54:05 -07004281 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 BRDENABLE(portp->brdnr, portp->pagenr);
4283 if (len == 1) {
4284 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4285 portp->stats.txbreaks++;
4286 } else {
4287 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4288 }
4289 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004290 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291}
4292
4293/*****************************************************************************/
4294
4295/*
4296 * Take flow control actions...
4297 */
4298
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004299static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300{
4301 struct tty_struct *tty;
4302 unsigned long flags;
4303 unsigned char mr0;
4304
Jiri Slabya0564e12006-12-08 02:38:37 -08004305 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306
Jiri Slaby615e4a72006-12-08 02:38:38 -08004307 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 return;
4309 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004310 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 return;
4312
Alan Coxb65b5b52006-06-27 02:54:05 -07004313 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 BRDENABLE(portp->brdnr, portp->pagenr);
4315
4316 if (state) {
4317 if (tty->termios->c_iflag & IXOFF) {
4318 mr0 = stl_sc26198getreg(portp, MR0);
4319 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4320 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4321 mr0 |= MR0_SWFRX;
4322 portp->stats.rxxon++;
4323 stl_sc26198wait(portp);
4324 stl_sc26198setreg(portp, MR0, mr0);
4325 }
4326/*
4327 * Question: should we return RTS to what it was before? It may
4328 * have been set by an ioctl... Suppose not, since if you have
4329 * hardware flow control set then it is pretty silly to go and
4330 * set the RTS line by hand.
4331 */
4332 if (tty->termios->c_cflag & CRTSCTS) {
4333 stl_sc26198setreg(portp, MR1,
4334 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4335 stl_sc26198setreg(portp, IOPIOR,
4336 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4337 portp->stats.rxrtson++;
4338 }
4339 } else {
4340 if (tty->termios->c_iflag & IXOFF) {
4341 mr0 = stl_sc26198getreg(portp, MR0);
4342 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4343 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4344 mr0 &= ~MR0_SWFRX;
4345 portp->stats.rxxoff++;
4346 stl_sc26198wait(portp);
4347 stl_sc26198setreg(portp, MR0, mr0);
4348 }
4349 if (tty->termios->c_cflag & CRTSCTS) {
4350 stl_sc26198setreg(portp, MR1,
4351 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4352 stl_sc26198setreg(portp, IOPIOR,
4353 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4354 portp->stats.rxrtsoff++;
4355 }
4356 }
4357
4358 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004359 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360}
4361
4362/*****************************************************************************/
4363
4364/*
4365 * Send a flow control character.
4366 */
4367
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004368static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369{
4370 struct tty_struct *tty;
4371 unsigned long flags;
4372 unsigned char mr0;
4373
Jiri Slabya0564e12006-12-08 02:38:37 -08004374 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
Jiri Slaby615e4a72006-12-08 02:38:38 -08004376 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 return;
4378 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004379 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380 return;
4381
Alan Coxb65b5b52006-06-27 02:54:05 -07004382 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383 BRDENABLE(portp->brdnr, portp->pagenr);
4384 if (state) {
4385 mr0 = stl_sc26198getreg(portp, MR0);
4386 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4387 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4388 mr0 |= MR0_SWFRX;
4389 portp->stats.rxxon++;
4390 stl_sc26198wait(portp);
4391 stl_sc26198setreg(portp, MR0, mr0);
4392 } else {
4393 mr0 = stl_sc26198getreg(portp, MR0);
4394 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4395 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4396 mr0 &= ~MR0_SWFRX;
4397 portp->stats.rxxoff++;
4398 stl_sc26198wait(portp);
4399 stl_sc26198setreg(portp, MR0, mr0);
4400 }
4401 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004402 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403}
4404
4405/*****************************************************************************/
4406
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004407static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408{
4409 unsigned long flags;
4410
Jiri Slabya0564e12006-12-08 02:38:37 -08004411 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
Jiri Slaby615e4a72006-12-08 02:38:38 -08004413 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 return;
4415
Alan Coxb65b5b52006-06-27 02:54:05 -07004416 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417 BRDENABLE(portp->brdnr, portp->pagenr);
4418 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4419 stl_sc26198setreg(portp, SCCR, portp->crenable);
4420 BRDDISABLE(portp->brdnr);
4421 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004422 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423}
4424
4425/*****************************************************************************/
4426
4427/*
4428 * Return the current state of data flow on this port. This is only
4429 * really interresting when determining if data has fully completed
4430 * transmission or not... The sc26198 interrupt scheme cannot
4431 * determine when all data has actually drained, so we need to
4432 * check the port statusy register to be sure.
4433 */
4434
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004435static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436{
4437 unsigned long flags;
4438 unsigned char sr;
4439
Jiri Slabya0564e12006-12-08 02:38:37 -08004440 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
Jiri Slaby615e4a72006-12-08 02:38:38 -08004442 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004443 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004445 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446
Alan Coxb65b5b52006-06-27 02:54:05 -07004447 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 BRDENABLE(portp->brdnr, portp->pagenr);
4449 sr = stl_sc26198getreg(portp, SR);
4450 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004451 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Jesper Juhl014c2542006-01-15 02:37:08 +01004453 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454}
4455
4456/*****************************************************************************/
4457
4458/*
4459 * Delay for a small amount of time, to give the sc26198 a chance
4460 * to process a command...
4461 */
4462
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004463static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464{
4465 int i;
4466
Jiri Slabya0564e12006-12-08 02:38:37 -08004467 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468
Jiri Slaby615e4a72006-12-08 02:38:38 -08004469 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 return;
4471
4472 for (i = 0; (i < 20); i++)
4473 stl_sc26198getglobreg(portp, TSTR);
4474}
4475
4476/*****************************************************************************/
4477
4478/*
4479 * If we are TX flow controlled and in IXANY mode then we may
4480 * need to unflow control here. We gotta do this because of the
4481 * automatic flow control modes of the sc26198.
4482 */
4483
Jiri Slaby60be4812006-12-08 02:38:40 -08004484static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485{
4486 unsigned char mr0;
4487
4488 mr0 = stl_sc26198getreg(portp, MR0);
4489 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4490 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4491 stl_sc26198wait(portp);
4492 stl_sc26198setreg(portp, MR0, mr0);
4493 clear_bit(ASYI_TXFLOWED, &portp->istate);
4494}
4495
4496/*****************************************************************************/
4497
4498/*
4499 * Interrupt service routine for sc26198 panels.
4500 */
4501
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004502static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004504 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505 unsigned int iack;
4506
Alan Coxb65b5b52006-06-27 02:54:05 -07004507 spin_lock(&brd_lock);
4508
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509/*
4510 * Work around bug in sc26198 chip... Cannot have A6 address
4511 * line of UART high, else iack will be returned as 0.
4512 */
4513 outb(0, (iobase + 1));
4514
4515 iack = inb(iobase + XP_IACK);
4516 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4517
4518 if (iack & IVR_RXDATA)
4519 stl_sc26198rxisr(portp, iack);
4520 else if (iack & IVR_TXDATA)
4521 stl_sc26198txisr(portp);
4522 else
4523 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004524
4525 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526}
4527
4528/*****************************************************************************/
4529
4530/*
4531 * Transmit interrupt handler. This has gotta be fast! Handling TX
4532 * chars is pretty simple, stuff as many as possible from the TX buffer
4533 * into the sc26198 FIFO.
4534 * In practice it is possible that interrupts are enabled but that the
4535 * port has been hung up. Need to handle not having any TX buffer here,
4536 * this is done by using the side effect that head and tail will also
4537 * be NULL if the buffer has been freed.
4538 */
4539
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004540static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541{
4542 unsigned int ioaddr;
4543 unsigned char mr0;
4544 int len, stlen;
4545 char *head, *tail;
4546
Jiri Slabya0564e12006-12-08 02:38:37 -08004547 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548
4549 ioaddr = portp->ioaddr;
4550 head = portp->tx.head;
4551 tail = portp->tx.tail;
4552 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4553 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4554 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4555 set_bit(ASYI_TXLOW, &portp->istate);
4556 schedule_work(&portp->tqueue);
4557 }
4558
4559 if (len == 0) {
4560 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4561 mr0 = inb(ioaddr + XP_DATA);
4562 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4563 portp->imr &= ~IR_TXRDY;
4564 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4565 outb(portp->imr, (ioaddr + XP_DATA));
4566 clear_bit(ASYI_TXBUSY, &portp->istate);
4567 } else {
4568 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4569 outb(mr0, (ioaddr + XP_DATA));
4570 }
4571 } else {
4572 len = MIN(len, SC26198_TXFIFOSIZE);
4573 portp->stats.txtotal += len;
4574 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
4575 outb(GTXFIFO, (ioaddr + XP_ADDR));
4576 outsb((ioaddr + XP_DATA), tail, stlen);
4577 len -= stlen;
4578 tail += stlen;
4579 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4580 tail = portp->tx.buf;
4581 if (len > 0) {
4582 outsb((ioaddr + XP_DATA), tail, len);
4583 tail += len;
4584 }
4585 portp->tx.tail = tail;
4586 }
4587}
4588
4589/*****************************************************************************/
4590
4591/*
4592 * Receive character interrupt handler. Determine if we have good chars
4593 * or bad chars and then process appropriately. Good chars are easy
4594 * just shove the lot into the RX buffer and set all status byte to 0.
4595 * If a bad RX char then process as required. This routine needs to be
4596 * fast! In practice it is possible that we get an interrupt on a port
4597 * that is closed. This can happen on hangups - since they completely
4598 * shutdown a port not in user context. Need to handle this case.
4599 */
4600
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004601static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602{
4603 struct tty_struct *tty;
4604 unsigned int len, buflen, ioaddr;
4605
Jiri Slabya0564e12006-12-08 02:38:37 -08004606 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607
4608 tty = portp->tty;
4609 ioaddr = portp->ioaddr;
4610 outb(GIBCR, (ioaddr + XP_ADDR));
4611 len = inb(ioaddr + XP_DATA) + 1;
4612
4613 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004614 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 len = MIN(len, sizeof(stl_unwanted));
4616 outb(GRXFIFO, (ioaddr + XP_ADDR));
4617 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4618 portp->stats.rxlost += len;
4619 portp->stats.rxtotal += len;
4620 } else {
4621 len = MIN(len, buflen);
4622 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004623 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004625 tty_prepare_flip_string(tty, &ptr, len);
4626 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627 tty_schedule_flip(tty);
4628 portp->stats.rxtotal += len;
4629 }
4630 }
4631 } else {
4632 stl_sc26198rxbadchars(portp);
4633 }
4634
4635/*
4636 * If we are TX flow controlled and in IXANY mode then we may need
4637 * to unflow control here. We gotta do this because of the automatic
4638 * flow control modes of the sc26198.
4639 */
4640 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004641 if ((tty != NULL) &&
4642 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643 (tty->termios->c_iflag & IXANY)) {
4644 stl_sc26198txunflow(portp, tty);
4645 }
4646 }
4647}
4648
4649/*****************************************************************************/
4650
4651/*
4652 * Process an RX bad character.
4653 */
4654
Jiri Slaby60be4812006-12-08 02:38:40 -08004655static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656{
4657 struct tty_struct *tty;
4658 unsigned int ioaddr;
4659
4660 tty = portp->tty;
4661 ioaddr = portp->ioaddr;
4662
4663 if (status & SR_RXPARITY)
4664 portp->stats.rxparity++;
4665 if (status & SR_RXFRAMING)
4666 portp->stats.rxframing++;
4667 if (status & SR_RXOVERRUN)
4668 portp->stats.rxoverrun++;
4669 if (status & SR_RXBREAK)
4670 portp->stats.rxbreaks++;
4671
Jiri Slaby615e4a72006-12-08 02:38:38 -08004672 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673 ((portp->rxignoremsk & status) == 0)) {
4674 if (portp->rxmarkmsk & status) {
4675 if (status & SR_RXBREAK) {
4676 status = TTY_BREAK;
4677 if (portp->flags & ASYNC_SAK) {
4678 do_SAK(tty);
4679 BRDENABLE(portp->brdnr, portp->pagenr);
4680 }
4681 } else if (status & SR_RXPARITY) {
4682 status = TTY_PARITY;
4683 } else if (status & SR_RXFRAMING) {
4684 status = TTY_FRAME;
4685 } else if(status & SR_RXOVERRUN) {
4686 status = TTY_OVERRUN;
4687 } else {
4688 status = 0;
4689 }
4690 } else {
4691 status = 0;
4692 }
4693
Alan Cox33f0f882006-01-09 20:54:13 -08004694 tty_insert_flip_char(tty, ch, status);
4695 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696
4697 if (status == 0)
4698 portp->stats.rxtotal++;
4699 }
4700}
4701
4702/*****************************************************************************/
4703
4704/*
4705 * Process all characters in the RX FIFO of the UART. Check all char
4706 * status bytes as well, and process as required. We need to check
4707 * all bytes in the FIFO, in case some more enter the FIFO while we
4708 * are here. To get the exact character error type we need to switch
4709 * into CHAR error mode (that is why we need to make sure we empty
4710 * the FIFO).
4711 */
4712
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004713static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714{
4715 unsigned char status, mr1;
4716 char ch;
4717
4718/*
4719 * To get the precise error type for each character we must switch
4720 * back into CHAR error mode.
4721 */
4722 mr1 = stl_sc26198getreg(portp, MR1);
4723 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4724
4725 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4726 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4727 ch = stl_sc26198getreg(portp, RXFIFO);
4728 stl_sc26198rxbadch(portp, status, ch);
4729 }
4730
4731/*
4732 * To get correct interrupt class we must switch back into BLOCK
4733 * error mode.
4734 */
4735 stl_sc26198setreg(portp, MR1, mr1);
4736}
4737
4738/*****************************************************************************/
4739
4740/*
4741 * Other interrupt handler. This includes modem signals, flow
4742 * control actions, etc. Most stuff is left to off-level interrupt
4743 * processing time.
4744 */
4745
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004746static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747{
4748 unsigned char cir, ipr, xisr;
4749
Jiri Slabya0564e12006-12-08 02:38:37 -08004750 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004751
4752 cir = stl_sc26198getglobreg(portp, CIR);
4753
4754 switch (cir & CIR_SUBTYPEMASK) {
4755 case CIR_SUBCOS:
4756 ipr = stl_sc26198getreg(portp, IPR);
4757 if (ipr & IPR_DCDCHANGE) {
4758 set_bit(ASYI_DCDCHANGE, &portp->istate);
4759 schedule_work(&portp->tqueue);
4760 portp->stats.modem++;
4761 }
4762 break;
4763 case CIR_SUBXONXOFF:
4764 xisr = stl_sc26198getreg(portp, XISR);
4765 if (xisr & XISR_RXXONGOT) {
4766 set_bit(ASYI_TXFLOWED, &portp->istate);
4767 portp->stats.txxoff++;
4768 }
4769 if (xisr & XISR_RXXOFFGOT) {
4770 clear_bit(ASYI_TXFLOWED, &portp->istate);
4771 portp->stats.txxon++;
4772 }
4773 break;
4774 case CIR_SUBBREAK:
4775 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4776 stl_sc26198rxbadchars(portp);
4777 break;
4778 default:
4779 break;
4780 }
4781}
4782
Jiri Slaby23b85a12006-12-08 02:38:40 -08004783/*
4784 * Loadable module initialization stuff.
4785 */
4786static int __init stallion_module_init(void)
4787{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004788 unsigned int i, retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004789
4790 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4791
4792 spin_lock_init(&stallion_lock);
4793 spin_lock_init(&brd_lock);
4794
4795 stl_initbrds();
4796
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004797 retval = pci_register_driver(&stl_pcidriver);
4798 if (retval)
4799 goto err;
4800
Jiri Slaby23b85a12006-12-08 02:38:40 -08004801 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4802 if (!stl_serial)
4803 return -1;
4804
4805/*
4806 * Set up a character driver for per board stuff. This is mainly used
4807 * to do stats ioctls on the ports.
4808 */
4809 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4810 printk("STALLION: failed to register serial board device\n");
4811
4812 stallion_class = class_create(THIS_MODULE, "staliomem");
4813 for (i = 0; i < 4; i++)
4814 class_device_create(stallion_class, NULL,
4815 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4816 "staliomem%d", i);
4817
4818 stl_serial->owner = THIS_MODULE;
4819 stl_serial->driver_name = stl_drvname;
4820 stl_serial->name = "ttyE";
4821 stl_serial->major = STL_SERIALMAJOR;
4822 stl_serial->minor_start = 0;
4823 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4824 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4825 stl_serial->init_termios = stl_deftermios;
4826 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4827 tty_set_operations(stl_serial, &stl_ops);
4828
4829 if (tty_register_driver(stl_serial)) {
4830 put_tty_driver(stl_serial);
4831 printk("STALLION: failed to register serial driver\n");
4832 return -1;
4833 }
4834
4835 return 0;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004836err:
4837 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004838}
4839
4840static void __exit stallion_module_exit(void)
4841{
4842 struct stlbrd *brdp;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004843 int i;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004844
4845 pr_debug("cleanup_module()\n");
4846
4847 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4848 stl_drvversion);
4849
4850/*
4851 * Free up all allocated resources used by the ports. This includes
4852 * memory and interrupts. As part of this process we will also do
4853 * a hangup on every open port - to try to flush out any processes
4854 * hanging onto ports.
4855 */
4856 i = tty_unregister_driver(stl_serial);
4857 put_tty_driver(stl_serial);
4858 if (i) {
4859 printk("STALLION: failed to un-register tty driver, "
4860 "errno=%d\n", -i);
4861 return;
4862 }
4863 for (i = 0; i < 4; i++)
4864 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4865 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4866 printk("STALLION: failed to un-register serial memory device, "
4867 "errno=%d\n", -i);
4868 class_destroy(stallion_class);
4869
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004870 pci_unregister_driver(&stl_pcidriver);
4871
Jiri Slaby23b85a12006-12-08 02:38:40 -08004872 for (i = 0; (i < stl_nrbrds); i++) {
4873 if ((brdp = stl_brds[i]) == NULL)
4874 continue;
4875
4876 free_irq(brdp->irq, brdp);
4877
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004878 stl_cleanup_panels(brdp);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004879
4880 release_region(brdp->ioaddr1, brdp->iosize1);
4881 if (brdp->iosize2 > 0)
4882 release_region(brdp->ioaddr2, brdp->iosize2);
4883
4884 kfree(brdp);
4885 stl_brds[i] = NULL;
4886 }
4887}
4888
4889module_init(stallion_module_init);
4890module_exit(stallion_module_exit);
4891
4892MODULE_AUTHOR("Greg Ungerer");
4893MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4894MODULE_LICENSE("GPL");