blob: 12aecdaf61ec083933957611b8294c830a51dd8b [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>
Jiri Slaby843b5682006-12-08 02:39:12 -080044#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46#include <asm/io.h>
47#include <asm/uaccess.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51/*****************************************************************************/
52
53/*
54 * Define different board types. Use the standard Stallion "assigned"
55 * board numbers. Boards supported in this driver are abbreviated as
56 * EIO = EasyIO and ECH = EasyConnection 8/32.
57 */
58#define BRD_EASYIO 20
59#define BRD_ECH 21
60#define BRD_ECHMC 22
61#define BRD_ECHPCI 26
62#define BRD_ECH64PCI 27
63#define BRD_EASYIOPCI 28
64
Jiri Slaby843b5682006-12-08 02:39:12 -080065struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080066 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 int ioaddr1;
68 int ioaddr2;
69 unsigned long memaddr;
70 int irq;
71 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072};
73
Jiri Slaby843b5682006-12-08 02:39:12 -080074static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76/*****************************************************************************/
77
78/*
79 * Define some important driver characteristics. Device major numbers
80 * allocated as per Linux Device Registry.
81 */
82#ifndef STL_SIOMEMMAJOR
83#define STL_SIOMEMMAJOR 28
84#endif
85#ifndef STL_SERIALMAJOR
86#define STL_SERIALMAJOR 24
87#endif
88#ifndef STL_CALLOUTMAJOR
89#define STL_CALLOUTMAJOR 25
90#endif
91
92/*
93 * Set the TX buffer size. Bigger is better, but we don't want
94 * to chew too much memory with buffers!
95 */
96#define STL_TXBUFLOW 512
97#define STL_TXBUFSIZE 4096
98
99/*****************************************************************************/
100
101/*
102 * Define our local driver identity first. Set up stuff to deal with
103 * all the local structures required by a serial tty driver.
104 */
105static char *stl_drvtitle = "Stallion Multiport Serial Driver";
106static char *stl_drvname = "stallion";
107static char *stl_drvversion = "5.6.0";
108
109static struct tty_driver *stl_serial;
110
111/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * Define a local default termios struct. All ports will be created
113 * with this termios initially. Basically all it defines is a raw port
114 * at 9600, 8 data bits, 1 stop bit.
115 */
Alan Cox606d0992006-12-08 02:38:45 -0800116static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
118 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800119 .c_ispeed = 9600,
120 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121};
122
123/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 * Define global place to put buffer overflow characters.
125 */
126static char stl_unwanted[SC26198_RXFIFOSIZE];
127
128/*****************************************************************************/
129
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800130static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800131static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Alan Cox31f35932009-01-02 13:45:05 +0000133static const struct tty_port_operations stl_port_ops;
134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135/*
136 * Per board state flags. Used with the state field of the board struct.
137 * Not really much here!
138 */
139#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800140#define STL_PROBED 0x2
141
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143/*
144 * Define the port structure istate flags. These set of flags are
145 * modified at interrupt time - so setting and reseting them needs
146 * to be atomic. Use the bit clear/setting routines for this.
147 */
148#define ASYI_TXBUSY 1
149#define ASYI_TXLOW 2
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800150#define ASYI_TXFLOWED 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
152/*
153 * Define an array of board names as printable strings. Handy for
154 * referencing boards when printing trace and stuff.
155 */
156static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800157 NULL,
158 NULL,
159 NULL,
160 NULL,
161 NULL,
162 NULL,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
176 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 "EasyIO",
178 "EC8/32-AT",
179 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800180 NULL,
181 NULL,
182 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 "EC8/32-PCI",
184 "EC8/64-PCI",
185 "EasyIO-PCI",
186};
187
188/*****************************************************************************/
189
190/*
191 * Define some string labels for arguments passed from the module
192 * load line. These allow for easy board definitions, and easy
193 * modification of the io, memory and irq resoucres.
194 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800195static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196static char *board0[4];
197static char *board1[4];
198static char *board2[4];
199static char *board3[4];
200
201static char **stl_brdsp[] = {
202 (char **) &board0,
203 (char **) &board1,
204 (char **) &board2,
205 (char **) &board3
206};
207
208/*
209 * Define a set of common board names, and types. This is used to
210 * parse any module arguments.
211 */
212
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800213static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 char *name;
215 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800216} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 { "easyio", BRD_EASYIO },
218 { "eio", BRD_EASYIO },
219 { "20", BRD_EASYIO },
220 { "ec8/32", BRD_ECH },
221 { "ec8/32-at", BRD_ECH },
222 { "ec8/32-isa", BRD_ECH },
223 { "ech", BRD_ECH },
224 { "echat", BRD_ECH },
225 { "21", BRD_ECH },
226 { "ec8/32-mc", BRD_ECHMC },
227 { "ec8/32-mca", BRD_ECHMC },
228 { "echmc", BRD_ECHMC },
229 { "echmca", BRD_ECHMC },
230 { "22", BRD_ECHMC },
231 { "ec8/32-pc", BRD_ECHPCI },
232 { "ec8/32-pci", BRD_ECHPCI },
233 { "26", BRD_ECHPCI },
234 { "ec8/64-pc", BRD_ECH64PCI },
235 { "ec8/64-pci", BRD_ECH64PCI },
236 { "ech-pci", BRD_ECH64PCI },
237 { "echpci", BRD_ECH64PCI },
238 { "echpc", BRD_ECH64PCI },
239 { "27", BRD_ECH64PCI },
240 { "easyio-pc", BRD_EASYIOPCI },
241 { "easyio-pci", BRD_EASYIOPCI },
242 { "eio-pci", BRD_EASYIOPCI },
243 { "eiopci", BRD_EASYIOPCI },
244 { "28", BRD_EASYIOPCI },
245};
246
247/*
248 * Define the module agruments.
249 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
251module_param_array(board0, charp, &stl_nargs, 0);
252MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
253module_param_array(board1, charp, &stl_nargs, 0);
254MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
255module_param_array(board2, charp, &stl_nargs, 0);
256MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
257module_param_array(board3, charp, &stl_nargs, 0);
258MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
259
260/*****************************************************************************/
261
262/*
263 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
264 * to the directly accessible io ports of these boards (not the uarts -
265 * they are in cd1400.h and sc26198.h).
266 */
267#define EIO_8PORTRS 0x04
268#define EIO_4PORTRS 0x05
269#define EIO_8PORTDI 0x00
270#define EIO_8PORTM 0x06
271#define EIO_MK3 0x03
272#define EIO_IDBITMASK 0x07
273
274#define EIO_BRDMASK 0xf0
275#define ID_BRD4 0x10
276#define ID_BRD8 0x20
277#define ID_BRD16 0x30
278
279#define EIO_INTRPEND 0x08
280#define EIO_INTEDGE 0x00
281#define EIO_INTLEVEL 0x08
282#define EIO_0WS 0x10
283
284#define ECH_ID 0xa0
285#define ECH_IDBITMASK 0xe0
286#define ECH_BRDENABLE 0x08
287#define ECH_BRDDISABLE 0x00
288#define ECH_INTENABLE 0x01
289#define ECH_INTDISABLE 0x00
290#define ECH_INTLEVEL 0x02
291#define ECH_INTEDGE 0x00
292#define ECH_INTRPEND 0x01
293#define ECH_BRDRESET 0x01
294
295#define ECHMC_INTENABLE 0x01
296#define ECHMC_BRDRESET 0x02
297
298#define ECH_PNLSTATUS 2
299#define ECH_PNL16PORT 0x20
300#define ECH_PNLIDMASK 0x07
301#define ECH_PNLXPID 0x40
302#define ECH_PNLINTRPEND 0x80
303
304#define ECH_ADDR2MASK 0x1e0
305
306/*
307 * Define the vector mapping bits for the programmable interrupt board
308 * hardware. These bits encode the interrupt for the board to use - it
309 * is software selectable (except the EIO-8M).
310 */
311static unsigned char stl_vecmap[] = {
312 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
313 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
314};
315
316/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700317 * Lock ordering is that you may not take stallion_lock holding
318 * brd_lock.
319 */
320
321static spinlock_t brd_lock; /* Guard the board mapping */
322static spinlock_t stallion_lock; /* Guard the tty driver */
323
324/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 * Set up enable and disable macros for the ECH boards. They require
326 * the secondary io address space to be activated and deactivated.
327 * This way all ECH boards can share their secondary io region.
328 * If this is an ECH-PCI board then also need to set the page pointer
329 * to point to the correct page.
330 */
331#define BRDENABLE(brdnr,pagenr) \
332 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
333 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
334 stl_brds[(brdnr)]->ioctrl); \
335 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
336 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
337
338#define BRDDISABLE(brdnr) \
339 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
340 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
341 stl_brds[(brdnr)]->ioctrl);
342
343#define STL_CD1400MAXBAUD 230400
344#define STL_SC26198MAXBAUD 460800
345
346#define STL_BAUDBASE 115200
347#define STL_CLOSEDELAY (5 * HZ / 10)
348
349/*****************************************************************************/
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351/*
352 * Define the Stallion PCI vendor and device IDs.
353 */
354#ifndef PCI_VENDOR_ID_STALLION
355#define PCI_VENDOR_ID_STALLION 0x124d
356#endif
357#ifndef PCI_DEVICE_ID_ECHPCI832
358#define PCI_DEVICE_ID_ECHPCI832 0x0000
359#endif
360#ifndef PCI_DEVICE_ID_ECHPCI864
361#define PCI_DEVICE_ID_ECHPCI864 0x0002
362#endif
363#ifndef PCI_DEVICE_ID_EIOPCI
364#define PCI_DEVICE_ID_EIOPCI 0x0003
365#endif
366
367/*
368 * Define structure to hold all Stallion PCI boards.
369 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800371static struct pci_device_id stl_pcibrds[] = {
372 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
373 .driver_data = BRD_ECH64PCI },
374 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
375 .driver_data = BRD_EASYIOPCI },
376 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
377 .driver_data = BRD_ECHPCI },
378 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
379 .driver_data = BRD_ECHPCI },
380 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800382MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
384/*****************************************************************************/
385
386/*
387 * Define macros to extract a brd/port number from a minor number.
388 */
389#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
390#define MINOR2PORT(min) ((min) & 0x3f)
391
392/*
393 * Define a baud rate table that converts termios baud rate selector
394 * into the actual baud rate value. All baud rate calculations are
395 * based on the actual baud rate required.
396 */
397static unsigned int stl_baudrates[] = {
398 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
399 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
400};
401
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402/*****************************************************************************/
403
404/*
405 * Declare all those functions in this driver!
406 */
407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800409static int stl_brdinit(struct stlbrd *brdp);
Alan Coxd18a7502008-10-13 10:40:07 +0100410static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800411static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Alan Coxd18a7502008-10-13 10:40:07 +0100412static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414/*
415 * CD1400 uart specific handling functions.
416 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800417static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
418static int stl_cd1400getreg(struct stlport *portp, int regnr);
419static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
420static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
421static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800422static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800423static int stl_cd1400getsignals(struct stlport *portp);
424static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
425static void stl_cd1400ccrwait(struct stlport *portp);
426static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
427static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
428static void stl_cd1400disableintrs(struct stlport *portp);
429static void stl_cd1400sendbreak(struct stlport *portp, int len);
430static void stl_cd1400flowctrl(struct stlport *portp, int state);
431static void stl_cd1400sendflow(struct stlport *portp, int state);
432static void stl_cd1400flush(struct stlport *portp);
433static int stl_cd1400datastate(struct stlport *portp);
434static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
435static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
436static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
437static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
438static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800440static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
442/*
443 * SC26198 uart specific handling functions.
444 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800445static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
446static int stl_sc26198getreg(struct stlport *portp, int regnr);
447static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
448static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
449static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
450static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800451static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800452static int stl_sc26198getsignals(struct stlport *portp);
453static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
454static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
455static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
456static void stl_sc26198disableintrs(struct stlport *portp);
457static void stl_sc26198sendbreak(struct stlport *portp, int len);
458static void stl_sc26198flowctrl(struct stlport *portp, int state);
459static void stl_sc26198sendflow(struct stlport *portp, int state);
460static void stl_sc26198flush(struct stlport *portp);
461static int stl_sc26198datastate(struct stlport *portp);
462static void stl_sc26198wait(struct stlport *portp);
463static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
464static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
465static void stl_sc26198txisr(struct stlport *port);
466static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
467static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
468static void stl_sc26198rxbadchars(struct stlport *portp);
469static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471/*****************************************************************************/
472
473/*
474 * Generic UART support structure.
475 */
476typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800477 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
478 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800479 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800480 int (*getsignals)(struct stlport *portp);
481 void (*setsignals)(struct stlport *portp, int dtr, int rts);
482 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
483 void (*startrxtx)(struct stlport *portp, int rx, int tx);
484 void (*disableintrs)(struct stlport *portp);
485 void (*sendbreak)(struct stlport *portp, int len);
486 void (*flowctrl)(struct stlport *portp, int state);
487 void (*sendflow)(struct stlport *portp, int state);
488 void (*flush)(struct stlport *portp);
489 int (*datastate)(struct stlport *portp);
490 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491} uart_t;
492
493/*
494 * Define some macros to make calling these functions nice and clean.
495 */
496#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
497#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
498#define stl_setport (* ((uart_t *) portp->uartp)->setport)
499#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
500#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
501#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
502#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
503#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
504#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
505#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
506#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
507#define stl_flush (* ((uart_t *) portp->uartp)->flush)
508#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
509
510/*****************************************************************************/
511
512/*
513 * CD1400 UART specific data initialization.
514 */
515static uart_t stl_cd1400uart = {
516 stl_cd1400panelinit,
517 stl_cd1400portinit,
518 stl_cd1400setport,
519 stl_cd1400getsignals,
520 stl_cd1400setsignals,
521 stl_cd1400enablerxtx,
522 stl_cd1400startrxtx,
523 stl_cd1400disableintrs,
524 stl_cd1400sendbreak,
525 stl_cd1400flowctrl,
526 stl_cd1400sendflow,
527 stl_cd1400flush,
528 stl_cd1400datastate,
529 stl_cd1400eiointr
530};
531
532/*
533 * Define the offsets within the register bank of a cd1400 based panel.
534 * These io address offsets are common to the EasyIO board as well.
535 */
536#define EREG_ADDR 0
537#define EREG_DATA 4
538#define EREG_RXACK 5
539#define EREG_TXACK 6
540#define EREG_MDACK 7
541
542#define EREG_BANKSIZE 8
543
544#define CD1400_CLK 25000000
545#define CD1400_CLK8M 20000000
546
547/*
548 * Define the cd1400 baud rate clocks. These are used when calculating
549 * what clock and divisor to use for the required baud rate. Also
550 * define the maximum baud rate allowed, and the default base baud.
551 */
552static int stl_cd1400clkdivs[] = {
553 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
554};
555
556/*****************************************************************************/
557
558/*
559 * SC26198 UART specific data initization.
560 */
561static uart_t stl_sc26198uart = {
562 stl_sc26198panelinit,
563 stl_sc26198portinit,
564 stl_sc26198setport,
565 stl_sc26198getsignals,
566 stl_sc26198setsignals,
567 stl_sc26198enablerxtx,
568 stl_sc26198startrxtx,
569 stl_sc26198disableintrs,
570 stl_sc26198sendbreak,
571 stl_sc26198flowctrl,
572 stl_sc26198sendflow,
573 stl_sc26198flush,
574 stl_sc26198datastate,
575 stl_sc26198intr
576};
577
578/*
579 * Define the offsets within the register bank of a sc26198 based panel.
580 */
581#define XP_DATA 0
582#define XP_ADDR 1
583#define XP_MODID 2
584#define XP_STATUS 2
585#define XP_IACK 3
586
587#define XP_BANKSIZE 4
588
589/*
590 * Define the sc26198 baud rate table. Offsets within the table
591 * represent the actual baud rate selector of sc26198 registers.
592 */
593static unsigned int sc26198_baudtable[] = {
594 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
595 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
596 230400, 460800, 921600
597};
598
Tobias Klauserfe971072006-01-09 20:54:02 -0800599#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
601/*****************************************************************************/
602
603/*
604 * Define the driver info for a user level control device. Used mainly
605 * to get at port stats - only not using the port device itself.
606 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700607static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 .owner = THIS_MODULE,
609 .ioctl = stl_memioctl,
610};
611
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800612static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800614static void stl_cd_change(struct stlport *portp)
615{
616 unsigned int oldsigs = portp->sigs;
Alan Coxd18a7502008-10-13 10:40:07 +0100617 struct tty_struct *tty = tty_port_tty_get(&portp->port);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800618
Alan Coxd18a7502008-10-13 10:40:07 +0100619 if (!tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800620 return;
621
622 portp->sigs = stl_getsignals(portp);
623
624 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100625 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800626
627 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100628 if (portp->port.flags & ASYNC_CHECK_CD)
Alan Coxd18a7502008-10-13 10:40:07 +0100629 tty_hangup(tty);
630 tty_kref_put(tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800631}
632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 * Check for any arguments passed in on the module load command line.
635 */
636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637/*****************************************************************************/
638
639/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 * Parse the supplied argument string, into the board conf struct.
641 */
642
Jiri Slaby40e82652006-12-08 02:38:41 -0800643static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
645 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800646 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Jiri Slabya0564e12006-12-08 02:38:37 -0800648 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Jiri Slaby615e4a72006-12-08 02:38:38 -0800650 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100651 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Jiri Slabyc62429d2006-12-08 02:39:14 -0800653 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800654 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Jiri Slabyc62429d2006-12-08 02:39:14 -0800656 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
658 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800659
Tobias Klauserfe971072006-01-09 20:54:02 -0800660 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800662 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
664
665 confp->brdtype = stl_brdstr[i].type;
666
667 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800668 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800669 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 i++;
671 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800672 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800673 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 i++;
675 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800676 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800677 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100678 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679}
680
681/*****************************************************************************/
682
683/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 * Allocate a new board structure. Fill out the basic info in it.
685 */
686
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800687static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800689 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800691 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800692 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700693 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800694 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800695 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 }
697
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100699 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700}
701
702/*****************************************************************************/
703
704static int stl_open(struct tty_struct *tty, struct file *filp)
705{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800706 struct stlport *portp;
707 struct stlbrd *brdp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800708 unsigned int minordev, brdnr, panelnr;
709 int portnr, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Jiri Slabya0564e12006-12-08 02:38:37 -0800711 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
713 minordev = tty->index;
714 brdnr = MINOR2BRD(minordev);
715 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100716 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800718 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100719 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800721 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800722 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 break;
724 if (minordev < brdp->panels[panelnr]->nrports) {
725 portnr = minordev;
726 break;
727 }
728 minordev -= brdp->panels[panelnr]->nrports;
729 }
730 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100731 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800734 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100735 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
737/*
738 * On the first open of the device setup the port hardware, and
739 * initialize the per port data structure.
740 */
Alan Coxd18a7502008-10-13 10:40:07 +0100741 tty_port_tty_set(&portp->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 tty->driver_data = portp;
Alan Coxf8ae4762008-07-16 21:56:37 +0100743 portp->port.count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
Alan Coxf8ae4762008-07-16 21:56:37 +0100745 if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800746 if (!portp->tx.buf) {
747 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
748 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100749 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 portp->tx.head = portp->tx.buf;
751 portp->tx.tail = portp->tx.buf;
752 }
753 stl_setport(portp, tty->termios);
754 portp->sigs = stl_getsignals(portp);
755 stl_setsignals(portp, 1, 1);
756 stl_enablerxtx(portp, 1, 1);
757 stl_startrxtx(portp, 1, 0);
758 clear_bit(TTY_IO_ERROR, &tty->flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100759 portp->port.flags |= ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 }
761
762/*
763 * Check if this port is in the middle of closing. If so then wait
764 * until it is closed then return error status, based on flag settings.
765 * The sleep here does not need interrupt protection since the wakeup
766 * for it is done with the same context.
767 */
Alan Coxf8ae4762008-07-16 21:56:37 +0100768 if (portp->port.flags & ASYNC_CLOSING) {
769 interruptible_sleep_on(&portp->port.close_wait);
770 if (portp->port.flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100771 return -EAGAIN;
772 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 }
774
775/*
776 * Based on type of open being done check if it can overlap with any
777 * previous opens still in effect. If we are a normal serial device
778 * then also we might have to wait for carrier.
779 */
Jiri Slabyc62429d2006-12-08 02:39:14 -0800780 if (!(filp->f_flags & O_NONBLOCK))
Alan Coxd18a7502008-10-13 10:40:07 +0100781 if ((rc = stl_waitcarrier(tty, portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100782 return rc;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800783
Alan Coxf8ae4762008-07-16 21:56:37 +0100784 portp->port.flags |= ASYNC_NORMAL_ACTIVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
Jesper Juhl014c2542006-01-15 02:37:08 +0100786 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787}
788
789/*****************************************************************************/
790
Alan Cox31f35932009-01-02 13:45:05 +0000791static int stl_carrier_raised(struct tty_port *port)
792{
793 struct stlport *portp = container_of(port, struct stlport, port);
794 return (portp->sigs & TIOCM_CD) ? 1 : 0;
795}
796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797/*
798 * Possibly need to wait for carrier (DCD signal) to come high. Say
799 * maybe because if we are clocal then we don't need to wait...
800 */
801
Alan Coxd18a7502008-10-13 10:40:07 +0100802static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp,
803 struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804{
805 unsigned long flags;
806 int rc, doclocal;
Alan Cox31f35932009-01-02 13:45:05 +0000807 struct tty_port *port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Jiri Slabya0564e12006-12-08 02:38:37 -0800809 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
811 rc = 0;
812 doclocal = 0;
813
Alan Coxb65b5b52006-06-27 02:54:05 -0700814 spin_lock_irqsave(&stallion_lock, flags);
815
Alan Coxd18a7502008-10-13 10:40:07 +0100816 if (tty->termios->c_cflag & CLOCAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 doclocal++;
818
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 portp->openwaitcnt++;
820 if (! tty_hung_up_p(filp))
Alan Cox31f35932009-01-02 13:45:05 +0000821 port->count--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
823 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700824 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 stl_setsignals(portp, 1, 1);
826 if (tty_hung_up_p(filp) ||
Alan Cox31f35932009-01-02 13:45:05 +0000827 ((port->flags & ASYNC_INITIALIZED) == 0)) {
828 if (port->flags & ASYNC_HUP_NOTIFY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 rc = -EBUSY;
830 else
831 rc = -ERESTARTSYS;
832 break;
833 }
Alan Cox31f35932009-01-02 13:45:05 +0000834 if (((port->flags & ASYNC_CLOSING) == 0) &&
835 (doclocal || tty_port_carrier_raised(port)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 if (signal_pending(current)) {
838 rc = -ERESTARTSYS;
839 break;
840 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700841 /* FIXME */
Alan Cox31f35932009-01-02 13:45:05 +0000842 interruptible_sleep_on(&port->open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 }
844
845 if (! tty_hung_up_p(filp))
Alan Cox31f35932009-01-02 13:45:05 +0000846 port->count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700848 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
Jesper Juhl014c2542006-01-15 02:37:08 +0100850 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851}
852
853/*****************************************************************************/
854
Jiri Slaby96b066b2006-12-08 02:38:42 -0800855static void stl_flushbuffer(struct tty_struct *tty)
856{
857 struct stlport *portp;
858
859 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
860
Jiri Slaby96b066b2006-12-08 02:38:42 -0800861 portp = tty->driver_data;
862 if (portp == NULL)
863 return;
864
865 stl_flush(portp);
866 tty_wakeup(tty);
867}
868
869/*****************************************************************************/
870
871static void stl_waituntilsent(struct tty_struct *tty, int timeout)
872{
873 struct stlport *portp;
874 unsigned long tend;
875
876 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
877
Jiri Slaby96b066b2006-12-08 02:38:42 -0800878 portp = tty->driver_data;
879 if (portp == NULL)
880 return;
881
882 if (timeout == 0)
883 timeout = HZ;
884 tend = jiffies + timeout;
885
Alan Cox978e5952008-04-30 00:53:59 -0700886 lock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800887 while (stl_datastate(portp)) {
888 if (signal_pending(current))
889 break;
890 msleep_interruptible(20);
891 if (time_after_eq(jiffies, tend))
892 break;
893 }
Alan Cox978e5952008-04-30 00:53:59 -0700894 unlock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800895}
896
897/*****************************************************************************/
898
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899static void stl_close(struct tty_struct *tty, struct file *filp)
900{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800901 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 unsigned long flags;
903
Jiri Slabya0564e12006-12-08 02:38:37 -0800904 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800907 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 return;
909
Alan Coxb65b5b52006-06-27 02:54:05 -0700910 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700912 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 return;
914 }
Alan Coxf8ae4762008-07-16 21:56:37 +0100915 if ((tty->count == 1) && (portp->port.count != 1))
916 portp->port.count = 1;
917 if (portp->port.count-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700918 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 return;
920 }
921
Alan Coxf8ae4762008-07-16 21:56:37 +0100922 portp->port.count = 0;
923 portp->port.flags |= ASYNC_CLOSING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
925/*
926 * May want to wait for any data to drain before closing. The BUSY
927 * flag keeps track of whether we are still sending or not - it is
928 * very accurate for the cd1400, not quite so for the sc26198.
929 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
930 */
931 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700932
933 spin_unlock_irqrestore(&stallion_lock, flags);
934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
936 tty_wait_until_sent(tty, portp->closing_wait);
937 stl_waituntilsent(tty, (HZ / 2));
938
Alan Coxb65b5b52006-06-27 02:54:05 -0700939
940 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100941 portp->port.flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700942 spin_unlock_irqrestore(&stallion_lock, flags);
943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 stl_disableintrs(portp);
945 if (tty->termios->c_cflag & HUPCL)
946 stl_setsignals(portp, 0, 0);
947 stl_enablerxtx(portp, 0, 0);
948 stl_flushbuffer(tty);
949 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800950 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800952 portp->tx.buf = NULL;
953 portp->tx.head = NULL;
954 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 }
956 set_bit(TTY_IO_ERROR, &tty->flags);
957 tty_ldisc_flush(tty);
958
959 tty->closing = 0;
Alan Coxd18a7502008-10-13 10:40:07 +0100960 tty_port_tty_set(&portp->port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
962 if (portp->openwaitcnt) {
963 if (portp->close_delay)
964 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
Alan Coxf8ae4762008-07-16 21:56:37 +0100965 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 }
967
Alan Coxf8ae4762008-07-16 21:56:37 +0100968 portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
969 wake_up_interruptible(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970}
971
972/*****************************************************************************/
973
974/*
975 * Write routine. Take data and stuff it in to the TX ring queue.
976 * If transmit interrupts are not running then start them.
977 */
978
979static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
980{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800981 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 unsigned int len, stlen;
983 unsigned char *chbuf;
984 char *head, *tail;
985
Jiri Slabya0564e12006-12-08 02:38:37 -0800986 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800989 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100990 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800991 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100992 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
994/*
995 * If copying direct from user space we must cater for page faults,
996 * causing us to "sleep" here for a while. To handle this copy in all
997 * the data we need now, into a local buffer. Then when we got it all
998 * copy it into the TX buffer.
999 */
1000 chbuf = (unsigned char *) buf;
1001
1002 head = portp->tx.head;
1003 tail = portp->tx.tail;
1004 if (head >= tail) {
1005 len = STL_TXBUFSIZE - (head - tail) - 1;
1006 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1007 } else {
1008 len = tail - head - 1;
1009 stlen = len;
1010 }
1011
Jiri Slaby843b5682006-12-08 02:39:12 -08001012 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 count = 0;
1014 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08001015 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 memcpy(head, chbuf, stlen);
1017 len -= stlen;
1018 chbuf += stlen;
1019 count += stlen;
1020 head += stlen;
1021 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1022 head = portp->tx.buf;
1023 stlen = tail - head;
1024 }
1025 }
1026 portp->tx.head = head;
1027
1028 clear_bit(ASYI_TXLOW, &portp->istate);
1029 stl_startrxtx(portp, -1, 1);
1030
Jesper Juhl014c2542006-01-15 02:37:08 +01001031 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032}
1033
1034/*****************************************************************************/
1035
David Howells4a561222008-07-22 11:18:43 +01001036static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001038 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 unsigned int len;
1040 char *head, *tail;
1041
Jiri Slabya0564e12006-12-08 02:38:37 -08001042 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001045 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001046 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001047 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +01001048 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
1050 head = portp->tx.head;
1051 tail = portp->tx.tail;
1052
1053 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1054 len--;
1055
1056 if (len > 0) {
1057 *head++ = ch;
1058 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1059 head = portp->tx.buf;
1060 }
1061 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +01001062 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063}
1064
1065/*****************************************************************************/
1066
1067/*
1068 * If there are any characters in the buffer then make sure that TX
1069 * interrupts are on and get'em out. Normally used after the putchar
1070 * routine has been called.
1071 */
1072
1073static void stl_flushchars(struct tty_struct *tty)
1074{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001075 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
Jiri Slabya0564e12006-12-08 02:38:37 -08001077 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001080 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001082 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 return;
1084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 stl_startrxtx(portp, -1, 1);
1086}
1087
1088/*****************************************************************************/
1089
1090static int stl_writeroom(struct tty_struct *tty)
1091{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001092 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 char *head, *tail;
1094
Jiri Slabya0564e12006-12-08 02:38:37 -08001095 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001098 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001099 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001100 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001101 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
1103 head = portp->tx.head;
1104 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001105 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106}
1107
1108/*****************************************************************************/
1109
1110/*
1111 * Return number of chars in the TX buffer. Normally we would just
1112 * calculate the number of chars in the buffer and return that, but if
1113 * the buffer is empty and TX interrupts are still on then we return
1114 * that the buffer still has 1 char in it. This way whoever called us
1115 * will not think that ALL chars have drained - since the UART still
1116 * must have some chars in it (we are busy after all).
1117 */
1118
1119static int stl_charsinbuffer(struct tty_struct *tty)
1120{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001121 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 unsigned int size;
1123 char *head, *tail;
1124
Jiri Slabya0564e12006-12-08 02:38:37 -08001125 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001128 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001129 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001130 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001131 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
1133 head = portp->tx.head;
1134 tail = portp->tx.tail;
1135 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1136 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1137 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001138 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139}
1140
1141/*****************************************************************************/
1142
1143/*
1144 * Generate the serial struct info.
1145 */
1146
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001147static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148{
1149 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001150 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Jiri Slabya0564e12006-12-08 02:38:37 -08001152 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
1154 memset(&sio, 0, sizeof(struct serial_struct));
1155 sio.line = portp->portnr;
1156 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001157 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 sio.baud_base = portp->baud_base;
1159 sio.close_delay = portp->close_delay;
1160 sio.closing_wait = portp->closing_wait;
1161 sio.custom_divisor = portp->custom_divisor;
1162 sio.hub6 = 0;
1163 if (portp->uartp == &stl_cd1400uart) {
1164 sio.type = PORT_CIRRUS;
1165 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1166 } else {
1167 sio.type = PORT_UNKNOWN;
1168 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1169 }
1170
1171 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001172 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 sio.irq = brdp->irq;
1174
1175 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1176}
1177
1178/*****************************************************************************/
1179
1180/*
1181 * Set port according to the serial struct info.
1182 * At this point we do not do any auto-configure stuff, so we will
1183 * just quietly ignore any requests to change irq, etc.
1184 */
1185
Alan Coxd18a7502008-10-13 10:40:07 +01001186static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187{
Alan Coxd18a7502008-10-13 10:40:07 +01001188 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 struct serial_struct sio;
1190
Jiri Slabya0564e12006-12-08 02:38:37 -08001191 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
1193 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1194 return -EFAULT;
1195 if (!capable(CAP_SYS_ADMIN)) {
1196 if ((sio.baud_base != portp->baud_base) ||
1197 (sio.close_delay != portp->close_delay) ||
1198 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001199 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001200 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 }
1202
Alan Coxf8ae4762008-07-16 21:56:37 +01001203 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 (sio.flags & ASYNC_USR_MASK);
1205 portp->baud_base = sio.baud_base;
1206 portp->close_delay = sio.close_delay;
1207 portp->closing_wait = sio.closing_wait;
1208 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001209 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001210 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211}
1212
1213/*****************************************************************************/
1214
1215static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1216{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001217 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001220 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001221 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001223 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225 return stl_getsignals(portp);
1226}
1227
1228static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1229 unsigned int set, unsigned int clear)
1230{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001231 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 int rts = -1, dtr = -1;
1233
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001235 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001236 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001238 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
1240 if (set & TIOCM_RTS)
1241 rts = 1;
1242 if (set & TIOCM_DTR)
1243 dtr = 1;
1244 if (clear & TIOCM_RTS)
1245 rts = 0;
1246 if (clear & TIOCM_DTR)
1247 dtr = 0;
1248
1249 stl_setsignals(portp, dtr, rts);
1250 return 0;
1251}
1252
1253static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1254{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001255 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 int rc;
1257 void __user *argp = (void __user *)arg;
1258
Jiri Slabya0564e12006-12-08 02:38:37 -08001259 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1260 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001263 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001264 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
1266 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001267 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001269 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 rc = 0;
1272
Alan Coxf433c652008-04-30 00:53:23 -07001273 lock_kernel();
1274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 case TIOCGSERIAL:
1277 rc = stl_getserial(portp, argp);
1278 break;
1279 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001280 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 break;
1282 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001283 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 break;
1285 case COM_CLRPORTSTATS:
1286 rc = stl_clrportstats(portp, argp);
1287 break;
1288 case TIOCSERCONFIG:
1289 case TIOCSERGWILD:
1290 case TIOCSERSWILD:
1291 case TIOCSERGETLSR:
1292 case TIOCSERGSTRUCT:
1293 case TIOCSERGETMULTI:
1294 case TIOCSERSETMULTI:
1295 default:
1296 rc = -ENOIOCTLCMD;
1297 break;
1298 }
Alan Coxf433c652008-04-30 00:53:23 -07001299 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001300 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301}
1302
1303/*****************************************************************************/
1304
Jiri Slaby96b066b2006-12-08 02:38:42 -08001305/*
1306 * Start the transmitter again. Just turn TX interrupts back on.
1307 */
1308
1309static void stl_start(struct tty_struct *tty)
1310{
1311 struct stlport *portp;
1312
1313 pr_debug("stl_start(tty=%p)\n", tty);
1314
Jiri Slaby96b066b2006-12-08 02:38:42 -08001315 portp = tty->driver_data;
1316 if (portp == NULL)
1317 return;
1318 stl_startrxtx(portp, -1, 1);
1319}
1320
1321/*****************************************************************************/
1322
Alan Cox606d0992006-12-08 02:38:45 -08001323static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001325 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001326 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
Jiri Slabya0564e12006-12-08 02:38:37 -08001328 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001331 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 return;
1333
1334 tiosp = tty->termios;
1335 if ((tiosp->c_cflag == old->c_cflag) &&
1336 (tiosp->c_iflag == old->c_iflag))
1337 return;
1338
1339 stl_setport(portp, tiosp);
1340 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1341 -1);
1342 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1343 tty->hw_stopped = 0;
1344 stl_start(tty);
1345 }
1346 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001347 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348}
1349
1350/*****************************************************************************/
1351
1352/*
1353 * Attempt to flow control who ever is sending us data. Based on termios
1354 * settings use software or/and hardware flow control.
1355 */
1356
1357static void stl_throttle(struct tty_struct *tty)
1358{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001359 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Jiri Slabya0564e12006-12-08 02:38:37 -08001361 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001364 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 return;
1366 stl_flowctrl(portp, 0);
1367}
1368
1369/*****************************************************************************/
1370
1371/*
1372 * Unflow control the device sending us data...
1373 */
1374
1375static void stl_unthrottle(struct tty_struct *tty)
1376{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001377 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
Jiri Slabya0564e12006-12-08 02:38:37 -08001379 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001382 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 return;
1384 stl_flowctrl(portp, 1);
1385}
1386
1387/*****************************************************************************/
1388
1389/*
1390 * Stop the transmitter. Basically to do this we will just turn TX
1391 * interrupts off.
1392 */
1393
1394static void stl_stop(struct tty_struct *tty)
1395{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001396 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
Jiri Slabya0564e12006-12-08 02:38:37 -08001398 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001401 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 return;
1403 stl_startrxtx(portp, -1, 0);
1404}
1405
1406/*****************************************************************************/
1407
1408/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 * Hangup this port. This is pretty much like closing the port, only
1410 * a little more brutal. No waiting for data to drain. Shutdown the
1411 * port and maybe drop signals.
1412 */
1413
1414static void stl_hangup(struct tty_struct *tty)
1415{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001416 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Jiri Slabya0564e12006-12-08 02:38:37 -08001418 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001421 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 return;
1423
Alan Coxf8ae4762008-07-16 21:56:37 +01001424 portp->port.flags &= ~ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 stl_disableintrs(portp);
1426 if (tty->termios->c_cflag & HUPCL)
1427 stl_setsignals(portp, 0, 0);
1428 stl_enablerxtx(portp, 0, 0);
1429 stl_flushbuffer(tty);
1430 portp->istate = 0;
1431 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001432 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001434 portp->tx.buf = NULL;
1435 portp->tx.head = NULL;
1436 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 }
Alan Coxd18a7502008-10-13 10:40:07 +01001438 tty_port_tty_set(&portp->port, NULL);
Alan Coxf8ae4762008-07-16 21:56:37 +01001439 portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1440 portp->port.count = 0;
1441 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442}
1443
1444/*****************************************************************************/
1445
David Howells4a561222008-07-22 11:18:43 +01001446static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001448 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Jiri Slabya0564e12006-12-08 02:38:37 -08001450 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001453 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001454 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
1456 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001457 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458}
1459
1460/*****************************************************************************/
1461
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462static void stl_sendxchar(struct tty_struct *tty, char ch)
1463{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001464 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
Jiri Slabya0564e12006-12-08 02:38:37 -08001466 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001469 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 return;
1471
1472 if (ch == STOP_CHAR(tty))
1473 stl_sendflow(portp, 0);
1474 else if (ch == START_CHAR(tty))
1475 stl_sendflow(portp, 1);
1476 else
1477 stl_putchar(tty, ch);
1478}
1479
1480/*****************************************************************************/
1481
1482#define MAXLINE 80
1483
1484/*
1485 * Format info for a specified port. The line is deliberately limited
1486 * to 80 characters. (If it is too long it will be truncated, if too
1487 * short then padded with spaces).
1488 */
1489
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001490static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491{
1492 char *sp;
1493 int sigs, cnt;
1494
1495 sp = pos;
1496 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1497 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1498 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1499
1500 if (portp->stats.rxframing)
1501 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1502 if (portp->stats.rxparity)
1503 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1504 if (portp->stats.rxbreaks)
1505 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1506 if (portp->stats.rxoverrun)
1507 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1508
1509 sigs = stl_getsignals(portp);
1510 cnt = sprintf(sp, "%s%s%s%s%s ",
1511 (sigs & TIOCM_RTS) ? "|RTS" : "",
1512 (sigs & TIOCM_CTS) ? "|CTS" : "",
1513 (sigs & TIOCM_DTR) ? "|DTR" : "",
1514 (sigs & TIOCM_CD) ? "|DCD" : "",
1515 (sigs & TIOCM_DSR) ? "|DSR" : "");
1516 *sp = ' ';
1517 sp += cnt;
1518
Jiri Slabyc62429d2006-12-08 02:39:14 -08001519 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 *sp++ = ' ';
1521 if (cnt >= MAXLINE)
1522 pos[(MAXLINE - 2)] = '+';
1523 pos[(MAXLINE - 1)] = '\n';
1524
Jesper Juhl014c2542006-01-15 02:37:08 +01001525 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526}
1527
1528/*****************************************************************************/
1529
1530/*
1531 * Port info, read from the /proc file system.
1532 */
1533
1534static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1535{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001536 struct stlbrd *brdp;
1537 struct stlpanel *panelp;
1538 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001539 unsigned int brdnr, panelnr, portnr;
1540 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 char *pos;
1542
Jiri Slabya0564e12006-12-08 02:38:37 -08001543 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1544 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545
1546 pos = page;
1547 totalport = 0;
1548 curoff = 0;
1549
1550 if (off == 0) {
1551 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1552 stl_drvversion);
1553 while (pos < (page + MAXLINE - 1))
1554 *pos++ = ' ';
1555 *pos++ = '\n';
1556 }
1557 curoff = MAXLINE;
1558
1559/*
1560 * We scan through for each board, panel and port. The offset is
1561 * calculated on the fly, and irrelevant ports are skipped.
1562 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001563 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001565 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 continue;
1567 if (brdp->state == 0)
1568 continue;
1569
1570 maxoff = curoff + (brdp->nrports * MAXLINE);
1571 if (off >= maxoff) {
1572 curoff = maxoff;
1573 continue;
1574 }
1575
1576 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001577 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001579 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 continue;
1581
1582 maxoff = curoff + (panelp->nrports * MAXLINE);
1583 if (off >= maxoff) {
1584 curoff = maxoff;
1585 totalport += panelp->nrports;
1586 continue;
1587 }
1588
Jiri Slabyc62429d2006-12-08 02:39:14 -08001589 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 totalport++) {
1591 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001592 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 continue;
1594 if (off >= (curoff += MAXLINE))
1595 continue;
1596 if ((pos - page + MAXLINE) > count)
1597 goto stl_readdone;
1598 pos += stl_portinfo(portp, totalport, pos);
1599 }
1600 }
1601 }
1602
1603 *eof = 1;
1604
1605stl_readdone:
1606 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001607 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608}
1609
1610/*****************************************************************************/
1611
1612/*
1613 * All board interrupts are vectored through here first. This code then
1614 * calls off to the approrpriate board interrupt handlers.
1615 */
1616
David Howells7d12e782006-10-05 14:55:46 +01001617static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001619 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
Jeff Garzika6f97b22007-10-31 05:20:49 -04001621 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
1623 return IRQ_RETVAL((* brdp->isr)(brdp));
1624}
1625
1626/*****************************************************************************/
1627
1628/*
1629 * Interrupt service routine for EasyIO board types.
1630 */
1631
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001632static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001634 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 unsigned int iobase;
1636 int handled = 0;
1637
Alan Coxb65b5b52006-06-27 02:54:05 -07001638 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 panelp = brdp->panels[0];
1640 iobase = panelp->iobase;
1641 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1642 handled = 1;
1643 (* panelp->isr)(panelp, iobase);
1644 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001645 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 return handled;
1647}
1648
1649/*****************************************************************************/
1650
1651/*
1652 * Interrupt service routine for ECH-AT board types.
1653 */
1654
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001655static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001657 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001658 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 int handled = 0;
1660
1661 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1662
1663 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1664 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001665 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 ioaddr = brdp->bnkstataddr[bnknr];
1667 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1668 panelp = brdp->bnk2panel[bnknr];
1669 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1670 }
1671 }
1672 }
1673
1674 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1675
1676 return handled;
1677}
1678
1679/*****************************************************************************/
1680
1681/*
1682 * Interrupt service routine for ECH-MCA board types.
1683 */
1684
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001685static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001687 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001688 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 int handled = 0;
1690
1691 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1692 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001693 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 ioaddr = brdp->bnkstataddr[bnknr];
1695 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1696 panelp = brdp->bnk2panel[bnknr];
1697 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1698 }
1699 }
1700 }
1701 return handled;
1702}
1703
1704/*****************************************************************************/
1705
1706/*
1707 * Interrupt service routine for ECH-PCI board types.
1708 */
1709
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001710static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001712 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001713 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 int handled = 0;
1715
1716 while (1) {
1717 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001718 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1720 ioaddr = brdp->bnkstataddr[bnknr];
1721 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1722 panelp = brdp->bnk2panel[bnknr];
1723 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1724 recheck++;
1725 handled = 1;
1726 }
1727 }
1728 if (! recheck)
1729 break;
1730 }
1731 return handled;
1732}
1733
1734/*****************************************************************************/
1735
1736/*
1737 * Interrupt service routine for ECH-8/64-PCI board types.
1738 */
1739
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001740static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001742 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001743 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 int handled = 0;
1745
1746 while (inb(brdp->ioctrl) & 0x1) {
1747 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001748 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 ioaddr = brdp->bnkstataddr[bnknr];
1750 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1751 panelp = brdp->bnk2panel[bnknr];
1752 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1753 }
1754 }
1755 }
1756
1757 return handled;
1758}
1759
1760/*****************************************************************************/
1761
1762/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 * Initialize all the ports on a panel.
1764 */
1765
Jiri Slaby705c1862006-12-08 02:39:11 -08001766static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001768 struct stlport *portp;
1769 unsigned int i;
1770 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
Jiri Slabya0564e12006-12-08 02:38:37 -08001772 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774 chipmask = stl_panelinit(brdp, panelp);
1775
1776/*
1777 * All UART's are initialized (if found!). Now go through and setup
1778 * each ports data structures.
1779 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001780 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001781 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001782 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001784 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 break;
1786 }
Alan Coxd18a7502008-10-13 10:40:07 +01001787 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001788 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 portp->magic = STL_PORTMAGIC;
1790 portp->portnr = i;
1791 portp->brdnr = panelp->brdnr;
1792 portp->panelnr = panelp->panelnr;
1793 portp->uartp = panelp->uartp;
1794 portp->clk = brdp->clk;
1795 portp->baud_base = STL_BAUDBASE;
1796 portp->close_delay = STL_CLOSEDELAY;
1797 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001798 init_waitqueue_head(&portp->port.open_wait);
1799 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 portp->stats.brd = portp->brdnr;
1801 portp->stats.panel = portp->panelnr;
1802 portp->stats.port = portp->portnr;
1803 panelp->ports[i] = portp;
1804 stl_portinit(brdp, panelp, portp);
1805 }
1806
Jiri Slabyc62429d2006-12-08 02:39:14 -08001807 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808}
1809
Jiri Slaby3b85b342006-12-08 02:39:10 -08001810static void stl_cleanup_panels(struct stlbrd *brdp)
1811{
1812 struct stlpanel *panelp;
1813 struct stlport *portp;
1814 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001815 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001816
1817 for (j = 0; j < STL_MAXPANELS; j++) {
1818 panelp = brdp->panels[j];
1819 if (panelp == NULL)
1820 continue;
1821 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1822 portp = panelp->ports[k];
1823 if (portp == NULL)
1824 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001825 tty = tty_port_tty_get(&portp->port);
1826 if (tty != NULL) {
1827 stl_hangup(tty);
1828 tty_kref_put(tty);
1829 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001830 kfree(portp->tx.buf);
1831 kfree(portp);
1832 }
1833 kfree(panelp);
1834 }
1835}
1836
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837/*****************************************************************************/
1838
1839/*
1840 * Try to find and initialize an EasyIO board.
1841 */
1842
Jiri Slaby705c1862006-12-08 02:39:11 -08001843static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001845 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 unsigned int status;
1847 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001848 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849
Jiri Slabya0564e12006-12-08 02:38:37 -08001850 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
1852 brdp->ioctrl = brdp->ioaddr1 + 1;
1853 brdp->iostatus = brdp->ioaddr1 + 2;
1854
1855 status = inb(brdp->iostatus);
1856 if ((status & EIO_IDBITMASK) == EIO_MK3)
1857 brdp->ioctrl++;
1858
1859/*
1860 * Handle board specific stuff now. The real difference is PCI
1861 * or not PCI.
1862 */
1863 if (brdp->brdtype == BRD_EASYIOPCI) {
1864 brdp->iosize1 = 0x80;
1865 brdp->iosize2 = 0x80;
1866 name = "serial(EIO-PCI)";
1867 outb(0x41, (brdp->ioaddr2 + 0x4c));
1868 } else {
1869 brdp->iosize1 = 8;
1870 name = "serial(EIO)";
1871 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1872 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1873 printk("STALLION: invalid irq=%d for brd=%d\n",
1874 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001875 retval = -EINVAL;
1876 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 }
1878 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1879 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1880 brdp->ioctrl);
1881 }
1882
Jiri Slaby3b85b342006-12-08 02:39:10 -08001883 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1885 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1886 "%x conflicts with another device\n", brdp->brdnr,
1887 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001888 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 }
1890
1891 if (brdp->iosize2 > 0)
1892 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1893 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1894 "address %x conflicts with another device\n",
1895 brdp->brdnr, brdp->ioaddr2);
1896 printk(KERN_WARNING "STALLION: Warning, also "
1897 "releasing board %d I/O address %x \n",
1898 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001899 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 }
1901
1902/*
1903 * Everything looks OK, so let's go ahead and probe for the hardware.
1904 */
1905 brdp->clk = CD1400_CLK;
1906 brdp->isr = stl_eiointr;
1907
Jiri Slaby3b85b342006-12-08 02:39:10 -08001908 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 switch (status & EIO_IDBITMASK) {
1910 case EIO_8PORTM:
1911 brdp->clk = CD1400_CLK8M;
1912 /* fall thru */
1913 case EIO_8PORTRS:
1914 case EIO_8PORTDI:
1915 brdp->nrports = 8;
1916 break;
1917 case EIO_4PORTRS:
1918 brdp->nrports = 4;
1919 break;
1920 case EIO_MK3:
1921 switch (status & EIO_BRDMASK) {
1922 case ID_BRD4:
1923 brdp->nrports = 4;
1924 break;
1925 case ID_BRD8:
1926 brdp->nrports = 8;
1927 break;
1928 case ID_BRD16:
1929 brdp->nrports = 16;
1930 break;
1931 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001932 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 }
1934 break;
1935 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001936 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 }
1938
1939/*
1940 * We have verified that the board is actually present, so now we
1941 * can complete the setup.
1942 */
1943
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001944 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001945 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001947 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001948 retval = -ENOMEM;
1949 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
1952 panelp->magic = STL_PANELMAGIC;
1953 panelp->brdnr = brdp->brdnr;
1954 panelp->panelnr = 0;
1955 panelp->nrports = brdp->nrports;
1956 panelp->iobase = brdp->ioaddr1;
1957 panelp->hwid = status;
1958 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001959 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 panelp->isr = stl_sc26198intr;
1961 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001962 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 panelp->isr = stl_cd1400eiointr;
1964 }
1965
1966 brdp->panels[0] = panelp;
1967 brdp->nrpanels = 1;
1968 brdp->state |= BRD_FOUND;
1969 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001970 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 printk("STALLION: failed to register interrupt "
1972 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001973 retval = -ENODEV;
1974 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001976
1977 return 0;
1978err_fr:
1979 stl_cleanup_panels(brdp);
1980err_rel2:
1981 if (brdp->iosize2 > 0)
1982 release_region(brdp->ioaddr2, brdp->iosize2);
1983err_rel1:
1984 release_region(brdp->ioaddr1, brdp->iosize1);
1985err:
1986 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987}
1988
1989/*****************************************************************************/
1990
1991/*
1992 * Try to find an ECH board and initialize it. This code is capable of
1993 * dealing with all types of ECH board.
1994 */
1995
Jiri Slaby705c1862006-12-08 02:39:11 -08001996static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001998 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001999 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
2000 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 char *name;
2002
Jiri Slabya0564e12006-12-08 02:38:37 -08002003 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
2005 status = 0;
2006 conflict = 0;
2007
2008/*
2009 * Set up the initial board register contents for boards. This varies a
2010 * bit between the different board types. So we need to handle each
2011 * separately. Also do a check that the supplied IRQ is good.
2012 */
2013 switch (brdp->brdtype) {
2014
2015 case BRD_ECH:
2016 brdp->isr = stl_echatintr;
2017 brdp->ioctrl = brdp->ioaddr1 + 1;
2018 brdp->iostatus = brdp->ioaddr1 + 1;
2019 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002020 if ((status & ECH_IDBITMASK) != ECH_ID) {
2021 retval = -ENODEV;
2022 goto err;
2023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2025 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2026 printk("STALLION: invalid irq=%d for brd=%d\n",
2027 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002028 retval = -EINVAL;
2029 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 }
2031 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2032 status |= (stl_vecmap[brdp->irq] << 1);
2033 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2034 brdp->ioctrlval = ECH_INTENABLE |
2035 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002036 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2038 brdp->iosize1 = 2;
2039 brdp->iosize2 = 32;
2040 name = "serial(EC8/32)";
2041 outb(status, brdp->ioaddr1);
2042 break;
2043
2044 case BRD_ECHMC:
2045 brdp->isr = stl_echmcaintr;
2046 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2047 brdp->iostatus = brdp->ioctrl;
2048 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002049 if ((status & ECH_IDBITMASK) != ECH_ID) {
2050 retval = -ENODEV;
2051 goto err;
2052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2054 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2055 printk("STALLION: invalid irq=%d for brd=%d\n",
2056 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002057 retval = -EINVAL;
2058 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 }
2060 outb(ECHMC_BRDRESET, brdp->ioctrl);
2061 outb(ECHMC_INTENABLE, brdp->ioctrl);
2062 brdp->iosize1 = 64;
2063 name = "serial(EC8/32-MC)";
2064 break;
2065
2066 case BRD_ECHPCI:
2067 brdp->isr = stl_echpciintr;
2068 brdp->ioctrl = brdp->ioaddr1 + 2;
2069 brdp->iosize1 = 4;
2070 brdp->iosize2 = 8;
2071 name = "serial(EC8/32-PCI)";
2072 break;
2073
2074 case BRD_ECH64PCI:
2075 brdp->isr = stl_echpci64intr;
2076 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2077 outb(0x43, (brdp->ioaddr1 + 0x4c));
2078 brdp->iosize1 = 0x80;
2079 brdp->iosize2 = 0x80;
2080 name = "serial(EC8/64-PCI)";
2081 break;
2082
2083 default:
2084 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002085 retval = -EINVAL;
2086 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 }
2088
2089/*
2090 * Check boards for possible IO address conflicts and return fail status
2091 * if an IO conflict found.
2092 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002093 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2095 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2096 "%x conflicts with another device\n", brdp->brdnr,
2097 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002098 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 }
2100
2101 if (brdp->iosize2 > 0)
2102 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2103 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2104 "address %x conflicts with another device\n",
2105 brdp->brdnr, brdp->ioaddr2);
2106 printk(KERN_WARNING "STALLION: Warning, also "
2107 "releasing board %d I/O address %x \n",
2108 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002109 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 }
2111
2112/*
2113 * Scan through the secondary io address space looking for panels.
2114 * As we find'em allocate and initialize panel structures for each.
2115 */
2116 brdp->clk = CD1400_CLK;
2117 brdp->hwid = status;
2118
2119 ioaddr = brdp->ioaddr2;
2120 banknr = 0;
2121 panelnr = 0;
2122 nxtid = 0;
2123
Jiri Slabyc62429d2006-12-08 02:39:14 -08002124 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 if (brdp->brdtype == BRD_ECHPCI) {
2126 outb(nxtid, brdp->ioctrl);
2127 ioaddr = brdp->ioaddr2;
2128 }
2129 status = inb(ioaddr + ECH_PNLSTATUS);
2130 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002131 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002132 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002133 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002135 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002136 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002137 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 panelp->magic = STL_PANELMAGIC;
2140 panelp->brdnr = brdp->brdnr;
2141 panelp->panelnr = panelnr;
2142 panelp->iobase = ioaddr;
2143 panelp->pagenr = nxtid;
2144 panelp->hwid = status;
2145 brdp->bnk2panel[banknr] = panelp;
2146 brdp->bnkpageaddr[banknr] = nxtid;
2147 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2148
2149 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002150 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 panelp->isr = stl_sc26198intr;
2152 if (status & ECH_PNL16PORT) {
2153 panelp->nrports = 16;
2154 brdp->bnk2panel[banknr] = panelp;
2155 brdp->bnkpageaddr[banknr] = nxtid;
2156 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2157 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002158 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002161 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 panelp->isr = stl_cd1400echintr;
2163 if (status & ECH_PNL16PORT) {
2164 panelp->nrports = 16;
2165 panelp->ackmask = 0x80;
2166 if (brdp->brdtype != BRD_ECHPCI)
2167 ioaddr += EREG_BANKSIZE;
2168 brdp->bnk2panel[banknr] = panelp;
2169 brdp->bnkpageaddr[banknr] = ++nxtid;
2170 brdp->bnkstataddr[banknr++] = ioaddr +
2171 ECH_PNLSTATUS;
2172 } else {
2173 panelp->nrports = 8;
2174 panelp->ackmask = 0xc0;
2175 }
2176 }
2177
2178 nxtid++;
2179 ioaddr += EREG_BANKSIZE;
2180 brdp->nrports += panelp->nrports;
2181 brdp->panels[panelnr++] = panelp;
2182 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002183 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2184 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002185 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 }
2188
2189 brdp->nrpanels = panelnr;
2190 brdp->nrbnks = banknr;
2191 if (brdp->brdtype == BRD_ECH)
2192 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2193
2194 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002195 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 printk("STALLION: failed to register interrupt "
2197 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002198 retval = -ENODEV;
2199 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 }
2201
Jiri Slaby3b85b342006-12-08 02:39:10 -08002202 return 0;
2203err_fr:
2204 stl_cleanup_panels(brdp);
2205 if (brdp->iosize2 > 0)
2206 release_region(brdp->ioaddr2, brdp->iosize2);
2207err_rel1:
2208 release_region(brdp->ioaddr1, brdp->iosize1);
2209err:
2210 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211}
2212
2213/*****************************************************************************/
2214
2215/*
2216 * Initialize and configure the specified board.
2217 * Scan through all the boards in the configuration and see what we
2218 * can find. Handle EIO and the ECH boards a little differently here
2219 * since the initial search and setup is very different.
2220 */
2221
Jiri Slaby705c1862006-12-08 02:39:11 -08002222static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002224 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
Jiri Slabya0564e12006-12-08 02:38:37 -08002226 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
2228 switch (brdp->brdtype) {
2229 case BRD_EASYIO:
2230 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002231 retval = stl_initeio(brdp);
2232 if (retval)
2233 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 break;
2235 case BRD_ECH:
2236 case BRD_ECHMC:
2237 case BRD_ECHPCI:
2238 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002239 retval = stl_initech(brdp);
2240 if (retval)
2241 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 break;
2243 default:
2244 printk("STALLION: board=%d is unknown board type=%d\n",
2245 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002246 retval = -ENODEV;
2247 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 }
2249
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 if ((brdp->state & BRD_FOUND) == 0) {
2251 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2252 stl_brdnames[brdp->brdtype], brdp->brdnr,
2253 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002254 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 }
2256
Jiri Slabyc62429d2006-12-08 02:39:14 -08002257 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002258 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 stl_initports(brdp, brdp->panels[i]);
2260
2261 printk("STALLION: %s found, board=%d io=%x irq=%d "
2262 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2263 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2264 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002265
2266 return 0;
2267err_free:
2268 free_irq(brdp->irq, brdp);
2269
2270 stl_cleanup_panels(brdp);
2271
2272 release_region(brdp->ioaddr1, brdp->iosize1);
2273 if (brdp->iosize2 > 0)
2274 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002275err:
2276 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277}
2278
2279/*****************************************************************************/
2280
2281/*
2282 * Find the next available board number that is free.
2283 */
2284
Jiri Slaby705c1862006-12-08 02:39:11 -08002285static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002287 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
Jiri Slabyc62429d2006-12-08 02:39:14 -08002289 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002290 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 if (i >= stl_nrbrds)
2292 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002293 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002295
2296 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297}
2298
2299/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300/*
2301 * We have a Stallion board. Allocate a board structure and
2302 * initialize it. Read its IO and IRQ resources from PCI
2303 * configuration space.
2304 */
2305
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002306static int __devinit stl_pciprobe(struct pci_dev *pdev,
2307 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002309 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002310 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002311 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002313 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002314 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002315
Jiri Slaby3b85b342006-12-08 02:39:10 -08002316 retval = pci_enable_device(pdev);
2317 if (retval)
2318 goto err;
2319 brdp = stl_allocbrd();
2320 if (brdp == NULL) {
2321 retval = -ENOMEM;
2322 goto err;
2323 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002324 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002325 brdnr = stl_getbrdnr();
2326 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002327 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002329 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002330 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002331 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002333 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002334 stl_brds[brdp->brdnr] = brdp;
2335 mutex_unlock(&stl_brdslock);
2336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002338 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339
2340/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 * We have all resources from the board, so let's setup the actual
2342 * board structure now.
2343 */
2344 switch (brdtype) {
2345 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002346 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2347 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 break;
2349 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002350 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2351 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 break;
2353 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002354 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2355 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 break;
2357 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002358 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 break;
2360 }
2361
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002362 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002363 retval = stl_brdinit(brdp);
2364 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002365 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002367 pci_set_drvdata(pdev, brdp);
2368
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002369 for (i = 0; i < brdp->nrports; i++)
2370 tty_register_device(stl_serial,
2371 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2372
Jiri Slaby3b85b342006-12-08 02:39:10 -08002373 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002374err_null:
2375 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002376err_fr:
2377 kfree(brdp);
2378err:
2379 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380}
2381
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002382static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002384 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002385 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002387 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002389 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002391 release_region(brdp->ioaddr1, brdp->iosize1);
2392 if (brdp->iosize2 > 0)
2393 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002395 for (i = 0; i < brdp->nrports; i++)
2396 tty_unregister_device(stl_serial,
2397 brdp->brdnr * STL_MAXPORTS + i);
2398
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002399 stl_brds[brdp->brdnr] = NULL;
2400 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401}
2402
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002403static struct pci_driver stl_pcidriver = {
2404 .name = "stallion",
2405 .id_table = stl_pcibrds,
2406 .probe = stl_pciprobe,
2407 .remove = __devexit_p(stl_pciremove)
2408};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
2410/*****************************************************************************/
2411
2412/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 * Return the board stats structure to user app.
2414 */
2415
2416static int stl_getbrdstats(combrd_t __user *bp)
2417{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002418 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002419 struct stlbrd *brdp;
2420 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002421 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
2423 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2424 return -EFAULT;
2425 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002426 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002428 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002429 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430
2431 memset(&stl_brdstats, 0, sizeof(combrd_t));
2432 stl_brdstats.brd = brdp->brdnr;
2433 stl_brdstats.type = brdp->brdtype;
2434 stl_brdstats.hwid = brdp->hwid;
2435 stl_brdstats.state = brdp->state;
2436 stl_brdstats.ioaddr = brdp->ioaddr1;
2437 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2438 stl_brdstats.irq = brdp->irq;
2439 stl_brdstats.nrpanels = brdp->nrpanels;
2440 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002441 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 panelp = brdp->panels[i];
2443 stl_brdstats.panels[i].panel = i;
2444 stl_brdstats.panels[i].hwid = panelp->hwid;
2445 stl_brdstats.panels[i].nrports = panelp->nrports;
2446 }
2447
2448 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2449}
2450
2451/*****************************************************************************/
2452
2453/*
2454 * Resolve the referenced port number into a port struct pointer.
2455 */
2456
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002457static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002459 struct stlbrd *brdp;
2460 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461
Jiri Slabyc62429d2006-12-08 02:39:14 -08002462 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2463 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002465 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002466 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002467 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002468 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002470 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002471 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002472 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002473 return NULL;
2474 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475}
2476
2477/*****************************************************************************/
2478
2479/*
2480 * Return the port stats structure to user app. A NULL port struct
2481 * pointer passed in means that we need to find out from the app
2482 * what port to get stats for (used through board control device).
2483 */
2484
Alan Coxd18a7502008-10-13 10:40:07 +01002485static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002487 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 unsigned char *head, *tail;
2489 unsigned long flags;
2490
2491 if (!portp) {
2492 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2493 return -EFAULT;
2494 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2495 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002496 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002497 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 }
2499
2500 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002501 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 portp->stats.hwid = portp->hwid;
2503
2504 portp->stats.ttystate = 0;
2505 portp->stats.cflags = 0;
2506 portp->stats.iflags = 0;
2507 portp->stats.oflags = 0;
2508 portp->stats.lflags = 0;
2509 portp->stats.rxbuffered = 0;
2510
Alan Coxb65b5b52006-06-27 02:54:05 -07002511 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002512 if (tty != NULL && portp->port.tty == tty) {
2513 portp->stats.ttystate = tty->flags;
2514 /* No longer available as a statistic */
2515 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2516 if (tty->termios != NULL) {
2517 portp->stats.cflags = tty->termios->c_cflag;
2518 portp->stats.iflags = tty->termios->c_iflag;
2519 portp->stats.oflags = tty->termios->c_oflag;
2520 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 }
Alan Coxd18a7502008-10-13 10:40:07 +01002522 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002523 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524
2525 head = portp->tx.head;
2526 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002527 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2528 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529
2530 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2531
2532 return copy_to_user(cp, &portp->stats,
2533 sizeof(comstats_t)) ? -EFAULT : 0;
2534}
2535
2536/*****************************************************************************/
2537
2538/*
2539 * Clear the port stats structure. We also return it zeroed out...
2540 */
2541
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002542static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002544 comstats_t stl_comstats;
2545
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 if (!portp) {
2547 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2548 return -EFAULT;
2549 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2550 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002551 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002552 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 }
2554
2555 memset(&portp->stats, 0, sizeof(comstats_t));
2556 portp->stats.brd = portp->brdnr;
2557 portp->stats.panel = portp->panelnr;
2558 portp->stats.port = portp->portnr;
2559 return copy_to_user(cp, &portp->stats,
2560 sizeof(comstats_t)) ? -EFAULT : 0;
2561}
2562
2563/*****************************************************************************/
2564
2565/*
2566 * Return the entire driver ports structure to a user app.
2567 */
2568
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002569static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002571 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002572 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002574 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 return -EFAULT;
2576 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2577 stl_dummyport.portnr);
2578 if (!portp)
2579 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002580 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581}
2582
2583/*****************************************************************************/
2584
2585/*
2586 * Return the entire driver board structure to a user app.
2587 */
2588
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002589static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002591 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002592 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002594 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002596 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 return -ENODEV;
2598 brdp = stl_brds[stl_dummybrd.brdnr];
2599 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002600 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002601 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602}
2603
2604/*****************************************************************************/
2605
2606/*
2607 * The "staliomem" device is also required to do some special operations
2608 * on the board and/or ports. In this driver it is mostly used for stats
2609 * collection.
2610 */
2611
2612static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2613{
2614 int brdnr, rc;
2615 void __user *argp = (void __user *)arg;
2616
Jiri Slabya0564e12006-12-08 02:38:37 -08002617 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618
2619 brdnr = iminor(ip);
2620 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002621 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 rc = 0;
2623
2624 switch (cmd) {
2625 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002626 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 break;
2628 case COM_CLRPORTSTATS:
2629 rc = stl_clrportstats(NULL, argp);
2630 break;
2631 case COM_GETBRDSTATS:
2632 rc = stl_getbrdstats(argp);
2633 break;
2634 case COM_READPORT:
2635 rc = stl_getportstruct(argp);
2636 break;
2637 case COM_READBOARD:
2638 rc = stl_getbrdstruct(argp);
2639 break;
2640 default:
2641 rc = -ENOIOCTLCMD;
2642 break;
2643 }
2644
Jiri Slabyc62429d2006-12-08 02:39:14 -08002645 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646}
2647
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002648static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 .open = stl_open,
2650 .close = stl_close,
2651 .write = stl_write,
2652 .put_char = stl_putchar,
2653 .flush_chars = stl_flushchars,
2654 .write_room = stl_writeroom,
2655 .chars_in_buffer = stl_charsinbuffer,
2656 .ioctl = stl_ioctl,
2657 .set_termios = stl_settermios,
2658 .throttle = stl_throttle,
2659 .unthrottle = stl_unthrottle,
2660 .stop = stl_stop,
2661 .start = stl_start,
2662 .hangup = stl_hangup,
2663 .flush_buffer = stl_flushbuffer,
2664 .break_ctl = stl_breakctl,
2665 .wait_until_sent = stl_waituntilsent,
2666 .send_xchar = stl_sendxchar,
2667 .read_proc = stl_readproc,
2668 .tiocmget = stl_tiocmget,
2669 .tiocmset = stl_tiocmset,
2670};
2671
Alan Cox31f35932009-01-02 13:45:05 +00002672static const struct tty_port_operations stl_port_ops = {
2673 .carrier_raised = stl_carrier_raised,
2674};
2675
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677/* CD1400 HARDWARE FUNCTIONS */
2678/*****************************************************************************/
2679
2680/*
2681 * These functions get/set/update the registers of the cd1400 UARTs.
2682 * Access to the cd1400 registers is via an address/data io port pair.
2683 * (Maybe should make this inline...)
2684 */
2685
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002686static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687{
2688 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002689 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690}
2691
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002692static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002694 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 outb(value, portp->ioaddr + EREG_DATA);
2696}
2697
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002698static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002700 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 if (inb(portp->ioaddr + EREG_DATA) != value) {
2702 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002703 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002705 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706}
2707
2708/*****************************************************************************/
2709
2710/*
2711 * Inbitialize the UARTs in a panel. We don't care what sort of board
2712 * these ports are on - since the port io registers are almost
2713 * identical when dealing with ports.
2714 */
2715
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002716static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717{
2718 unsigned int gfrcr;
2719 int chipmask, i, j;
2720 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002721 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
Jiri Slabya0564e12006-12-08 02:38:37 -08002723 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
Alan Coxb65b5b52006-06-27 02:54:05 -07002725 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 BRDENABLE(panelp->brdnr, panelp->pagenr);
2727
2728/*
2729 * Check that each chip is present and started up OK.
2730 */
2731 chipmask = 0;
2732 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002733 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 if (brdp->brdtype == BRD_ECHPCI) {
2735 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2736 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002737 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 uartaddr = (i & 0x01) ? 0x080 : 0;
2740 outb((GFRCR + uartaddr), ioaddr);
2741 outb(0, (ioaddr + EREG_DATA));
2742 outb((CCR + uartaddr), ioaddr);
2743 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2744 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2745 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002746 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2748 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002749
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2751 printk("STALLION: cd1400 not responding, "
2752 "brd=%d panel=%d chip=%d\n",
2753 panelp->brdnr, panelp->panelnr, i);
2754 continue;
2755 }
2756 chipmask |= (0x1 << i);
2757 outb((PPR + uartaddr), ioaddr);
2758 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2759 }
2760
2761 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002762 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002763 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764}
2765
2766/*****************************************************************************/
2767
2768/*
2769 * Initialize hardware specific port registers.
2770 */
2771
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002772static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773{
Alan Coxb65b5b52006-06-27 02:54:05 -07002774 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002775 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2776 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
Jiri Slaby615e4a72006-12-08 02:38:38 -08002778 if ((brdp == NULL) || (panelp == NULL) ||
2779 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 return;
2781
Alan Coxb65b5b52006-06-27 02:54:05 -07002782 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2784 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2785 portp->uartaddr = (portp->portnr & 0x04) << 5;
2786 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2787
2788 BRDENABLE(portp->brdnr, portp->pagenr);
2789 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2790 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2791 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2792 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002793 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794}
2795
2796/*****************************************************************************/
2797
2798/*
2799 * Wait for the command register to be ready. We will poll this,
2800 * since it won't usually take too long to be ready.
2801 */
2802
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002803static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804{
2805 int i;
2806
Jiri Slabyc62429d2006-12-08 02:39:14 -08002807 for (i = 0; i < CCR_MAXWAIT; i++)
2808 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810
2811 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2812 portp->portnr, portp->panelnr, portp->brdnr);
2813}
2814
2815/*****************************************************************************/
2816
2817/*
2818 * Set up the cd1400 registers for a port based on the termios port
2819 * settings.
2820 */
2821
Alan Cox606d0992006-12-08 02:38:45 -08002822static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002824 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 unsigned long flags;
2826 unsigned int clkdiv, baudrate;
2827 unsigned char cor1, cor2, cor3;
2828 unsigned char cor4, cor5, ccr;
2829 unsigned char srer, sreron, sreroff;
2830 unsigned char mcor1, mcor2, rtpr;
2831 unsigned char clk, div;
2832
2833 cor1 = 0;
2834 cor2 = 0;
2835 cor3 = 0;
2836 cor4 = 0;
2837 cor5 = 0;
2838 ccr = 0;
2839 rtpr = 0;
2840 clk = 0;
2841 div = 0;
2842 mcor1 = 0;
2843 mcor2 = 0;
2844 sreron = 0;
2845 sreroff = 0;
2846
2847 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002848 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 return;
2850
2851/*
2852 * Set up the RX char ignore mask with those RX error types we
2853 * can ignore. We can get the cd1400 to help us out a little here,
2854 * it will ignore parity errors and breaks for us.
2855 */
2856 portp->rxignoremsk = 0;
2857 if (tiosp->c_iflag & IGNPAR) {
2858 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2859 cor1 |= COR1_PARIGNORE;
2860 }
2861 if (tiosp->c_iflag & IGNBRK) {
2862 portp->rxignoremsk |= ST_BREAK;
2863 cor4 |= COR4_IGNBRK;
2864 }
2865
2866 portp->rxmarkmsk = ST_OVERRUN;
2867 if (tiosp->c_iflag & (INPCK | PARMRK))
2868 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2869 if (tiosp->c_iflag & BRKINT)
2870 portp->rxmarkmsk |= ST_BREAK;
2871
2872/*
2873 * Go through the char size, parity and stop bits and set all the
2874 * option register appropriately.
2875 */
2876 switch (tiosp->c_cflag & CSIZE) {
2877 case CS5:
2878 cor1 |= COR1_CHL5;
2879 break;
2880 case CS6:
2881 cor1 |= COR1_CHL6;
2882 break;
2883 case CS7:
2884 cor1 |= COR1_CHL7;
2885 break;
2886 default:
2887 cor1 |= COR1_CHL8;
2888 break;
2889 }
2890
2891 if (tiosp->c_cflag & CSTOPB)
2892 cor1 |= COR1_STOP2;
2893 else
2894 cor1 |= COR1_STOP1;
2895
2896 if (tiosp->c_cflag & PARENB) {
2897 if (tiosp->c_cflag & PARODD)
2898 cor1 |= (COR1_PARENB | COR1_PARODD);
2899 else
2900 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2901 } else {
2902 cor1 |= COR1_PARNONE;
2903 }
2904
2905/*
2906 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2907 * space for hardware flow control and the like. This should be set to
2908 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2909 * really be based on VTIME.
2910 */
2911 cor3 |= FIFO_RXTHRESHOLD;
2912 rtpr = 2;
2913
2914/*
2915 * Calculate the baud rate timers. For now we will just assume that
2916 * the input and output baud are the same. Could have used a baud
2917 * table here, but this way we can generate virtually any baud rate
2918 * we like!
2919 */
2920 baudrate = tiosp->c_cflag & CBAUD;
2921 if (baudrate & CBAUDEX) {
2922 baudrate &= ~CBAUDEX;
2923 if ((baudrate < 1) || (baudrate > 4))
2924 tiosp->c_cflag &= ~CBAUDEX;
2925 else
2926 baudrate += 15;
2927 }
2928 baudrate = stl_baudrates[baudrate];
2929 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002930 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002932 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002934 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002936 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002938 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 baudrate = (portp->baud_base / portp->custom_divisor);
2940 }
2941 if (baudrate > STL_CD1400MAXBAUD)
2942 baudrate = STL_CD1400MAXBAUD;
2943
2944 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002945 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2946 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 if (clkdiv < 0x100)
2948 break;
2949 }
2950 div = (unsigned char) clkdiv;
2951 }
2952
2953/*
2954 * Check what form of modem signaling is required and set it up.
2955 */
2956 if ((tiosp->c_cflag & CLOCAL) == 0) {
2957 mcor1 |= MCOR1_DCD;
2958 mcor2 |= MCOR2_DCD;
2959 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002960 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002961 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002962 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963
2964/*
2965 * Setup cd1400 enhanced modes if we can. In particular we want to
2966 * handle as much of the flow control as possible automatically. As
2967 * well as saving a few CPU cycles it will also greatly improve flow
2968 * control reliability.
2969 */
2970 if (tiosp->c_iflag & IXON) {
2971 cor2 |= COR2_TXIBE;
2972 cor3 |= COR3_SCD12;
2973 if (tiosp->c_iflag & IXANY)
2974 cor2 |= COR2_IXM;
2975 }
2976
2977 if (tiosp->c_cflag & CRTSCTS) {
2978 cor2 |= COR2_CTSAE;
2979 mcor1 |= FIFO_RTSTHRESHOLD;
2980 }
2981
2982/*
2983 * All cd1400 register values calculated so go through and set
2984 * them all up.
2985 */
2986
Jiri Slabya0564e12006-12-08 02:38:37 -08002987 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002989 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002991 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002993 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2994 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2996 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997
Alan Coxb65b5b52006-06-27 02:54:05 -07002998 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 BRDENABLE(portp->brdnr, portp->pagenr);
3000 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3001 srer = stl_cd1400getreg(portp, SRER);
3002 stl_cd1400setreg(portp, SRER, 0);
3003 if (stl_cd1400updatereg(portp, COR1, cor1))
3004 ccr = 1;
3005 if (stl_cd1400updatereg(portp, COR2, cor2))
3006 ccr = 1;
3007 if (stl_cd1400updatereg(portp, COR3, cor3))
3008 ccr = 1;
3009 if (ccr) {
3010 stl_cd1400ccrwait(portp);
3011 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3012 }
3013 stl_cd1400setreg(portp, COR4, cor4);
3014 stl_cd1400setreg(portp, COR5, cor5);
3015 stl_cd1400setreg(portp, MCOR1, mcor1);
3016 stl_cd1400setreg(portp, MCOR2, mcor2);
3017 if (baudrate > 0) {
3018 stl_cd1400setreg(portp, TCOR, clk);
3019 stl_cd1400setreg(portp, TBPR, div);
3020 stl_cd1400setreg(portp, RCOR, clk);
3021 stl_cd1400setreg(portp, RBPR, div);
3022 }
3023 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3024 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3025 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3026 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3027 stl_cd1400setreg(portp, RTPR, rtpr);
3028 mcor1 = stl_cd1400getreg(portp, MSVR1);
3029 if (mcor1 & MSVR1_DCD)
3030 portp->sigs |= TIOCM_CD;
3031 else
3032 portp->sigs &= ~TIOCM_CD;
3033 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3034 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003035 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036}
3037
3038/*****************************************************************************/
3039
3040/*
3041 * Set the state of the DTR and RTS signals.
3042 */
3043
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003044static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045{
3046 unsigned char msvr1, msvr2;
3047 unsigned long flags;
3048
Jiri Slabya0564e12006-12-08 02:38:37 -08003049 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3050 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051
3052 msvr1 = 0;
3053 msvr2 = 0;
3054 if (dtr > 0)
3055 msvr1 = MSVR1_DTR;
3056 if (rts > 0)
3057 msvr2 = MSVR2_RTS;
3058
Alan Coxb65b5b52006-06-27 02:54:05 -07003059 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 BRDENABLE(portp->brdnr, portp->pagenr);
3061 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3062 if (rts >= 0)
3063 stl_cd1400setreg(portp, MSVR2, msvr2);
3064 if (dtr >= 0)
3065 stl_cd1400setreg(portp, MSVR1, msvr1);
3066 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003067 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068}
3069
3070/*****************************************************************************/
3071
3072/*
3073 * Return the state of the signals.
3074 */
3075
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003076static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077{
3078 unsigned char msvr1, msvr2;
3079 unsigned long flags;
3080 int sigs;
3081
Jiri Slabya0564e12006-12-08 02:38:37 -08003082 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083
Alan Coxb65b5b52006-06-27 02:54:05 -07003084 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 BRDENABLE(portp->brdnr, portp->pagenr);
3086 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3087 msvr1 = stl_cd1400getreg(portp, MSVR1);
3088 msvr2 = stl_cd1400getreg(portp, MSVR2);
3089 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003090 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091
3092 sigs = 0;
3093 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3094 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3095 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3096 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3097#if 0
3098 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3099 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3100#else
3101 sigs |= TIOCM_DSR;
3102#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003103 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104}
3105
3106/*****************************************************************************/
3107
3108/*
3109 * Enable/Disable the Transmitter and/or Receiver.
3110 */
3111
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003112static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113{
3114 unsigned char ccr;
3115 unsigned long flags;
3116
Jiri Slabya0564e12006-12-08 02:38:37 -08003117 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3118
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 ccr = 0;
3120
3121 if (tx == 0)
3122 ccr |= CCR_TXDISABLE;
3123 else if (tx > 0)
3124 ccr |= CCR_TXENABLE;
3125 if (rx == 0)
3126 ccr |= CCR_RXDISABLE;
3127 else if (rx > 0)
3128 ccr |= CCR_RXENABLE;
3129
Alan Coxb65b5b52006-06-27 02:54:05 -07003130 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 BRDENABLE(portp->brdnr, portp->pagenr);
3132 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3133 stl_cd1400ccrwait(portp);
3134 stl_cd1400setreg(portp, CCR, ccr);
3135 stl_cd1400ccrwait(portp);
3136 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003137 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138}
3139
3140/*****************************************************************************/
3141
3142/*
3143 * Start/stop the Transmitter and/or Receiver.
3144 */
3145
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003146static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147{
3148 unsigned char sreron, sreroff;
3149 unsigned long flags;
3150
Jiri Slabya0564e12006-12-08 02:38:37 -08003151 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152
3153 sreron = 0;
3154 sreroff = 0;
3155 if (tx == 0)
3156 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3157 else if (tx == 1)
3158 sreron |= SRER_TXDATA;
3159 else if (tx >= 2)
3160 sreron |= SRER_TXEMPTY;
3161 if (rx == 0)
3162 sreroff |= SRER_RXDATA;
3163 else if (rx > 0)
3164 sreron |= SRER_RXDATA;
3165
Alan Coxb65b5b52006-06-27 02:54:05 -07003166 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 BRDENABLE(portp->brdnr, portp->pagenr);
3168 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3169 stl_cd1400setreg(portp, SRER,
3170 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3171 BRDDISABLE(portp->brdnr);
3172 if (tx > 0)
3173 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003174 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175}
3176
3177/*****************************************************************************/
3178
3179/*
3180 * Disable all interrupts from this port.
3181 */
3182
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003183static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184{
3185 unsigned long flags;
3186
Jiri Slabya0564e12006-12-08 02:38:37 -08003187 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3188
Alan Coxb65b5b52006-06-27 02:54:05 -07003189 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190 BRDENABLE(portp->brdnr, portp->pagenr);
3191 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3192 stl_cd1400setreg(portp, SRER, 0);
3193 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003194 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195}
3196
3197/*****************************************************************************/
3198
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003199static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200{
3201 unsigned long flags;
3202
Jiri Slabya0564e12006-12-08 02:38:37 -08003203 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204
Alan Coxb65b5b52006-06-27 02:54:05 -07003205 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 BRDENABLE(portp->brdnr, portp->pagenr);
3207 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3208 stl_cd1400setreg(portp, SRER,
3209 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3210 SRER_TXEMPTY));
3211 BRDDISABLE(portp->brdnr);
3212 portp->brklen = len;
3213 if (len == 1)
3214 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003215 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216}
3217
3218/*****************************************************************************/
3219
3220/*
3221 * Take flow control actions...
3222 */
3223
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003224static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225{
3226 struct tty_struct *tty;
3227 unsigned long flags;
3228
Jiri Slabya0564e12006-12-08 02:38:37 -08003229 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
Jiri Slaby615e4a72006-12-08 02:38:38 -08003231 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003233 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003234 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 return;
3236
Alan Coxb65b5b52006-06-27 02:54:05 -07003237 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 BRDENABLE(portp->brdnr, portp->pagenr);
3239 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3240
3241 if (state) {
3242 if (tty->termios->c_iflag & IXOFF) {
3243 stl_cd1400ccrwait(portp);
3244 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3245 portp->stats.rxxon++;
3246 stl_cd1400ccrwait(portp);
3247 }
3248/*
3249 * Question: should we return RTS to what it was before? It may
3250 * have been set by an ioctl... Suppose not, since if you have
3251 * hardware flow control set then it is pretty silly to go and
3252 * set the RTS line by hand.
3253 */
3254 if (tty->termios->c_cflag & CRTSCTS) {
3255 stl_cd1400setreg(portp, MCOR1,
3256 (stl_cd1400getreg(portp, MCOR1) |
3257 FIFO_RTSTHRESHOLD));
3258 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3259 portp->stats.rxrtson++;
3260 }
3261 } else {
3262 if (tty->termios->c_iflag & IXOFF) {
3263 stl_cd1400ccrwait(portp);
3264 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3265 portp->stats.rxxoff++;
3266 stl_cd1400ccrwait(portp);
3267 }
3268 if (tty->termios->c_cflag & CRTSCTS) {
3269 stl_cd1400setreg(portp, MCOR1,
3270 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3271 stl_cd1400setreg(portp, MSVR2, 0);
3272 portp->stats.rxrtsoff++;
3273 }
3274 }
3275
3276 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003277 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003278 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279}
3280
3281/*****************************************************************************/
3282
3283/*
3284 * Send a flow control character...
3285 */
3286
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003287static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288{
3289 struct tty_struct *tty;
3290 unsigned long flags;
3291
Jiri Slabya0564e12006-12-08 02:38:37 -08003292 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293
Jiri Slaby615e4a72006-12-08 02:38:38 -08003294 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003296 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003297 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 return;
3299
Alan Coxb65b5b52006-06-27 02:54:05 -07003300 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301 BRDENABLE(portp->brdnr, portp->pagenr);
3302 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3303 if (state) {
3304 stl_cd1400ccrwait(portp);
3305 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3306 portp->stats.rxxon++;
3307 stl_cd1400ccrwait(portp);
3308 } else {
3309 stl_cd1400ccrwait(portp);
3310 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3311 portp->stats.rxxoff++;
3312 stl_cd1400ccrwait(portp);
3313 }
3314 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003315 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003316 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317}
3318
3319/*****************************************************************************/
3320
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003321static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322{
3323 unsigned long flags;
3324
Jiri Slabya0564e12006-12-08 02:38:37 -08003325 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326
Jiri Slaby615e4a72006-12-08 02:38:38 -08003327 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328 return;
3329
Alan Coxb65b5b52006-06-27 02:54:05 -07003330 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331 BRDENABLE(portp->brdnr, portp->pagenr);
3332 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3333 stl_cd1400ccrwait(portp);
3334 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3335 stl_cd1400ccrwait(portp);
3336 portp->tx.tail = portp->tx.head;
3337 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003338 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339}
3340
3341/*****************************************************************************/
3342
3343/*
3344 * Return the current state of data flow on this port. This is only
3345 * really interresting when determining if data has fully completed
3346 * transmission or not... This is easy for the cd1400, it accurately
3347 * maintains the busy port flag.
3348 */
3349
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003350static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351{
Jiri Slabya0564e12006-12-08 02:38:37 -08003352 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353
Jiri Slaby615e4a72006-12-08 02:38:38 -08003354 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003355 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356
Jesper Juhl014c2542006-01-15 02:37:08 +01003357 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358}
3359
3360/*****************************************************************************/
3361
3362/*
3363 * Interrupt service routine for cd1400 EasyIO boards.
3364 */
3365
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003366static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367{
3368 unsigned char svrtype;
3369
Jiri Slabya0564e12006-12-08 02:38:37 -08003370 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371
Alan Coxb65b5b52006-06-27 02:54:05 -07003372 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 outb(SVRR, iobase);
3374 svrtype = inb(iobase + EREG_DATA);
3375 if (panelp->nrports > 4) {
3376 outb((SVRR + 0x80), iobase);
3377 svrtype |= inb(iobase + EREG_DATA);
3378 }
3379
3380 if (svrtype & SVRR_RX)
3381 stl_cd1400rxisr(panelp, iobase);
3382 else if (svrtype & SVRR_TX)
3383 stl_cd1400txisr(panelp, iobase);
3384 else if (svrtype & SVRR_MDM)
3385 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003386
3387 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388}
3389
3390/*****************************************************************************/
3391
3392/*
3393 * Interrupt service routine for cd1400 panels.
3394 */
3395
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003396static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397{
3398 unsigned char svrtype;
3399
Jiri Slabya0564e12006-12-08 02:38:37 -08003400 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401
3402 outb(SVRR, iobase);
3403 svrtype = inb(iobase + EREG_DATA);
3404 outb((SVRR + 0x80), iobase);
3405 svrtype |= inb(iobase + EREG_DATA);
3406 if (svrtype & SVRR_RX)
3407 stl_cd1400rxisr(panelp, iobase);
3408 else if (svrtype & SVRR_TX)
3409 stl_cd1400txisr(panelp, iobase);
3410 else if (svrtype & SVRR_MDM)
3411 stl_cd1400mdmisr(panelp, iobase);
3412}
3413
3414
3415/*****************************************************************************/
3416
3417/*
3418 * Unfortunately we need to handle breaks in the TX data stream, since
3419 * this is the only way to generate them on the cd1400.
3420 */
3421
Jiri Slaby60be4812006-12-08 02:38:40 -08003422static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423{
3424 if (portp->brklen == 1) {
3425 outb((COR2 + portp->uartaddr), ioaddr);
3426 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3427 (ioaddr + EREG_DATA));
3428 outb((TDR + portp->uartaddr), ioaddr);
3429 outb(ETC_CMD, (ioaddr + EREG_DATA));
3430 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3431 outb((SRER + portp->uartaddr), ioaddr);
3432 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3433 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003434 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 } else if (portp->brklen > 1) {
3436 outb((TDR + portp->uartaddr), ioaddr);
3437 outb(ETC_CMD, (ioaddr + EREG_DATA));
3438 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3439 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003440 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 } else {
3442 outb((COR2 + portp->uartaddr), ioaddr);
3443 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3444 (ioaddr + EREG_DATA));
3445 portp->brklen = 0;
3446 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003447 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448}
3449
3450/*****************************************************************************/
3451
3452/*
3453 * Transmit interrupt handler. This has gotta be fast! Handling TX
3454 * chars is pretty simple, stuff as many as possible from the TX buffer
3455 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3456 * are embedded as commands in the data stream. Oh no, had to use a goto!
3457 * This could be optimized more, will do when I get time...
3458 * In practice it is possible that interrupts are enabled but that the
3459 * port has been hung up. Need to handle not having any TX buffer here,
3460 * this is done by using the side effect that head and tail will also
3461 * be NULL if the buffer has been freed.
3462 */
3463
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003464static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003466 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 int len, stlen;
3468 char *head, *tail;
3469 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003470 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471
Jiri Slabya0564e12006-12-08 02:38:37 -08003472 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473
3474 ioack = inb(ioaddr + EREG_TXACK);
3475 if (((ioack & panelp->ackmask) != 0) ||
3476 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3477 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3478 return;
3479 }
3480 portp = panelp->ports[(ioack >> 3)];
3481
3482/*
3483 * Unfortunately we need to handle breaks in the data stream, since
3484 * this is the only way to generate them on the cd1400. Do it now if
3485 * a break is to be sent.
3486 */
3487 if (portp->brklen != 0)
3488 if (stl_cd1400breakisr(portp, ioaddr))
3489 goto stl_txalldone;
3490
3491 head = portp->tx.head;
3492 tail = portp->tx.tail;
3493 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3494 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3495 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3496 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003497 tty = tty_port_tty_get(&portp->port);
3498 if (tty) {
3499 tty_wakeup(tty);
3500 tty_kref_put(tty);
3501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 }
3503
3504 if (len == 0) {
3505 outb((SRER + portp->uartaddr), ioaddr);
3506 srer = inb(ioaddr + EREG_DATA);
3507 if (srer & SRER_TXDATA) {
3508 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3509 } else {
3510 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3511 clear_bit(ASYI_TXBUSY, &portp->istate);
3512 }
3513 outb(srer, (ioaddr + EREG_DATA));
3514 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003515 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003517 stlen = min_t(unsigned int, len,
3518 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 outb((TDR + portp->uartaddr), ioaddr);
3520 outsb((ioaddr + EREG_DATA), tail, stlen);
3521 len -= stlen;
3522 tail += stlen;
3523 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3524 tail = portp->tx.buf;
3525 if (len > 0) {
3526 outsb((ioaddr + EREG_DATA), tail, len);
3527 tail += len;
3528 }
3529 portp->tx.tail = tail;
3530 }
3531
3532stl_txalldone:
3533 outb((EOSRR + portp->uartaddr), ioaddr);
3534 outb(0, (ioaddr + EREG_DATA));
3535}
3536
3537/*****************************************************************************/
3538
3539/*
3540 * Receive character interrupt handler. Determine if we have good chars
3541 * or bad chars and then process appropriately. Good chars are easy
3542 * just shove the lot into the RX buffer and set all status byte to 0.
3543 * If a bad RX char then process as required. This routine needs to be
3544 * fast! In practice it is possible that we get an interrupt on a port
3545 * that is closed. This can happen on hangups - since they completely
3546 * shutdown a port not in user context. Need to handle this case.
3547 */
3548
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003549static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003551 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 struct tty_struct *tty;
3553 unsigned int ioack, len, buflen;
3554 unsigned char status;
3555 char ch;
3556
Jiri Slabya0564e12006-12-08 02:38:37 -08003557 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558
3559 ioack = inb(ioaddr + EREG_RXACK);
3560 if ((ioack & panelp->ackmask) != 0) {
3561 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3562 return;
3563 }
3564 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003565 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566
3567 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3568 outb((RDCR + portp->uartaddr), ioaddr);
3569 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003570 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003571 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 outb((RDSR + portp->uartaddr), ioaddr);
3573 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3574 portp->stats.rxlost += len;
3575 portp->stats.rxtotal += len;
3576 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003577 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003579 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003581 tty_prepare_flip_string(tty, &ptr, len);
3582 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583 tty_schedule_flip(tty);
3584 portp->stats.rxtotal += len;
3585 }
3586 }
3587 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3588 outb((RDSR + portp->uartaddr), ioaddr);
3589 status = inb(ioaddr + EREG_DATA);
3590 ch = inb(ioaddr + EREG_DATA);
3591 if (status & ST_PARITY)
3592 portp->stats.rxparity++;
3593 if (status & ST_FRAMING)
3594 portp->stats.rxframing++;
3595 if (status & ST_OVERRUN)
3596 portp->stats.rxoverrun++;
3597 if (status & ST_BREAK)
3598 portp->stats.rxbreaks++;
3599 if (status & ST_SCHARMASK) {
3600 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3601 portp->stats.txxon++;
3602 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3603 portp->stats.txxoff++;
3604 goto stl_rxalldone;
3605 }
Alan Cox33f0f882006-01-09 20:54:13 -08003606 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607 if (portp->rxmarkmsk & status) {
3608 if (status & ST_BREAK) {
3609 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003610 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 do_SAK(tty);
3612 BRDENABLE(portp->brdnr, portp->pagenr);
3613 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003614 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003616 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003618 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003620 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003622 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003624 tty_insert_flip_char(tty, ch, status);
3625 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 }
3627 } else {
3628 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003629 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 return;
3631 }
3632
3633stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003634 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 outb((EOSRR + portp->uartaddr), ioaddr);
3636 outb(0, (ioaddr + EREG_DATA));
3637}
3638
3639/*****************************************************************************/
3640
3641/*
3642 * Modem interrupt handler. The is called when the modem signal line
3643 * (DCD) has changed state. Leave most of the work to the off-level
3644 * processing routine.
3645 */
3646
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003647static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003649 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 unsigned int ioack;
3651 unsigned char misr;
3652
Jiri Slabya0564e12006-12-08 02:38:37 -08003653 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654
3655 ioack = inb(ioaddr + EREG_MDACK);
3656 if (((ioack & panelp->ackmask) != 0) ||
3657 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3658 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3659 return;
3660 }
3661 portp = panelp->ports[(ioack >> 3)];
3662
3663 outb((MISR + portp->uartaddr), ioaddr);
3664 misr = inb(ioaddr + EREG_DATA);
3665 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003666 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667 portp->stats.modem++;
3668 }
3669
3670 outb((EOSRR + portp->uartaddr), ioaddr);
3671 outb(0, (ioaddr + EREG_DATA));
3672}
3673
3674/*****************************************************************************/
3675/* SC26198 HARDWARE FUNCTIONS */
3676/*****************************************************************************/
3677
3678/*
3679 * These functions get/set/update the registers of the sc26198 UARTs.
3680 * Access to the sc26198 registers is via an address/data io port pair.
3681 * (Maybe should make this inline...)
3682 */
3683
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003684static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685{
3686 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003687 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688}
3689
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003690static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691{
3692 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3693 outb(value, (portp->ioaddr + XP_DATA));
3694}
3695
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003696static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697{
3698 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3699 if (inb(portp->ioaddr + XP_DATA) != value) {
3700 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003701 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003703 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704}
3705
3706/*****************************************************************************/
3707
3708/*
3709 * Functions to get and set the sc26198 global registers.
3710 */
3711
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003712static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713{
3714 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003715 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716}
3717
3718#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003719static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720{
3721 outb(regnr, (portp->ioaddr + XP_ADDR));
3722 outb(value, (portp->ioaddr + XP_DATA));
3723}
3724#endif
3725
3726/*****************************************************************************/
3727
3728/*
3729 * Inbitialize the UARTs in a panel. We don't care what sort of board
3730 * these ports are on - since the port io registers are almost
3731 * identical when dealing with ports.
3732 */
3733
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003734static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735{
3736 int chipmask, i;
3737 int nrchips, ioaddr;
3738
Jiri Slabya0564e12006-12-08 02:38:37 -08003739 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
3741 BRDENABLE(panelp->brdnr, panelp->pagenr);
3742
3743/*
3744 * Check that each chip is present and started up OK.
3745 */
3746 chipmask = 0;
3747 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3748 if (brdp->brdtype == BRD_ECHPCI)
3749 outb(panelp->pagenr, brdp->ioctrl);
3750
Jiri Slabyc62429d2006-12-08 02:39:14 -08003751 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752 ioaddr = panelp->iobase + (i * 4);
3753 outb(SCCR, (ioaddr + XP_ADDR));
3754 outb(CR_RESETALL, (ioaddr + XP_DATA));
3755 outb(TSTR, (ioaddr + XP_ADDR));
3756 if (inb(ioaddr + XP_DATA) != 0) {
3757 printk("STALLION: sc26198 not responding, "
3758 "brd=%d panel=%d chip=%d\n",
3759 panelp->brdnr, panelp->panelnr, i);
3760 continue;
3761 }
3762 chipmask |= (0x1 << i);
3763 outb(GCCR, (ioaddr + XP_ADDR));
3764 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3765 outb(WDTRCR, (ioaddr + XP_ADDR));
3766 outb(0xff, (ioaddr + XP_DATA));
3767 }
3768
3769 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003770 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771}
3772
3773/*****************************************************************************/
3774
3775/*
3776 * Initialize hardware specific port registers.
3777 */
3778
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003779static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780{
Jiri Slabya0564e12006-12-08 02:38:37 -08003781 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3782 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783
Jiri Slaby615e4a72006-12-08 02:38:38 -08003784 if ((brdp == NULL) || (panelp == NULL) ||
3785 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 return;
3787
3788 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3789 portp->uartaddr = (portp->portnr & 0x07) << 4;
3790 portp->pagenr = panelp->pagenr;
3791 portp->hwid = 0x1;
3792
3793 BRDENABLE(portp->brdnr, portp->pagenr);
3794 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3795 BRDDISABLE(portp->brdnr);
3796}
3797
3798/*****************************************************************************/
3799
3800/*
3801 * Set up the sc26198 registers for a port based on the termios port
3802 * settings.
3803 */
3804
Alan Cox606d0992006-12-08 02:38:45 -08003805static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003807 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808 unsigned long flags;
3809 unsigned int baudrate;
3810 unsigned char mr0, mr1, mr2, clk;
3811 unsigned char imron, imroff, iopr, ipr;
3812
3813 mr0 = 0;
3814 mr1 = 0;
3815 mr2 = 0;
3816 clk = 0;
3817 iopr = 0;
3818 imron = 0;
3819 imroff = 0;
3820
3821 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003822 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823 return;
3824
3825/*
3826 * Set up the RX char ignore mask with those RX error types we
3827 * can ignore.
3828 */
3829 portp->rxignoremsk = 0;
3830 if (tiosp->c_iflag & IGNPAR)
3831 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3832 SR_RXOVERRUN);
3833 if (tiosp->c_iflag & IGNBRK)
3834 portp->rxignoremsk |= SR_RXBREAK;
3835
3836 portp->rxmarkmsk = SR_RXOVERRUN;
3837 if (tiosp->c_iflag & (INPCK | PARMRK))
3838 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3839 if (tiosp->c_iflag & BRKINT)
3840 portp->rxmarkmsk |= SR_RXBREAK;
3841
3842/*
3843 * Go through the char size, parity and stop bits and set all the
3844 * option register appropriately.
3845 */
3846 switch (tiosp->c_cflag & CSIZE) {
3847 case CS5:
3848 mr1 |= MR1_CS5;
3849 break;
3850 case CS6:
3851 mr1 |= MR1_CS6;
3852 break;
3853 case CS7:
3854 mr1 |= MR1_CS7;
3855 break;
3856 default:
3857 mr1 |= MR1_CS8;
3858 break;
3859 }
3860
3861 if (tiosp->c_cflag & CSTOPB)
3862 mr2 |= MR2_STOP2;
3863 else
3864 mr2 |= MR2_STOP1;
3865
3866 if (tiosp->c_cflag & PARENB) {
3867 if (tiosp->c_cflag & PARODD)
3868 mr1 |= (MR1_PARENB | MR1_PARODD);
3869 else
3870 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003871 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873
3874 mr1 |= MR1_ERRBLOCK;
3875
3876/*
3877 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3878 * space for hardware flow control and the like. This should be set to
3879 * VMIN.
3880 */
3881 mr2 |= MR2_RXFIFOHALF;
3882
3883/*
3884 * Calculate the baud rate timers. For now we will just assume that
3885 * the input and output baud are the same. The sc26198 has a fixed
3886 * baud rate table, so only discrete baud rates possible.
3887 */
3888 baudrate = tiosp->c_cflag & CBAUD;
3889 if (baudrate & CBAUDEX) {
3890 baudrate &= ~CBAUDEX;
3891 if ((baudrate < 1) || (baudrate > 4))
3892 tiosp->c_cflag &= ~CBAUDEX;
3893 else
3894 baudrate += 15;
3895 }
3896 baudrate = stl_baudrates[baudrate];
3897 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003898 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003900 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003902 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003904 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003906 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 baudrate = (portp->baud_base / portp->custom_divisor);
3908 }
3909 if (baudrate > STL_SC26198MAXBAUD)
3910 baudrate = STL_SC26198MAXBAUD;
3911
Jiri Slabyc62429d2006-12-08 02:39:14 -08003912 if (baudrate > 0)
3913 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914 if (baudrate <= sc26198_baudtable[clk])
3915 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916
3917/*
3918 * Check what form of modem signaling is required and set it up.
3919 */
3920 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003921 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 } else {
3923 iopr |= IOPR_DCDCOS;
3924 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003925 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 }
3927
3928/*
3929 * Setup sc26198 enhanced modes if we can. In particular we want to
3930 * handle as much of the flow control as possible automatically. As
3931 * well as saving a few CPU cycles it will also greatly improve flow
3932 * control reliability.
3933 */
3934 if (tiosp->c_iflag & IXON) {
3935 mr0 |= MR0_SWFTX | MR0_SWFT;
3936 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003937 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003939
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 if (tiosp->c_iflag & IXOFF)
3941 mr0 |= MR0_SWFRX;
3942
3943 if (tiosp->c_cflag & CRTSCTS) {
3944 mr2 |= MR2_AUTOCTS;
3945 mr1 |= MR1_AUTORTS;
3946 }
3947
3948/*
3949 * All sc26198 register values calculated so go through and set
3950 * them all up.
3951 */
3952
Jiri Slabya0564e12006-12-08 02:38:37 -08003953 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003955 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3956 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3957 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3959 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960
Alan Coxb65b5b52006-06-27 02:54:05 -07003961 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 BRDENABLE(portp->brdnr, portp->pagenr);
3963 stl_sc26198setreg(portp, IMR, 0);
3964 stl_sc26198updatereg(portp, MR0, mr0);
3965 stl_sc26198updatereg(portp, MR1, mr1);
3966 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3967 stl_sc26198updatereg(portp, MR2, mr2);
3968 stl_sc26198updatereg(portp, IOPIOR,
3969 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3970
3971 if (baudrate > 0) {
3972 stl_sc26198setreg(portp, TXCSR, clk);
3973 stl_sc26198setreg(portp, RXCSR, clk);
3974 }
3975
3976 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3977 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3978
3979 ipr = stl_sc26198getreg(portp, IPR);
3980 if (ipr & IPR_DCD)
3981 portp->sigs &= ~TIOCM_CD;
3982 else
3983 portp->sigs |= TIOCM_CD;
3984
3985 portp->imr = (portp->imr & ~imroff) | imron;
3986 stl_sc26198setreg(portp, IMR, portp->imr);
3987 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003988 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989}
3990
3991/*****************************************************************************/
3992
3993/*
3994 * Set the state of the DTR and RTS signals.
3995 */
3996
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003997static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998{
3999 unsigned char iopioron, iopioroff;
4000 unsigned long flags;
4001
Jiri Slabya0564e12006-12-08 02:38:37 -08004002 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4003 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004
4005 iopioron = 0;
4006 iopioroff = 0;
4007 if (dtr == 0)
4008 iopioroff |= IPR_DTR;
4009 else if (dtr > 0)
4010 iopioron |= IPR_DTR;
4011 if (rts == 0)
4012 iopioroff |= IPR_RTS;
4013 else if (rts > 0)
4014 iopioron |= IPR_RTS;
4015
Alan Coxb65b5b52006-06-27 02:54:05 -07004016 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 BRDENABLE(portp->brdnr, portp->pagenr);
4018 stl_sc26198setreg(portp, IOPIOR,
4019 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4020 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004021 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022}
4023
4024/*****************************************************************************/
4025
4026/*
4027 * Return the state of the signals.
4028 */
4029
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004030static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031{
4032 unsigned char ipr;
4033 unsigned long flags;
4034 int sigs;
4035
Jiri Slabya0564e12006-12-08 02:38:37 -08004036 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
Alan Coxb65b5b52006-06-27 02:54:05 -07004038 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 BRDENABLE(portp->brdnr, portp->pagenr);
4040 ipr = stl_sc26198getreg(portp, IPR);
4041 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004042 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043
4044 sigs = 0;
4045 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4046 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4047 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4048 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4049 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004050 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051}
4052
4053/*****************************************************************************/
4054
4055/*
4056 * Enable/Disable the Transmitter and/or Receiver.
4057 */
4058
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004059static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060{
4061 unsigned char ccr;
4062 unsigned long flags;
4063
Jiri Slabya0564e12006-12-08 02:38:37 -08004064 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
4066 ccr = portp->crenable;
4067 if (tx == 0)
4068 ccr &= ~CR_TXENABLE;
4069 else if (tx > 0)
4070 ccr |= CR_TXENABLE;
4071 if (rx == 0)
4072 ccr &= ~CR_RXENABLE;
4073 else if (rx > 0)
4074 ccr |= CR_RXENABLE;
4075
Alan Coxb65b5b52006-06-27 02:54:05 -07004076 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 BRDENABLE(portp->brdnr, portp->pagenr);
4078 stl_sc26198setreg(portp, SCCR, ccr);
4079 BRDDISABLE(portp->brdnr);
4080 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004081 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082}
4083
4084/*****************************************************************************/
4085
4086/*
4087 * Start/stop the Transmitter and/or Receiver.
4088 */
4089
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004090static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091{
4092 unsigned char imr;
4093 unsigned long flags;
4094
Jiri Slabya0564e12006-12-08 02:38:37 -08004095 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
4097 imr = portp->imr;
4098 if (tx == 0)
4099 imr &= ~IR_TXRDY;
4100 else if (tx == 1)
4101 imr |= IR_TXRDY;
4102 if (rx == 0)
4103 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4104 else if (rx > 0)
4105 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4106
Alan Coxb65b5b52006-06-27 02:54:05 -07004107 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108 BRDENABLE(portp->brdnr, portp->pagenr);
4109 stl_sc26198setreg(portp, IMR, imr);
4110 BRDDISABLE(portp->brdnr);
4111 portp->imr = imr;
4112 if (tx > 0)
4113 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004114 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115}
4116
4117/*****************************************************************************/
4118
4119/*
4120 * Disable all interrupts from this port.
4121 */
4122
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004123static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124{
4125 unsigned long flags;
4126
Jiri Slabya0564e12006-12-08 02:38:37 -08004127 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128
Alan Coxb65b5b52006-06-27 02:54:05 -07004129 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 BRDENABLE(portp->brdnr, portp->pagenr);
4131 portp->imr = 0;
4132 stl_sc26198setreg(portp, IMR, 0);
4133 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004134 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135}
4136
4137/*****************************************************************************/
4138
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004139static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140{
4141 unsigned long flags;
4142
Jiri Slabya0564e12006-12-08 02:38:37 -08004143 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144
Alan Coxb65b5b52006-06-27 02:54:05 -07004145 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 BRDENABLE(portp->brdnr, portp->pagenr);
4147 if (len == 1) {
4148 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4149 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004150 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004152
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004154 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155}
4156
4157/*****************************************************************************/
4158
4159/*
4160 * Take flow control actions...
4161 */
4162
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004163static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164{
4165 struct tty_struct *tty;
4166 unsigned long flags;
4167 unsigned char mr0;
4168
Jiri Slabya0564e12006-12-08 02:38:37 -08004169 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170
Jiri Slaby615e4a72006-12-08 02:38:38 -08004171 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004173 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004174 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 return;
4176
Alan Coxb65b5b52006-06-27 02:54:05 -07004177 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 BRDENABLE(portp->brdnr, portp->pagenr);
4179
4180 if (state) {
4181 if (tty->termios->c_iflag & IXOFF) {
4182 mr0 = stl_sc26198getreg(portp, MR0);
4183 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4184 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4185 mr0 |= MR0_SWFRX;
4186 portp->stats.rxxon++;
4187 stl_sc26198wait(portp);
4188 stl_sc26198setreg(portp, MR0, mr0);
4189 }
4190/*
4191 * Question: should we return RTS to what it was before? It may
4192 * have been set by an ioctl... Suppose not, since if you have
4193 * hardware flow control set then it is pretty silly to go and
4194 * set the RTS line by hand.
4195 */
4196 if (tty->termios->c_cflag & CRTSCTS) {
4197 stl_sc26198setreg(portp, MR1,
4198 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4199 stl_sc26198setreg(portp, IOPIOR,
4200 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4201 portp->stats.rxrtson++;
4202 }
4203 } else {
4204 if (tty->termios->c_iflag & IXOFF) {
4205 mr0 = stl_sc26198getreg(portp, MR0);
4206 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4207 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4208 mr0 &= ~MR0_SWFRX;
4209 portp->stats.rxxoff++;
4210 stl_sc26198wait(portp);
4211 stl_sc26198setreg(portp, MR0, mr0);
4212 }
4213 if (tty->termios->c_cflag & CRTSCTS) {
4214 stl_sc26198setreg(portp, MR1,
4215 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4216 stl_sc26198setreg(portp, IOPIOR,
4217 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4218 portp->stats.rxrtsoff++;
4219 }
4220 }
4221
4222 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004223 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004224 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225}
4226
4227/*****************************************************************************/
4228
4229/*
4230 * Send a flow control character.
4231 */
4232
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004233static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234{
4235 struct tty_struct *tty;
4236 unsigned long flags;
4237 unsigned char mr0;
4238
Jiri Slabya0564e12006-12-08 02:38:37 -08004239 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240
Jiri Slaby615e4a72006-12-08 02:38:38 -08004241 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004243 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004244 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 return;
4246
Alan Coxb65b5b52006-06-27 02:54:05 -07004247 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 BRDENABLE(portp->brdnr, portp->pagenr);
4249 if (state) {
4250 mr0 = stl_sc26198getreg(portp, MR0);
4251 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4252 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4253 mr0 |= MR0_SWFRX;
4254 portp->stats.rxxon++;
4255 stl_sc26198wait(portp);
4256 stl_sc26198setreg(portp, MR0, mr0);
4257 } else {
4258 mr0 = stl_sc26198getreg(portp, MR0);
4259 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4260 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4261 mr0 &= ~MR0_SWFRX;
4262 portp->stats.rxxoff++;
4263 stl_sc26198wait(portp);
4264 stl_sc26198setreg(portp, MR0, mr0);
4265 }
4266 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004267 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004268 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269}
4270
4271/*****************************************************************************/
4272
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004273static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274{
4275 unsigned long flags;
4276
Jiri Slabya0564e12006-12-08 02:38:37 -08004277 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278
Jiri Slaby615e4a72006-12-08 02:38:38 -08004279 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 return;
4281
Alan Coxb65b5b52006-06-27 02:54:05 -07004282 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 BRDENABLE(portp->brdnr, portp->pagenr);
4284 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4285 stl_sc26198setreg(portp, SCCR, portp->crenable);
4286 BRDDISABLE(portp->brdnr);
4287 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004288 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289}
4290
4291/*****************************************************************************/
4292
4293/*
4294 * Return the current state of data flow on this port. This is only
4295 * really interresting when determining if data has fully completed
4296 * transmission or not... The sc26198 interrupt scheme cannot
4297 * determine when all data has actually drained, so we need to
4298 * check the port statusy register to be sure.
4299 */
4300
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004301static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302{
4303 unsigned long flags;
4304 unsigned char sr;
4305
Jiri Slabya0564e12006-12-08 02:38:37 -08004306 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307
Jiri Slaby615e4a72006-12-08 02:38:38 -08004308 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004309 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004311 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
Alan Coxb65b5b52006-06-27 02:54:05 -07004313 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 BRDENABLE(portp->brdnr, portp->pagenr);
4315 sr = stl_sc26198getreg(portp, SR);
4316 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004317 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
Jesper Juhl014c2542006-01-15 02:37:08 +01004319 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320}
4321
4322/*****************************************************************************/
4323
4324/*
4325 * Delay for a small amount of time, to give the sc26198 a chance
4326 * to process a command...
4327 */
4328
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004329static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330{
4331 int i;
4332
Jiri Slabya0564e12006-12-08 02:38:37 -08004333 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334
Jiri Slaby615e4a72006-12-08 02:38:38 -08004335 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 return;
4337
Jiri Slabyc62429d2006-12-08 02:39:14 -08004338 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 stl_sc26198getglobreg(portp, TSTR);
4340}
4341
4342/*****************************************************************************/
4343
4344/*
4345 * If we are TX flow controlled and in IXANY mode then we may
4346 * need to unflow control here. We gotta do this because of the
4347 * automatic flow control modes of the sc26198.
4348 */
4349
Jiri Slaby60be4812006-12-08 02:38:40 -08004350static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351{
4352 unsigned char mr0;
4353
4354 mr0 = stl_sc26198getreg(portp, MR0);
4355 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4356 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4357 stl_sc26198wait(portp);
4358 stl_sc26198setreg(portp, MR0, mr0);
4359 clear_bit(ASYI_TXFLOWED, &portp->istate);
4360}
4361
4362/*****************************************************************************/
4363
4364/*
4365 * Interrupt service routine for sc26198 panels.
4366 */
4367
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004368static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004370 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371 unsigned int iack;
4372
Alan Coxb65b5b52006-06-27 02:54:05 -07004373 spin_lock(&brd_lock);
4374
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375/*
4376 * Work around bug in sc26198 chip... Cannot have A6 address
4377 * line of UART high, else iack will be returned as 0.
4378 */
4379 outb(0, (iobase + 1));
4380
4381 iack = inb(iobase + XP_IACK);
4382 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4383
4384 if (iack & IVR_RXDATA)
4385 stl_sc26198rxisr(portp, iack);
4386 else if (iack & IVR_TXDATA)
4387 stl_sc26198txisr(portp);
4388 else
4389 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004390
4391 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392}
4393
4394/*****************************************************************************/
4395
4396/*
4397 * Transmit interrupt handler. This has gotta be fast! Handling TX
4398 * chars is pretty simple, stuff as many as possible from the TX buffer
4399 * into the sc26198 FIFO.
4400 * In practice it is possible that interrupts are enabled but that the
4401 * port has been hung up. Need to handle not having any TX buffer here,
4402 * this is done by using the side effect that head and tail will also
4403 * be NULL if the buffer has been freed.
4404 */
4405
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004406static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407{
Alan Coxd18a7502008-10-13 10:40:07 +01004408 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409 unsigned int ioaddr;
4410 unsigned char mr0;
4411 int len, stlen;
4412 char *head, *tail;
4413
Jiri Slabya0564e12006-12-08 02:38:37 -08004414 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415
4416 ioaddr = portp->ioaddr;
4417 head = portp->tx.head;
4418 tail = portp->tx.tail;
4419 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4420 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4421 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4422 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004423 tty = tty_port_tty_get(&portp->port);
4424 if (tty) {
4425 tty_wakeup(tty);
4426 tty_kref_put(tty);
4427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428 }
4429
4430 if (len == 0) {
4431 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4432 mr0 = inb(ioaddr + XP_DATA);
4433 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4434 portp->imr &= ~IR_TXRDY;
4435 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4436 outb(portp->imr, (ioaddr + XP_DATA));
4437 clear_bit(ASYI_TXBUSY, &portp->istate);
4438 } else {
4439 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4440 outb(mr0, (ioaddr + XP_DATA));
4441 }
4442 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004443 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004445 stlen = min_t(unsigned int, len,
4446 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447 outb(GTXFIFO, (ioaddr + XP_ADDR));
4448 outsb((ioaddr + XP_DATA), tail, stlen);
4449 len -= stlen;
4450 tail += stlen;
4451 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4452 tail = portp->tx.buf;
4453 if (len > 0) {
4454 outsb((ioaddr + XP_DATA), tail, len);
4455 tail += len;
4456 }
4457 portp->tx.tail = tail;
4458 }
4459}
4460
4461/*****************************************************************************/
4462
4463/*
4464 * Receive character interrupt handler. Determine if we have good chars
4465 * or bad chars and then process appropriately. Good chars are easy
4466 * just shove the lot into the RX buffer and set all status byte to 0.
4467 * If a bad RX char then process as required. This routine needs to be
4468 * fast! In practice it is possible that we get an interrupt on a port
4469 * that is closed. This can happen on hangups - since they completely
4470 * shutdown a port not in user context. Need to handle this case.
4471 */
4472
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004473static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474{
4475 struct tty_struct *tty;
4476 unsigned int len, buflen, ioaddr;
4477
Jiri Slabya0564e12006-12-08 02:38:37 -08004478 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479
Alan Coxd18a7502008-10-13 10:40:07 +01004480 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481 ioaddr = portp->ioaddr;
4482 outb(GIBCR, (ioaddr + XP_ADDR));
4483 len = inb(ioaddr + XP_DATA) + 1;
4484
4485 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004486 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004487 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488 outb(GRXFIFO, (ioaddr + XP_ADDR));
4489 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4490 portp->stats.rxlost += len;
4491 portp->stats.rxtotal += len;
4492 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004493 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004495 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004497 tty_prepare_flip_string(tty, &ptr, len);
4498 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499 tty_schedule_flip(tty);
4500 portp->stats.rxtotal += len;
4501 }
4502 }
4503 } else {
4504 stl_sc26198rxbadchars(portp);
4505 }
4506
4507/*
4508 * If we are TX flow controlled and in IXANY mode then we may need
4509 * to unflow control here. We gotta do this because of the automatic
4510 * flow control modes of the sc26198.
4511 */
4512 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004513 if ((tty != NULL) &&
4514 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 (tty->termios->c_iflag & IXANY)) {
4516 stl_sc26198txunflow(portp, tty);
4517 }
4518 }
Alan Coxd18a7502008-10-13 10:40:07 +01004519 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520}
4521
4522/*****************************************************************************/
4523
4524/*
4525 * Process an RX bad character.
4526 */
4527
Jiri Slaby60be4812006-12-08 02:38:40 -08004528static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529{
4530 struct tty_struct *tty;
4531 unsigned int ioaddr;
4532
Alan Coxd18a7502008-10-13 10:40:07 +01004533 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534 ioaddr = portp->ioaddr;
4535
4536 if (status & SR_RXPARITY)
4537 portp->stats.rxparity++;
4538 if (status & SR_RXFRAMING)
4539 portp->stats.rxframing++;
4540 if (status & SR_RXOVERRUN)
4541 portp->stats.rxoverrun++;
4542 if (status & SR_RXBREAK)
4543 portp->stats.rxbreaks++;
4544
Jiri Slaby615e4a72006-12-08 02:38:38 -08004545 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546 ((portp->rxignoremsk & status) == 0)) {
4547 if (portp->rxmarkmsk & status) {
4548 if (status & SR_RXBREAK) {
4549 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004550 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 do_SAK(tty);
4552 BRDENABLE(portp->brdnr, portp->pagenr);
4553 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004554 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004556 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004558 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004560 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004562 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564
Alan Cox33f0f882006-01-09 20:54:13 -08004565 tty_insert_flip_char(tty, ch, status);
4566 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567
4568 if (status == 0)
4569 portp->stats.rxtotal++;
4570 }
Alan Coxd18a7502008-10-13 10:40:07 +01004571 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572}
4573
4574/*****************************************************************************/
4575
4576/*
4577 * Process all characters in the RX FIFO of the UART. Check all char
4578 * status bytes as well, and process as required. We need to check
4579 * all bytes in the FIFO, in case some more enter the FIFO while we
4580 * are here. To get the exact character error type we need to switch
4581 * into CHAR error mode (that is why we need to make sure we empty
4582 * the FIFO).
4583 */
4584
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004585static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586{
4587 unsigned char status, mr1;
4588 char ch;
4589
4590/*
4591 * To get the precise error type for each character we must switch
4592 * back into CHAR error mode.
4593 */
4594 mr1 = stl_sc26198getreg(portp, MR1);
4595 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4596
4597 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4598 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4599 ch = stl_sc26198getreg(portp, RXFIFO);
4600 stl_sc26198rxbadch(portp, status, ch);
4601 }
4602
4603/*
4604 * To get correct interrupt class we must switch back into BLOCK
4605 * error mode.
4606 */
4607 stl_sc26198setreg(portp, MR1, mr1);
4608}
4609
4610/*****************************************************************************/
4611
4612/*
4613 * Other interrupt handler. This includes modem signals, flow
4614 * control actions, etc. Most stuff is left to off-level interrupt
4615 * processing time.
4616 */
4617
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004618static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004619{
4620 unsigned char cir, ipr, xisr;
4621
Jiri Slabya0564e12006-12-08 02:38:37 -08004622 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623
4624 cir = stl_sc26198getglobreg(portp, CIR);
4625
4626 switch (cir & CIR_SUBTYPEMASK) {
4627 case CIR_SUBCOS:
4628 ipr = stl_sc26198getreg(portp, IPR);
4629 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004630 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004631 portp->stats.modem++;
4632 }
4633 break;
4634 case CIR_SUBXONXOFF:
4635 xisr = stl_sc26198getreg(portp, XISR);
4636 if (xisr & XISR_RXXONGOT) {
4637 set_bit(ASYI_TXFLOWED, &portp->istate);
4638 portp->stats.txxoff++;
4639 }
4640 if (xisr & XISR_RXXOFFGOT) {
4641 clear_bit(ASYI_TXFLOWED, &portp->istate);
4642 portp->stats.txxon++;
4643 }
4644 break;
4645 case CIR_SUBBREAK:
4646 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4647 stl_sc26198rxbadchars(portp);
4648 break;
4649 default:
4650 break;
4651 }
4652}
4653
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004654static void stl_free_isabrds(void)
4655{
4656 struct stlbrd *brdp;
4657 unsigned int i;
4658
4659 for (i = 0; i < stl_nrbrds; i++) {
4660 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4661 continue;
4662
4663 free_irq(brdp->irq, brdp);
4664
4665 stl_cleanup_panels(brdp);
4666
4667 release_region(brdp->ioaddr1, brdp->iosize1);
4668 if (brdp->iosize2 > 0)
4669 release_region(brdp->ioaddr2, brdp->iosize2);
4670
4671 kfree(brdp);
4672 stl_brds[i] = NULL;
4673 }
4674}
4675
Jiri Slaby23b85a12006-12-08 02:38:40 -08004676/*
4677 * Loadable module initialization stuff.
4678 */
4679static int __init stallion_module_init(void)
4680{
Jiri Slaby843b5682006-12-08 02:39:12 -08004681 struct stlbrd *brdp;
4682 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004683 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004684 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004685
4686 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4687
4688 spin_lock_init(&stallion_lock);
4689 spin_lock_init(&brd_lock);
4690
Jiri Slabye4151092007-06-08 13:46:52 -07004691 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4692 if (!stl_serial) {
4693 retval = -ENOMEM;
4694 goto err;
4695 }
4696
4697 stl_serial->owner = THIS_MODULE;
4698 stl_serial->driver_name = stl_drvname;
4699 stl_serial->name = "ttyE";
4700 stl_serial->major = STL_SERIALMAJOR;
4701 stl_serial->minor_start = 0;
4702 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4703 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4704 stl_serial->init_termios = stl_deftermios;
4705 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4706 tty_set_operations(stl_serial, &stl_ops);
4707
4708 retval = tty_register_driver(stl_serial);
4709 if (retval) {
4710 printk("STALLION: failed to register serial driver\n");
4711 goto err_frtty;
4712 }
4713
Jiri Slaby843b5682006-12-08 02:39:12 -08004714/*
4715 * Find any dynamically supported boards. That is via module load
4716 * line options.
4717 */
4718 for (i = stl_nrbrds; i < stl_nargs; i++) {
4719 memset(&conf, 0, sizeof(conf));
4720 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4721 continue;
4722 if ((brdp = stl_allocbrd()) == NULL)
4723 continue;
4724 brdp->brdnr = i;
4725 brdp->brdtype = conf.brdtype;
4726 brdp->ioaddr1 = conf.ioaddr1;
4727 brdp->ioaddr2 = conf.ioaddr2;
4728 brdp->irq = conf.irq;
4729 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004730 stl_brds[brdp->brdnr] = brdp;
4731 if (stl_brdinit(brdp)) {
4732 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004733 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004734 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004735 for (j = 0; j < brdp->nrports; j++)
4736 tty_register_device(stl_serial,
4737 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004738 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004739 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004740 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004741
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004742 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004743 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004744 if (retval && stl_nrbrds == 0) {
4745 printk(KERN_ERR "STALLION: can't register pci driver\n");
4746 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004747 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004748
4749/*
4750 * Set up a character driver for per board stuff. This is mainly used
4751 * to do stats ioctls on the ports.
4752 */
4753 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4754 printk("STALLION: failed to register serial board device\n");
4755
4756 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004757 if (IS_ERR(stallion_class))
4758 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004759 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004760 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4761 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004762
Jiri Slaby23b85a12006-12-08 02:38:40 -08004763 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004764err_unrtty:
4765 tty_unregister_driver(stl_serial);
4766err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004767 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004768err:
4769 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004770}
4771
4772static void __exit stallion_module_exit(void)
4773{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004774 struct stlbrd *brdp;
4775 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004776
4777 pr_debug("cleanup_module()\n");
4778
4779 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4780 stl_drvversion);
4781
4782/*
4783 * Free up all allocated resources used by the ports. This includes
4784 * memory and interrupts. As part of this process we will also do
4785 * a hangup on every open port - to try to flush out any processes
4786 * hanging onto ports.
4787 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004788 for (i = 0; i < stl_nrbrds; i++) {
4789 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4790 continue;
4791 for (j = 0; j < brdp->nrports; j++)
4792 tty_unregister_device(stl_serial,
4793 brdp->brdnr * STL_MAXPORTS + j);
4794 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004795
Jiri Slaby23b85a12006-12-08 02:38:40 -08004796 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004797 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004798 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004799 class_destroy(stallion_class);
4800
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004801 pci_unregister_driver(&stl_pcidriver);
4802
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004803 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004804
4805 tty_unregister_driver(stl_serial);
4806 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004807}
4808
4809module_init(stallion_module_init);
4810module_exit(stallion_module_exit);
4811
4812MODULE_AUTHOR("Greg Ungerer");
4813MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4814MODULE_LICENSE("GPL");