blob: 596e69c2fd0c8ea34a30f3e2b1548267878301dc [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;
Jiri Slaby3b85b342006-12-08 02:39:10 -0800782 if (stl_brdinit(brdp))
783 kfree(brdp);
Jiri Slaby96b066b2006-12-08 02:38:42 -0800784 }
785}
786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787/*****************************************************************************/
788
789static int stl_open(struct tty_struct *tty, struct file *filp)
790{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800791 struct stlport *portp;
792 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 unsigned int minordev;
794 int brdnr, panelnr, portnr, rc;
795
Jiri Slabya0564e12006-12-08 02:38:37 -0800796 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
798 minordev = tty->index;
799 brdnr = MINOR2BRD(minordev);
800 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100801 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800803 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100804 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 minordev = MINOR2PORT(minordev);
806 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800807 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 break;
809 if (minordev < brdp->panels[panelnr]->nrports) {
810 portnr = minordev;
811 break;
812 }
813 minordev -= brdp->panels[panelnr]->nrports;
814 }
815 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100816 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
818 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800819 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100820 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822/*
823 * On the first open of the device setup the port hardware, and
824 * initialize the per port data structure.
825 */
826 portp->tty = tty;
827 tty->driver_data = portp;
828 portp->refcount++;
829
830 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800831 if (!portp->tx.buf) {
832 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
833 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100834 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 portp->tx.head = portp->tx.buf;
836 portp->tx.tail = portp->tx.buf;
837 }
838 stl_setport(portp, tty->termios);
839 portp->sigs = stl_getsignals(portp);
840 stl_setsignals(portp, 1, 1);
841 stl_enablerxtx(portp, 1, 1);
842 stl_startrxtx(portp, 1, 0);
843 clear_bit(TTY_IO_ERROR, &tty->flags);
844 portp->flags |= ASYNC_INITIALIZED;
845 }
846
847/*
848 * Check if this port is in the middle of closing. If so then wait
849 * until it is closed then return error status, based on flag settings.
850 * The sleep here does not need interrupt protection since the wakeup
851 * for it is done with the same context.
852 */
853 if (portp->flags & ASYNC_CLOSING) {
854 interruptible_sleep_on(&portp->close_wait);
855 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100856 return -EAGAIN;
857 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 }
859
860/*
861 * Based on type of open being done check if it can overlap with any
862 * previous opens still in effect. If we are a normal serial device
863 * then also we might have to wait for carrier.
864 */
865 if (!(filp->f_flags & O_NONBLOCK)) {
866 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100867 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 }
869 portp->flags |= ASYNC_NORMAL_ACTIVE;
870
Jesper Juhl014c2542006-01-15 02:37:08 +0100871 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872}
873
874/*****************************************************************************/
875
876/*
877 * Possibly need to wait for carrier (DCD signal) to come high. Say
878 * maybe because if we are clocal then we don't need to wait...
879 */
880
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800881static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882{
883 unsigned long flags;
884 int rc, doclocal;
885
Jiri Slabya0564e12006-12-08 02:38:37 -0800886 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
888 rc = 0;
889 doclocal = 0;
890
Alan Coxb65b5b52006-06-27 02:54:05 -0700891 spin_lock_irqsave(&stallion_lock, flags);
892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 if (portp->tty->termios->c_cflag & CLOCAL)
894 doclocal++;
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 portp->openwaitcnt++;
897 if (! tty_hung_up_p(filp))
898 portp->refcount--;
899
900 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700901 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 stl_setsignals(portp, 1, 1);
903 if (tty_hung_up_p(filp) ||
904 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
905 if (portp->flags & ASYNC_HUP_NOTIFY)
906 rc = -EBUSY;
907 else
908 rc = -ERESTARTSYS;
909 break;
910 }
911 if (((portp->flags & ASYNC_CLOSING) == 0) &&
912 (doclocal || (portp->sigs & TIOCM_CD))) {
913 break;
914 }
915 if (signal_pending(current)) {
916 rc = -ERESTARTSYS;
917 break;
918 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700919 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 interruptible_sleep_on(&portp->open_wait);
921 }
922
923 if (! tty_hung_up_p(filp))
924 portp->refcount++;
925 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700926 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
Jesper Juhl014c2542006-01-15 02:37:08 +0100928 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929}
930
931/*****************************************************************************/
932
Jiri Slaby96b066b2006-12-08 02:38:42 -0800933static void stl_flushbuffer(struct tty_struct *tty)
934{
935 struct stlport *portp;
936
937 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
938
939 if (tty == NULL)
940 return;
941 portp = tty->driver_data;
942 if (portp == NULL)
943 return;
944
945 stl_flush(portp);
946 tty_wakeup(tty);
947}
948
949/*****************************************************************************/
950
951static void stl_waituntilsent(struct tty_struct *tty, int timeout)
952{
953 struct stlport *portp;
954 unsigned long tend;
955
956 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
957
958 if (tty == NULL)
959 return;
960 portp = tty->driver_data;
961 if (portp == NULL)
962 return;
963
964 if (timeout == 0)
965 timeout = HZ;
966 tend = jiffies + timeout;
967
968 while (stl_datastate(portp)) {
969 if (signal_pending(current))
970 break;
971 msleep_interruptible(20);
972 if (time_after_eq(jiffies, tend))
973 break;
974 }
975}
976
977/*****************************************************************************/
978
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979static void stl_close(struct tty_struct *tty, struct file *filp)
980{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800981 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 unsigned long flags;
983
Jiri Slabya0564e12006-12-08 02:38:37 -0800984 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
986 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800987 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 return;
989
Alan Coxb65b5b52006-06-27 02:54:05 -0700990 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700992 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 return;
994 }
995 if ((tty->count == 1) && (portp->refcount != 1))
996 portp->refcount = 1;
997 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700998 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 return;
1000 }
1001
1002 portp->refcount = 0;
1003 portp->flags |= ASYNC_CLOSING;
1004
1005/*
1006 * May want to wait for any data to drain before closing. The BUSY
1007 * flag keeps track of whether we are still sending or not - it is
1008 * very accurate for the cd1400, not quite so for the sc26198.
1009 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
1010 */
1011 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -07001012
1013 spin_unlock_irqrestore(&stallion_lock, flags);
1014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1016 tty_wait_until_sent(tty, portp->closing_wait);
1017 stl_waituntilsent(tty, (HZ / 2));
1018
Alan Coxb65b5b52006-06-27 02:54:05 -07001019
1020 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -07001022 spin_unlock_irqrestore(&stallion_lock, flags);
1023
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 stl_disableintrs(portp);
1025 if (tty->termios->c_cflag & HUPCL)
1026 stl_setsignals(portp, 0, 0);
1027 stl_enablerxtx(portp, 0, 0);
1028 stl_flushbuffer(tty);
1029 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001030 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001032 portp->tx.buf = NULL;
1033 portp->tx.head = NULL;
1034 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 }
1036 set_bit(TTY_IO_ERROR, &tty->flags);
1037 tty_ldisc_flush(tty);
1038
1039 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001040 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
1042 if (portp->openwaitcnt) {
1043 if (portp->close_delay)
1044 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
1045 wake_up_interruptible(&portp->open_wait);
1046 }
1047
1048 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1049 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050}
1051
1052/*****************************************************************************/
1053
1054/*
1055 * Write routine. Take data and stuff it in to the TX ring queue.
1056 * If transmit interrupts are not running then start them.
1057 */
1058
1059static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
1060{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001061 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 unsigned int len, stlen;
1063 unsigned char *chbuf;
1064 char *head, *tail;
1065
Jiri Slabya0564e12006-12-08 02:38:37 -08001066 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001069 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001070 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001071 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001072 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
1074/*
1075 * If copying direct from user space we must cater for page faults,
1076 * causing us to "sleep" here for a while. To handle this copy in all
1077 * the data we need now, into a local buffer. Then when we got it all
1078 * copy it into the TX buffer.
1079 */
1080 chbuf = (unsigned char *) buf;
1081
1082 head = portp->tx.head;
1083 tail = portp->tx.tail;
1084 if (head >= tail) {
1085 len = STL_TXBUFSIZE - (head - tail) - 1;
1086 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1087 } else {
1088 len = tail - head - 1;
1089 stlen = len;
1090 }
1091
1092 len = MIN(len, count);
1093 count = 0;
1094 while (len > 0) {
1095 stlen = MIN(len, stlen);
1096 memcpy(head, chbuf, stlen);
1097 len -= stlen;
1098 chbuf += stlen;
1099 count += stlen;
1100 head += stlen;
1101 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1102 head = portp->tx.buf;
1103 stlen = tail - head;
1104 }
1105 }
1106 portp->tx.head = head;
1107
1108 clear_bit(ASYI_TXLOW, &portp->istate);
1109 stl_startrxtx(portp, -1, 1);
1110
Jesper Juhl014c2542006-01-15 02:37:08 +01001111 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112}
1113
1114/*****************************************************************************/
1115
1116static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1117{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001118 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 unsigned int len;
1120 char *head, *tail;
1121
Jiri Slabya0564e12006-12-08 02:38:37 -08001122 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Jiri Slaby615e4a72006-12-08 02:38:38 -08001124 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 return;
1126 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001127 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001129 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 return;
1131
1132 head = portp->tx.head;
1133 tail = portp->tx.tail;
1134
1135 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1136 len--;
1137
1138 if (len > 0) {
1139 *head++ = ch;
1140 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1141 head = portp->tx.buf;
1142 }
1143 portp->tx.head = head;
1144}
1145
1146/*****************************************************************************/
1147
1148/*
1149 * If there are any characters in the buffer then make sure that TX
1150 * interrupts are on and get'em out. Normally used after the putchar
1151 * routine has been called.
1152 */
1153
1154static void stl_flushchars(struct tty_struct *tty)
1155{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001156 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
Jiri Slabya0564e12006-12-08 02:38:37 -08001158 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
Jiri Slaby615e4a72006-12-08 02:38:38 -08001160 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 return;
1162 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001163 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001165 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 return;
1167
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 stl_startrxtx(portp, -1, 1);
1169}
1170
1171/*****************************************************************************/
1172
1173static int stl_writeroom(struct tty_struct *tty)
1174{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001175 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 char *head, *tail;
1177
Jiri Slabya0564e12006-12-08 02:38:37 -08001178 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
Jiri Slaby615e4a72006-12-08 02:38:38 -08001180 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001181 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001183 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001184 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001185 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001186 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
1188 head = portp->tx.head;
1189 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001190 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191}
1192
1193/*****************************************************************************/
1194
1195/*
1196 * Return number of chars in the TX buffer. Normally we would just
1197 * calculate the number of chars in the buffer and return that, but if
1198 * the buffer is empty and TX interrupts are still on then we return
1199 * that the buffer still has 1 char in it. This way whoever called us
1200 * will not think that ALL chars have drained - since the UART still
1201 * must have some chars in it (we are busy after all).
1202 */
1203
1204static int stl_charsinbuffer(struct tty_struct *tty)
1205{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001206 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 unsigned int size;
1208 char *head, *tail;
1209
Jiri Slabya0564e12006-12-08 02:38:37 -08001210 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
Jiri Slaby615e4a72006-12-08 02:38:38 -08001212 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001213 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001215 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001216 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001217 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001218 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220 head = portp->tx.head;
1221 tail = portp->tx.tail;
1222 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1223 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1224 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001225 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226}
1227
1228/*****************************************************************************/
1229
1230/*
1231 * Generate the serial struct info.
1232 */
1233
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001234static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235{
1236 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001237 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Jiri Slabya0564e12006-12-08 02:38:37 -08001239 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
1241 memset(&sio, 0, sizeof(struct serial_struct));
1242 sio.line = portp->portnr;
1243 sio.port = portp->ioaddr;
1244 sio.flags = portp->flags;
1245 sio.baud_base = portp->baud_base;
1246 sio.close_delay = portp->close_delay;
1247 sio.closing_wait = portp->closing_wait;
1248 sio.custom_divisor = portp->custom_divisor;
1249 sio.hub6 = 0;
1250 if (portp->uartp == &stl_cd1400uart) {
1251 sio.type = PORT_CIRRUS;
1252 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1253 } else {
1254 sio.type = PORT_UNKNOWN;
1255 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1256 }
1257
1258 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001259 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 sio.irq = brdp->irq;
1261
1262 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1263}
1264
1265/*****************************************************************************/
1266
1267/*
1268 * Set port according to the serial struct info.
1269 * At this point we do not do any auto-configure stuff, so we will
1270 * just quietly ignore any requests to change irq, etc.
1271 */
1272
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001273static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274{
1275 struct serial_struct sio;
1276
Jiri Slabya0564e12006-12-08 02:38:37 -08001277 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
1279 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1280 return -EFAULT;
1281 if (!capable(CAP_SYS_ADMIN)) {
1282 if ((sio.baud_base != portp->baud_base) ||
1283 (sio.close_delay != portp->close_delay) ||
1284 ((sio.flags & ~ASYNC_USR_MASK) !=
1285 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001286 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 }
1288
1289 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1290 (sio.flags & ASYNC_USR_MASK);
1291 portp->baud_base = sio.baud_base;
1292 portp->close_delay = sio.close_delay;
1293 portp->closing_wait = sio.closing_wait;
1294 portp->custom_divisor = sio.custom_divisor;
1295 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001296 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297}
1298
1299/*****************************************************************************/
1300
1301static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1302{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001303 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
Jiri Slaby615e4a72006-12-08 02:38:38 -08001305 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001306 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001308 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001309 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001311 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
1313 return stl_getsignals(portp);
1314}
1315
1316static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1317 unsigned int set, unsigned int clear)
1318{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001319 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 int rts = -1, dtr = -1;
1321
Jiri Slaby615e4a72006-12-08 02:38:38 -08001322 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001323 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001325 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001326 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001328 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
1330 if (set & TIOCM_RTS)
1331 rts = 1;
1332 if (set & TIOCM_DTR)
1333 dtr = 1;
1334 if (clear & TIOCM_RTS)
1335 rts = 0;
1336 if (clear & TIOCM_DTR)
1337 dtr = 0;
1338
1339 stl_setsignals(portp, dtr, rts);
1340 return 0;
1341}
1342
1343static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1344{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001345 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 unsigned int ival;
1347 int rc;
1348 void __user *argp = (void __user *)arg;
1349
Jiri Slabya0564e12006-12-08 02:38:37 -08001350 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1351 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Jiri Slaby615e4a72006-12-08 02:38:38 -08001353 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001354 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001356 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001357 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
1359 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1360 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1361 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001362 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 }
1364
1365 rc = 0;
1366
1367 switch (cmd) {
1368 case TIOCGSOFTCAR:
1369 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1370 (unsigned __user *) argp);
1371 break;
1372 case TIOCSSOFTCAR:
1373 if (get_user(ival, (unsigned int __user *) arg))
1374 return -EFAULT;
1375 tty->termios->c_cflag =
1376 (tty->termios->c_cflag & ~CLOCAL) |
1377 (ival ? CLOCAL : 0);
1378 break;
1379 case TIOCGSERIAL:
1380 rc = stl_getserial(portp, argp);
1381 break;
1382 case TIOCSSERIAL:
1383 rc = stl_setserial(portp, argp);
1384 break;
1385 case COM_GETPORTSTATS:
1386 rc = stl_getportstats(portp, argp);
1387 break;
1388 case COM_CLRPORTSTATS:
1389 rc = stl_clrportstats(portp, argp);
1390 break;
1391 case TIOCSERCONFIG:
1392 case TIOCSERGWILD:
1393 case TIOCSERSWILD:
1394 case TIOCSERGETLSR:
1395 case TIOCSERGSTRUCT:
1396 case TIOCSERGETMULTI:
1397 case TIOCSERSETMULTI:
1398 default:
1399 rc = -ENOIOCTLCMD;
1400 break;
1401 }
1402
Jesper Juhl014c2542006-01-15 02:37:08 +01001403 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404}
1405
1406/*****************************************************************************/
1407
Jiri Slaby96b066b2006-12-08 02:38:42 -08001408/*
1409 * Start the transmitter again. Just turn TX interrupts back on.
1410 */
1411
1412static void stl_start(struct tty_struct *tty)
1413{
1414 struct stlport *portp;
1415
1416 pr_debug("stl_start(tty=%p)\n", tty);
1417
1418 if (tty == NULL)
1419 return;
1420 portp = tty->driver_data;
1421 if (portp == NULL)
1422 return;
1423 stl_startrxtx(portp, -1, 1);
1424}
1425
1426/*****************************************************************************/
1427
Alan Cox606d0992006-12-08 02:38:45 -08001428static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001430 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001431 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
Jiri Slabya0564e12006-12-08 02:38:37 -08001433 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Jiri Slaby615e4a72006-12-08 02:38:38 -08001435 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 return;
1437 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001438 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 return;
1440
1441 tiosp = tty->termios;
1442 if ((tiosp->c_cflag == old->c_cflag) &&
1443 (tiosp->c_iflag == old->c_iflag))
1444 return;
1445
1446 stl_setport(portp, tiosp);
1447 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1448 -1);
1449 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1450 tty->hw_stopped = 0;
1451 stl_start(tty);
1452 }
1453 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1454 wake_up_interruptible(&portp->open_wait);
1455}
1456
1457/*****************************************************************************/
1458
1459/*
1460 * Attempt to flow control who ever is sending us data. Based on termios
1461 * settings use software or/and hardware flow control.
1462 */
1463
1464static void stl_throttle(struct tty_struct *tty)
1465{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001466 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Jiri Slabya0564e12006-12-08 02:38:37 -08001468 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Jiri Slaby615e4a72006-12-08 02:38:38 -08001470 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 return;
1472 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001473 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 return;
1475 stl_flowctrl(portp, 0);
1476}
1477
1478/*****************************************************************************/
1479
1480/*
1481 * Unflow control the device sending us data...
1482 */
1483
1484static void stl_unthrottle(struct tty_struct *tty)
1485{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001486 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Jiri Slabya0564e12006-12-08 02:38:37 -08001488 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489
Jiri Slaby615e4a72006-12-08 02:38:38 -08001490 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 return;
1492 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001493 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 return;
1495 stl_flowctrl(portp, 1);
1496}
1497
1498/*****************************************************************************/
1499
1500/*
1501 * Stop the transmitter. Basically to do this we will just turn TX
1502 * interrupts off.
1503 */
1504
1505static void stl_stop(struct tty_struct *tty)
1506{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001507 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
Jiri Slabya0564e12006-12-08 02:38:37 -08001509 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
Jiri Slaby615e4a72006-12-08 02:38:38 -08001511 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 return;
1513 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001514 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 return;
1516 stl_startrxtx(portp, -1, 0);
1517}
1518
1519/*****************************************************************************/
1520
1521/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 * Hangup this port. This is pretty much like closing the port, only
1523 * a little more brutal. No waiting for data to drain. Shutdown the
1524 * port and maybe drop signals.
1525 */
1526
1527static void stl_hangup(struct tty_struct *tty)
1528{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001529 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
Jiri Slabya0564e12006-12-08 02:38:37 -08001531 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
Jiri Slaby615e4a72006-12-08 02:38:38 -08001533 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 return;
1535 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001536 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 return;
1538
1539 portp->flags &= ~ASYNC_INITIALIZED;
1540 stl_disableintrs(portp);
1541 if (tty->termios->c_cflag & HUPCL)
1542 stl_setsignals(portp, 0, 0);
1543 stl_enablerxtx(portp, 0, 0);
1544 stl_flushbuffer(tty);
1545 portp->istate = 0;
1546 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001547 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001549 portp->tx.buf = NULL;
1550 portp->tx.head = NULL;
1551 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001553 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1555 portp->refcount = 0;
1556 wake_up_interruptible(&portp->open_wait);
1557}
1558
1559/*****************************************************************************/
1560
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561static void stl_breakctl(struct tty_struct *tty, int state)
1562{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001563 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
Jiri Slabya0564e12006-12-08 02:38:37 -08001565 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
Jiri Slaby615e4a72006-12-08 02:38:38 -08001567 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 return;
1569 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001570 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 return;
1572
1573 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1574}
1575
1576/*****************************************************************************/
1577
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578static void stl_sendxchar(struct tty_struct *tty, char ch)
1579{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001580 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
Jiri Slabya0564e12006-12-08 02:38:37 -08001582 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Jiri Slaby615e4a72006-12-08 02:38:38 -08001584 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 return;
1586 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001587 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 return;
1589
1590 if (ch == STOP_CHAR(tty))
1591 stl_sendflow(portp, 0);
1592 else if (ch == START_CHAR(tty))
1593 stl_sendflow(portp, 1);
1594 else
1595 stl_putchar(tty, ch);
1596}
1597
1598/*****************************************************************************/
1599
1600#define MAXLINE 80
1601
1602/*
1603 * Format info for a specified port. The line is deliberately limited
1604 * to 80 characters. (If it is too long it will be truncated, if too
1605 * short then padded with spaces).
1606 */
1607
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001608static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609{
1610 char *sp;
1611 int sigs, cnt;
1612
1613 sp = pos;
1614 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1615 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1616 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1617
1618 if (portp->stats.rxframing)
1619 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1620 if (portp->stats.rxparity)
1621 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1622 if (portp->stats.rxbreaks)
1623 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1624 if (portp->stats.rxoverrun)
1625 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1626
1627 sigs = stl_getsignals(portp);
1628 cnt = sprintf(sp, "%s%s%s%s%s ",
1629 (sigs & TIOCM_RTS) ? "|RTS" : "",
1630 (sigs & TIOCM_CTS) ? "|CTS" : "",
1631 (sigs & TIOCM_DTR) ? "|DTR" : "",
1632 (sigs & TIOCM_CD) ? "|DCD" : "",
1633 (sigs & TIOCM_DSR) ? "|DSR" : "");
1634 *sp = ' ';
1635 sp += cnt;
1636
1637 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1638 *sp++ = ' ';
1639 if (cnt >= MAXLINE)
1640 pos[(MAXLINE - 2)] = '+';
1641 pos[(MAXLINE - 1)] = '\n';
1642
Jesper Juhl014c2542006-01-15 02:37:08 +01001643 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644}
1645
1646/*****************************************************************************/
1647
1648/*
1649 * Port info, read from the /proc file system.
1650 */
1651
1652static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1653{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001654 struct stlbrd *brdp;
1655 struct stlpanel *panelp;
1656 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 int brdnr, panelnr, portnr, totalport;
1658 int curoff, maxoff;
1659 char *pos;
1660
Jiri Slabya0564e12006-12-08 02:38:37 -08001661 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1662 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663
1664 pos = page;
1665 totalport = 0;
1666 curoff = 0;
1667
1668 if (off == 0) {
1669 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1670 stl_drvversion);
1671 while (pos < (page + MAXLINE - 1))
1672 *pos++ = ' ';
1673 *pos++ = '\n';
1674 }
1675 curoff = MAXLINE;
1676
1677/*
1678 * We scan through for each board, panel and port. The offset is
1679 * calculated on the fly, and irrelevant ports are skipped.
1680 */
1681 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1682 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001683 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 continue;
1685 if (brdp->state == 0)
1686 continue;
1687
1688 maxoff = curoff + (brdp->nrports * MAXLINE);
1689 if (off >= maxoff) {
1690 curoff = maxoff;
1691 continue;
1692 }
1693
1694 totalport = brdnr * STL_MAXPORTS;
1695 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1696 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001697 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 continue;
1699
1700 maxoff = curoff + (panelp->nrports * MAXLINE);
1701 if (off >= maxoff) {
1702 curoff = maxoff;
1703 totalport += panelp->nrports;
1704 continue;
1705 }
1706
1707 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1708 totalport++) {
1709 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001710 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 continue;
1712 if (off >= (curoff += MAXLINE))
1713 continue;
1714 if ((pos - page + MAXLINE) > count)
1715 goto stl_readdone;
1716 pos += stl_portinfo(portp, totalport, pos);
1717 }
1718 }
1719 }
1720
1721 *eof = 1;
1722
1723stl_readdone:
1724 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001725 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726}
1727
1728/*****************************************************************************/
1729
1730/*
1731 * All board interrupts are vectored through here first. This code then
1732 * calls off to the approrpriate board interrupt handlers.
1733 */
1734
David Howells7d12e782006-10-05 14:55:46 +01001735static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001737 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
Jiri Slabya0564e12006-12-08 02:38:37 -08001739 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
1741 return IRQ_RETVAL((* brdp->isr)(brdp));
1742}
1743
1744/*****************************************************************************/
1745
1746/*
1747 * Interrupt service routine for EasyIO board types.
1748 */
1749
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001750static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001752 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 unsigned int iobase;
1754 int handled = 0;
1755
Alan Coxb65b5b52006-06-27 02:54:05 -07001756 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 panelp = brdp->panels[0];
1758 iobase = panelp->iobase;
1759 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1760 handled = 1;
1761 (* panelp->isr)(panelp, iobase);
1762 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001763 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 return handled;
1765}
1766
1767/*****************************************************************************/
1768
1769/*
1770 * Interrupt service routine for ECH-AT board types.
1771 */
1772
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001773static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001775 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 unsigned int ioaddr;
1777 int bnknr;
1778 int handled = 0;
1779
1780 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1781
1782 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1783 handled = 1;
1784 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1785 ioaddr = brdp->bnkstataddr[bnknr];
1786 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1787 panelp = brdp->bnk2panel[bnknr];
1788 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1789 }
1790 }
1791 }
1792
1793 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1794
1795 return handled;
1796}
1797
1798/*****************************************************************************/
1799
1800/*
1801 * Interrupt service routine for ECH-MCA board types.
1802 */
1803
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001804static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001806 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 unsigned int ioaddr;
1808 int bnknr;
1809 int handled = 0;
1810
1811 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1812 handled = 1;
1813 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1814 ioaddr = brdp->bnkstataddr[bnknr];
1815 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1816 panelp = brdp->bnk2panel[bnknr];
1817 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1818 }
1819 }
1820 }
1821 return handled;
1822}
1823
1824/*****************************************************************************/
1825
1826/*
1827 * Interrupt service routine for ECH-PCI board types.
1828 */
1829
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001830static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001832 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 unsigned int ioaddr;
1834 int bnknr, recheck;
1835 int handled = 0;
1836
1837 while (1) {
1838 recheck = 0;
1839 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1840 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1841 ioaddr = brdp->bnkstataddr[bnknr];
1842 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1843 panelp = brdp->bnk2panel[bnknr];
1844 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1845 recheck++;
1846 handled = 1;
1847 }
1848 }
1849 if (! recheck)
1850 break;
1851 }
1852 return handled;
1853}
1854
1855/*****************************************************************************/
1856
1857/*
1858 * Interrupt service routine for ECH-8/64-PCI board types.
1859 */
1860
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001861static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001863 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 unsigned int ioaddr;
1865 int bnknr;
1866 int handled = 0;
1867
1868 while (inb(brdp->ioctrl) & 0x1) {
1869 handled = 1;
1870 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1871 ioaddr = brdp->bnkstataddr[bnknr];
1872 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1873 panelp = brdp->bnk2panel[bnknr];
1874 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1875 }
1876 }
1877 }
1878
1879 return handled;
1880}
1881
1882/*****************************************************************************/
1883
1884/*
1885 * Service an off-level request for some channel.
1886 */
Al Viro3e577a82006-12-06 18:41:45 +00001887static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001889 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 struct tty_struct *tty;
1891 unsigned int oldsigs;
1892
Jiri Slabya0564e12006-12-08 02:38:37 -08001893 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894
Jiri Slaby615e4a72006-12-08 02:38:38 -08001895 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 return;
1897
1898 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001899 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 return;
1901
1902 lock_kernel();
1903 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1904 tty_wakeup(tty);
1905 }
1906 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1907 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1908 oldsigs = portp->sigs;
1909 portp->sigs = stl_getsignals(portp);
1910 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1911 wake_up_interruptible(&portp->open_wait);
1912 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1913 if (portp->flags & ASYNC_CHECK_CD)
1914 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1915 }
1916 }
1917 unlock_kernel();
1918}
1919
1920/*****************************************************************************/
1921
1922/*
1923 * Initialize all the ports on a panel.
1924 */
1925
Jiri Slaby705c1862006-12-08 02:39:11 -08001926static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001928 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 int chipmask, i;
1930
Jiri Slabya0564e12006-12-08 02:38:37 -08001931 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
1933 chipmask = stl_panelinit(brdp, panelp);
1934
1935/*
1936 * All UART's are initialized (if found!). Now go through and setup
1937 * each ports data structures.
1938 */
1939 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001940 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001941 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001943 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 break;
1945 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
1947 portp->magic = STL_PORTMAGIC;
1948 portp->portnr = i;
1949 portp->brdnr = panelp->brdnr;
1950 portp->panelnr = panelp->panelnr;
1951 portp->uartp = panelp->uartp;
1952 portp->clk = brdp->clk;
1953 portp->baud_base = STL_BAUDBASE;
1954 portp->close_delay = STL_CLOSEDELAY;
1955 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001956 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 init_waitqueue_head(&portp->open_wait);
1958 init_waitqueue_head(&portp->close_wait);
1959 portp->stats.brd = portp->brdnr;
1960 portp->stats.panel = portp->panelnr;
1961 portp->stats.port = portp->portnr;
1962 panelp->ports[i] = portp;
1963 stl_portinit(brdp, panelp, portp);
1964 }
1965
1966 return(0);
1967}
1968
Jiri Slaby3b85b342006-12-08 02:39:10 -08001969static void stl_cleanup_panels(struct stlbrd *brdp)
1970{
1971 struct stlpanel *panelp;
1972 struct stlport *portp;
1973 unsigned int j, k;
1974
1975 for (j = 0; j < STL_MAXPANELS; j++) {
1976 panelp = brdp->panels[j];
1977 if (panelp == NULL)
1978 continue;
1979 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1980 portp = panelp->ports[k];
1981 if (portp == NULL)
1982 continue;
1983 if (portp->tty != NULL)
1984 stl_hangup(portp->tty);
1985 kfree(portp->tx.buf);
1986 kfree(portp);
1987 }
1988 kfree(panelp);
1989 }
1990}
1991
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992/*****************************************************************************/
1993
1994/*
1995 * Try to find and initialize an EasyIO board.
1996 */
1997
Jiri Slaby705c1862006-12-08 02:39:11 -08001998static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002000 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 unsigned int status;
2002 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002003 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
Jiri Slabya0564e12006-12-08 02:38:37 -08002005 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
2007 brdp->ioctrl = brdp->ioaddr1 + 1;
2008 brdp->iostatus = brdp->ioaddr1 + 2;
2009
2010 status = inb(brdp->iostatus);
2011 if ((status & EIO_IDBITMASK) == EIO_MK3)
2012 brdp->ioctrl++;
2013
2014/*
2015 * Handle board specific stuff now. The real difference is PCI
2016 * or not PCI.
2017 */
2018 if (brdp->brdtype == BRD_EASYIOPCI) {
2019 brdp->iosize1 = 0x80;
2020 brdp->iosize2 = 0x80;
2021 name = "serial(EIO-PCI)";
2022 outb(0x41, (brdp->ioaddr2 + 0x4c));
2023 } else {
2024 brdp->iosize1 = 8;
2025 name = "serial(EIO)";
2026 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2027 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2028 printk("STALLION: invalid irq=%d for brd=%d\n",
2029 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002030 retval = -EINVAL;
2031 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 }
2033 outb((stl_vecmap[brdp->irq] | EIO_0WS |
2034 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
2035 brdp->ioctrl);
2036 }
2037
Jiri Slaby3b85b342006-12-08 02:39:10 -08002038 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2040 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2041 "%x conflicts with another device\n", brdp->brdnr,
2042 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002043 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 }
2045
2046 if (brdp->iosize2 > 0)
2047 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2048 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2049 "address %x conflicts with another device\n",
2050 brdp->brdnr, brdp->ioaddr2);
2051 printk(KERN_WARNING "STALLION: Warning, also "
2052 "releasing board %d I/O address %x \n",
2053 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002054 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 }
2056
2057/*
2058 * Everything looks OK, so let's go ahead and probe for the hardware.
2059 */
2060 brdp->clk = CD1400_CLK;
2061 brdp->isr = stl_eiointr;
2062
Jiri Slaby3b85b342006-12-08 02:39:10 -08002063 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 switch (status & EIO_IDBITMASK) {
2065 case EIO_8PORTM:
2066 brdp->clk = CD1400_CLK8M;
2067 /* fall thru */
2068 case EIO_8PORTRS:
2069 case EIO_8PORTDI:
2070 brdp->nrports = 8;
2071 break;
2072 case EIO_4PORTRS:
2073 brdp->nrports = 4;
2074 break;
2075 case EIO_MK3:
2076 switch (status & EIO_BRDMASK) {
2077 case ID_BRD4:
2078 brdp->nrports = 4;
2079 break;
2080 case ID_BRD8:
2081 brdp->nrports = 8;
2082 break;
2083 case ID_BRD16:
2084 brdp->nrports = 16;
2085 break;
2086 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002087 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 }
2089 break;
2090 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002091 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 }
2093
2094/*
2095 * We have verified that the board is actually present, so now we
2096 * can complete the setup.
2097 */
2098
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002099 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002100 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002102 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002103 retval = -ENOMEM;
2104 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
2107 panelp->magic = STL_PANELMAGIC;
2108 panelp->brdnr = brdp->brdnr;
2109 panelp->panelnr = 0;
2110 panelp->nrports = brdp->nrports;
2111 panelp->iobase = brdp->ioaddr1;
2112 panelp->hwid = status;
2113 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002114 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 panelp->isr = stl_sc26198intr;
2116 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002117 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 panelp->isr = stl_cd1400eiointr;
2119 }
2120
2121 brdp->panels[0] = panelp;
2122 brdp->nrpanels = 1;
2123 brdp->state |= BRD_FOUND;
2124 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002125 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 printk("STALLION: failed to register interrupt "
2127 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002128 retval = -ENODEV;
2129 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08002131
2132 return 0;
2133err_fr:
2134 stl_cleanup_panels(brdp);
2135err_rel2:
2136 if (brdp->iosize2 > 0)
2137 release_region(brdp->ioaddr2, brdp->iosize2);
2138err_rel1:
2139 release_region(brdp->ioaddr1, brdp->iosize1);
2140err:
2141 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142}
2143
2144/*****************************************************************************/
2145
2146/*
2147 * Try to find an ECH board and initialize it. This code is capable of
2148 * dealing with all types of ECH board.
2149 */
2150
Jiri Slaby705c1862006-12-08 02:39:11 -08002151static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002153 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 unsigned int status, nxtid, ioaddr, conflict;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002155 int panelnr, banknr, i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 char *name;
2157
Jiri Slabya0564e12006-12-08 02:38:37 -08002158 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160 status = 0;
2161 conflict = 0;
2162
2163/*
2164 * Set up the initial board register contents for boards. This varies a
2165 * bit between the different board types. So we need to handle each
2166 * separately. Also do a check that the supplied IRQ is good.
2167 */
2168 switch (brdp->brdtype) {
2169
2170 case BRD_ECH:
2171 brdp->isr = stl_echatintr;
2172 brdp->ioctrl = brdp->ioaddr1 + 1;
2173 brdp->iostatus = brdp->ioaddr1 + 1;
2174 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002175 if ((status & ECH_IDBITMASK) != ECH_ID) {
2176 retval = -ENODEV;
2177 goto err;
2178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2180 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2181 printk("STALLION: invalid irq=%d for brd=%d\n",
2182 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002183 retval = -EINVAL;
2184 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 }
2186 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2187 status |= (stl_vecmap[brdp->irq] << 1);
2188 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2189 brdp->ioctrlval = ECH_INTENABLE |
2190 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2191 for (i = 0; (i < 10); i++)
2192 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2193 brdp->iosize1 = 2;
2194 brdp->iosize2 = 32;
2195 name = "serial(EC8/32)";
2196 outb(status, brdp->ioaddr1);
2197 break;
2198
2199 case BRD_ECHMC:
2200 brdp->isr = stl_echmcaintr;
2201 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2202 brdp->iostatus = brdp->ioctrl;
2203 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002204 if ((status & ECH_IDBITMASK) != ECH_ID) {
2205 retval = -ENODEV;
2206 goto err;
2207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2209 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2210 printk("STALLION: invalid irq=%d for brd=%d\n",
2211 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002212 retval = -EINVAL;
2213 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 }
2215 outb(ECHMC_BRDRESET, brdp->ioctrl);
2216 outb(ECHMC_INTENABLE, brdp->ioctrl);
2217 brdp->iosize1 = 64;
2218 name = "serial(EC8/32-MC)";
2219 break;
2220
2221 case BRD_ECHPCI:
2222 brdp->isr = stl_echpciintr;
2223 brdp->ioctrl = brdp->ioaddr1 + 2;
2224 brdp->iosize1 = 4;
2225 brdp->iosize2 = 8;
2226 name = "serial(EC8/32-PCI)";
2227 break;
2228
2229 case BRD_ECH64PCI:
2230 brdp->isr = stl_echpci64intr;
2231 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2232 outb(0x43, (brdp->ioaddr1 + 0x4c));
2233 brdp->iosize1 = 0x80;
2234 brdp->iosize2 = 0x80;
2235 name = "serial(EC8/64-PCI)";
2236 break;
2237
2238 default:
2239 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002240 retval = -EINVAL;
2241 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 }
2243
2244/*
2245 * Check boards for possible IO address conflicts and return fail status
2246 * if an IO conflict found.
2247 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002248 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2250 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2251 "%x conflicts with another device\n", brdp->brdnr,
2252 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002253 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
2255
2256 if (brdp->iosize2 > 0)
2257 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2258 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2259 "address %x conflicts with another device\n",
2260 brdp->brdnr, brdp->ioaddr2);
2261 printk(KERN_WARNING "STALLION: Warning, also "
2262 "releasing board %d I/O address %x \n",
2263 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002264 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 }
2266
2267/*
2268 * Scan through the secondary io address space looking for panels.
2269 * As we find'em allocate and initialize panel structures for each.
2270 */
2271 brdp->clk = CD1400_CLK;
2272 brdp->hwid = status;
2273
2274 ioaddr = brdp->ioaddr2;
2275 banknr = 0;
2276 panelnr = 0;
2277 nxtid = 0;
2278
2279 for (i = 0; (i < STL_MAXPANELS); i++) {
2280 if (brdp->brdtype == BRD_ECHPCI) {
2281 outb(nxtid, brdp->ioctrl);
2282 ioaddr = brdp->ioaddr2;
2283 }
2284 status = inb(ioaddr + ECH_PNLSTATUS);
2285 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002286 goto err_fr;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002287 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002288 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002290 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002291 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 panelp->magic = STL_PANELMAGIC;
2294 panelp->brdnr = brdp->brdnr;
2295 panelp->panelnr = panelnr;
2296 panelp->iobase = ioaddr;
2297 panelp->pagenr = nxtid;
2298 panelp->hwid = status;
2299 brdp->bnk2panel[banknr] = panelp;
2300 brdp->bnkpageaddr[banknr] = nxtid;
2301 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2302
2303 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002304 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 panelp->isr = stl_sc26198intr;
2306 if (status & ECH_PNL16PORT) {
2307 panelp->nrports = 16;
2308 brdp->bnk2panel[banknr] = panelp;
2309 brdp->bnkpageaddr[banknr] = nxtid;
2310 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2311 ECH_PNLSTATUS;
2312 } else {
2313 panelp->nrports = 8;
2314 }
2315 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002316 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 panelp->isr = stl_cd1400echintr;
2318 if (status & ECH_PNL16PORT) {
2319 panelp->nrports = 16;
2320 panelp->ackmask = 0x80;
2321 if (brdp->brdtype != BRD_ECHPCI)
2322 ioaddr += EREG_BANKSIZE;
2323 brdp->bnk2panel[banknr] = panelp;
2324 brdp->bnkpageaddr[banknr] = ++nxtid;
2325 brdp->bnkstataddr[banknr++] = ioaddr +
2326 ECH_PNLSTATUS;
2327 } else {
2328 panelp->nrports = 8;
2329 panelp->ackmask = 0xc0;
2330 }
2331 }
2332
2333 nxtid++;
2334 ioaddr += EREG_BANKSIZE;
2335 brdp->nrports += panelp->nrports;
2336 brdp->panels[panelnr++] = panelp;
2337 if ((brdp->brdtype != BRD_ECHPCI) &&
2338 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
Jiri Slaby3b85b342006-12-08 02:39:10 -08002339 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 }
2341
2342 brdp->nrpanels = panelnr;
2343 brdp->nrbnks = banknr;
2344 if (brdp->brdtype == BRD_ECH)
2345 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2346
2347 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002348 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 printk("STALLION: failed to register interrupt "
2350 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002351 retval = -ENODEV;
2352 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 }
2354
Jiri Slaby3b85b342006-12-08 02:39:10 -08002355 return 0;
2356err_fr:
2357 stl_cleanup_panels(brdp);
2358 if (brdp->iosize2 > 0)
2359 release_region(brdp->ioaddr2, brdp->iosize2);
2360err_rel1:
2361 release_region(brdp->ioaddr1, brdp->iosize1);
2362err:
2363 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364}
2365
2366/*****************************************************************************/
2367
2368/*
2369 * Initialize and configure the specified board.
2370 * Scan through all the boards in the configuration and see what we
2371 * can find. Handle EIO and the ECH boards a little differently here
2372 * since the initial search and setup is very different.
2373 */
2374
Jiri Slaby705c1862006-12-08 02:39:11 -08002375static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002377 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Jiri Slabya0564e12006-12-08 02:38:37 -08002379 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
2381 switch (brdp->brdtype) {
2382 case BRD_EASYIO:
2383 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002384 retval = stl_initeio(brdp);
2385 if (retval)
2386 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 break;
2388 case BRD_ECH:
2389 case BRD_ECHMC:
2390 case BRD_ECHPCI:
2391 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002392 retval = stl_initech(brdp);
2393 if (retval)
2394 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 break;
2396 default:
2397 printk("STALLION: board=%d is unknown board type=%d\n",
2398 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002399 retval = -ENODEV;
2400 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 }
2402
2403 stl_brds[brdp->brdnr] = brdp;
2404 if ((brdp->state & BRD_FOUND) == 0) {
2405 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2406 stl_brdnames[brdp->brdtype], brdp->brdnr,
2407 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002408 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 }
2410
2411 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002412 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 stl_initports(brdp, brdp->panels[i]);
2414
2415 printk("STALLION: %s found, board=%d io=%x irq=%d "
2416 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2417 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2418 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002419
2420 return 0;
2421err_free:
2422 free_irq(brdp->irq, brdp);
2423
2424 stl_cleanup_panels(brdp);
2425
2426 release_region(brdp->ioaddr1, brdp->iosize1);
2427 if (brdp->iosize2 > 0)
2428 release_region(brdp->ioaddr2, brdp->iosize2);
2429
2430 stl_brds[brdp->brdnr] = NULL;
2431err:
2432 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433}
2434
2435/*****************************************************************************/
2436
2437/*
2438 * Find the next available board number that is free.
2439 */
2440
Jiri Slaby705c1862006-12-08 02:39:11 -08002441static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442{
2443 int i;
2444
2445 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002446 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 if (i >= stl_nrbrds)
2448 stl_nrbrds = i + 1;
2449 return(i);
2450 }
2451 }
2452 return(-1);
2453}
2454
2455/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456/*
2457 * We have a Stallion board. Allocate a board structure and
2458 * initialize it. Read its IO and IRQ resources from PCI
2459 * configuration space.
2460 */
2461
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002462static int __devinit stl_pciprobe(struct pci_dev *pdev,
2463 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002465 struct stlbrd *brdp;
2466 unsigned int brdtype = ent->driver_data;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002467 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002469 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002470 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002471
2472 dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
2473 pdev->vendor, pdev->device, pdev->class);
2474
Jiri Slaby3b85b342006-12-08 02:39:10 -08002475 retval = pci_enable_device(pdev);
2476 if (retval)
2477 goto err;
2478 brdp = stl_allocbrd();
2479 if (brdp == NULL) {
2480 retval = -ENOMEM;
2481 goto err;
2482 }
2483 brdp->brdnr = stl_getbrdnr();
2484 if (brdp->brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002485 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002487 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 }
2489 brdp->brdtype = brdtype;
2490
2491/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 * We have all resources from the board, so let's setup the actual
2493 * board structure now.
2494 */
2495 switch (brdtype) {
2496 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002497 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2498 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 break;
2500 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002501 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2502 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 break;
2504 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002505 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2506 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 break;
2508 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002509 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 break;
2511 }
2512
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002513 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002514 retval = stl_brdinit(brdp);
2515 if (retval)
2516 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002518 pci_set_drvdata(pdev, brdp);
2519
Jiri Slaby3b85b342006-12-08 02:39:10 -08002520 return 0;
2521err_fr:
2522 kfree(brdp);
2523err:
2524 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525}
2526
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002527static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002529 struct stlbrd *brdp = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002531 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002533 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002535 release_region(brdp->ioaddr1, brdp->iosize1);
2536 if (brdp->iosize2 > 0)
2537 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002539 stl_brds[brdp->brdnr] = NULL;
2540 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541}
2542
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002543static struct pci_driver stl_pcidriver = {
2544 .name = "stallion",
2545 .id_table = stl_pcibrds,
2546 .probe = stl_pciprobe,
2547 .remove = __devexit_p(stl_pciremove)
2548};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549
2550/*****************************************************************************/
2551
2552/*
2553 * Scan through all the boards in the configuration and see what we
2554 * can find. Handle EIO and the ECH boards a little differently here
2555 * since the initial search and setup is too different.
2556 */
2557
Jiri Slaby40e82652006-12-08 02:38:41 -08002558static int __init stl_initbrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002560 struct stlbrd *brdp;
2561 struct stlconf *confp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 int i;
2563
Jiri Slabya0564e12006-12-08 02:38:37 -08002564 pr_debug("stl_initbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
2566 if (stl_nrbrds > STL_MAXBRDS) {
2567 printk("STALLION: too many boards in configuration table, "
2568 "truncating to %d\n", STL_MAXBRDS);
2569 stl_nrbrds = STL_MAXBRDS;
2570 }
2571
2572/*
2573 * Firstly scan the list of static boards configured. Allocate
2574 * resources and initialize the boards as found.
2575 */
2576 for (i = 0; (i < stl_nrbrds); i++) {
2577 confp = &stl_brdconf[i];
2578 stl_parsebrd(confp, stl_brdsp[i]);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002579 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 return(-ENOMEM);
2581 brdp->brdnr = i;
2582 brdp->brdtype = confp->brdtype;
2583 brdp->ioaddr1 = confp->ioaddr1;
2584 brdp->ioaddr2 = confp->ioaddr2;
2585 brdp->irq = confp->irq;
2586 brdp->irqtype = confp->irqtype;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002587 if (stl_brdinit(brdp))
2588 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 }
2590
2591/*
2592 * Find any dynamically supported boards. That is via module load
2593 * line options or auto-detected on the PCI bus.
2594 */
2595 stl_argbrds();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
2597 return(0);
2598}
2599
2600/*****************************************************************************/
2601
2602/*
2603 * Return the board stats structure to user app.
2604 */
2605
2606static int stl_getbrdstats(combrd_t __user *bp)
2607{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002608 struct stlbrd *brdp;
2609 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 int i;
2611
2612 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2613 return -EFAULT;
2614 if (stl_brdstats.brd >= STL_MAXBRDS)
2615 return(-ENODEV);
2616 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002617 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 return(-ENODEV);
2619
2620 memset(&stl_brdstats, 0, sizeof(combrd_t));
2621 stl_brdstats.brd = brdp->brdnr;
2622 stl_brdstats.type = brdp->brdtype;
2623 stl_brdstats.hwid = brdp->hwid;
2624 stl_brdstats.state = brdp->state;
2625 stl_brdstats.ioaddr = brdp->ioaddr1;
2626 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2627 stl_brdstats.irq = brdp->irq;
2628 stl_brdstats.nrpanels = brdp->nrpanels;
2629 stl_brdstats.nrports = brdp->nrports;
2630 for (i = 0; (i < brdp->nrpanels); i++) {
2631 panelp = brdp->panels[i];
2632 stl_brdstats.panels[i].panel = i;
2633 stl_brdstats.panels[i].hwid = panelp->hwid;
2634 stl_brdstats.panels[i].nrports = panelp->nrports;
2635 }
2636
2637 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2638}
2639
2640/*****************************************************************************/
2641
2642/*
2643 * Resolve the referenced port number into a port struct pointer.
2644 */
2645
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002646static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002648 struct stlbrd *brdp;
2649 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
2651 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002652 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002654 if (brdp == NULL)
2655 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002657 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002659 if (panelp == NULL)
2660 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002662 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 return(panelp->ports[portnr]);
2664}
2665
2666/*****************************************************************************/
2667
2668/*
2669 * Return the port stats structure to user app. A NULL port struct
2670 * pointer passed in means that we need to find out from the app
2671 * what port to get stats for (used through board control device).
2672 */
2673
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002674static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675{
2676 unsigned char *head, *tail;
2677 unsigned long flags;
2678
2679 if (!portp) {
2680 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2681 return -EFAULT;
2682 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2683 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002684 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 return(-ENODEV);
2686 }
2687
2688 portp->stats.state = portp->istate;
2689 portp->stats.flags = portp->flags;
2690 portp->stats.hwid = portp->hwid;
2691
2692 portp->stats.ttystate = 0;
2693 portp->stats.cflags = 0;
2694 portp->stats.iflags = 0;
2695 portp->stats.oflags = 0;
2696 portp->stats.lflags = 0;
2697 portp->stats.rxbuffered = 0;
2698
Alan Coxb65b5b52006-06-27 02:54:05 -07002699 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002700 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 if (portp->tty->driver_data == portp) {
2702 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002703 /* No longer available as a statistic */
2704 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002705 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 portp->stats.cflags = portp->tty->termios->c_cflag;
2707 portp->stats.iflags = portp->tty->termios->c_iflag;
2708 portp->stats.oflags = portp->tty->termios->c_oflag;
2709 portp->stats.lflags = portp->tty->termios->c_lflag;
2710 }
2711 }
2712 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002713 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714
2715 head = portp->tx.head;
2716 tail = portp->tx.tail;
2717 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2718 (STL_TXBUFSIZE - (tail - head)));
2719
2720 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2721
2722 return copy_to_user(cp, &portp->stats,
2723 sizeof(comstats_t)) ? -EFAULT : 0;
2724}
2725
2726/*****************************************************************************/
2727
2728/*
2729 * Clear the port stats structure. We also return it zeroed out...
2730 */
2731
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002732static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733{
2734 if (!portp) {
2735 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2736 return -EFAULT;
2737 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2738 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002739 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 return(-ENODEV);
2741 }
2742
2743 memset(&portp->stats, 0, sizeof(comstats_t));
2744 portp->stats.brd = portp->brdnr;
2745 portp->stats.panel = portp->panelnr;
2746 portp->stats.port = portp->portnr;
2747 return copy_to_user(cp, &portp->stats,
2748 sizeof(comstats_t)) ? -EFAULT : 0;
2749}
2750
2751/*****************************************************************************/
2752
2753/*
2754 * Return the entire driver ports structure to a user app.
2755 */
2756
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002757static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002759 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002761 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 return -EFAULT;
2763 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2764 stl_dummyport.portnr);
2765 if (!portp)
2766 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002767 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768}
2769
2770/*****************************************************************************/
2771
2772/*
2773 * Return the entire driver board structure to a user app.
2774 */
2775
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002776static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002778 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002780 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 return -EFAULT;
2782 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2783 return -ENODEV;
2784 brdp = stl_brds[stl_dummybrd.brdnr];
2785 if (!brdp)
2786 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002787 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788}
2789
2790/*****************************************************************************/
2791
2792/*
2793 * The "staliomem" device is also required to do some special operations
2794 * on the board and/or ports. In this driver it is mostly used for stats
2795 * collection.
2796 */
2797
2798static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2799{
2800 int brdnr, rc;
2801 void __user *argp = (void __user *)arg;
2802
Jiri Slabya0564e12006-12-08 02:38:37 -08002803 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
2805 brdnr = iminor(ip);
2806 if (brdnr >= STL_MAXBRDS)
2807 return(-ENODEV);
2808 rc = 0;
2809
2810 switch (cmd) {
2811 case COM_GETPORTSTATS:
2812 rc = stl_getportstats(NULL, argp);
2813 break;
2814 case COM_CLRPORTSTATS:
2815 rc = stl_clrportstats(NULL, argp);
2816 break;
2817 case COM_GETBRDSTATS:
2818 rc = stl_getbrdstats(argp);
2819 break;
2820 case COM_READPORT:
2821 rc = stl_getportstruct(argp);
2822 break;
2823 case COM_READBOARD:
2824 rc = stl_getbrdstruct(argp);
2825 break;
2826 default:
2827 rc = -ENOIOCTLCMD;
2828 break;
2829 }
2830
2831 return(rc);
2832}
2833
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002834static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835 .open = stl_open,
2836 .close = stl_close,
2837 .write = stl_write,
2838 .put_char = stl_putchar,
2839 .flush_chars = stl_flushchars,
2840 .write_room = stl_writeroom,
2841 .chars_in_buffer = stl_charsinbuffer,
2842 .ioctl = stl_ioctl,
2843 .set_termios = stl_settermios,
2844 .throttle = stl_throttle,
2845 .unthrottle = stl_unthrottle,
2846 .stop = stl_stop,
2847 .start = stl_start,
2848 .hangup = stl_hangup,
2849 .flush_buffer = stl_flushbuffer,
2850 .break_ctl = stl_breakctl,
2851 .wait_until_sent = stl_waituntilsent,
2852 .send_xchar = stl_sendxchar,
2853 .read_proc = stl_readproc,
2854 .tiocmget = stl_tiocmget,
2855 .tiocmset = stl_tiocmset,
2856};
2857
2858/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859/* CD1400 HARDWARE FUNCTIONS */
2860/*****************************************************************************/
2861
2862/*
2863 * These functions get/set/update the registers of the cd1400 UARTs.
2864 * Access to the cd1400 registers is via an address/data io port pair.
2865 * (Maybe should make this inline...)
2866 */
2867
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002868static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869{
2870 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002871 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872}
2873
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002874static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875{
2876 outb((regnr + portp->uartaddr), portp->ioaddr);
2877 outb(value, portp->ioaddr + EREG_DATA);
2878}
2879
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002880static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881{
2882 outb((regnr + portp->uartaddr), portp->ioaddr);
2883 if (inb(portp->ioaddr + EREG_DATA) != value) {
2884 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002885 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002887 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888}
2889
2890/*****************************************************************************/
2891
2892/*
2893 * Inbitialize the UARTs in a panel. We don't care what sort of board
2894 * these ports are on - since the port io registers are almost
2895 * identical when dealing with ports.
2896 */
2897
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002898static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899{
2900 unsigned int gfrcr;
2901 int chipmask, i, j;
2902 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002903 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904
Jiri Slabya0564e12006-12-08 02:38:37 -08002905 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906
Alan Coxb65b5b52006-06-27 02:54:05 -07002907 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 BRDENABLE(panelp->brdnr, panelp->pagenr);
2909
2910/*
2911 * Check that each chip is present and started up OK.
2912 */
2913 chipmask = 0;
2914 nrchips = panelp->nrports / CD1400_PORTS;
2915 for (i = 0; (i < nrchips); i++) {
2916 if (brdp->brdtype == BRD_ECHPCI) {
2917 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2918 ioaddr = panelp->iobase;
2919 } else {
2920 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2921 }
2922 uartaddr = (i & 0x01) ? 0x080 : 0;
2923 outb((GFRCR + uartaddr), ioaddr);
2924 outb(0, (ioaddr + EREG_DATA));
2925 outb((CCR + uartaddr), ioaddr);
2926 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2927 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2928 outb((GFRCR + uartaddr), ioaddr);
2929 for (j = 0; (j < CCR_MAXWAIT); j++) {
2930 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2931 break;
2932 }
2933 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2934 printk("STALLION: cd1400 not responding, "
2935 "brd=%d panel=%d chip=%d\n",
2936 panelp->brdnr, panelp->panelnr, i);
2937 continue;
2938 }
2939 chipmask |= (0x1 << i);
2940 outb((PPR + uartaddr), ioaddr);
2941 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2942 }
2943
2944 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002945 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002946 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947}
2948
2949/*****************************************************************************/
2950
2951/*
2952 * Initialize hardware specific port registers.
2953 */
2954
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002955static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956{
Alan Coxb65b5b52006-06-27 02:54:05 -07002957 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002958 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2959 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960
Jiri Slaby615e4a72006-12-08 02:38:38 -08002961 if ((brdp == NULL) || (panelp == NULL) ||
2962 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 return;
2964
Alan Coxb65b5b52006-06-27 02:54:05 -07002965 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2967 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2968 portp->uartaddr = (portp->portnr & 0x04) << 5;
2969 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2970
2971 BRDENABLE(portp->brdnr, portp->pagenr);
2972 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2973 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2974 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2975 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002976 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977}
2978
2979/*****************************************************************************/
2980
2981/*
2982 * Wait for the command register to be ready. We will poll this,
2983 * since it won't usually take too long to be ready.
2984 */
2985
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002986static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987{
2988 int i;
2989
2990 for (i = 0; (i < CCR_MAXWAIT); i++) {
2991 if (stl_cd1400getreg(portp, CCR) == 0) {
2992 return;
2993 }
2994 }
2995
2996 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2997 portp->portnr, portp->panelnr, portp->brdnr);
2998}
2999
3000/*****************************************************************************/
3001
3002/*
3003 * Set up the cd1400 registers for a port based on the termios port
3004 * settings.
3005 */
3006
Alan Cox606d0992006-12-08 02:38:45 -08003007static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003009 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 unsigned long flags;
3011 unsigned int clkdiv, baudrate;
3012 unsigned char cor1, cor2, cor3;
3013 unsigned char cor4, cor5, ccr;
3014 unsigned char srer, sreron, sreroff;
3015 unsigned char mcor1, mcor2, rtpr;
3016 unsigned char clk, div;
3017
3018 cor1 = 0;
3019 cor2 = 0;
3020 cor3 = 0;
3021 cor4 = 0;
3022 cor5 = 0;
3023 ccr = 0;
3024 rtpr = 0;
3025 clk = 0;
3026 div = 0;
3027 mcor1 = 0;
3028 mcor2 = 0;
3029 sreron = 0;
3030 sreroff = 0;
3031
3032 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003033 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 return;
3035
3036/*
3037 * Set up the RX char ignore mask with those RX error types we
3038 * can ignore. We can get the cd1400 to help us out a little here,
3039 * it will ignore parity errors and breaks for us.
3040 */
3041 portp->rxignoremsk = 0;
3042 if (tiosp->c_iflag & IGNPAR) {
3043 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
3044 cor1 |= COR1_PARIGNORE;
3045 }
3046 if (tiosp->c_iflag & IGNBRK) {
3047 portp->rxignoremsk |= ST_BREAK;
3048 cor4 |= COR4_IGNBRK;
3049 }
3050
3051 portp->rxmarkmsk = ST_OVERRUN;
3052 if (tiosp->c_iflag & (INPCK | PARMRK))
3053 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
3054 if (tiosp->c_iflag & BRKINT)
3055 portp->rxmarkmsk |= ST_BREAK;
3056
3057/*
3058 * Go through the char size, parity and stop bits and set all the
3059 * option register appropriately.
3060 */
3061 switch (tiosp->c_cflag & CSIZE) {
3062 case CS5:
3063 cor1 |= COR1_CHL5;
3064 break;
3065 case CS6:
3066 cor1 |= COR1_CHL6;
3067 break;
3068 case CS7:
3069 cor1 |= COR1_CHL7;
3070 break;
3071 default:
3072 cor1 |= COR1_CHL8;
3073 break;
3074 }
3075
3076 if (tiosp->c_cflag & CSTOPB)
3077 cor1 |= COR1_STOP2;
3078 else
3079 cor1 |= COR1_STOP1;
3080
3081 if (tiosp->c_cflag & PARENB) {
3082 if (tiosp->c_cflag & PARODD)
3083 cor1 |= (COR1_PARENB | COR1_PARODD);
3084 else
3085 cor1 |= (COR1_PARENB | COR1_PAREVEN);
3086 } else {
3087 cor1 |= COR1_PARNONE;
3088 }
3089
3090/*
3091 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
3092 * space for hardware flow control and the like. This should be set to
3093 * VMIN. Also here we will set the RX data timeout to 10ms - this should
3094 * really be based on VTIME.
3095 */
3096 cor3 |= FIFO_RXTHRESHOLD;
3097 rtpr = 2;
3098
3099/*
3100 * Calculate the baud rate timers. For now we will just assume that
3101 * the input and output baud are the same. Could have used a baud
3102 * table here, but this way we can generate virtually any baud rate
3103 * we like!
3104 */
3105 baudrate = tiosp->c_cflag & CBAUD;
3106 if (baudrate & CBAUDEX) {
3107 baudrate &= ~CBAUDEX;
3108 if ((baudrate < 1) || (baudrate > 4))
3109 tiosp->c_cflag &= ~CBAUDEX;
3110 else
3111 baudrate += 15;
3112 }
3113 baudrate = stl_baudrates[baudrate];
3114 if ((tiosp->c_cflag & CBAUD) == B38400) {
3115 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3116 baudrate = 57600;
3117 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3118 baudrate = 115200;
3119 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3120 baudrate = 230400;
3121 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3122 baudrate = 460800;
3123 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3124 baudrate = (portp->baud_base / portp->custom_divisor);
3125 }
3126 if (baudrate > STL_CD1400MAXBAUD)
3127 baudrate = STL_CD1400MAXBAUD;
3128
3129 if (baudrate > 0) {
3130 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
3131 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
3132 if (clkdiv < 0x100)
3133 break;
3134 }
3135 div = (unsigned char) clkdiv;
3136 }
3137
3138/*
3139 * Check what form of modem signaling is required and set it up.
3140 */
3141 if ((tiosp->c_cflag & CLOCAL) == 0) {
3142 mcor1 |= MCOR1_DCD;
3143 mcor2 |= MCOR2_DCD;
3144 sreron |= SRER_MODEM;
3145 portp->flags |= ASYNC_CHECK_CD;
3146 } else {
3147 portp->flags &= ~ASYNC_CHECK_CD;
3148 }
3149
3150/*
3151 * Setup cd1400 enhanced modes if we can. In particular we want to
3152 * handle as much of the flow control as possible automatically. As
3153 * well as saving a few CPU cycles it will also greatly improve flow
3154 * control reliability.
3155 */
3156 if (tiosp->c_iflag & IXON) {
3157 cor2 |= COR2_TXIBE;
3158 cor3 |= COR3_SCD12;
3159 if (tiosp->c_iflag & IXANY)
3160 cor2 |= COR2_IXM;
3161 }
3162
3163 if (tiosp->c_cflag & CRTSCTS) {
3164 cor2 |= COR2_CTSAE;
3165 mcor1 |= FIFO_RTSTHRESHOLD;
3166 }
3167
3168/*
3169 * All cd1400 register values calculated so go through and set
3170 * them all up.
3171 */
3172
Jiri Slabya0564e12006-12-08 02:38:37 -08003173 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003175 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003177 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003179 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3180 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3182 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183
Alan Coxb65b5b52006-06-27 02:54:05 -07003184 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 BRDENABLE(portp->brdnr, portp->pagenr);
3186 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3187 srer = stl_cd1400getreg(portp, SRER);
3188 stl_cd1400setreg(portp, SRER, 0);
3189 if (stl_cd1400updatereg(portp, COR1, cor1))
3190 ccr = 1;
3191 if (stl_cd1400updatereg(portp, COR2, cor2))
3192 ccr = 1;
3193 if (stl_cd1400updatereg(portp, COR3, cor3))
3194 ccr = 1;
3195 if (ccr) {
3196 stl_cd1400ccrwait(portp);
3197 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3198 }
3199 stl_cd1400setreg(portp, COR4, cor4);
3200 stl_cd1400setreg(portp, COR5, cor5);
3201 stl_cd1400setreg(portp, MCOR1, mcor1);
3202 stl_cd1400setreg(portp, MCOR2, mcor2);
3203 if (baudrate > 0) {
3204 stl_cd1400setreg(portp, TCOR, clk);
3205 stl_cd1400setreg(portp, TBPR, div);
3206 stl_cd1400setreg(portp, RCOR, clk);
3207 stl_cd1400setreg(portp, RBPR, div);
3208 }
3209 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3210 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3211 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3212 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3213 stl_cd1400setreg(portp, RTPR, rtpr);
3214 mcor1 = stl_cd1400getreg(portp, MSVR1);
3215 if (mcor1 & MSVR1_DCD)
3216 portp->sigs |= TIOCM_CD;
3217 else
3218 portp->sigs &= ~TIOCM_CD;
3219 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3220 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003221 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222}
3223
3224/*****************************************************************************/
3225
3226/*
3227 * Set the state of the DTR and RTS signals.
3228 */
3229
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003230static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231{
3232 unsigned char msvr1, msvr2;
3233 unsigned long flags;
3234
Jiri Slabya0564e12006-12-08 02:38:37 -08003235 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3236 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237
3238 msvr1 = 0;
3239 msvr2 = 0;
3240 if (dtr > 0)
3241 msvr1 = MSVR1_DTR;
3242 if (rts > 0)
3243 msvr2 = MSVR2_RTS;
3244
Alan Coxb65b5b52006-06-27 02:54:05 -07003245 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246 BRDENABLE(portp->brdnr, portp->pagenr);
3247 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3248 if (rts >= 0)
3249 stl_cd1400setreg(portp, MSVR2, msvr2);
3250 if (dtr >= 0)
3251 stl_cd1400setreg(portp, MSVR1, msvr1);
3252 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003253 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254}
3255
3256/*****************************************************************************/
3257
3258/*
3259 * Return the state of the signals.
3260 */
3261
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003262static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263{
3264 unsigned char msvr1, msvr2;
3265 unsigned long flags;
3266 int sigs;
3267
Jiri Slabya0564e12006-12-08 02:38:37 -08003268 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
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 msvr1 = stl_cd1400getreg(portp, MSVR1);
3274 msvr2 = stl_cd1400getreg(portp, MSVR2);
3275 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003276 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277
3278 sigs = 0;
3279 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3280 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3281 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3282 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3283#if 0
3284 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3285 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3286#else
3287 sigs |= TIOCM_DSR;
3288#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003289 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290}
3291
3292/*****************************************************************************/
3293
3294/*
3295 * Enable/Disable the Transmitter and/or Receiver.
3296 */
3297
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003298static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299{
3300 unsigned char ccr;
3301 unsigned long flags;
3302
Jiri Slabya0564e12006-12-08 02:38:37 -08003303 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3304
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 ccr = 0;
3306
3307 if (tx == 0)
3308 ccr |= CCR_TXDISABLE;
3309 else if (tx > 0)
3310 ccr |= CCR_TXENABLE;
3311 if (rx == 0)
3312 ccr |= CCR_RXDISABLE;
3313 else if (rx > 0)
3314 ccr |= CCR_RXENABLE;
3315
Alan Coxb65b5b52006-06-27 02:54:05 -07003316 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317 BRDENABLE(portp->brdnr, portp->pagenr);
3318 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3319 stl_cd1400ccrwait(portp);
3320 stl_cd1400setreg(portp, CCR, ccr);
3321 stl_cd1400ccrwait(portp);
3322 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003323 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324}
3325
3326/*****************************************************************************/
3327
3328/*
3329 * Start/stop the Transmitter and/or Receiver.
3330 */
3331
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003332static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333{
3334 unsigned char sreron, sreroff;
3335 unsigned long flags;
3336
Jiri Slabya0564e12006-12-08 02:38:37 -08003337 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338
3339 sreron = 0;
3340 sreroff = 0;
3341 if (tx == 0)
3342 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3343 else if (tx == 1)
3344 sreron |= SRER_TXDATA;
3345 else if (tx >= 2)
3346 sreron |= SRER_TXEMPTY;
3347 if (rx == 0)
3348 sreroff |= SRER_RXDATA;
3349 else if (rx > 0)
3350 sreron |= SRER_RXDATA;
3351
Alan Coxb65b5b52006-06-27 02:54:05 -07003352 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 BRDENABLE(portp->brdnr, portp->pagenr);
3354 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3355 stl_cd1400setreg(portp, SRER,
3356 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3357 BRDDISABLE(portp->brdnr);
3358 if (tx > 0)
3359 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003360 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361}
3362
3363/*****************************************************************************/
3364
3365/*
3366 * Disable all interrupts from this port.
3367 */
3368
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003369static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370{
3371 unsigned long flags;
3372
Jiri Slabya0564e12006-12-08 02:38:37 -08003373 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3374
Alan Coxb65b5b52006-06-27 02:54:05 -07003375 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 BRDENABLE(portp->brdnr, portp->pagenr);
3377 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3378 stl_cd1400setreg(portp, SRER, 0);
3379 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003380 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381}
3382
3383/*****************************************************************************/
3384
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003385static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386{
3387 unsigned long flags;
3388
Jiri Slabya0564e12006-12-08 02:38:37 -08003389 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
Alan Coxb65b5b52006-06-27 02:54:05 -07003391 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392 BRDENABLE(portp->brdnr, portp->pagenr);
3393 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3394 stl_cd1400setreg(portp, SRER,
3395 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3396 SRER_TXEMPTY));
3397 BRDDISABLE(portp->brdnr);
3398 portp->brklen = len;
3399 if (len == 1)
3400 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003401 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402}
3403
3404/*****************************************************************************/
3405
3406/*
3407 * Take flow control actions...
3408 */
3409
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003410static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411{
3412 struct tty_struct *tty;
3413 unsigned long flags;
3414
Jiri Slabya0564e12006-12-08 02:38:37 -08003415 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416
Jiri Slaby615e4a72006-12-08 02:38:38 -08003417 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418 return;
3419 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003420 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 return;
3422
Alan Coxb65b5b52006-06-27 02:54:05 -07003423 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424 BRDENABLE(portp->brdnr, portp->pagenr);
3425 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3426
3427 if (state) {
3428 if (tty->termios->c_iflag & IXOFF) {
3429 stl_cd1400ccrwait(portp);
3430 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3431 portp->stats.rxxon++;
3432 stl_cd1400ccrwait(portp);
3433 }
3434/*
3435 * Question: should we return RTS to what it was before? It may
3436 * have been set by an ioctl... Suppose not, since if you have
3437 * hardware flow control set then it is pretty silly to go and
3438 * set the RTS line by hand.
3439 */
3440 if (tty->termios->c_cflag & CRTSCTS) {
3441 stl_cd1400setreg(portp, MCOR1,
3442 (stl_cd1400getreg(portp, MCOR1) |
3443 FIFO_RTSTHRESHOLD));
3444 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3445 portp->stats.rxrtson++;
3446 }
3447 } else {
3448 if (tty->termios->c_iflag & IXOFF) {
3449 stl_cd1400ccrwait(portp);
3450 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3451 portp->stats.rxxoff++;
3452 stl_cd1400ccrwait(portp);
3453 }
3454 if (tty->termios->c_cflag & CRTSCTS) {
3455 stl_cd1400setreg(portp, MCOR1,
3456 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3457 stl_cd1400setreg(portp, MSVR2, 0);
3458 portp->stats.rxrtsoff++;
3459 }
3460 }
3461
3462 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003463 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464}
3465
3466/*****************************************************************************/
3467
3468/*
3469 * Send a flow control character...
3470 */
3471
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003472static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473{
3474 struct tty_struct *tty;
3475 unsigned long flags;
3476
Jiri Slabya0564e12006-12-08 02:38:37 -08003477 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478
Jiri Slaby615e4a72006-12-08 02:38:38 -08003479 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 return;
3481 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003482 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 return;
3484
Alan Coxb65b5b52006-06-27 02:54:05 -07003485 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 BRDENABLE(portp->brdnr, portp->pagenr);
3487 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3488 if (state) {
3489 stl_cd1400ccrwait(portp);
3490 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3491 portp->stats.rxxon++;
3492 stl_cd1400ccrwait(portp);
3493 } else {
3494 stl_cd1400ccrwait(portp);
3495 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3496 portp->stats.rxxoff++;
3497 stl_cd1400ccrwait(portp);
3498 }
3499 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003500 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501}
3502
3503/*****************************************************************************/
3504
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003505static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506{
3507 unsigned long flags;
3508
Jiri Slabya0564e12006-12-08 02:38:37 -08003509 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510
Jiri Slaby615e4a72006-12-08 02:38:38 -08003511 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 return;
3513
Alan Coxb65b5b52006-06-27 02:54:05 -07003514 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 BRDENABLE(portp->brdnr, portp->pagenr);
3516 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3517 stl_cd1400ccrwait(portp);
3518 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3519 stl_cd1400ccrwait(portp);
3520 portp->tx.tail = portp->tx.head;
3521 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003522 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523}
3524
3525/*****************************************************************************/
3526
3527/*
3528 * Return the current state of data flow on this port. This is only
3529 * really interresting when determining if data has fully completed
3530 * transmission or not... This is easy for the cd1400, it accurately
3531 * maintains the busy port flag.
3532 */
3533
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003534static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535{
Jiri Slabya0564e12006-12-08 02:38:37 -08003536 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537
Jiri Slaby615e4a72006-12-08 02:38:38 -08003538 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003539 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
Jesper Juhl014c2542006-01-15 02:37:08 +01003541 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542}
3543
3544/*****************************************************************************/
3545
3546/*
3547 * Interrupt service routine for cd1400 EasyIO boards.
3548 */
3549
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003550static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551{
3552 unsigned char svrtype;
3553
Jiri Slabya0564e12006-12-08 02:38:37 -08003554 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555
Alan Coxb65b5b52006-06-27 02:54:05 -07003556 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 outb(SVRR, iobase);
3558 svrtype = inb(iobase + EREG_DATA);
3559 if (panelp->nrports > 4) {
3560 outb((SVRR + 0x80), iobase);
3561 svrtype |= inb(iobase + EREG_DATA);
3562 }
3563
3564 if (svrtype & SVRR_RX)
3565 stl_cd1400rxisr(panelp, iobase);
3566 else if (svrtype & SVRR_TX)
3567 stl_cd1400txisr(panelp, iobase);
3568 else if (svrtype & SVRR_MDM)
3569 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003570
3571 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572}
3573
3574/*****************************************************************************/
3575
3576/*
3577 * Interrupt service routine for cd1400 panels.
3578 */
3579
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003580static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581{
3582 unsigned char svrtype;
3583
Jiri Slabya0564e12006-12-08 02:38:37 -08003584 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585
3586 outb(SVRR, iobase);
3587 svrtype = inb(iobase + EREG_DATA);
3588 outb((SVRR + 0x80), iobase);
3589 svrtype |= inb(iobase + EREG_DATA);
3590 if (svrtype & SVRR_RX)
3591 stl_cd1400rxisr(panelp, iobase);
3592 else if (svrtype & SVRR_TX)
3593 stl_cd1400txisr(panelp, iobase);
3594 else if (svrtype & SVRR_MDM)
3595 stl_cd1400mdmisr(panelp, iobase);
3596}
3597
3598
3599/*****************************************************************************/
3600
3601/*
3602 * Unfortunately we need to handle breaks in the TX data stream, since
3603 * this is the only way to generate them on the cd1400.
3604 */
3605
Jiri Slaby60be4812006-12-08 02:38:40 -08003606static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607{
3608 if (portp->brklen == 1) {
3609 outb((COR2 + portp->uartaddr), ioaddr);
3610 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3611 (ioaddr + EREG_DATA));
3612 outb((TDR + portp->uartaddr), ioaddr);
3613 outb(ETC_CMD, (ioaddr + EREG_DATA));
3614 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3615 outb((SRER + portp->uartaddr), ioaddr);
3616 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3617 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003618 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 } else if (portp->brklen > 1) {
3620 outb((TDR + portp->uartaddr), ioaddr);
3621 outb(ETC_CMD, (ioaddr + EREG_DATA));
3622 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3623 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003624 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 } else {
3626 outb((COR2 + portp->uartaddr), ioaddr);
3627 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3628 (ioaddr + EREG_DATA));
3629 portp->brklen = 0;
3630 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003631 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632}
3633
3634/*****************************************************************************/
3635
3636/*
3637 * Transmit interrupt handler. This has gotta be fast! Handling TX
3638 * chars is pretty simple, stuff as many as possible from the TX buffer
3639 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3640 * are embedded as commands in the data stream. Oh no, had to use a goto!
3641 * This could be optimized more, will do when I get time...
3642 * In practice it is possible that interrupts are enabled but that the
3643 * port has been hung up. Need to handle not having any TX buffer here,
3644 * this is done by using the side effect that head and tail will also
3645 * be NULL if the buffer has been freed.
3646 */
3647
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003648static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003650 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 int len, stlen;
3652 char *head, *tail;
3653 unsigned char ioack, srer;
3654
Jiri Slabya0564e12006-12-08 02:38:37 -08003655 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656
3657 ioack = inb(ioaddr + EREG_TXACK);
3658 if (((ioack & panelp->ackmask) != 0) ||
3659 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3660 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3661 return;
3662 }
3663 portp = panelp->ports[(ioack >> 3)];
3664
3665/*
3666 * Unfortunately we need to handle breaks in the data stream, since
3667 * this is the only way to generate them on the cd1400. Do it now if
3668 * a break is to be sent.
3669 */
3670 if (portp->brklen != 0)
3671 if (stl_cd1400breakisr(portp, ioaddr))
3672 goto stl_txalldone;
3673
3674 head = portp->tx.head;
3675 tail = portp->tx.tail;
3676 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3677 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3678 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3679 set_bit(ASYI_TXLOW, &portp->istate);
3680 schedule_work(&portp->tqueue);
3681 }
3682
3683 if (len == 0) {
3684 outb((SRER + portp->uartaddr), ioaddr);
3685 srer = inb(ioaddr + EREG_DATA);
3686 if (srer & SRER_TXDATA) {
3687 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3688 } else {
3689 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3690 clear_bit(ASYI_TXBUSY, &portp->istate);
3691 }
3692 outb(srer, (ioaddr + EREG_DATA));
3693 } else {
3694 len = MIN(len, CD1400_TXFIFOSIZE);
3695 portp->stats.txtotal += len;
3696 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
3697 outb((TDR + portp->uartaddr), ioaddr);
3698 outsb((ioaddr + EREG_DATA), tail, stlen);
3699 len -= stlen;
3700 tail += stlen;
3701 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3702 tail = portp->tx.buf;
3703 if (len > 0) {
3704 outsb((ioaddr + EREG_DATA), tail, len);
3705 tail += len;
3706 }
3707 portp->tx.tail = tail;
3708 }
3709
3710stl_txalldone:
3711 outb((EOSRR + portp->uartaddr), ioaddr);
3712 outb(0, (ioaddr + EREG_DATA));
3713}
3714
3715/*****************************************************************************/
3716
3717/*
3718 * Receive character interrupt handler. Determine if we have good chars
3719 * or bad chars and then process appropriately. Good chars are easy
3720 * just shove the lot into the RX buffer and set all status byte to 0.
3721 * If a bad RX char then process as required. This routine needs to be
3722 * fast! In practice it is possible that we get an interrupt on a port
3723 * that is closed. This can happen on hangups - since they completely
3724 * shutdown a port not in user context. Need to handle this case.
3725 */
3726
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003727static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003729 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 struct tty_struct *tty;
3731 unsigned int ioack, len, buflen;
3732 unsigned char status;
3733 char ch;
3734
Jiri Slabya0564e12006-12-08 02:38:37 -08003735 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736
3737 ioack = inb(ioaddr + EREG_RXACK);
3738 if ((ioack & panelp->ackmask) != 0) {
3739 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3740 return;
3741 }
3742 portp = panelp->ports[(ioack >> 3)];
3743 tty = portp->tty;
3744
3745 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3746 outb((RDCR + portp->uartaddr), ioaddr);
3747 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003748 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 len = MIN(len, sizeof(stl_unwanted));
3750 outb((RDSR + portp->uartaddr), ioaddr);
3751 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3752 portp->stats.rxlost += len;
3753 portp->stats.rxtotal += len;
3754 } else {
3755 len = MIN(len, buflen);
3756 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003757 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003759 tty_prepare_flip_string(tty, &ptr, len);
3760 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 tty_schedule_flip(tty);
3762 portp->stats.rxtotal += len;
3763 }
3764 }
3765 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3766 outb((RDSR + portp->uartaddr), ioaddr);
3767 status = inb(ioaddr + EREG_DATA);
3768 ch = inb(ioaddr + EREG_DATA);
3769 if (status & ST_PARITY)
3770 portp->stats.rxparity++;
3771 if (status & ST_FRAMING)
3772 portp->stats.rxframing++;
3773 if (status & ST_OVERRUN)
3774 portp->stats.rxoverrun++;
3775 if (status & ST_BREAK)
3776 portp->stats.rxbreaks++;
3777 if (status & ST_SCHARMASK) {
3778 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3779 portp->stats.txxon++;
3780 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3781 portp->stats.txxoff++;
3782 goto stl_rxalldone;
3783 }
Alan Cox33f0f882006-01-09 20:54:13 -08003784 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 if (portp->rxmarkmsk & status) {
3786 if (status & ST_BREAK) {
3787 status = TTY_BREAK;
3788 if (portp->flags & ASYNC_SAK) {
3789 do_SAK(tty);
3790 BRDENABLE(portp->brdnr, portp->pagenr);
3791 }
3792 } else if (status & ST_PARITY) {
3793 status = TTY_PARITY;
3794 } else if (status & ST_FRAMING) {
3795 status = TTY_FRAME;
3796 } else if(status & ST_OVERRUN) {
3797 status = TTY_OVERRUN;
3798 } else {
3799 status = 0;
3800 }
3801 } else {
3802 status = 0;
3803 }
Alan Cox33f0f882006-01-09 20:54:13 -08003804 tty_insert_flip_char(tty, ch, status);
3805 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 }
3807 } else {
3808 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3809 return;
3810 }
3811
3812stl_rxalldone:
3813 outb((EOSRR + portp->uartaddr), ioaddr);
3814 outb(0, (ioaddr + EREG_DATA));
3815}
3816
3817/*****************************************************************************/
3818
3819/*
3820 * Modem interrupt handler. The is called when the modem signal line
3821 * (DCD) has changed state. Leave most of the work to the off-level
3822 * processing routine.
3823 */
3824
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003825static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003827 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 unsigned int ioack;
3829 unsigned char misr;
3830
Jiri Slabya0564e12006-12-08 02:38:37 -08003831 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832
3833 ioack = inb(ioaddr + EREG_MDACK);
3834 if (((ioack & panelp->ackmask) != 0) ||
3835 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3836 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3837 return;
3838 }
3839 portp = panelp->ports[(ioack >> 3)];
3840
3841 outb((MISR + portp->uartaddr), ioaddr);
3842 misr = inb(ioaddr + EREG_DATA);
3843 if (misr & MISR_DCD) {
3844 set_bit(ASYI_DCDCHANGE, &portp->istate);
3845 schedule_work(&portp->tqueue);
3846 portp->stats.modem++;
3847 }
3848
3849 outb((EOSRR + portp->uartaddr), ioaddr);
3850 outb(0, (ioaddr + EREG_DATA));
3851}
3852
3853/*****************************************************************************/
3854/* SC26198 HARDWARE FUNCTIONS */
3855/*****************************************************************************/
3856
3857/*
3858 * These functions get/set/update the registers of the sc26198 UARTs.
3859 * Access to the sc26198 registers is via an address/data io port pair.
3860 * (Maybe should make this inline...)
3861 */
3862
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003863static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864{
3865 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003866 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867}
3868
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003869static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870{
3871 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3872 outb(value, (portp->ioaddr + XP_DATA));
3873}
3874
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003875static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876{
3877 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3878 if (inb(portp->ioaddr + XP_DATA) != value) {
3879 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003880 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003882 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883}
3884
3885/*****************************************************************************/
3886
3887/*
3888 * Functions to get and set the sc26198 global registers.
3889 */
3890
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003891static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892{
3893 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003894 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895}
3896
3897#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003898static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899{
3900 outb(regnr, (portp->ioaddr + XP_ADDR));
3901 outb(value, (portp->ioaddr + XP_DATA));
3902}
3903#endif
3904
3905/*****************************************************************************/
3906
3907/*
3908 * Inbitialize the UARTs in a panel. We don't care what sort of board
3909 * these ports are on - since the port io registers are almost
3910 * identical when dealing with ports.
3911 */
3912
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003913static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914{
3915 int chipmask, i;
3916 int nrchips, ioaddr;
3917
Jiri Slabya0564e12006-12-08 02:38:37 -08003918 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919
3920 BRDENABLE(panelp->brdnr, panelp->pagenr);
3921
3922/*
3923 * Check that each chip is present and started up OK.
3924 */
3925 chipmask = 0;
3926 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3927 if (brdp->brdtype == BRD_ECHPCI)
3928 outb(panelp->pagenr, brdp->ioctrl);
3929
3930 for (i = 0; (i < nrchips); i++) {
3931 ioaddr = panelp->iobase + (i * 4);
3932 outb(SCCR, (ioaddr + XP_ADDR));
3933 outb(CR_RESETALL, (ioaddr + XP_DATA));
3934 outb(TSTR, (ioaddr + XP_ADDR));
3935 if (inb(ioaddr + XP_DATA) != 0) {
3936 printk("STALLION: sc26198 not responding, "
3937 "brd=%d panel=%d chip=%d\n",
3938 panelp->brdnr, panelp->panelnr, i);
3939 continue;
3940 }
3941 chipmask |= (0x1 << i);
3942 outb(GCCR, (ioaddr + XP_ADDR));
3943 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3944 outb(WDTRCR, (ioaddr + XP_ADDR));
3945 outb(0xff, (ioaddr + XP_DATA));
3946 }
3947
3948 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003949 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950}
3951
3952/*****************************************************************************/
3953
3954/*
3955 * Initialize hardware specific port registers.
3956 */
3957
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003958static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959{
Jiri Slabya0564e12006-12-08 02:38:37 -08003960 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3961 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
Jiri Slaby615e4a72006-12-08 02:38:38 -08003963 if ((brdp == NULL) || (panelp == NULL) ||
3964 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 return;
3966
3967 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3968 portp->uartaddr = (portp->portnr & 0x07) << 4;
3969 portp->pagenr = panelp->pagenr;
3970 portp->hwid = 0x1;
3971
3972 BRDENABLE(portp->brdnr, portp->pagenr);
3973 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3974 BRDDISABLE(portp->brdnr);
3975}
3976
3977/*****************************************************************************/
3978
3979/*
3980 * Set up the sc26198 registers for a port based on the termios port
3981 * settings.
3982 */
3983
Alan Cox606d0992006-12-08 02:38:45 -08003984static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003986 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987 unsigned long flags;
3988 unsigned int baudrate;
3989 unsigned char mr0, mr1, mr2, clk;
3990 unsigned char imron, imroff, iopr, ipr;
3991
3992 mr0 = 0;
3993 mr1 = 0;
3994 mr2 = 0;
3995 clk = 0;
3996 iopr = 0;
3997 imron = 0;
3998 imroff = 0;
3999
4000 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08004001 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 return;
4003
4004/*
4005 * Set up the RX char ignore mask with those RX error types we
4006 * can ignore.
4007 */
4008 portp->rxignoremsk = 0;
4009 if (tiosp->c_iflag & IGNPAR)
4010 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
4011 SR_RXOVERRUN);
4012 if (tiosp->c_iflag & IGNBRK)
4013 portp->rxignoremsk |= SR_RXBREAK;
4014
4015 portp->rxmarkmsk = SR_RXOVERRUN;
4016 if (tiosp->c_iflag & (INPCK | PARMRK))
4017 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
4018 if (tiosp->c_iflag & BRKINT)
4019 portp->rxmarkmsk |= SR_RXBREAK;
4020
4021/*
4022 * Go through the char size, parity and stop bits and set all the
4023 * option register appropriately.
4024 */
4025 switch (tiosp->c_cflag & CSIZE) {
4026 case CS5:
4027 mr1 |= MR1_CS5;
4028 break;
4029 case CS6:
4030 mr1 |= MR1_CS6;
4031 break;
4032 case CS7:
4033 mr1 |= MR1_CS7;
4034 break;
4035 default:
4036 mr1 |= MR1_CS8;
4037 break;
4038 }
4039
4040 if (tiosp->c_cflag & CSTOPB)
4041 mr2 |= MR2_STOP2;
4042 else
4043 mr2 |= MR2_STOP1;
4044
4045 if (tiosp->c_cflag & PARENB) {
4046 if (tiosp->c_cflag & PARODD)
4047 mr1 |= (MR1_PARENB | MR1_PARODD);
4048 else
4049 mr1 |= (MR1_PARENB | MR1_PAREVEN);
4050 } else {
4051 mr1 |= MR1_PARNONE;
4052 }
4053
4054 mr1 |= MR1_ERRBLOCK;
4055
4056/*
4057 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
4058 * space for hardware flow control and the like. This should be set to
4059 * VMIN.
4060 */
4061 mr2 |= MR2_RXFIFOHALF;
4062
4063/*
4064 * Calculate the baud rate timers. For now we will just assume that
4065 * the input and output baud are the same. The sc26198 has a fixed
4066 * baud rate table, so only discrete baud rates possible.
4067 */
4068 baudrate = tiosp->c_cflag & CBAUD;
4069 if (baudrate & CBAUDEX) {
4070 baudrate &= ~CBAUDEX;
4071 if ((baudrate < 1) || (baudrate > 4))
4072 tiosp->c_cflag &= ~CBAUDEX;
4073 else
4074 baudrate += 15;
4075 }
4076 baudrate = stl_baudrates[baudrate];
4077 if ((tiosp->c_cflag & CBAUD) == B38400) {
4078 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
4079 baudrate = 57600;
4080 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
4081 baudrate = 115200;
4082 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
4083 baudrate = 230400;
4084 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
4085 baudrate = 460800;
4086 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
4087 baudrate = (portp->baud_base / portp->custom_divisor);
4088 }
4089 if (baudrate > STL_SC26198MAXBAUD)
4090 baudrate = STL_SC26198MAXBAUD;
4091
4092 if (baudrate > 0) {
4093 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
4094 if (baudrate <= sc26198_baudtable[clk])
4095 break;
4096 }
4097 }
4098
4099/*
4100 * Check what form of modem signaling is required and set it up.
4101 */
4102 if (tiosp->c_cflag & CLOCAL) {
4103 portp->flags &= ~ASYNC_CHECK_CD;
4104 } else {
4105 iopr |= IOPR_DCDCOS;
4106 imron |= IR_IOPORT;
4107 portp->flags |= ASYNC_CHECK_CD;
4108 }
4109
4110/*
4111 * Setup sc26198 enhanced modes if we can. In particular we want to
4112 * handle as much of the flow control as possible automatically. As
4113 * well as saving a few CPU cycles it will also greatly improve flow
4114 * control reliability.
4115 */
4116 if (tiosp->c_iflag & IXON) {
4117 mr0 |= MR0_SWFTX | MR0_SWFT;
4118 imron |= IR_XONXOFF;
4119 } else {
4120 imroff |= IR_XONXOFF;
4121 }
4122 if (tiosp->c_iflag & IXOFF)
4123 mr0 |= MR0_SWFRX;
4124
4125 if (tiosp->c_cflag & CRTSCTS) {
4126 mr2 |= MR2_AUTOCTS;
4127 mr1 |= MR1_AUTORTS;
4128 }
4129
4130/*
4131 * All sc26198 register values calculated so go through and set
4132 * them all up.
4133 */
4134
Jiri Slabya0564e12006-12-08 02:38:37 -08004135 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08004137 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
4138 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
4139 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4141 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142
Alan Coxb65b5b52006-06-27 02:54:05 -07004143 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 BRDENABLE(portp->brdnr, portp->pagenr);
4145 stl_sc26198setreg(portp, IMR, 0);
4146 stl_sc26198updatereg(portp, MR0, mr0);
4147 stl_sc26198updatereg(portp, MR1, mr1);
4148 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4149 stl_sc26198updatereg(portp, MR2, mr2);
4150 stl_sc26198updatereg(portp, IOPIOR,
4151 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4152
4153 if (baudrate > 0) {
4154 stl_sc26198setreg(portp, TXCSR, clk);
4155 stl_sc26198setreg(portp, RXCSR, clk);
4156 }
4157
4158 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4159 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4160
4161 ipr = stl_sc26198getreg(portp, IPR);
4162 if (ipr & IPR_DCD)
4163 portp->sigs &= ~TIOCM_CD;
4164 else
4165 portp->sigs |= TIOCM_CD;
4166
4167 portp->imr = (portp->imr & ~imroff) | imron;
4168 stl_sc26198setreg(portp, IMR, portp->imr);
4169 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004170 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171}
4172
4173/*****************************************************************************/
4174
4175/*
4176 * Set the state of the DTR and RTS signals.
4177 */
4178
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004179static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180{
4181 unsigned char iopioron, iopioroff;
4182 unsigned long flags;
4183
Jiri Slabya0564e12006-12-08 02:38:37 -08004184 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4185 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186
4187 iopioron = 0;
4188 iopioroff = 0;
4189 if (dtr == 0)
4190 iopioroff |= IPR_DTR;
4191 else if (dtr > 0)
4192 iopioron |= IPR_DTR;
4193 if (rts == 0)
4194 iopioroff |= IPR_RTS;
4195 else if (rts > 0)
4196 iopioron |= IPR_RTS;
4197
Alan Coxb65b5b52006-06-27 02:54:05 -07004198 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 BRDENABLE(portp->brdnr, portp->pagenr);
4200 stl_sc26198setreg(portp, IOPIOR,
4201 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4202 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004203 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204}
4205
4206/*****************************************************************************/
4207
4208/*
4209 * Return the state of the signals.
4210 */
4211
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004212static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213{
4214 unsigned char ipr;
4215 unsigned long flags;
4216 int sigs;
4217
Jiri Slabya0564e12006-12-08 02:38:37 -08004218 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219
Alan Coxb65b5b52006-06-27 02:54:05 -07004220 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 BRDENABLE(portp->brdnr, portp->pagenr);
4222 ipr = stl_sc26198getreg(portp, IPR);
4223 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004224 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225
4226 sigs = 0;
4227 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4228 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4229 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4230 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4231 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004232 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233}
4234
4235/*****************************************************************************/
4236
4237/*
4238 * Enable/Disable the Transmitter and/or Receiver.
4239 */
4240
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004241static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242{
4243 unsigned char ccr;
4244 unsigned long flags;
4245
Jiri Slabya0564e12006-12-08 02:38:37 -08004246 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247
4248 ccr = portp->crenable;
4249 if (tx == 0)
4250 ccr &= ~CR_TXENABLE;
4251 else if (tx > 0)
4252 ccr |= CR_TXENABLE;
4253 if (rx == 0)
4254 ccr &= ~CR_RXENABLE;
4255 else if (rx > 0)
4256 ccr |= CR_RXENABLE;
4257
Alan Coxb65b5b52006-06-27 02:54:05 -07004258 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 BRDENABLE(portp->brdnr, portp->pagenr);
4260 stl_sc26198setreg(portp, SCCR, ccr);
4261 BRDDISABLE(portp->brdnr);
4262 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004263 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264}
4265
4266/*****************************************************************************/
4267
4268/*
4269 * Start/stop the Transmitter and/or Receiver.
4270 */
4271
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004272static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273{
4274 unsigned char imr;
4275 unsigned long flags;
4276
Jiri Slabya0564e12006-12-08 02:38:37 -08004277 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278
4279 imr = portp->imr;
4280 if (tx == 0)
4281 imr &= ~IR_TXRDY;
4282 else if (tx == 1)
4283 imr |= IR_TXRDY;
4284 if (rx == 0)
4285 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4286 else if (rx > 0)
4287 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4288
Alan Coxb65b5b52006-06-27 02:54:05 -07004289 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290 BRDENABLE(portp->brdnr, portp->pagenr);
4291 stl_sc26198setreg(portp, IMR, imr);
4292 BRDDISABLE(portp->brdnr);
4293 portp->imr = imr;
4294 if (tx > 0)
4295 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004296 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297}
4298
4299/*****************************************************************************/
4300
4301/*
4302 * Disable all interrupts from this port.
4303 */
4304
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004305static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306{
4307 unsigned long flags;
4308
Jiri Slabya0564e12006-12-08 02:38:37 -08004309 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310
Alan Coxb65b5b52006-06-27 02:54:05 -07004311 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 BRDENABLE(portp->brdnr, portp->pagenr);
4313 portp->imr = 0;
4314 stl_sc26198setreg(portp, IMR, 0);
4315 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004316 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317}
4318
4319/*****************************************************************************/
4320
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004321static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322{
4323 unsigned long flags;
4324
Jiri Slabya0564e12006-12-08 02:38:37 -08004325 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326
Alan Coxb65b5b52006-06-27 02:54:05 -07004327 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328 BRDENABLE(portp->brdnr, portp->pagenr);
4329 if (len == 1) {
4330 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4331 portp->stats.txbreaks++;
4332 } else {
4333 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4334 }
4335 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004336 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337}
4338
4339/*****************************************************************************/
4340
4341/*
4342 * Take flow control actions...
4343 */
4344
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004345static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346{
4347 struct tty_struct *tty;
4348 unsigned long flags;
4349 unsigned char mr0;
4350
Jiri Slabya0564e12006-12-08 02:38:37 -08004351 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
Jiri Slaby615e4a72006-12-08 02:38:38 -08004353 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 return;
4355 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004356 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 return;
4358
Alan Coxb65b5b52006-06-27 02:54:05 -07004359 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 BRDENABLE(portp->brdnr, portp->pagenr);
4361
4362 if (state) {
4363 if (tty->termios->c_iflag & IXOFF) {
4364 mr0 = stl_sc26198getreg(portp, MR0);
4365 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4366 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4367 mr0 |= MR0_SWFRX;
4368 portp->stats.rxxon++;
4369 stl_sc26198wait(portp);
4370 stl_sc26198setreg(portp, MR0, mr0);
4371 }
4372/*
4373 * Question: should we return RTS to what it was before? It may
4374 * have been set by an ioctl... Suppose not, since if you have
4375 * hardware flow control set then it is pretty silly to go and
4376 * set the RTS line by hand.
4377 */
4378 if (tty->termios->c_cflag & CRTSCTS) {
4379 stl_sc26198setreg(portp, MR1,
4380 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4381 stl_sc26198setreg(portp, IOPIOR,
4382 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4383 portp->stats.rxrtson++;
4384 }
4385 } else {
4386 if (tty->termios->c_iflag & IXOFF) {
4387 mr0 = stl_sc26198getreg(portp, MR0);
4388 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4389 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4390 mr0 &= ~MR0_SWFRX;
4391 portp->stats.rxxoff++;
4392 stl_sc26198wait(portp);
4393 stl_sc26198setreg(portp, MR0, mr0);
4394 }
4395 if (tty->termios->c_cflag & CRTSCTS) {
4396 stl_sc26198setreg(portp, MR1,
4397 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4398 stl_sc26198setreg(portp, IOPIOR,
4399 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4400 portp->stats.rxrtsoff++;
4401 }
4402 }
4403
4404 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004405 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406}
4407
4408/*****************************************************************************/
4409
4410/*
4411 * Send a flow control character.
4412 */
4413
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004414static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415{
4416 struct tty_struct *tty;
4417 unsigned long flags;
4418 unsigned char mr0;
4419
Jiri Slabya0564e12006-12-08 02:38:37 -08004420 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421
Jiri Slaby615e4a72006-12-08 02:38:38 -08004422 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423 return;
4424 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004425 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426 return;
4427
Alan Coxb65b5b52006-06-27 02:54:05 -07004428 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 BRDENABLE(portp->brdnr, portp->pagenr);
4430 if (state) {
4431 mr0 = stl_sc26198getreg(portp, MR0);
4432 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4433 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4434 mr0 |= MR0_SWFRX;
4435 portp->stats.rxxon++;
4436 stl_sc26198wait(portp);
4437 stl_sc26198setreg(portp, MR0, mr0);
4438 } else {
4439 mr0 = stl_sc26198getreg(portp, MR0);
4440 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4441 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4442 mr0 &= ~MR0_SWFRX;
4443 portp->stats.rxxoff++;
4444 stl_sc26198wait(portp);
4445 stl_sc26198setreg(portp, MR0, mr0);
4446 }
4447 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004448 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449}
4450
4451/*****************************************************************************/
4452
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004453static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454{
4455 unsigned long flags;
4456
Jiri Slabya0564e12006-12-08 02:38:37 -08004457 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458
Jiri Slaby615e4a72006-12-08 02:38:38 -08004459 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460 return;
4461
Alan Coxb65b5b52006-06-27 02:54:05 -07004462 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463 BRDENABLE(portp->brdnr, portp->pagenr);
4464 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4465 stl_sc26198setreg(portp, SCCR, portp->crenable);
4466 BRDDISABLE(portp->brdnr);
4467 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004468 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469}
4470
4471/*****************************************************************************/
4472
4473/*
4474 * Return the current state of data flow on this port. This is only
4475 * really interresting when determining if data has fully completed
4476 * transmission or not... The sc26198 interrupt scheme cannot
4477 * determine when all data has actually drained, so we need to
4478 * check the port statusy register to be sure.
4479 */
4480
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004481static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482{
4483 unsigned long flags;
4484 unsigned char sr;
4485
Jiri Slabya0564e12006-12-08 02:38:37 -08004486 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
Jiri Slaby615e4a72006-12-08 02:38:38 -08004488 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004489 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004491 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492
Alan Coxb65b5b52006-06-27 02:54:05 -07004493 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 BRDENABLE(portp->brdnr, portp->pagenr);
4495 sr = stl_sc26198getreg(portp, SR);
4496 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004497 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498
Jesper Juhl014c2542006-01-15 02:37:08 +01004499 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500}
4501
4502/*****************************************************************************/
4503
4504/*
4505 * Delay for a small amount of time, to give the sc26198 a chance
4506 * to process a command...
4507 */
4508
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004509static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510{
4511 int i;
4512
Jiri Slabya0564e12006-12-08 02:38:37 -08004513 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514
Jiri Slaby615e4a72006-12-08 02:38:38 -08004515 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516 return;
4517
4518 for (i = 0; (i < 20); i++)
4519 stl_sc26198getglobreg(portp, TSTR);
4520}
4521
4522/*****************************************************************************/
4523
4524/*
4525 * If we are TX flow controlled and in IXANY mode then we may
4526 * need to unflow control here. We gotta do this because of the
4527 * automatic flow control modes of the sc26198.
4528 */
4529
Jiri Slaby60be4812006-12-08 02:38:40 -08004530static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531{
4532 unsigned char mr0;
4533
4534 mr0 = stl_sc26198getreg(portp, MR0);
4535 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4536 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4537 stl_sc26198wait(portp);
4538 stl_sc26198setreg(portp, MR0, mr0);
4539 clear_bit(ASYI_TXFLOWED, &portp->istate);
4540}
4541
4542/*****************************************************************************/
4543
4544/*
4545 * Interrupt service routine for sc26198 panels.
4546 */
4547
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004548static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004550 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 unsigned int iack;
4552
Alan Coxb65b5b52006-06-27 02:54:05 -07004553 spin_lock(&brd_lock);
4554
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555/*
4556 * Work around bug in sc26198 chip... Cannot have A6 address
4557 * line of UART high, else iack will be returned as 0.
4558 */
4559 outb(0, (iobase + 1));
4560
4561 iack = inb(iobase + XP_IACK);
4562 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4563
4564 if (iack & IVR_RXDATA)
4565 stl_sc26198rxisr(portp, iack);
4566 else if (iack & IVR_TXDATA)
4567 stl_sc26198txisr(portp);
4568 else
4569 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004570
4571 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572}
4573
4574/*****************************************************************************/
4575
4576/*
4577 * Transmit interrupt handler. This has gotta be fast! Handling TX
4578 * chars is pretty simple, stuff as many as possible from the TX buffer
4579 * into the sc26198 FIFO.
4580 * In practice it is possible that interrupts are enabled but that the
4581 * port has been hung up. Need to handle not having any TX buffer here,
4582 * this is done by using the side effect that head and tail will also
4583 * be NULL if the buffer has been freed.
4584 */
4585
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004586static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587{
4588 unsigned int ioaddr;
4589 unsigned char mr0;
4590 int len, stlen;
4591 char *head, *tail;
4592
Jiri Slabya0564e12006-12-08 02:38:37 -08004593 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594
4595 ioaddr = portp->ioaddr;
4596 head = portp->tx.head;
4597 tail = portp->tx.tail;
4598 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4599 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4600 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4601 set_bit(ASYI_TXLOW, &portp->istate);
4602 schedule_work(&portp->tqueue);
4603 }
4604
4605 if (len == 0) {
4606 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4607 mr0 = inb(ioaddr + XP_DATA);
4608 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4609 portp->imr &= ~IR_TXRDY;
4610 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4611 outb(portp->imr, (ioaddr + XP_DATA));
4612 clear_bit(ASYI_TXBUSY, &portp->istate);
4613 } else {
4614 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4615 outb(mr0, (ioaddr + XP_DATA));
4616 }
4617 } else {
4618 len = MIN(len, SC26198_TXFIFOSIZE);
4619 portp->stats.txtotal += len;
4620 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
4621 outb(GTXFIFO, (ioaddr + XP_ADDR));
4622 outsb((ioaddr + XP_DATA), tail, stlen);
4623 len -= stlen;
4624 tail += stlen;
4625 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4626 tail = portp->tx.buf;
4627 if (len > 0) {
4628 outsb((ioaddr + XP_DATA), tail, len);
4629 tail += len;
4630 }
4631 portp->tx.tail = tail;
4632 }
4633}
4634
4635/*****************************************************************************/
4636
4637/*
4638 * Receive character interrupt handler. Determine if we have good chars
4639 * or bad chars and then process appropriately. Good chars are easy
4640 * just shove the lot into the RX buffer and set all status byte to 0.
4641 * If a bad RX char then process as required. This routine needs to be
4642 * fast! In practice it is possible that we get an interrupt on a port
4643 * that is closed. This can happen on hangups - since they completely
4644 * shutdown a port not in user context. Need to handle this case.
4645 */
4646
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004647static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648{
4649 struct tty_struct *tty;
4650 unsigned int len, buflen, ioaddr;
4651
Jiri Slabya0564e12006-12-08 02:38:37 -08004652 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653
4654 tty = portp->tty;
4655 ioaddr = portp->ioaddr;
4656 outb(GIBCR, (ioaddr + XP_ADDR));
4657 len = inb(ioaddr + XP_DATA) + 1;
4658
4659 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004660 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004661 len = MIN(len, sizeof(stl_unwanted));
4662 outb(GRXFIFO, (ioaddr + XP_ADDR));
4663 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4664 portp->stats.rxlost += len;
4665 portp->stats.rxtotal += len;
4666 } else {
4667 len = MIN(len, buflen);
4668 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004669 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004671 tty_prepare_flip_string(tty, &ptr, len);
4672 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673 tty_schedule_flip(tty);
4674 portp->stats.rxtotal += len;
4675 }
4676 }
4677 } else {
4678 stl_sc26198rxbadchars(portp);
4679 }
4680
4681/*
4682 * If we are TX flow controlled and in IXANY mode then we may need
4683 * to unflow control here. We gotta do this because of the automatic
4684 * flow control modes of the sc26198.
4685 */
4686 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004687 if ((tty != NULL) &&
4688 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004689 (tty->termios->c_iflag & IXANY)) {
4690 stl_sc26198txunflow(portp, tty);
4691 }
4692 }
4693}
4694
4695/*****************************************************************************/
4696
4697/*
4698 * Process an RX bad character.
4699 */
4700
Jiri Slaby60be4812006-12-08 02:38:40 -08004701static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702{
4703 struct tty_struct *tty;
4704 unsigned int ioaddr;
4705
4706 tty = portp->tty;
4707 ioaddr = portp->ioaddr;
4708
4709 if (status & SR_RXPARITY)
4710 portp->stats.rxparity++;
4711 if (status & SR_RXFRAMING)
4712 portp->stats.rxframing++;
4713 if (status & SR_RXOVERRUN)
4714 portp->stats.rxoverrun++;
4715 if (status & SR_RXBREAK)
4716 portp->stats.rxbreaks++;
4717
Jiri Slaby615e4a72006-12-08 02:38:38 -08004718 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719 ((portp->rxignoremsk & status) == 0)) {
4720 if (portp->rxmarkmsk & status) {
4721 if (status & SR_RXBREAK) {
4722 status = TTY_BREAK;
4723 if (portp->flags & ASYNC_SAK) {
4724 do_SAK(tty);
4725 BRDENABLE(portp->brdnr, portp->pagenr);
4726 }
4727 } else if (status & SR_RXPARITY) {
4728 status = TTY_PARITY;
4729 } else if (status & SR_RXFRAMING) {
4730 status = TTY_FRAME;
4731 } else if(status & SR_RXOVERRUN) {
4732 status = TTY_OVERRUN;
4733 } else {
4734 status = 0;
4735 }
4736 } else {
4737 status = 0;
4738 }
4739
Alan Cox33f0f882006-01-09 20:54:13 -08004740 tty_insert_flip_char(tty, ch, status);
4741 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742
4743 if (status == 0)
4744 portp->stats.rxtotal++;
4745 }
4746}
4747
4748/*****************************************************************************/
4749
4750/*
4751 * Process all characters in the RX FIFO of the UART. Check all char
4752 * status bytes as well, and process as required. We need to check
4753 * all bytes in the FIFO, in case some more enter the FIFO while we
4754 * are here. To get the exact character error type we need to switch
4755 * into CHAR error mode (that is why we need to make sure we empty
4756 * the FIFO).
4757 */
4758
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004759static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760{
4761 unsigned char status, mr1;
4762 char ch;
4763
4764/*
4765 * To get the precise error type for each character we must switch
4766 * back into CHAR error mode.
4767 */
4768 mr1 = stl_sc26198getreg(portp, MR1);
4769 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4770
4771 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4772 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4773 ch = stl_sc26198getreg(portp, RXFIFO);
4774 stl_sc26198rxbadch(portp, status, ch);
4775 }
4776
4777/*
4778 * To get correct interrupt class we must switch back into BLOCK
4779 * error mode.
4780 */
4781 stl_sc26198setreg(portp, MR1, mr1);
4782}
4783
4784/*****************************************************************************/
4785
4786/*
4787 * Other interrupt handler. This includes modem signals, flow
4788 * control actions, etc. Most stuff is left to off-level interrupt
4789 * processing time.
4790 */
4791
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004792static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793{
4794 unsigned char cir, ipr, xisr;
4795
Jiri Slabya0564e12006-12-08 02:38:37 -08004796 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797
4798 cir = stl_sc26198getglobreg(portp, CIR);
4799
4800 switch (cir & CIR_SUBTYPEMASK) {
4801 case CIR_SUBCOS:
4802 ipr = stl_sc26198getreg(portp, IPR);
4803 if (ipr & IPR_DCDCHANGE) {
4804 set_bit(ASYI_DCDCHANGE, &portp->istate);
4805 schedule_work(&portp->tqueue);
4806 portp->stats.modem++;
4807 }
4808 break;
4809 case CIR_SUBXONXOFF:
4810 xisr = stl_sc26198getreg(portp, XISR);
4811 if (xisr & XISR_RXXONGOT) {
4812 set_bit(ASYI_TXFLOWED, &portp->istate);
4813 portp->stats.txxoff++;
4814 }
4815 if (xisr & XISR_RXXOFFGOT) {
4816 clear_bit(ASYI_TXFLOWED, &portp->istate);
4817 portp->stats.txxon++;
4818 }
4819 break;
4820 case CIR_SUBBREAK:
4821 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4822 stl_sc26198rxbadchars(portp);
4823 break;
4824 default:
4825 break;
4826 }
4827}
4828
Jiri Slaby23b85a12006-12-08 02:38:40 -08004829/*
4830 * Loadable module initialization stuff.
4831 */
4832static int __init stallion_module_init(void)
4833{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004834 unsigned int i, retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004835
4836 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4837
4838 spin_lock_init(&stallion_lock);
4839 spin_lock_init(&brd_lock);
4840
4841 stl_initbrds();
4842
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004843 retval = pci_register_driver(&stl_pcidriver);
4844 if (retval)
4845 goto err;
4846
Jiri Slaby23b85a12006-12-08 02:38:40 -08004847 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4848 if (!stl_serial)
4849 return -1;
4850
4851/*
4852 * Set up a character driver for per board stuff. This is mainly used
4853 * to do stats ioctls on the ports.
4854 */
4855 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4856 printk("STALLION: failed to register serial board device\n");
4857
4858 stallion_class = class_create(THIS_MODULE, "staliomem");
4859 for (i = 0; i < 4; i++)
4860 class_device_create(stallion_class, NULL,
4861 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4862 "staliomem%d", i);
4863
4864 stl_serial->owner = THIS_MODULE;
4865 stl_serial->driver_name = stl_drvname;
4866 stl_serial->name = "ttyE";
4867 stl_serial->major = STL_SERIALMAJOR;
4868 stl_serial->minor_start = 0;
4869 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4870 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4871 stl_serial->init_termios = stl_deftermios;
4872 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4873 tty_set_operations(stl_serial, &stl_ops);
4874
4875 if (tty_register_driver(stl_serial)) {
4876 put_tty_driver(stl_serial);
4877 printk("STALLION: failed to register serial driver\n");
4878 return -1;
4879 }
4880
4881 return 0;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004882err:
4883 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004884}
4885
4886static void __exit stallion_module_exit(void)
4887{
4888 struct stlbrd *brdp;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004889 int i;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004890
4891 pr_debug("cleanup_module()\n");
4892
4893 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4894 stl_drvversion);
4895
4896/*
4897 * Free up all allocated resources used by the ports. This includes
4898 * memory and interrupts. As part of this process we will also do
4899 * a hangup on every open port - to try to flush out any processes
4900 * hanging onto ports.
4901 */
4902 i = tty_unregister_driver(stl_serial);
4903 put_tty_driver(stl_serial);
4904 if (i) {
4905 printk("STALLION: failed to un-register tty driver, "
4906 "errno=%d\n", -i);
4907 return;
4908 }
4909 for (i = 0; i < 4; i++)
4910 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4911 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4912 printk("STALLION: failed to un-register serial memory device, "
4913 "errno=%d\n", -i);
4914 class_destroy(stallion_class);
4915
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004916 pci_unregister_driver(&stl_pcidriver);
4917
Jiri Slaby23b85a12006-12-08 02:38:40 -08004918 for (i = 0; (i < stl_nrbrds); i++) {
4919 if ((brdp = stl_brds[i]) == NULL)
4920 continue;
4921
4922 free_irq(brdp->irq, brdp);
4923
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004924 stl_cleanup_panels(brdp);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004925
4926 release_region(brdp->ioaddr1, brdp->iosize1);
4927 if (brdp->iosize2 > 0)
4928 release_region(brdp->ioaddr2, brdp->iosize2);
4929
4930 kfree(brdp);
4931 stl_brds[i] = NULL;
4932 }
4933}
4934
4935module_init(stallion_module_init);
4936module_exit(stallion_module_exit);
4937
4938MODULE_AUTHOR("Greg Ungerer");
4939MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4940MODULE_LICENSE("GPL");