blob: e1e0dd89ac9aa309e2f92c9183618948b09b6900 [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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413/*
414 * CD1400 uart specific handling functions.
415 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800416static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
417static int stl_cd1400getreg(struct stlport *portp, int regnr);
418static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
419static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
420static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800421static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800422static int stl_cd1400getsignals(struct stlport *portp);
423static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
424static void stl_cd1400ccrwait(struct stlport *portp);
425static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
426static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
427static void stl_cd1400disableintrs(struct stlport *portp);
428static void stl_cd1400sendbreak(struct stlport *portp, int len);
429static void stl_cd1400flowctrl(struct stlport *portp, int state);
430static void stl_cd1400sendflow(struct stlport *portp, int state);
431static void stl_cd1400flush(struct stlport *portp);
432static int stl_cd1400datastate(struct stlport *portp);
433static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
434static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
435static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
436static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
437static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800439static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
441/*
442 * SC26198 uart specific handling functions.
443 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800444static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
445static int stl_sc26198getreg(struct stlport *portp, int regnr);
446static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
447static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
448static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
449static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800450static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800451static int stl_sc26198getsignals(struct stlport *portp);
452static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
453static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
454static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
455static void stl_sc26198disableintrs(struct stlport *portp);
456static void stl_sc26198sendbreak(struct stlport *portp, int len);
457static void stl_sc26198flowctrl(struct stlport *portp, int state);
458static void stl_sc26198sendflow(struct stlport *portp, int state);
459static void stl_sc26198flush(struct stlport *portp);
460static int stl_sc26198datastate(struct stlport *portp);
461static void stl_sc26198wait(struct stlport *portp);
462static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
463static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
464static void stl_sc26198txisr(struct stlport *port);
465static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
466static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
467static void stl_sc26198rxbadchars(struct stlport *portp);
468static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470/*****************************************************************************/
471
472/*
473 * Generic UART support structure.
474 */
475typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800476 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
477 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800478 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800479 int (*getsignals)(struct stlport *portp);
480 void (*setsignals)(struct stlport *portp, int dtr, int rts);
481 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
482 void (*startrxtx)(struct stlport *portp, int rx, int tx);
483 void (*disableintrs)(struct stlport *portp);
484 void (*sendbreak)(struct stlport *portp, int len);
485 void (*flowctrl)(struct stlport *portp, int state);
486 void (*sendflow)(struct stlport *portp, int state);
487 void (*flush)(struct stlport *portp);
488 int (*datastate)(struct stlport *portp);
489 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490} uart_t;
491
492/*
493 * Define some macros to make calling these functions nice and clean.
494 */
495#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
496#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
497#define stl_setport (* ((uart_t *) portp->uartp)->setport)
498#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
499#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
500#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
501#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
502#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
503#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
504#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
505#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
506#define stl_flush (* ((uart_t *) portp->uartp)->flush)
507#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
508
509/*****************************************************************************/
510
511/*
512 * CD1400 UART specific data initialization.
513 */
514static uart_t stl_cd1400uart = {
515 stl_cd1400panelinit,
516 stl_cd1400portinit,
517 stl_cd1400setport,
518 stl_cd1400getsignals,
519 stl_cd1400setsignals,
520 stl_cd1400enablerxtx,
521 stl_cd1400startrxtx,
522 stl_cd1400disableintrs,
523 stl_cd1400sendbreak,
524 stl_cd1400flowctrl,
525 stl_cd1400sendflow,
526 stl_cd1400flush,
527 stl_cd1400datastate,
528 stl_cd1400eiointr
529};
530
531/*
532 * Define the offsets within the register bank of a cd1400 based panel.
533 * These io address offsets are common to the EasyIO board as well.
534 */
535#define EREG_ADDR 0
536#define EREG_DATA 4
537#define EREG_RXACK 5
538#define EREG_TXACK 6
539#define EREG_MDACK 7
540
541#define EREG_BANKSIZE 8
542
543#define CD1400_CLK 25000000
544#define CD1400_CLK8M 20000000
545
546/*
547 * Define the cd1400 baud rate clocks. These are used when calculating
548 * what clock and divisor to use for the required baud rate. Also
549 * define the maximum baud rate allowed, and the default base baud.
550 */
551static int stl_cd1400clkdivs[] = {
552 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
553};
554
555/*****************************************************************************/
556
557/*
558 * SC26198 UART specific data initization.
559 */
560static uart_t stl_sc26198uart = {
561 stl_sc26198panelinit,
562 stl_sc26198portinit,
563 stl_sc26198setport,
564 stl_sc26198getsignals,
565 stl_sc26198setsignals,
566 stl_sc26198enablerxtx,
567 stl_sc26198startrxtx,
568 stl_sc26198disableintrs,
569 stl_sc26198sendbreak,
570 stl_sc26198flowctrl,
571 stl_sc26198sendflow,
572 stl_sc26198flush,
573 stl_sc26198datastate,
574 stl_sc26198intr
575};
576
577/*
578 * Define the offsets within the register bank of a sc26198 based panel.
579 */
580#define XP_DATA 0
581#define XP_ADDR 1
582#define XP_MODID 2
583#define XP_STATUS 2
584#define XP_IACK 3
585
586#define XP_BANKSIZE 4
587
588/*
589 * Define the sc26198 baud rate table. Offsets within the table
590 * represent the actual baud rate selector of sc26198 registers.
591 */
592static unsigned int sc26198_baudtable[] = {
593 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
594 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
595 230400, 460800, 921600
596};
597
Tobias Klauserfe971072006-01-09 20:54:02 -0800598#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600/*****************************************************************************/
601
602/*
603 * Define the driver info for a user level control device. Used mainly
604 * to get at port stats - only not using the port device itself.
605 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700606static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 .owner = THIS_MODULE,
608 .ioctl = stl_memioctl,
609};
610
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800611static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800613static void stl_cd_change(struct stlport *portp)
614{
615 unsigned int oldsigs = portp->sigs;
Alan Coxd18a7502008-10-13 10:40:07 +0100616 struct tty_struct *tty = tty_port_tty_get(&portp->port);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800617
Alan Coxd18a7502008-10-13 10:40:07 +0100618 if (!tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800619 return;
620
621 portp->sigs = stl_getsignals(portp);
622
623 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100624 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800625
626 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100627 if (portp->port.flags & ASYNC_CHECK_CD)
Alan Coxd18a7502008-10-13 10:40:07 +0100628 tty_hangup(tty);
629 tty_kref_put(tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800630}
631
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 * Check for any arguments passed in on the module load command line.
634 */
635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636/*****************************************************************************/
637
638/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 * Parse the supplied argument string, into the board conf struct.
640 */
641
Jiri Slaby40e82652006-12-08 02:38:41 -0800642static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643{
644 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800645 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Jiri Slabya0564e12006-12-08 02:38:37 -0800647 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Jiri Slaby615e4a72006-12-08 02:38:38 -0800649 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100650 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Jiri Slabyc62429d2006-12-08 02:39:14 -0800652 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800653 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
Jiri Slabyc62429d2006-12-08 02:39:14 -0800655 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
657 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800658
Tobias Klauserfe971072006-01-09 20:54:02 -0800659 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800661 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 }
663
664 confp->brdtype = stl_brdstr[i].type;
665
666 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800667 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800668 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 i++;
670 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800671 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800672 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 i++;
674 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800675 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800676 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100677 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678}
679
680/*****************************************************************************/
681
682/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 * Allocate a new board structure. Fill out the basic info in it.
684 */
685
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800686static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800688 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800690 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800691 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700692 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800693 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800694 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 }
696
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100698 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699}
700
701/*****************************************************************************/
702
703static int stl_open(struct tty_struct *tty, struct file *filp)
704{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800705 struct stlport *portp;
706 struct stlbrd *brdp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000707 struct tty_port *port;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800708 unsigned int minordev, brdnr, panelnr;
Alan Cox4350f3f2009-01-02 13:46:24 +0000709 int portnr;
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;
Alan Cox4350f3f2009-01-02 13:46:24 +0000720
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800722 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800723 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 break;
725 if (minordev < brdp->panels[panelnr]->nrports) {
726 portnr = minordev;
727 break;
728 }
729 minordev -= brdp->panels[panelnr]->nrports;
730 }
731 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100732 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
734 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800735 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100736 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000737 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
739/*
740 * On the first open of the device setup the port hardware, and
741 * initialize the per port data structure.
742 */
Alan Cox4350f3f2009-01-02 13:46:24 +0000743 tty_port_tty_set(port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 tty->driver_data = portp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000745 port->count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
Alan Cox4350f3f2009-01-02 13:46:24 +0000747 if ((port->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800748 if (!portp->tx.buf) {
749 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
750 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100751 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 portp->tx.head = portp->tx.buf;
753 portp->tx.tail = portp->tx.buf;
754 }
755 stl_setport(portp, tty->termios);
756 portp->sigs = stl_getsignals(portp);
757 stl_setsignals(portp, 1, 1);
758 stl_enablerxtx(portp, 1, 1);
759 stl_startrxtx(portp, 1, 0);
760 clear_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox4350f3f2009-01-02 13:46:24 +0000761 port->flags |= ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 }
Alan Cox4350f3f2009-01-02 13:46:24 +0000763 return tty_port_block_til_ready(port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764}
765
766/*****************************************************************************/
767
Alan Cox31f35932009-01-02 13:45:05 +0000768static int stl_carrier_raised(struct tty_port *port)
769{
770 struct stlport *portp = container_of(port, struct stlport, port);
771 return (portp->sigs & TIOCM_CD) ? 1 : 0;
772}
773
Alan Cox4350f3f2009-01-02 13:46:24 +0000774static void stl_raise_dtr_rts(struct tty_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775{
Alan Cox4350f3f2009-01-02 13:46:24 +0000776 struct stlport *portp = container_of(port, struct stlport, port);
777 /* Takes brd_lock internally */
778 stl_setsignals(portp, 1, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779}
780
781/*****************************************************************************/
782
Jiri Slaby96b066b2006-12-08 02:38:42 -0800783static void stl_flushbuffer(struct tty_struct *tty)
784{
785 struct stlport *portp;
786
787 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
788
Jiri Slaby96b066b2006-12-08 02:38:42 -0800789 portp = tty->driver_data;
790 if (portp == NULL)
791 return;
792
793 stl_flush(portp);
794 tty_wakeup(tty);
795}
796
797/*****************************************************************************/
798
799static void stl_waituntilsent(struct tty_struct *tty, int timeout)
800{
801 struct stlport *portp;
802 unsigned long tend;
803
804 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
805
Jiri Slaby96b066b2006-12-08 02:38:42 -0800806 portp = tty->driver_data;
807 if (portp == NULL)
808 return;
809
810 if (timeout == 0)
811 timeout = HZ;
812 tend = jiffies + timeout;
813
Alan Cox978e5952008-04-30 00:53:59 -0700814 lock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800815 while (stl_datastate(portp)) {
816 if (signal_pending(current))
817 break;
818 msleep_interruptible(20);
819 if (time_after_eq(jiffies, tend))
820 break;
821 }
Alan Cox978e5952008-04-30 00:53:59 -0700822 unlock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800823}
824
825/*****************************************************************************/
826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827static void stl_close(struct tty_struct *tty, struct file *filp)
828{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800829 struct stlport *portp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000830 struct tty_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 unsigned long flags;
832
Jiri Slabya0564e12006-12-08 02:38:37 -0800833 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
835 portp = tty->driver_data;
Alan Coxa6614992009-01-02 13:46:50 +0000836 BUG_ON(portp == NULL);
837
Alan Cox4350f3f2009-01-02 13:46:24 +0000838 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839
Alan Coxa6614992009-01-02 13:46:50 +0000840 if (tty_port_close_start(port, tty, filp) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842/*
843 * May want to wait for any data to drain before closing. The BUSY
844 * flag keeps track of whether we are still sending or not - it is
845 * very accurate for the cd1400, not quite so for the sc26198.
846 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
847 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 stl_waituntilsent(tty, (HZ / 2));
849
Alan Cox4350f3f2009-01-02 13:46:24 +0000850 spin_lock_irqsave(&port->lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100851 portp->port.flags &= ~ASYNC_INITIALIZED;
Alan Cox4350f3f2009-01-02 13:46:24 +0000852 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxb65b5b52006-06-27 02:54:05 -0700853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 stl_disableintrs(portp);
855 if (tty->termios->c_cflag & HUPCL)
856 stl_setsignals(portp, 0, 0);
857 stl_enablerxtx(portp, 0, 0);
858 stl_flushbuffer(tty);
859 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800860 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800862 portp->tx.buf = NULL;
863 portp->tx.head = NULL;
864 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866
Alan Coxa6614992009-01-02 13:46:50 +0000867 tty_port_close_end(port, tty);
Alan Cox4350f3f2009-01-02 13:46:24 +0000868 tty_port_tty_set(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869}
870
871/*****************************************************************************/
872
873/*
874 * Write routine. Take data and stuff it in to the TX ring queue.
875 * If transmit interrupts are not running then start them.
876 */
877
878static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
879{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800880 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 unsigned int len, stlen;
882 unsigned char *chbuf;
883 char *head, *tail;
884
Jiri Slabya0564e12006-12-08 02:38:37 -0800885 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800888 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100889 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800890 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100891 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
893/*
894 * If copying direct from user space we must cater for page faults,
895 * causing us to "sleep" here for a while. To handle this copy in all
896 * the data we need now, into a local buffer. Then when we got it all
897 * copy it into the TX buffer.
898 */
899 chbuf = (unsigned char *) buf;
900
901 head = portp->tx.head;
902 tail = portp->tx.tail;
903 if (head >= tail) {
904 len = STL_TXBUFSIZE - (head - tail) - 1;
905 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
906 } else {
907 len = tail - head - 1;
908 stlen = len;
909 }
910
Jiri Slaby843b5682006-12-08 02:39:12 -0800911 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 count = 0;
913 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800914 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 memcpy(head, chbuf, stlen);
916 len -= stlen;
917 chbuf += stlen;
918 count += stlen;
919 head += stlen;
920 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
921 head = portp->tx.buf;
922 stlen = tail - head;
923 }
924 }
925 portp->tx.head = head;
926
927 clear_bit(ASYI_TXLOW, &portp->istate);
928 stl_startrxtx(portp, -1, 1);
929
Jesper Juhl014c2542006-01-15 02:37:08 +0100930 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931}
932
933/*****************************************************************************/
934
David Howells4a561222008-07-22 11:18:43 +0100935static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800937 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 unsigned int len;
939 char *head, *tail;
940
Jiri Slabya0564e12006-12-08 02:38:37 -0800941 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800944 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +0100945 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800946 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +0100947 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 head = portp->tx.head;
950 tail = portp->tx.tail;
951
952 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
953 len--;
954
955 if (len > 0) {
956 *head++ = ch;
957 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
958 head = portp->tx.buf;
959 }
960 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +0100961 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962}
963
964/*****************************************************************************/
965
966/*
967 * If there are any characters in the buffer then make sure that TX
968 * interrupts are on and get'em out. Normally used after the putchar
969 * routine has been called.
970 */
971
972static void stl_flushchars(struct tty_struct *tty)
973{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800974 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Jiri Slabya0564e12006-12-08 02:38:37 -0800976 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800979 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800981 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 return;
983
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 stl_startrxtx(portp, -1, 1);
985}
986
987/*****************************************************************************/
988
989static int stl_writeroom(struct tty_struct *tty)
990{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800991 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 char *head, *tail;
993
Jiri Slabya0564e12006-12-08 02:38:37 -0800994 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800997 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100998 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800999 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001000 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
1002 head = portp->tx.head;
1003 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001004 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005}
1006
1007/*****************************************************************************/
1008
1009/*
1010 * Return number of chars in the TX buffer. Normally we would just
1011 * calculate the number of chars in the buffer and return that, but if
1012 * the buffer is empty and TX interrupts are still on then we return
1013 * that the buffer still has 1 char in it. This way whoever called us
1014 * will not think that ALL chars have drained - since the UART still
1015 * must have some chars in it (we are busy after all).
1016 */
1017
1018static int stl_charsinbuffer(struct tty_struct *tty)
1019{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001020 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 unsigned int size;
1022 char *head, *tail;
1023
Jiri Slabya0564e12006-12-08 02:38:37 -08001024 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001027 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001028 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001029 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001030 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
1032 head = portp->tx.head;
1033 tail = portp->tx.tail;
1034 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1035 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1036 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001037 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038}
1039
1040/*****************************************************************************/
1041
1042/*
1043 * Generate the serial struct info.
1044 */
1045
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001046static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047{
1048 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001049 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
Jiri Slabya0564e12006-12-08 02:38:37 -08001051 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 memset(&sio, 0, sizeof(struct serial_struct));
1054 sio.line = portp->portnr;
1055 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001056 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 sio.baud_base = portp->baud_base;
1058 sio.close_delay = portp->close_delay;
1059 sio.closing_wait = portp->closing_wait;
1060 sio.custom_divisor = portp->custom_divisor;
1061 sio.hub6 = 0;
1062 if (portp->uartp == &stl_cd1400uart) {
1063 sio.type = PORT_CIRRUS;
1064 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1065 } else {
1066 sio.type = PORT_UNKNOWN;
1067 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1068 }
1069
1070 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001071 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 sio.irq = brdp->irq;
1073
1074 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1075}
1076
1077/*****************************************************************************/
1078
1079/*
1080 * Set port according to the serial struct info.
1081 * At this point we do not do any auto-configure stuff, so we will
1082 * just quietly ignore any requests to change irq, etc.
1083 */
1084
Alan Coxd18a7502008-10-13 10:40:07 +01001085static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086{
Alan Coxd18a7502008-10-13 10:40:07 +01001087 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 struct serial_struct sio;
1089
Jiri Slabya0564e12006-12-08 02:38:37 -08001090 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
1092 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1093 return -EFAULT;
1094 if (!capable(CAP_SYS_ADMIN)) {
1095 if ((sio.baud_base != portp->baud_base) ||
1096 (sio.close_delay != portp->close_delay) ||
1097 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001098 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001099 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101
Alan Coxf8ae4762008-07-16 21:56:37 +01001102 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 (sio.flags & ASYNC_USR_MASK);
1104 portp->baud_base = sio.baud_base;
1105 portp->close_delay = sio.close_delay;
1106 portp->closing_wait = sio.closing_wait;
1107 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001108 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001109 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110}
1111
1112/*****************************************************************************/
1113
1114static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1115{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001116 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001119 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001120 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001122 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
1124 return stl_getsignals(portp);
1125}
1126
1127static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1128 unsigned int set, unsigned int clear)
1129{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001130 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 int rts = -1, dtr = -1;
1132
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001134 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001135 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001137 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
1139 if (set & TIOCM_RTS)
1140 rts = 1;
1141 if (set & TIOCM_DTR)
1142 dtr = 1;
1143 if (clear & TIOCM_RTS)
1144 rts = 0;
1145 if (clear & TIOCM_DTR)
1146 dtr = 0;
1147
1148 stl_setsignals(portp, dtr, rts);
1149 return 0;
1150}
1151
1152static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1153{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001154 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 int rc;
1156 void __user *argp = (void __user *)arg;
1157
Jiri Slabya0564e12006-12-08 02:38:37 -08001158 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1159 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001162 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001163 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001166 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001168 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
1170 rc = 0;
1171
Alan Coxf433c652008-04-30 00:53:23 -07001172 lock_kernel();
1173
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 case TIOCGSERIAL:
1176 rc = stl_getserial(portp, argp);
1177 break;
1178 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001179 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 break;
1181 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001182 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 break;
1184 case COM_CLRPORTSTATS:
1185 rc = stl_clrportstats(portp, argp);
1186 break;
1187 case TIOCSERCONFIG:
1188 case TIOCSERGWILD:
1189 case TIOCSERSWILD:
1190 case TIOCSERGETLSR:
1191 case TIOCSERGSTRUCT:
1192 case TIOCSERGETMULTI:
1193 case TIOCSERSETMULTI:
1194 default:
1195 rc = -ENOIOCTLCMD;
1196 break;
1197 }
Alan Coxf433c652008-04-30 00:53:23 -07001198 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001199 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200}
1201
1202/*****************************************************************************/
1203
Jiri Slaby96b066b2006-12-08 02:38:42 -08001204/*
1205 * Start the transmitter again. Just turn TX interrupts back on.
1206 */
1207
1208static void stl_start(struct tty_struct *tty)
1209{
1210 struct stlport *portp;
1211
1212 pr_debug("stl_start(tty=%p)\n", tty);
1213
Jiri Slaby96b066b2006-12-08 02:38:42 -08001214 portp = tty->driver_data;
1215 if (portp == NULL)
1216 return;
1217 stl_startrxtx(portp, -1, 1);
1218}
1219
1220/*****************************************************************************/
1221
Alan Cox606d0992006-12-08 02:38:45 -08001222static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001224 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001225 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
Jiri Slabya0564e12006-12-08 02:38:37 -08001227 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001230 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 return;
1232
1233 tiosp = tty->termios;
1234 if ((tiosp->c_cflag == old->c_cflag) &&
1235 (tiosp->c_iflag == old->c_iflag))
1236 return;
1237
1238 stl_setport(portp, tiosp);
1239 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1240 -1);
1241 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1242 tty->hw_stopped = 0;
1243 stl_start(tty);
1244 }
1245 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001246 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247}
1248
1249/*****************************************************************************/
1250
1251/*
1252 * Attempt to flow control who ever is sending us data. Based on termios
1253 * settings use software or/and hardware flow control.
1254 */
1255
1256static void stl_throttle(struct tty_struct *tty)
1257{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001258 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
Jiri Slabya0564e12006-12-08 02:38:37 -08001260 pr_debug("stl_throttle(tty=%p)\n", tty);
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)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 return;
1265 stl_flowctrl(portp, 0);
1266}
1267
1268/*****************************************************************************/
1269
1270/*
1271 * Unflow control the device sending us data...
1272 */
1273
1274static void stl_unthrottle(struct tty_struct *tty)
1275{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001276 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Jiri Slabya0564e12006-12-08 02:38:37 -08001278 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001281 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 return;
1283 stl_flowctrl(portp, 1);
1284}
1285
1286/*****************************************************************************/
1287
1288/*
1289 * Stop the transmitter. Basically to do this we will just turn TX
1290 * interrupts off.
1291 */
1292
1293static void stl_stop(struct tty_struct *tty)
1294{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001295 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296
Jiri Slabya0564e12006-12-08 02:38:37 -08001297 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001300 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 return;
1302 stl_startrxtx(portp, -1, 0);
1303}
1304
1305/*****************************************************************************/
1306
1307/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 * Hangup this port. This is pretty much like closing the port, only
1309 * a little more brutal. No waiting for data to drain. Shutdown the
1310 * port and maybe drop signals.
1311 */
1312
1313static void stl_hangup(struct tty_struct *tty)
1314{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001315 struct stlport *portp;
Alan Cox4350f3f2009-01-02 13:46:24 +00001316 struct tty_port *port;
1317 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
Jiri Slabya0564e12006-12-08 02:38:37 -08001319 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001322 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 return;
Alan Cox4350f3f2009-01-02 13:46:24 +00001324 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
Alan Cox4350f3f2009-01-02 13:46:24 +00001326 spin_lock_irqsave(&port->lock, flags);
1327 port->flags &= ~ASYNC_INITIALIZED;
1328 spin_unlock_irqrestore(&port->lock, flags);
1329
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 stl_disableintrs(portp);
1331 if (tty->termios->c_cflag & HUPCL)
1332 stl_setsignals(portp, 0, 0);
1333 stl_enablerxtx(portp, 0, 0);
1334 stl_flushbuffer(tty);
1335 portp->istate = 0;
1336 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001337 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001339 portp->tx.buf = NULL;
1340 portp->tx.head = NULL;
1341 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 }
Alan Cox4350f3f2009-01-02 13:46:24 +00001343 tty_port_hangup(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344}
1345
1346/*****************************************************************************/
1347
David Howells4a561222008-07-22 11:18:43 +01001348static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001350 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Jiri Slabya0564e12006-12-08 02:38:37 -08001352 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001355 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001356 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
1358 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001359 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360}
1361
1362/*****************************************************************************/
1363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364static void stl_sendxchar(struct tty_struct *tty, char ch)
1365{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001366 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Jiri Slabya0564e12006-12-08 02:38:37 -08001368 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001371 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 return;
1373
1374 if (ch == STOP_CHAR(tty))
1375 stl_sendflow(portp, 0);
1376 else if (ch == START_CHAR(tty))
1377 stl_sendflow(portp, 1);
1378 else
1379 stl_putchar(tty, ch);
1380}
1381
1382/*****************************************************************************/
1383
1384#define MAXLINE 80
1385
1386/*
1387 * Format info for a specified port. The line is deliberately limited
1388 * to 80 characters. (If it is too long it will be truncated, if too
1389 * short then padded with spaces).
1390 */
1391
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001392static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393{
1394 char *sp;
1395 int sigs, cnt;
1396
1397 sp = pos;
1398 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1399 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1400 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1401
1402 if (portp->stats.rxframing)
1403 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1404 if (portp->stats.rxparity)
1405 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1406 if (portp->stats.rxbreaks)
1407 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1408 if (portp->stats.rxoverrun)
1409 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1410
1411 sigs = stl_getsignals(portp);
1412 cnt = sprintf(sp, "%s%s%s%s%s ",
1413 (sigs & TIOCM_RTS) ? "|RTS" : "",
1414 (sigs & TIOCM_CTS) ? "|CTS" : "",
1415 (sigs & TIOCM_DTR) ? "|DTR" : "",
1416 (sigs & TIOCM_CD) ? "|DCD" : "",
1417 (sigs & TIOCM_DSR) ? "|DSR" : "");
1418 *sp = ' ';
1419 sp += cnt;
1420
Jiri Slabyc62429d2006-12-08 02:39:14 -08001421 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 *sp++ = ' ';
1423 if (cnt >= MAXLINE)
1424 pos[(MAXLINE - 2)] = '+';
1425 pos[(MAXLINE - 1)] = '\n';
1426
Jesper Juhl014c2542006-01-15 02:37:08 +01001427 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428}
1429
1430/*****************************************************************************/
1431
1432/*
1433 * Port info, read from the /proc file system.
1434 */
1435
1436static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1437{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001438 struct stlbrd *brdp;
1439 struct stlpanel *panelp;
1440 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001441 unsigned int brdnr, panelnr, portnr;
1442 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 char *pos;
1444
Jiri Slabya0564e12006-12-08 02:38:37 -08001445 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1446 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
1448 pos = page;
1449 totalport = 0;
1450 curoff = 0;
1451
1452 if (off == 0) {
1453 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1454 stl_drvversion);
1455 while (pos < (page + MAXLINE - 1))
1456 *pos++ = ' ';
1457 *pos++ = '\n';
1458 }
1459 curoff = MAXLINE;
1460
1461/*
1462 * We scan through for each board, panel and port. The offset is
1463 * calculated on the fly, and irrelevant ports are skipped.
1464 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001465 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001467 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 continue;
1469 if (brdp->state == 0)
1470 continue;
1471
1472 maxoff = curoff + (brdp->nrports * MAXLINE);
1473 if (off >= maxoff) {
1474 curoff = maxoff;
1475 continue;
1476 }
1477
1478 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001479 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001481 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 continue;
1483
1484 maxoff = curoff + (panelp->nrports * MAXLINE);
1485 if (off >= maxoff) {
1486 curoff = maxoff;
1487 totalport += panelp->nrports;
1488 continue;
1489 }
1490
Jiri Slabyc62429d2006-12-08 02:39:14 -08001491 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 totalport++) {
1493 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001494 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 continue;
1496 if (off >= (curoff += MAXLINE))
1497 continue;
1498 if ((pos - page + MAXLINE) > count)
1499 goto stl_readdone;
1500 pos += stl_portinfo(portp, totalport, pos);
1501 }
1502 }
1503 }
1504
1505 *eof = 1;
1506
1507stl_readdone:
1508 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001509 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510}
1511
1512/*****************************************************************************/
1513
1514/*
1515 * All board interrupts are vectored through here first. This code then
1516 * calls off to the approrpriate board interrupt handlers.
1517 */
1518
David Howells7d12e782006-10-05 14:55:46 +01001519static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001521 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522
Jeff Garzika6f97b22007-10-31 05:20:49 -04001523 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
1525 return IRQ_RETVAL((* brdp->isr)(brdp));
1526}
1527
1528/*****************************************************************************/
1529
1530/*
1531 * Interrupt service routine for EasyIO board types.
1532 */
1533
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001534static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001536 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 unsigned int iobase;
1538 int handled = 0;
1539
Alan Coxb65b5b52006-06-27 02:54:05 -07001540 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 panelp = brdp->panels[0];
1542 iobase = panelp->iobase;
1543 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1544 handled = 1;
1545 (* panelp->isr)(panelp, iobase);
1546 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001547 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 return handled;
1549}
1550
1551/*****************************************************************************/
1552
1553/*
1554 * Interrupt service routine for ECH-AT board types.
1555 */
1556
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001557static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001559 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001560 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 int handled = 0;
1562
1563 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1564
1565 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1566 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001567 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 ioaddr = brdp->bnkstataddr[bnknr];
1569 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1570 panelp = brdp->bnk2panel[bnknr];
1571 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1572 }
1573 }
1574 }
1575
1576 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1577
1578 return handled;
1579}
1580
1581/*****************************************************************************/
1582
1583/*
1584 * Interrupt service routine for ECH-MCA board types.
1585 */
1586
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001587static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001589 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001590 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 int handled = 0;
1592
1593 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1594 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001595 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 ioaddr = brdp->bnkstataddr[bnknr];
1597 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1598 panelp = brdp->bnk2panel[bnknr];
1599 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1600 }
1601 }
1602 }
1603 return handled;
1604}
1605
1606/*****************************************************************************/
1607
1608/*
1609 * Interrupt service routine for ECH-PCI board types.
1610 */
1611
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001612static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001614 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001615 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 int handled = 0;
1617
1618 while (1) {
1619 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001620 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1622 ioaddr = brdp->bnkstataddr[bnknr];
1623 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1624 panelp = brdp->bnk2panel[bnknr];
1625 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1626 recheck++;
1627 handled = 1;
1628 }
1629 }
1630 if (! recheck)
1631 break;
1632 }
1633 return handled;
1634}
1635
1636/*****************************************************************************/
1637
1638/*
1639 * Interrupt service routine for ECH-8/64-PCI board types.
1640 */
1641
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001642static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001644 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001645 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 int handled = 0;
1647
1648 while (inb(brdp->ioctrl) & 0x1) {
1649 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001650 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 ioaddr = brdp->bnkstataddr[bnknr];
1652 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1653 panelp = brdp->bnk2panel[bnknr];
1654 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1655 }
1656 }
1657 }
1658
1659 return handled;
1660}
1661
1662/*****************************************************************************/
1663
1664/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 * Initialize all the ports on a panel.
1666 */
1667
Jiri Slaby705c1862006-12-08 02:39:11 -08001668static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001670 struct stlport *portp;
1671 unsigned int i;
1672 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
Jiri Slabya0564e12006-12-08 02:38:37 -08001674 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
1676 chipmask = stl_panelinit(brdp, panelp);
1677
1678/*
1679 * All UART's are initialized (if found!). Now go through and setup
1680 * each ports data structures.
1681 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001682 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001683 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001684 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001686 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 break;
1688 }
Alan Coxd18a7502008-10-13 10:40:07 +01001689 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001690 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 portp->magic = STL_PORTMAGIC;
1692 portp->portnr = i;
1693 portp->brdnr = panelp->brdnr;
1694 portp->panelnr = panelp->panelnr;
1695 portp->uartp = panelp->uartp;
1696 portp->clk = brdp->clk;
1697 portp->baud_base = STL_BAUDBASE;
1698 portp->close_delay = STL_CLOSEDELAY;
1699 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001700 init_waitqueue_head(&portp->port.open_wait);
1701 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 portp->stats.brd = portp->brdnr;
1703 portp->stats.panel = portp->panelnr;
1704 portp->stats.port = portp->portnr;
1705 panelp->ports[i] = portp;
1706 stl_portinit(brdp, panelp, portp);
1707 }
1708
Jiri Slabyc62429d2006-12-08 02:39:14 -08001709 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710}
1711
Jiri Slaby3b85b342006-12-08 02:39:10 -08001712static void stl_cleanup_panels(struct stlbrd *brdp)
1713{
1714 struct stlpanel *panelp;
1715 struct stlport *portp;
1716 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001717 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001718
1719 for (j = 0; j < STL_MAXPANELS; j++) {
1720 panelp = brdp->panels[j];
1721 if (panelp == NULL)
1722 continue;
1723 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1724 portp = panelp->ports[k];
1725 if (portp == NULL)
1726 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001727 tty = tty_port_tty_get(&portp->port);
1728 if (tty != NULL) {
1729 stl_hangup(tty);
1730 tty_kref_put(tty);
1731 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001732 kfree(portp->tx.buf);
1733 kfree(portp);
1734 }
1735 kfree(panelp);
1736 }
1737}
1738
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739/*****************************************************************************/
1740
1741/*
1742 * Try to find and initialize an EasyIO board.
1743 */
1744
Jiri Slaby705c1862006-12-08 02:39:11 -08001745static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001747 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 unsigned int status;
1749 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001750 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
Jiri Slabya0564e12006-12-08 02:38:37 -08001752 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
1754 brdp->ioctrl = brdp->ioaddr1 + 1;
1755 brdp->iostatus = brdp->ioaddr1 + 2;
1756
1757 status = inb(brdp->iostatus);
1758 if ((status & EIO_IDBITMASK) == EIO_MK3)
1759 brdp->ioctrl++;
1760
1761/*
1762 * Handle board specific stuff now. The real difference is PCI
1763 * or not PCI.
1764 */
1765 if (brdp->brdtype == BRD_EASYIOPCI) {
1766 brdp->iosize1 = 0x80;
1767 brdp->iosize2 = 0x80;
1768 name = "serial(EIO-PCI)";
1769 outb(0x41, (brdp->ioaddr2 + 0x4c));
1770 } else {
1771 brdp->iosize1 = 8;
1772 name = "serial(EIO)";
1773 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1774 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1775 printk("STALLION: invalid irq=%d for brd=%d\n",
1776 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001777 retval = -EINVAL;
1778 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 }
1780 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1781 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1782 brdp->ioctrl);
1783 }
1784
Jiri Slaby3b85b342006-12-08 02:39:10 -08001785 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1787 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1788 "%x conflicts with another device\n", brdp->brdnr,
1789 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001790 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 }
1792
1793 if (brdp->iosize2 > 0)
1794 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1795 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1796 "address %x conflicts with another device\n",
1797 brdp->brdnr, brdp->ioaddr2);
1798 printk(KERN_WARNING "STALLION: Warning, also "
1799 "releasing board %d I/O address %x \n",
1800 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001801 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 }
1803
1804/*
1805 * Everything looks OK, so let's go ahead and probe for the hardware.
1806 */
1807 brdp->clk = CD1400_CLK;
1808 brdp->isr = stl_eiointr;
1809
Jiri Slaby3b85b342006-12-08 02:39:10 -08001810 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 switch (status & EIO_IDBITMASK) {
1812 case EIO_8PORTM:
1813 brdp->clk = CD1400_CLK8M;
1814 /* fall thru */
1815 case EIO_8PORTRS:
1816 case EIO_8PORTDI:
1817 brdp->nrports = 8;
1818 break;
1819 case EIO_4PORTRS:
1820 brdp->nrports = 4;
1821 break;
1822 case EIO_MK3:
1823 switch (status & EIO_BRDMASK) {
1824 case ID_BRD4:
1825 brdp->nrports = 4;
1826 break;
1827 case ID_BRD8:
1828 brdp->nrports = 8;
1829 break;
1830 case ID_BRD16:
1831 brdp->nrports = 16;
1832 break;
1833 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001834 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 }
1836 break;
1837 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001838 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 }
1840
1841/*
1842 * We have verified that the board is actually present, so now we
1843 * can complete the setup.
1844 */
1845
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001846 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001847 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001849 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001850 retval = -ENOMEM;
1851 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853
1854 panelp->magic = STL_PANELMAGIC;
1855 panelp->brdnr = brdp->brdnr;
1856 panelp->panelnr = 0;
1857 panelp->nrports = brdp->nrports;
1858 panelp->iobase = brdp->ioaddr1;
1859 panelp->hwid = status;
1860 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001861 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 panelp->isr = stl_sc26198intr;
1863 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001864 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 panelp->isr = stl_cd1400eiointr;
1866 }
1867
1868 brdp->panels[0] = panelp;
1869 brdp->nrpanels = 1;
1870 brdp->state |= BRD_FOUND;
1871 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001872 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 printk("STALLION: failed to register interrupt "
1874 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001875 retval = -ENODEV;
1876 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001878
1879 return 0;
1880err_fr:
1881 stl_cleanup_panels(brdp);
1882err_rel2:
1883 if (brdp->iosize2 > 0)
1884 release_region(brdp->ioaddr2, brdp->iosize2);
1885err_rel1:
1886 release_region(brdp->ioaddr1, brdp->iosize1);
1887err:
1888 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889}
1890
1891/*****************************************************************************/
1892
1893/*
1894 * Try to find an ECH board and initialize it. This code is capable of
1895 * dealing with all types of ECH board.
1896 */
1897
Jiri Slaby705c1862006-12-08 02:39:11 -08001898static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001900 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001901 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1902 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 char *name;
1904
Jiri Slabya0564e12006-12-08 02:38:37 -08001905 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
1907 status = 0;
1908 conflict = 0;
1909
1910/*
1911 * Set up the initial board register contents for boards. This varies a
1912 * bit between the different board types. So we need to handle each
1913 * separately. Also do a check that the supplied IRQ is good.
1914 */
1915 switch (brdp->brdtype) {
1916
1917 case BRD_ECH:
1918 brdp->isr = stl_echatintr;
1919 brdp->ioctrl = brdp->ioaddr1 + 1;
1920 brdp->iostatus = brdp->ioaddr1 + 1;
1921 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001922 if ((status & ECH_IDBITMASK) != ECH_ID) {
1923 retval = -ENODEV;
1924 goto err;
1925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1927 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1928 printk("STALLION: invalid irq=%d for brd=%d\n",
1929 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001930 retval = -EINVAL;
1931 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 }
1933 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1934 status |= (stl_vecmap[brdp->irq] << 1);
1935 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1936 brdp->ioctrlval = ECH_INTENABLE |
1937 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001938 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1940 brdp->iosize1 = 2;
1941 brdp->iosize2 = 32;
1942 name = "serial(EC8/32)";
1943 outb(status, brdp->ioaddr1);
1944 break;
1945
1946 case BRD_ECHMC:
1947 brdp->isr = stl_echmcaintr;
1948 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1949 brdp->iostatus = brdp->ioctrl;
1950 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001951 if ((status & ECH_IDBITMASK) != ECH_ID) {
1952 retval = -ENODEV;
1953 goto err;
1954 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1956 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1957 printk("STALLION: invalid irq=%d for brd=%d\n",
1958 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001959 retval = -EINVAL;
1960 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 }
1962 outb(ECHMC_BRDRESET, brdp->ioctrl);
1963 outb(ECHMC_INTENABLE, brdp->ioctrl);
1964 brdp->iosize1 = 64;
1965 name = "serial(EC8/32-MC)";
1966 break;
1967
1968 case BRD_ECHPCI:
1969 brdp->isr = stl_echpciintr;
1970 brdp->ioctrl = brdp->ioaddr1 + 2;
1971 brdp->iosize1 = 4;
1972 brdp->iosize2 = 8;
1973 name = "serial(EC8/32-PCI)";
1974 break;
1975
1976 case BRD_ECH64PCI:
1977 brdp->isr = stl_echpci64intr;
1978 brdp->ioctrl = brdp->ioaddr2 + 0x40;
1979 outb(0x43, (brdp->ioaddr1 + 0x4c));
1980 brdp->iosize1 = 0x80;
1981 brdp->iosize2 = 0x80;
1982 name = "serial(EC8/64-PCI)";
1983 break;
1984
1985 default:
1986 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001987 retval = -EINVAL;
1988 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 }
1990
1991/*
1992 * Check boards for possible IO address conflicts and return fail status
1993 * if an IO conflict found.
1994 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08001995 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1997 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1998 "%x conflicts with another device\n", brdp->brdnr,
1999 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002000 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 }
2002
2003 if (brdp->iosize2 > 0)
2004 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2005 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2006 "address %x conflicts with another device\n",
2007 brdp->brdnr, brdp->ioaddr2);
2008 printk(KERN_WARNING "STALLION: Warning, also "
2009 "releasing board %d I/O address %x \n",
2010 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002011 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 }
2013
2014/*
2015 * Scan through the secondary io address space looking for panels.
2016 * As we find'em allocate and initialize panel structures for each.
2017 */
2018 brdp->clk = CD1400_CLK;
2019 brdp->hwid = status;
2020
2021 ioaddr = brdp->ioaddr2;
2022 banknr = 0;
2023 panelnr = 0;
2024 nxtid = 0;
2025
Jiri Slabyc62429d2006-12-08 02:39:14 -08002026 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 if (brdp->brdtype == BRD_ECHPCI) {
2028 outb(nxtid, brdp->ioctrl);
2029 ioaddr = brdp->ioaddr2;
2030 }
2031 status = inb(ioaddr + ECH_PNLSTATUS);
2032 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002033 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002034 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002035 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002037 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002038 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002039 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 panelp->magic = STL_PANELMAGIC;
2042 panelp->brdnr = brdp->brdnr;
2043 panelp->panelnr = panelnr;
2044 panelp->iobase = ioaddr;
2045 panelp->pagenr = nxtid;
2046 panelp->hwid = status;
2047 brdp->bnk2panel[banknr] = panelp;
2048 brdp->bnkpageaddr[banknr] = nxtid;
2049 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2050
2051 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002052 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 panelp->isr = stl_sc26198intr;
2054 if (status & ECH_PNL16PORT) {
2055 panelp->nrports = 16;
2056 brdp->bnk2panel[banknr] = panelp;
2057 brdp->bnkpageaddr[banknr] = nxtid;
2058 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2059 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002060 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002063 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 panelp->isr = stl_cd1400echintr;
2065 if (status & ECH_PNL16PORT) {
2066 panelp->nrports = 16;
2067 panelp->ackmask = 0x80;
2068 if (brdp->brdtype != BRD_ECHPCI)
2069 ioaddr += EREG_BANKSIZE;
2070 brdp->bnk2panel[banknr] = panelp;
2071 brdp->bnkpageaddr[banknr] = ++nxtid;
2072 brdp->bnkstataddr[banknr++] = ioaddr +
2073 ECH_PNLSTATUS;
2074 } else {
2075 panelp->nrports = 8;
2076 panelp->ackmask = 0xc0;
2077 }
2078 }
2079
2080 nxtid++;
2081 ioaddr += EREG_BANKSIZE;
2082 brdp->nrports += panelp->nrports;
2083 brdp->panels[panelnr++] = panelp;
2084 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002085 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2086 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002087 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 }
2090
2091 brdp->nrpanels = panelnr;
2092 brdp->nrbnks = banknr;
2093 if (brdp->brdtype == BRD_ECH)
2094 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2095
2096 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002097 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 printk("STALLION: failed to register interrupt "
2099 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002100 retval = -ENODEV;
2101 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 }
2103
Jiri Slaby3b85b342006-12-08 02:39:10 -08002104 return 0;
2105err_fr:
2106 stl_cleanup_panels(brdp);
2107 if (brdp->iosize2 > 0)
2108 release_region(brdp->ioaddr2, brdp->iosize2);
2109err_rel1:
2110 release_region(brdp->ioaddr1, brdp->iosize1);
2111err:
2112 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113}
2114
2115/*****************************************************************************/
2116
2117/*
2118 * Initialize and configure the specified board.
2119 * Scan through all the boards in the configuration and see what we
2120 * can find. Handle EIO and the ECH boards a little differently here
2121 * since the initial search and setup is very different.
2122 */
2123
Jiri Slaby705c1862006-12-08 02:39:11 -08002124static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002126 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
Jiri Slabya0564e12006-12-08 02:38:37 -08002128 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
2130 switch (brdp->brdtype) {
2131 case BRD_EASYIO:
2132 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002133 retval = stl_initeio(brdp);
2134 if (retval)
2135 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 break;
2137 case BRD_ECH:
2138 case BRD_ECHMC:
2139 case BRD_ECHPCI:
2140 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002141 retval = stl_initech(brdp);
2142 if (retval)
2143 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 break;
2145 default:
2146 printk("STALLION: board=%d is unknown board type=%d\n",
2147 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002148 retval = -ENODEV;
2149 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 }
2151
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 if ((brdp->state & BRD_FOUND) == 0) {
2153 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2154 stl_brdnames[brdp->brdtype], brdp->brdnr,
2155 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002156 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 }
2158
Jiri Slabyc62429d2006-12-08 02:39:14 -08002159 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002160 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 stl_initports(brdp, brdp->panels[i]);
2162
2163 printk("STALLION: %s found, board=%d io=%x irq=%d "
2164 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2165 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2166 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002167
2168 return 0;
2169err_free:
2170 free_irq(brdp->irq, brdp);
2171
2172 stl_cleanup_panels(brdp);
2173
2174 release_region(brdp->ioaddr1, brdp->iosize1);
2175 if (brdp->iosize2 > 0)
2176 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002177err:
2178 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179}
2180
2181/*****************************************************************************/
2182
2183/*
2184 * Find the next available board number that is free.
2185 */
2186
Jiri Slaby705c1862006-12-08 02:39:11 -08002187static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002189 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Jiri Slabyc62429d2006-12-08 02:39:14 -08002191 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002192 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 if (i >= stl_nrbrds)
2194 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002195 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002197
2198 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199}
2200
2201/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202/*
2203 * We have a Stallion board. Allocate a board structure and
2204 * initialize it. Read its IO and IRQ resources from PCI
2205 * configuration space.
2206 */
2207
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002208static int __devinit stl_pciprobe(struct pci_dev *pdev,
2209 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002211 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002212 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002213 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002215 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002216 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002217
Jiri Slaby3b85b342006-12-08 02:39:10 -08002218 retval = pci_enable_device(pdev);
2219 if (retval)
2220 goto err;
2221 brdp = stl_allocbrd();
2222 if (brdp == NULL) {
2223 retval = -ENOMEM;
2224 goto err;
2225 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002226 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002227 brdnr = stl_getbrdnr();
2228 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002229 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002231 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002232 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002233 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002235 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002236 stl_brds[brdp->brdnr] = brdp;
2237 mutex_unlock(&stl_brdslock);
2238
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002240 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
2242/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 * We have all resources from the board, so let's setup the actual
2244 * board structure now.
2245 */
2246 switch (brdtype) {
2247 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002248 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2249 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 break;
2251 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002252 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2253 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 break;
2255 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002256 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2257 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 break;
2259 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002260 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 break;
2262 }
2263
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002264 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002265 retval = stl_brdinit(brdp);
2266 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002267 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002269 pci_set_drvdata(pdev, brdp);
2270
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002271 for (i = 0; i < brdp->nrports; i++)
2272 tty_register_device(stl_serial,
2273 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2274
Jiri Slaby3b85b342006-12-08 02:39:10 -08002275 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002276err_null:
2277 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002278err_fr:
2279 kfree(brdp);
2280err:
2281 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282}
2283
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002284static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002286 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002287 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002289 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002291 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002293 release_region(brdp->ioaddr1, brdp->iosize1);
2294 if (brdp->iosize2 > 0)
2295 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002297 for (i = 0; i < brdp->nrports; i++)
2298 tty_unregister_device(stl_serial,
2299 brdp->brdnr * STL_MAXPORTS + i);
2300
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002301 stl_brds[brdp->brdnr] = NULL;
2302 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303}
2304
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002305static struct pci_driver stl_pcidriver = {
2306 .name = "stallion",
2307 .id_table = stl_pcibrds,
2308 .probe = stl_pciprobe,
2309 .remove = __devexit_p(stl_pciremove)
2310};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311
2312/*****************************************************************************/
2313
2314/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 * Return the board stats structure to user app.
2316 */
2317
2318static int stl_getbrdstats(combrd_t __user *bp)
2319{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002320 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002321 struct stlbrd *brdp;
2322 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002323 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324
2325 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2326 return -EFAULT;
2327 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002328 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002330 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002331 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332
2333 memset(&stl_brdstats, 0, sizeof(combrd_t));
2334 stl_brdstats.brd = brdp->brdnr;
2335 stl_brdstats.type = brdp->brdtype;
2336 stl_brdstats.hwid = brdp->hwid;
2337 stl_brdstats.state = brdp->state;
2338 stl_brdstats.ioaddr = brdp->ioaddr1;
2339 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2340 stl_brdstats.irq = brdp->irq;
2341 stl_brdstats.nrpanels = brdp->nrpanels;
2342 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002343 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 panelp = brdp->panels[i];
2345 stl_brdstats.panels[i].panel = i;
2346 stl_brdstats.panels[i].hwid = panelp->hwid;
2347 stl_brdstats.panels[i].nrports = panelp->nrports;
2348 }
2349
2350 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2351}
2352
2353/*****************************************************************************/
2354
2355/*
2356 * Resolve the referenced port number into a port struct pointer.
2357 */
2358
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002359static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002361 struct stlbrd *brdp;
2362 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
Jiri Slabyc62429d2006-12-08 02:39:14 -08002364 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2365 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002367 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002368 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002369 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002370 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002372 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002373 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002374 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002375 return NULL;
2376 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377}
2378
2379/*****************************************************************************/
2380
2381/*
2382 * Return the port stats structure to user app. A NULL port struct
2383 * pointer passed in means that we need to find out from the app
2384 * what port to get stats for (used through board control device).
2385 */
2386
Alan Coxd18a7502008-10-13 10:40:07 +01002387static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002389 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 unsigned char *head, *tail;
2391 unsigned long flags;
2392
2393 if (!portp) {
2394 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2395 return -EFAULT;
2396 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2397 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002398 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002399 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 }
2401
2402 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002403 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 portp->stats.hwid = portp->hwid;
2405
2406 portp->stats.ttystate = 0;
2407 portp->stats.cflags = 0;
2408 portp->stats.iflags = 0;
2409 portp->stats.oflags = 0;
2410 portp->stats.lflags = 0;
2411 portp->stats.rxbuffered = 0;
2412
Alan Coxb65b5b52006-06-27 02:54:05 -07002413 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002414 if (tty != NULL && portp->port.tty == tty) {
2415 portp->stats.ttystate = tty->flags;
2416 /* No longer available as a statistic */
2417 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2418 if (tty->termios != NULL) {
2419 portp->stats.cflags = tty->termios->c_cflag;
2420 portp->stats.iflags = tty->termios->c_iflag;
2421 portp->stats.oflags = tty->termios->c_oflag;
2422 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 }
Alan Coxd18a7502008-10-13 10:40:07 +01002424 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002425 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
2427 head = portp->tx.head;
2428 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002429 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2430 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
2432 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2433
2434 return copy_to_user(cp, &portp->stats,
2435 sizeof(comstats_t)) ? -EFAULT : 0;
2436}
2437
2438/*****************************************************************************/
2439
2440/*
2441 * Clear the port stats structure. We also return it zeroed out...
2442 */
2443
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002444static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002446 comstats_t stl_comstats;
2447
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 if (!portp) {
2449 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2450 return -EFAULT;
2451 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2452 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002453 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002454 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 }
2456
2457 memset(&portp->stats, 0, sizeof(comstats_t));
2458 portp->stats.brd = portp->brdnr;
2459 portp->stats.panel = portp->panelnr;
2460 portp->stats.port = portp->portnr;
2461 return copy_to_user(cp, &portp->stats,
2462 sizeof(comstats_t)) ? -EFAULT : 0;
2463}
2464
2465/*****************************************************************************/
2466
2467/*
2468 * Return the entire driver ports structure to a user app.
2469 */
2470
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002471static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002473 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002474 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002476 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 return -EFAULT;
2478 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2479 stl_dummyport.portnr);
2480 if (!portp)
2481 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002482 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483}
2484
2485/*****************************************************************************/
2486
2487/*
2488 * Return the entire driver board structure to a user app.
2489 */
2490
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002491static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002493 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002494 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002496 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002498 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 return -ENODEV;
2500 brdp = stl_brds[stl_dummybrd.brdnr];
2501 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002502 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002503 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504}
2505
2506/*****************************************************************************/
2507
2508/*
2509 * The "staliomem" device is also required to do some special operations
2510 * on the board and/or ports. In this driver it is mostly used for stats
2511 * collection.
2512 */
2513
2514static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2515{
2516 int brdnr, rc;
2517 void __user *argp = (void __user *)arg;
2518
Jiri Slabya0564e12006-12-08 02:38:37 -08002519 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520
2521 brdnr = iminor(ip);
2522 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002523 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 rc = 0;
2525
2526 switch (cmd) {
2527 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002528 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 break;
2530 case COM_CLRPORTSTATS:
2531 rc = stl_clrportstats(NULL, argp);
2532 break;
2533 case COM_GETBRDSTATS:
2534 rc = stl_getbrdstats(argp);
2535 break;
2536 case COM_READPORT:
2537 rc = stl_getportstruct(argp);
2538 break;
2539 case COM_READBOARD:
2540 rc = stl_getbrdstruct(argp);
2541 break;
2542 default:
2543 rc = -ENOIOCTLCMD;
2544 break;
2545 }
2546
Jiri Slabyc62429d2006-12-08 02:39:14 -08002547 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548}
2549
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002550static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 .open = stl_open,
2552 .close = stl_close,
2553 .write = stl_write,
2554 .put_char = stl_putchar,
2555 .flush_chars = stl_flushchars,
2556 .write_room = stl_writeroom,
2557 .chars_in_buffer = stl_charsinbuffer,
2558 .ioctl = stl_ioctl,
2559 .set_termios = stl_settermios,
2560 .throttle = stl_throttle,
2561 .unthrottle = stl_unthrottle,
2562 .stop = stl_stop,
2563 .start = stl_start,
2564 .hangup = stl_hangup,
2565 .flush_buffer = stl_flushbuffer,
2566 .break_ctl = stl_breakctl,
2567 .wait_until_sent = stl_waituntilsent,
2568 .send_xchar = stl_sendxchar,
2569 .read_proc = stl_readproc,
2570 .tiocmget = stl_tiocmget,
2571 .tiocmset = stl_tiocmset,
2572};
2573
Alan Cox31f35932009-01-02 13:45:05 +00002574static const struct tty_port_operations stl_port_ops = {
2575 .carrier_raised = stl_carrier_raised,
Alan Cox4350f3f2009-01-02 13:46:24 +00002576 .raise_dtr_rts = stl_raise_dtr_rts,
Alan Cox31f35932009-01-02 13:45:05 +00002577};
2578
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580/* CD1400 HARDWARE FUNCTIONS */
2581/*****************************************************************************/
2582
2583/*
2584 * These functions get/set/update the registers of the cd1400 UARTs.
2585 * Access to the cd1400 registers is via an address/data io port pair.
2586 * (Maybe should make this inline...)
2587 */
2588
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002589static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590{
2591 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002592 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593}
2594
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002595static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002597 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 outb(value, portp->ioaddr + EREG_DATA);
2599}
2600
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002601static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002603 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 if (inb(portp->ioaddr + EREG_DATA) != value) {
2605 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002606 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002608 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609}
2610
2611/*****************************************************************************/
2612
2613/*
2614 * Inbitialize the UARTs in a panel. We don't care what sort of board
2615 * these ports are on - since the port io registers are almost
2616 * identical when dealing with ports.
2617 */
2618
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002619static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620{
2621 unsigned int gfrcr;
2622 int chipmask, i, j;
2623 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002624 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625
Jiri Slabya0564e12006-12-08 02:38:37 -08002626 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
Alan Coxb65b5b52006-06-27 02:54:05 -07002628 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 BRDENABLE(panelp->brdnr, panelp->pagenr);
2630
2631/*
2632 * Check that each chip is present and started up OK.
2633 */
2634 chipmask = 0;
2635 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002636 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 if (brdp->brdtype == BRD_ECHPCI) {
2638 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2639 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002640 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 uartaddr = (i & 0x01) ? 0x080 : 0;
2643 outb((GFRCR + uartaddr), ioaddr);
2644 outb(0, (ioaddr + EREG_DATA));
2645 outb((CCR + uartaddr), ioaddr);
2646 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2647 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2648 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002649 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2651 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002652
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2654 printk("STALLION: cd1400 not responding, "
2655 "brd=%d panel=%d chip=%d\n",
2656 panelp->brdnr, panelp->panelnr, i);
2657 continue;
2658 }
2659 chipmask |= (0x1 << i);
2660 outb((PPR + uartaddr), ioaddr);
2661 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2662 }
2663
2664 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002665 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002666 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667}
2668
2669/*****************************************************************************/
2670
2671/*
2672 * Initialize hardware specific port registers.
2673 */
2674
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002675static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676{
Alan Coxb65b5b52006-06-27 02:54:05 -07002677 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002678 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2679 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680
Jiri Slaby615e4a72006-12-08 02:38:38 -08002681 if ((brdp == NULL) || (panelp == NULL) ||
2682 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 return;
2684
Alan Coxb65b5b52006-06-27 02:54:05 -07002685 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2687 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2688 portp->uartaddr = (portp->portnr & 0x04) << 5;
2689 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2690
2691 BRDENABLE(portp->brdnr, portp->pagenr);
2692 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2693 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2694 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2695 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002696 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697}
2698
2699/*****************************************************************************/
2700
2701/*
2702 * Wait for the command register to be ready. We will poll this,
2703 * since it won't usually take too long to be ready.
2704 */
2705
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002706static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707{
2708 int i;
2709
Jiri Slabyc62429d2006-12-08 02:39:14 -08002710 for (i = 0; i < CCR_MAXWAIT; i++)
2711 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713
2714 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2715 portp->portnr, portp->panelnr, portp->brdnr);
2716}
2717
2718/*****************************************************************************/
2719
2720/*
2721 * Set up the cd1400 registers for a port based on the termios port
2722 * settings.
2723 */
2724
Alan Cox606d0992006-12-08 02:38:45 -08002725static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002727 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 unsigned long flags;
2729 unsigned int clkdiv, baudrate;
2730 unsigned char cor1, cor2, cor3;
2731 unsigned char cor4, cor5, ccr;
2732 unsigned char srer, sreron, sreroff;
2733 unsigned char mcor1, mcor2, rtpr;
2734 unsigned char clk, div;
2735
2736 cor1 = 0;
2737 cor2 = 0;
2738 cor3 = 0;
2739 cor4 = 0;
2740 cor5 = 0;
2741 ccr = 0;
2742 rtpr = 0;
2743 clk = 0;
2744 div = 0;
2745 mcor1 = 0;
2746 mcor2 = 0;
2747 sreron = 0;
2748 sreroff = 0;
2749
2750 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002751 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 return;
2753
2754/*
2755 * Set up the RX char ignore mask with those RX error types we
2756 * can ignore. We can get the cd1400 to help us out a little here,
2757 * it will ignore parity errors and breaks for us.
2758 */
2759 portp->rxignoremsk = 0;
2760 if (tiosp->c_iflag & IGNPAR) {
2761 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2762 cor1 |= COR1_PARIGNORE;
2763 }
2764 if (tiosp->c_iflag & IGNBRK) {
2765 portp->rxignoremsk |= ST_BREAK;
2766 cor4 |= COR4_IGNBRK;
2767 }
2768
2769 portp->rxmarkmsk = ST_OVERRUN;
2770 if (tiosp->c_iflag & (INPCK | PARMRK))
2771 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2772 if (tiosp->c_iflag & BRKINT)
2773 portp->rxmarkmsk |= ST_BREAK;
2774
2775/*
2776 * Go through the char size, parity and stop bits and set all the
2777 * option register appropriately.
2778 */
2779 switch (tiosp->c_cflag & CSIZE) {
2780 case CS5:
2781 cor1 |= COR1_CHL5;
2782 break;
2783 case CS6:
2784 cor1 |= COR1_CHL6;
2785 break;
2786 case CS7:
2787 cor1 |= COR1_CHL7;
2788 break;
2789 default:
2790 cor1 |= COR1_CHL8;
2791 break;
2792 }
2793
2794 if (tiosp->c_cflag & CSTOPB)
2795 cor1 |= COR1_STOP2;
2796 else
2797 cor1 |= COR1_STOP1;
2798
2799 if (tiosp->c_cflag & PARENB) {
2800 if (tiosp->c_cflag & PARODD)
2801 cor1 |= (COR1_PARENB | COR1_PARODD);
2802 else
2803 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2804 } else {
2805 cor1 |= COR1_PARNONE;
2806 }
2807
2808/*
2809 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2810 * space for hardware flow control and the like. This should be set to
2811 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2812 * really be based on VTIME.
2813 */
2814 cor3 |= FIFO_RXTHRESHOLD;
2815 rtpr = 2;
2816
2817/*
2818 * Calculate the baud rate timers. For now we will just assume that
2819 * the input and output baud are the same. Could have used a baud
2820 * table here, but this way we can generate virtually any baud rate
2821 * we like!
2822 */
2823 baudrate = tiosp->c_cflag & CBAUD;
2824 if (baudrate & CBAUDEX) {
2825 baudrate &= ~CBAUDEX;
2826 if ((baudrate < 1) || (baudrate > 4))
2827 tiosp->c_cflag &= ~CBAUDEX;
2828 else
2829 baudrate += 15;
2830 }
2831 baudrate = stl_baudrates[baudrate];
2832 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002833 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002835 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002837 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002839 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002841 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 baudrate = (portp->baud_base / portp->custom_divisor);
2843 }
2844 if (baudrate > STL_CD1400MAXBAUD)
2845 baudrate = STL_CD1400MAXBAUD;
2846
2847 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002848 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2849 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 if (clkdiv < 0x100)
2851 break;
2852 }
2853 div = (unsigned char) clkdiv;
2854 }
2855
2856/*
2857 * Check what form of modem signaling is required and set it up.
2858 */
2859 if ((tiosp->c_cflag & CLOCAL) == 0) {
2860 mcor1 |= MCOR1_DCD;
2861 mcor2 |= MCOR2_DCD;
2862 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002863 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002864 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002865 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866
2867/*
2868 * Setup cd1400 enhanced modes if we can. In particular we want to
2869 * handle as much of the flow control as possible automatically. As
2870 * well as saving a few CPU cycles it will also greatly improve flow
2871 * control reliability.
2872 */
2873 if (tiosp->c_iflag & IXON) {
2874 cor2 |= COR2_TXIBE;
2875 cor3 |= COR3_SCD12;
2876 if (tiosp->c_iflag & IXANY)
2877 cor2 |= COR2_IXM;
2878 }
2879
2880 if (tiosp->c_cflag & CRTSCTS) {
2881 cor2 |= COR2_CTSAE;
2882 mcor1 |= FIFO_RTSTHRESHOLD;
2883 }
2884
2885/*
2886 * All cd1400 register values calculated so go through and set
2887 * them all up.
2888 */
2889
Jiri Slabya0564e12006-12-08 02:38:37 -08002890 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002892 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002894 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002896 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2897 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2899 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900
Alan Coxb65b5b52006-06-27 02:54:05 -07002901 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 BRDENABLE(portp->brdnr, portp->pagenr);
2903 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2904 srer = stl_cd1400getreg(portp, SRER);
2905 stl_cd1400setreg(portp, SRER, 0);
2906 if (stl_cd1400updatereg(portp, COR1, cor1))
2907 ccr = 1;
2908 if (stl_cd1400updatereg(portp, COR2, cor2))
2909 ccr = 1;
2910 if (stl_cd1400updatereg(portp, COR3, cor3))
2911 ccr = 1;
2912 if (ccr) {
2913 stl_cd1400ccrwait(portp);
2914 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2915 }
2916 stl_cd1400setreg(portp, COR4, cor4);
2917 stl_cd1400setreg(portp, COR5, cor5);
2918 stl_cd1400setreg(portp, MCOR1, mcor1);
2919 stl_cd1400setreg(portp, MCOR2, mcor2);
2920 if (baudrate > 0) {
2921 stl_cd1400setreg(portp, TCOR, clk);
2922 stl_cd1400setreg(portp, TBPR, div);
2923 stl_cd1400setreg(portp, RCOR, clk);
2924 stl_cd1400setreg(portp, RBPR, div);
2925 }
2926 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2927 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2928 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2929 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2930 stl_cd1400setreg(portp, RTPR, rtpr);
2931 mcor1 = stl_cd1400getreg(portp, MSVR1);
2932 if (mcor1 & MSVR1_DCD)
2933 portp->sigs |= TIOCM_CD;
2934 else
2935 portp->sigs &= ~TIOCM_CD;
2936 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2937 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002938 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939}
2940
2941/*****************************************************************************/
2942
2943/*
2944 * Set the state of the DTR and RTS signals.
2945 */
2946
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002947static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948{
2949 unsigned char msvr1, msvr2;
2950 unsigned long flags;
2951
Jiri Slabya0564e12006-12-08 02:38:37 -08002952 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2953 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954
2955 msvr1 = 0;
2956 msvr2 = 0;
2957 if (dtr > 0)
2958 msvr1 = MSVR1_DTR;
2959 if (rts > 0)
2960 msvr2 = MSVR2_RTS;
2961
Alan Coxb65b5b52006-06-27 02:54:05 -07002962 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 BRDENABLE(portp->brdnr, portp->pagenr);
2964 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2965 if (rts >= 0)
2966 stl_cd1400setreg(portp, MSVR2, msvr2);
2967 if (dtr >= 0)
2968 stl_cd1400setreg(portp, MSVR1, msvr1);
2969 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002970 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971}
2972
2973/*****************************************************************************/
2974
2975/*
2976 * Return the state of the signals.
2977 */
2978
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002979static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980{
2981 unsigned char msvr1, msvr2;
2982 unsigned long flags;
2983 int sigs;
2984
Jiri Slabya0564e12006-12-08 02:38:37 -08002985 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986
Alan Coxb65b5b52006-06-27 02:54:05 -07002987 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 BRDENABLE(portp->brdnr, portp->pagenr);
2989 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2990 msvr1 = stl_cd1400getreg(portp, MSVR1);
2991 msvr2 = stl_cd1400getreg(portp, MSVR2);
2992 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002993 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994
2995 sigs = 0;
2996 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
2997 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
2998 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
2999 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3000#if 0
3001 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3002 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3003#else
3004 sigs |= TIOCM_DSR;
3005#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003006 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007}
3008
3009/*****************************************************************************/
3010
3011/*
3012 * Enable/Disable the Transmitter and/or Receiver.
3013 */
3014
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003015static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016{
3017 unsigned char ccr;
3018 unsigned long flags;
3019
Jiri Slabya0564e12006-12-08 02:38:37 -08003020 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3021
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 ccr = 0;
3023
3024 if (tx == 0)
3025 ccr |= CCR_TXDISABLE;
3026 else if (tx > 0)
3027 ccr |= CCR_TXENABLE;
3028 if (rx == 0)
3029 ccr |= CCR_RXDISABLE;
3030 else if (rx > 0)
3031 ccr |= CCR_RXENABLE;
3032
Alan Coxb65b5b52006-06-27 02:54:05 -07003033 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 BRDENABLE(portp->brdnr, portp->pagenr);
3035 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3036 stl_cd1400ccrwait(portp);
3037 stl_cd1400setreg(portp, CCR, ccr);
3038 stl_cd1400ccrwait(portp);
3039 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003040 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041}
3042
3043/*****************************************************************************/
3044
3045/*
3046 * Start/stop the Transmitter and/or Receiver.
3047 */
3048
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003049static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050{
3051 unsigned char sreron, sreroff;
3052 unsigned long flags;
3053
Jiri Slabya0564e12006-12-08 02:38:37 -08003054 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055
3056 sreron = 0;
3057 sreroff = 0;
3058 if (tx == 0)
3059 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3060 else if (tx == 1)
3061 sreron |= SRER_TXDATA;
3062 else if (tx >= 2)
3063 sreron |= SRER_TXEMPTY;
3064 if (rx == 0)
3065 sreroff |= SRER_RXDATA;
3066 else if (rx > 0)
3067 sreron |= SRER_RXDATA;
3068
Alan Coxb65b5b52006-06-27 02:54:05 -07003069 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 BRDENABLE(portp->brdnr, portp->pagenr);
3071 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3072 stl_cd1400setreg(portp, SRER,
3073 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3074 BRDDISABLE(portp->brdnr);
3075 if (tx > 0)
3076 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003077 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078}
3079
3080/*****************************************************************************/
3081
3082/*
3083 * Disable all interrupts from this port.
3084 */
3085
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003086static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087{
3088 unsigned long flags;
3089
Jiri Slabya0564e12006-12-08 02:38:37 -08003090 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3091
Alan Coxb65b5b52006-06-27 02:54:05 -07003092 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093 BRDENABLE(portp->brdnr, portp->pagenr);
3094 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3095 stl_cd1400setreg(portp, SRER, 0);
3096 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003097 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098}
3099
3100/*****************************************************************************/
3101
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003102static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103{
3104 unsigned long flags;
3105
Jiri Slabya0564e12006-12-08 02:38:37 -08003106 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
Alan Coxb65b5b52006-06-27 02:54:05 -07003108 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 BRDENABLE(portp->brdnr, portp->pagenr);
3110 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3111 stl_cd1400setreg(portp, SRER,
3112 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3113 SRER_TXEMPTY));
3114 BRDDISABLE(portp->brdnr);
3115 portp->brklen = len;
3116 if (len == 1)
3117 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003118 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119}
3120
3121/*****************************************************************************/
3122
3123/*
3124 * Take flow control actions...
3125 */
3126
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003127static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128{
3129 struct tty_struct *tty;
3130 unsigned long flags;
3131
Jiri Slabya0564e12006-12-08 02:38:37 -08003132 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133
Jiri Slaby615e4a72006-12-08 02:38:38 -08003134 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003136 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003137 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 return;
3139
Alan Coxb65b5b52006-06-27 02:54:05 -07003140 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 BRDENABLE(portp->brdnr, portp->pagenr);
3142 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3143
3144 if (state) {
3145 if (tty->termios->c_iflag & IXOFF) {
3146 stl_cd1400ccrwait(portp);
3147 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3148 portp->stats.rxxon++;
3149 stl_cd1400ccrwait(portp);
3150 }
3151/*
3152 * Question: should we return RTS to what it was before? It may
3153 * have been set by an ioctl... Suppose not, since if you have
3154 * hardware flow control set then it is pretty silly to go and
3155 * set the RTS line by hand.
3156 */
3157 if (tty->termios->c_cflag & CRTSCTS) {
3158 stl_cd1400setreg(portp, MCOR1,
3159 (stl_cd1400getreg(portp, MCOR1) |
3160 FIFO_RTSTHRESHOLD));
3161 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3162 portp->stats.rxrtson++;
3163 }
3164 } else {
3165 if (tty->termios->c_iflag & IXOFF) {
3166 stl_cd1400ccrwait(portp);
3167 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3168 portp->stats.rxxoff++;
3169 stl_cd1400ccrwait(portp);
3170 }
3171 if (tty->termios->c_cflag & CRTSCTS) {
3172 stl_cd1400setreg(portp, MCOR1,
3173 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3174 stl_cd1400setreg(portp, MSVR2, 0);
3175 portp->stats.rxrtsoff++;
3176 }
3177 }
3178
3179 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003180 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003181 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182}
3183
3184/*****************************************************************************/
3185
3186/*
3187 * Send a flow control character...
3188 */
3189
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003190static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191{
3192 struct tty_struct *tty;
3193 unsigned long flags;
3194
Jiri Slabya0564e12006-12-08 02:38:37 -08003195 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
Jiri Slaby615e4a72006-12-08 02:38:38 -08003197 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003199 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003200 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 return;
3202
Alan Coxb65b5b52006-06-27 02:54:05 -07003203 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204 BRDENABLE(portp->brdnr, portp->pagenr);
3205 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3206 if (state) {
3207 stl_cd1400ccrwait(portp);
3208 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3209 portp->stats.rxxon++;
3210 stl_cd1400ccrwait(portp);
3211 } else {
3212 stl_cd1400ccrwait(portp);
3213 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3214 portp->stats.rxxoff++;
3215 stl_cd1400ccrwait(portp);
3216 }
3217 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003218 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003219 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220}
3221
3222/*****************************************************************************/
3223
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003224static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225{
3226 unsigned long flags;
3227
Jiri Slabya0564e12006-12-08 02:38:37 -08003228 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229
Jiri Slaby615e4a72006-12-08 02:38:38 -08003230 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 return;
3232
Alan Coxb65b5b52006-06-27 02:54:05 -07003233 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 BRDENABLE(portp->brdnr, portp->pagenr);
3235 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3236 stl_cd1400ccrwait(portp);
3237 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3238 stl_cd1400ccrwait(portp);
3239 portp->tx.tail = portp->tx.head;
3240 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003241 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242}
3243
3244/*****************************************************************************/
3245
3246/*
3247 * Return the current state of data flow on this port. This is only
3248 * really interresting when determining if data has fully completed
3249 * transmission or not... This is easy for the cd1400, it accurately
3250 * maintains the busy port flag.
3251 */
3252
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003253static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254{
Jiri Slabya0564e12006-12-08 02:38:37 -08003255 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256
Jiri Slaby615e4a72006-12-08 02:38:38 -08003257 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003258 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
Jesper Juhl014c2542006-01-15 02:37:08 +01003260 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261}
3262
3263/*****************************************************************************/
3264
3265/*
3266 * Interrupt service routine for cd1400 EasyIO boards.
3267 */
3268
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003269static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270{
3271 unsigned char svrtype;
3272
Jiri Slabya0564e12006-12-08 02:38:37 -08003273 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274
Alan Coxb65b5b52006-06-27 02:54:05 -07003275 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276 outb(SVRR, iobase);
3277 svrtype = inb(iobase + EREG_DATA);
3278 if (panelp->nrports > 4) {
3279 outb((SVRR + 0x80), iobase);
3280 svrtype |= inb(iobase + EREG_DATA);
3281 }
3282
3283 if (svrtype & SVRR_RX)
3284 stl_cd1400rxisr(panelp, iobase);
3285 else if (svrtype & SVRR_TX)
3286 stl_cd1400txisr(panelp, iobase);
3287 else if (svrtype & SVRR_MDM)
3288 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003289
3290 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291}
3292
3293/*****************************************************************************/
3294
3295/*
3296 * Interrupt service routine for cd1400 panels.
3297 */
3298
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003299static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300{
3301 unsigned char svrtype;
3302
Jiri Slabya0564e12006-12-08 02:38:37 -08003303 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
3305 outb(SVRR, iobase);
3306 svrtype = inb(iobase + EREG_DATA);
3307 outb((SVRR + 0x80), iobase);
3308 svrtype |= inb(iobase + EREG_DATA);
3309 if (svrtype & SVRR_RX)
3310 stl_cd1400rxisr(panelp, iobase);
3311 else if (svrtype & SVRR_TX)
3312 stl_cd1400txisr(panelp, iobase);
3313 else if (svrtype & SVRR_MDM)
3314 stl_cd1400mdmisr(panelp, iobase);
3315}
3316
3317
3318/*****************************************************************************/
3319
3320/*
3321 * Unfortunately we need to handle breaks in the TX data stream, since
3322 * this is the only way to generate them on the cd1400.
3323 */
3324
Jiri Slaby60be4812006-12-08 02:38:40 -08003325static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326{
3327 if (portp->brklen == 1) {
3328 outb((COR2 + portp->uartaddr), ioaddr);
3329 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3330 (ioaddr + EREG_DATA));
3331 outb((TDR + portp->uartaddr), ioaddr);
3332 outb(ETC_CMD, (ioaddr + EREG_DATA));
3333 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3334 outb((SRER + portp->uartaddr), ioaddr);
3335 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3336 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003337 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 } else if (portp->brklen > 1) {
3339 outb((TDR + portp->uartaddr), ioaddr);
3340 outb(ETC_CMD, (ioaddr + EREG_DATA));
3341 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3342 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003343 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 } else {
3345 outb((COR2 + portp->uartaddr), ioaddr);
3346 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3347 (ioaddr + EREG_DATA));
3348 portp->brklen = 0;
3349 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003350 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351}
3352
3353/*****************************************************************************/
3354
3355/*
3356 * Transmit interrupt handler. This has gotta be fast! Handling TX
3357 * chars is pretty simple, stuff as many as possible from the TX buffer
3358 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3359 * are embedded as commands in the data stream. Oh no, had to use a goto!
3360 * This could be optimized more, will do when I get time...
3361 * In practice it is possible that interrupts are enabled but that the
3362 * port has been hung up. Need to handle not having any TX buffer here,
3363 * this is done by using the side effect that head and tail will also
3364 * be NULL if the buffer has been freed.
3365 */
3366
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003367static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003369 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 int len, stlen;
3371 char *head, *tail;
3372 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003373 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374
Jiri Slabya0564e12006-12-08 02:38:37 -08003375 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376
3377 ioack = inb(ioaddr + EREG_TXACK);
3378 if (((ioack & panelp->ackmask) != 0) ||
3379 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3380 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3381 return;
3382 }
3383 portp = panelp->ports[(ioack >> 3)];
3384
3385/*
3386 * Unfortunately we need to handle breaks in the data stream, since
3387 * this is the only way to generate them on the cd1400. Do it now if
3388 * a break is to be sent.
3389 */
3390 if (portp->brklen != 0)
3391 if (stl_cd1400breakisr(portp, ioaddr))
3392 goto stl_txalldone;
3393
3394 head = portp->tx.head;
3395 tail = portp->tx.tail;
3396 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3397 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3398 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3399 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003400 tty = tty_port_tty_get(&portp->port);
3401 if (tty) {
3402 tty_wakeup(tty);
3403 tty_kref_put(tty);
3404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 }
3406
3407 if (len == 0) {
3408 outb((SRER + portp->uartaddr), ioaddr);
3409 srer = inb(ioaddr + EREG_DATA);
3410 if (srer & SRER_TXDATA) {
3411 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3412 } else {
3413 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3414 clear_bit(ASYI_TXBUSY, &portp->istate);
3415 }
3416 outb(srer, (ioaddr + EREG_DATA));
3417 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003418 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003420 stlen = min_t(unsigned int, len,
3421 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 outb((TDR + portp->uartaddr), ioaddr);
3423 outsb((ioaddr + EREG_DATA), tail, stlen);
3424 len -= stlen;
3425 tail += stlen;
3426 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3427 tail = portp->tx.buf;
3428 if (len > 0) {
3429 outsb((ioaddr + EREG_DATA), tail, len);
3430 tail += len;
3431 }
3432 portp->tx.tail = tail;
3433 }
3434
3435stl_txalldone:
3436 outb((EOSRR + portp->uartaddr), ioaddr);
3437 outb(0, (ioaddr + EREG_DATA));
3438}
3439
3440/*****************************************************************************/
3441
3442/*
3443 * Receive character interrupt handler. Determine if we have good chars
3444 * or bad chars and then process appropriately. Good chars are easy
3445 * just shove the lot into the RX buffer and set all status byte to 0.
3446 * If a bad RX char then process as required. This routine needs to be
3447 * fast! In practice it is possible that we get an interrupt on a port
3448 * that is closed. This can happen on hangups - since they completely
3449 * shutdown a port not in user context. Need to handle this case.
3450 */
3451
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003452static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003454 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 struct tty_struct *tty;
3456 unsigned int ioack, len, buflen;
3457 unsigned char status;
3458 char ch;
3459
Jiri Slabya0564e12006-12-08 02:38:37 -08003460 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461
3462 ioack = inb(ioaddr + EREG_RXACK);
3463 if ((ioack & panelp->ackmask) != 0) {
3464 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3465 return;
3466 }
3467 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003468 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469
3470 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3471 outb((RDCR + portp->uartaddr), ioaddr);
3472 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003473 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003474 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475 outb((RDSR + portp->uartaddr), ioaddr);
3476 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3477 portp->stats.rxlost += len;
3478 portp->stats.rxtotal += len;
3479 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003480 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003482 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003484 tty_prepare_flip_string(tty, &ptr, len);
3485 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 tty_schedule_flip(tty);
3487 portp->stats.rxtotal += len;
3488 }
3489 }
3490 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3491 outb((RDSR + portp->uartaddr), ioaddr);
3492 status = inb(ioaddr + EREG_DATA);
3493 ch = inb(ioaddr + EREG_DATA);
3494 if (status & ST_PARITY)
3495 portp->stats.rxparity++;
3496 if (status & ST_FRAMING)
3497 portp->stats.rxframing++;
3498 if (status & ST_OVERRUN)
3499 portp->stats.rxoverrun++;
3500 if (status & ST_BREAK)
3501 portp->stats.rxbreaks++;
3502 if (status & ST_SCHARMASK) {
3503 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3504 portp->stats.txxon++;
3505 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3506 portp->stats.txxoff++;
3507 goto stl_rxalldone;
3508 }
Alan Cox33f0f882006-01-09 20:54:13 -08003509 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 if (portp->rxmarkmsk & status) {
3511 if (status & ST_BREAK) {
3512 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003513 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 do_SAK(tty);
3515 BRDENABLE(portp->brdnr, portp->pagenr);
3516 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003517 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003519 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003521 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003523 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003525 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003527 tty_insert_flip_char(tty, ch, status);
3528 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529 }
3530 } else {
3531 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003532 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 return;
3534 }
3535
3536stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003537 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538 outb((EOSRR + portp->uartaddr), ioaddr);
3539 outb(0, (ioaddr + EREG_DATA));
3540}
3541
3542/*****************************************************************************/
3543
3544/*
3545 * Modem interrupt handler. The is called when the modem signal line
3546 * (DCD) has changed state. Leave most of the work to the off-level
3547 * processing routine.
3548 */
3549
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003550static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003552 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553 unsigned int ioack;
3554 unsigned char misr;
3555
Jiri Slabya0564e12006-12-08 02:38:37 -08003556 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557
3558 ioack = inb(ioaddr + EREG_MDACK);
3559 if (((ioack & panelp->ackmask) != 0) ||
3560 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3561 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3562 return;
3563 }
3564 portp = panelp->ports[(ioack >> 3)];
3565
3566 outb((MISR + portp->uartaddr), ioaddr);
3567 misr = inb(ioaddr + EREG_DATA);
3568 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003569 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570 portp->stats.modem++;
3571 }
3572
3573 outb((EOSRR + portp->uartaddr), ioaddr);
3574 outb(0, (ioaddr + EREG_DATA));
3575}
3576
3577/*****************************************************************************/
3578/* SC26198 HARDWARE FUNCTIONS */
3579/*****************************************************************************/
3580
3581/*
3582 * These functions get/set/update the registers of the sc26198 UARTs.
3583 * Access to the sc26198 registers is via an address/data io port pair.
3584 * (Maybe should make this inline...)
3585 */
3586
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003587static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588{
3589 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003590 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591}
3592
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003593static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594{
3595 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3596 outb(value, (portp->ioaddr + XP_DATA));
3597}
3598
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003599static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600{
3601 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3602 if (inb(portp->ioaddr + XP_DATA) != value) {
3603 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003604 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003606 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607}
3608
3609/*****************************************************************************/
3610
3611/*
3612 * Functions to get and set the sc26198 global registers.
3613 */
3614
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003615static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616{
3617 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003618 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619}
3620
3621#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003622static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623{
3624 outb(regnr, (portp->ioaddr + XP_ADDR));
3625 outb(value, (portp->ioaddr + XP_DATA));
3626}
3627#endif
3628
3629/*****************************************************************************/
3630
3631/*
3632 * Inbitialize the UARTs in a panel. We don't care what sort of board
3633 * these ports are on - since the port io registers are almost
3634 * identical when dealing with ports.
3635 */
3636
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003637static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638{
3639 int chipmask, i;
3640 int nrchips, ioaddr;
3641
Jiri Slabya0564e12006-12-08 02:38:37 -08003642 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643
3644 BRDENABLE(panelp->brdnr, panelp->pagenr);
3645
3646/*
3647 * Check that each chip is present and started up OK.
3648 */
3649 chipmask = 0;
3650 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3651 if (brdp->brdtype == BRD_ECHPCI)
3652 outb(panelp->pagenr, brdp->ioctrl);
3653
Jiri Slabyc62429d2006-12-08 02:39:14 -08003654 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655 ioaddr = panelp->iobase + (i * 4);
3656 outb(SCCR, (ioaddr + XP_ADDR));
3657 outb(CR_RESETALL, (ioaddr + XP_DATA));
3658 outb(TSTR, (ioaddr + XP_ADDR));
3659 if (inb(ioaddr + XP_DATA) != 0) {
3660 printk("STALLION: sc26198 not responding, "
3661 "brd=%d panel=%d chip=%d\n",
3662 panelp->brdnr, panelp->panelnr, i);
3663 continue;
3664 }
3665 chipmask |= (0x1 << i);
3666 outb(GCCR, (ioaddr + XP_ADDR));
3667 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3668 outb(WDTRCR, (ioaddr + XP_ADDR));
3669 outb(0xff, (ioaddr + XP_DATA));
3670 }
3671
3672 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003673 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674}
3675
3676/*****************************************************************************/
3677
3678/*
3679 * Initialize hardware specific port registers.
3680 */
3681
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003682static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683{
Jiri Slabya0564e12006-12-08 02:38:37 -08003684 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3685 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686
Jiri Slaby615e4a72006-12-08 02:38:38 -08003687 if ((brdp == NULL) || (panelp == NULL) ||
3688 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 return;
3690
3691 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3692 portp->uartaddr = (portp->portnr & 0x07) << 4;
3693 portp->pagenr = panelp->pagenr;
3694 portp->hwid = 0x1;
3695
3696 BRDENABLE(portp->brdnr, portp->pagenr);
3697 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3698 BRDDISABLE(portp->brdnr);
3699}
3700
3701/*****************************************************************************/
3702
3703/*
3704 * Set up the sc26198 registers for a port based on the termios port
3705 * settings.
3706 */
3707
Alan Cox606d0992006-12-08 02:38:45 -08003708static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003710 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 unsigned long flags;
3712 unsigned int baudrate;
3713 unsigned char mr0, mr1, mr2, clk;
3714 unsigned char imron, imroff, iopr, ipr;
3715
3716 mr0 = 0;
3717 mr1 = 0;
3718 mr2 = 0;
3719 clk = 0;
3720 iopr = 0;
3721 imron = 0;
3722 imroff = 0;
3723
3724 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003725 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 return;
3727
3728/*
3729 * Set up the RX char ignore mask with those RX error types we
3730 * can ignore.
3731 */
3732 portp->rxignoremsk = 0;
3733 if (tiosp->c_iflag & IGNPAR)
3734 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3735 SR_RXOVERRUN);
3736 if (tiosp->c_iflag & IGNBRK)
3737 portp->rxignoremsk |= SR_RXBREAK;
3738
3739 portp->rxmarkmsk = SR_RXOVERRUN;
3740 if (tiosp->c_iflag & (INPCK | PARMRK))
3741 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3742 if (tiosp->c_iflag & BRKINT)
3743 portp->rxmarkmsk |= SR_RXBREAK;
3744
3745/*
3746 * Go through the char size, parity and stop bits and set all the
3747 * option register appropriately.
3748 */
3749 switch (tiosp->c_cflag & CSIZE) {
3750 case CS5:
3751 mr1 |= MR1_CS5;
3752 break;
3753 case CS6:
3754 mr1 |= MR1_CS6;
3755 break;
3756 case CS7:
3757 mr1 |= MR1_CS7;
3758 break;
3759 default:
3760 mr1 |= MR1_CS8;
3761 break;
3762 }
3763
3764 if (tiosp->c_cflag & CSTOPB)
3765 mr2 |= MR2_STOP2;
3766 else
3767 mr2 |= MR2_STOP1;
3768
3769 if (tiosp->c_cflag & PARENB) {
3770 if (tiosp->c_cflag & PARODD)
3771 mr1 |= (MR1_PARENB | MR1_PARODD);
3772 else
3773 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003774 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776
3777 mr1 |= MR1_ERRBLOCK;
3778
3779/*
3780 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3781 * space for hardware flow control and the like. This should be set to
3782 * VMIN.
3783 */
3784 mr2 |= MR2_RXFIFOHALF;
3785
3786/*
3787 * Calculate the baud rate timers. For now we will just assume that
3788 * the input and output baud are the same. The sc26198 has a fixed
3789 * baud rate table, so only discrete baud rates possible.
3790 */
3791 baudrate = tiosp->c_cflag & CBAUD;
3792 if (baudrate & CBAUDEX) {
3793 baudrate &= ~CBAUDEX;
3794 if ((baudrate < 1) || (baudrate > 4))
3795 tiosp->c_cflag &= ~CBAUDEX;
3796 else
3797 baudrate += 15;
3798 }
3799 baudrate = stl_baudrates[baudrate];
3800 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003801 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003803 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003805 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003807 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003809 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 baudrate = (portp->baud_base / portp->custom_divisor);
3811 }
3812 if (baudrate > STL_SC26198MAXBAUD)
3813 baudrate = STL_SC26198MAXBAUD;
3814
Jiri Slabyc62429d2006-12-08 02:39:14 -08003815 if (baudrate > 0)
3816 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 if (baudrate <= sc26198_baudtable[clk])
3818 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819
3820/*
3821 * Check what form of modem signaling is required and set it up.
3822 */
3823 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003824 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 } else {
3826 iopr |= IOPR_DCDCOS;
3827 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003828 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829 }
3830
3831/*
3832 * Setup sc26198 enhanced modes if we can. In particular we want to
3833 * handle as much of the flow control as possible automatically. As
3834 * well as saving a few CPU cycles it will also greatly improve flow
3835 * control reliability.
3836 */
3837 if (tiosp->c_iflag & IXON) {
3838 mr0 |= MR0_SWFTX | MR0_SWFT;
3839 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003840 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003842
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 if (tiosp->c_iflag & IXOFF)
3844 mr0 |= MR0_SWFRX;
3845
3846 if (tiosp->c_cflag & CRTSCTS) {
3847 mr2 |= MR2_AUTOCTS;
3848 mr1 |= MR1_AUTORTS;
3849 }
3850
3851/*
3852 * All sc26198 register values calculated so go through and set
3853 * them all up.
3854 */
3855
Jiri Slabya0564e12006-12-08 02:38:37 -08003856 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003858 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3859 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3860 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3862 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863
Alan Coxb65b5b52006-06-27 02:54:05 -07003864 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 BRDENABLE(portp->brdnr, portp->pagenr);
3866 stl_sc26198setreg(portp, IMR, 0);
3867 stl_sc26198updatereg(portp, MR0, mr0);
3868 stl_sc26198updatereg(portp, MR1, mr1);
3869 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3870 stl_sc26198updatereg(portp, MR2, mr2);
3871 stl_sc26198updatereg(portp, IOPIOR,
3872 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3873
3874 if (baudrate > 0) {
3875 stl_sc26198setreg(portp, TXCSR, clk);
3876 stl_sc26198setreg(portp, RXCSR, clk);
3877 }
3878
3879 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3880 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3881
3882 ipr = stl_sc26198getreg(portp, IPR);
3883 if (ipr & IPR_DCD)
3884 portp->sigs &= ~TIOCM_CD;
3885 else
3886 portp->sigs |= TIOCM_CD;
3887
3888 portp->imr = (portp->imr & ~imroff) | imron;
3889 stl_sc26198setreg(portp, IMR, portp->imr);
3890 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003891 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892}
3893
3894/*****************************************************************************/
3895
3896/*
3897 * Set the state of the DTR and RTS signals.
3898 */
3899
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003900static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901{
3902 unsigned char iopioron, iopioroff;
3903 unsigned long flags;
3904
Jiri Slabya0564e12006-12-08 02:38:37 -08003905 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3906 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
3908 iopioron = 0;
3909 iopioroff = 0;
3910 if (dtr == 0)
3911 iopioroff |= IPR_DTR;
3912 else if (dtr > 0)
3913 iopioron |= IPR_DTR;
3914 if (rts == 0)
3915 iopioroff |= IPR_RTS;
3916 else if (rts > 0)
3917 iopioron |= IPR_RTS;
3918
Alan Coxb65b5b52006-06-27 02:54:05 -07003919 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 BRDENABLE(portp->brdnr, portp->pagenr);
3921 stl_sc26198setreg(portp, IOPIOR,
3922 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3923 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003924 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925}
3926
3927/*****************************************************************************/
3928
3929/*
3930 * Return the state of the signals.
3931 */
3932
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003933static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934{
3935 unsigned char ipr;
3936 unsigned long flags;
3937 int sigs;
3938
Jiri Slabya0564e12006-12-08 02:38:37 -08003939 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
Alan Coxb65b5b52006-06-27 02:54:05 -07003941 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 BRDENABLE(portp->brdnr, portp->pagenr);
3943 ipr = stl_sc26198getreg(portp, IPR);
3944 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003945 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
3947 sigs = 0;
3948 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3949 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3950 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3951 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3952 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003953 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954}
3955
3956/*****************************************************************************/
3957
3958/*
3959 * Enable/Disable the Transmitter and/or Receiver.
3960 */
3961
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003962static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963{
3964 unsigned char ccr;
3965 unsigned long flags;
3966
Jiri Slabya0564e12006-12-08 02:38:37 -08003967 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968
3969 ccr = portp->crenable;
3970 if (tx == 0)
3971 ccr &= ~CR_TXENABLE;
3972 else if (tx > 0)
3973 ccr |= CR_TXENABLE;
3974 if (rx == 0)
3975 ccr &= ~CR_RXENABLE;
3976 else if (rx > 0)
3977 ccr |= CR_RXENABLE;
3978
Alan Coxb65b5b52006-06-27 02:54:05 -07003979 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 BRDENABLE(portp->brdnr, portp->pagenr);
3981 stl_sc26198setreg(portp, SCCR, ccr);
3982 BRDDISABLE(portp->brdnr);
3983 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003984 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985}
3986
3987/*****************************************************************************/
3988
3989/*
3990 * Start/stop the Transmitter and/or Receiver.
3991 */
3992
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003993static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994{
3995 unsigned char imr;
3996 unsigned long flags;
3997
Jiri Slabya0564e12006-12-08 02:38:37 -08003998 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
4000 imr = portp->imr;
4001 if (tx == 0)
4002 imr &= ~IR_TXRDY;
4003 else if (tx == 1)
4004 imr |= IR_TXRDY;
4005 if (rx == 0)
4006 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4007 else if (rx > 0)
4008 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4009
Alan Coxb65b5b52006-06-27 02:54:05 -07004010 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 BRDENABLE(portp->brdnr, portp->pagenr);
4012 stl_sc26198setreg(portp, IMR, imr);
4013 BRDDISABLE(portp->brdnr);
4014 portp->imr = imr;
4015 if (tx > 0)
4016 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004017 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018}
4019
4020/*****************************************************************************/
4021
4022/*
4023 * Disable all interrupts from this port.
4024 */
4025
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004026static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027{
4028 unsigned long flags;
4029
Jiri Slabya0564e12006-12-08 02:38:37 -08004030 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
Alan Coxb65b5b52006-06-27 02:54:05 -07004032 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 BRDENABLE(portp->brdnr, portp->pagenr);
4034 portp->imr = 0;
4035 stl_sc26198setreg(portp, IMR, 0);
4036 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004037 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038}
4039
4040/*****************************************************************************/
4041
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004042static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043{
4044 unsigned long flags;
4045
Jiri Slabya0564e12006-12-08 02:38:37 -08004046 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047
Alan Coxb65b5b52006-06-27 02:54:05 -07004048 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049 BRDENABLE(portp->brdnr, portp->pagenr);
4050 if (len == 1) {
4051 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4052 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004053 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004055
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004057 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058}
4059
4060/*****************************************************************************/
4061
4062/*
4063 * Take flow control actions...
4064 */
4065
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004066static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067{
4068 struct tty_struct *tty;
4069 unsigned long flags;
4070 unsigned char mr0;
4071
Jiri Slabya0564e12006-12-08 02:38:37 -08004072 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
Jiri Slaby615e4a72006-12-08 02:38:38 -08004074 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004076 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004077 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 return;
4079
Alan Coxb65b5b52006-06-27 02:54:05 -07004080 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 BRDENABLE(portp->brdnr, portp->pagenr);
4082
4083 if (state) {
4084 if (tty->termios->c_iflag & IXOFF) {
4085 mr0 = stl_sc26198getreg(portp, MR0);
4086 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4087 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4088 mr0 |= MR0_SWFRX;
4089 portp->stats.rxxon++;
4090 stl_sc26198wait(portp);
4091 stl_sc26198setreg(portp, MR0, mr0);
4092 }
4093/*
4094 * Question: should we return RTS to what it was before? It may
4095 * have been set by an ioctl... Suppose not, since if you have
4096 * hardware flow control set then it is pretty silly to go and
4097 * set the RTS line by hand.
4098 */
4099 if (tty->termios->c_cflag & CRTSCTS) {
4100 stl_sc26198setreg(portp, MR1,
4101 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4102 stl_sc26198setreg(portp, IOPIOR,
4103 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4104 portp->stats.rxrtson++;
4105 }
4106 } else {
4107 if (tty->termios->c_iflag & IXOFF) {
4108 mr0 = stl_sc26198getreg(portp, MR0);
4109 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4110 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4111 mr0 &= ~MR0_SWFRX;
4112 portp->stats.rxxoff++;
4113 stl_sc26198wait(portp);
4114 stl_sc26198setreg(portp, MR0, mr0);
4115 }
4116 if (tty->termios->c_cflag & CRTSCTS) {
4117 stl_sc26198setreg(portp, MR1,
4118 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4119 stl_sc26198setreg(portp, IOPIOR,
4120 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4121 portp->stats.rxrtsoff++;
4122 }
4123 }
4124
4125 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004126 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004127 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128}
4129
4130/*****************************************************************************/
4131
4132/*
4133 * Send a flow control character.
4134 */
4135
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004136static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137{
4138 struct tty_struct *tty;
4139 unsigned long flags;
4140 unsigned char mr0;
4141
Jiri Slabya0564e12006-12-08 02:38:37 -08004142 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143
Jiri Slaby615e4a72006-12-08 02:38:38 -08004144 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004146 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004147 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 return;
4149
Alan Coxb65b5b52006-06-27 02:54:05 -07004150 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 BRDENABLE(portp->brdnr, portp->pagenr);
4152 if (state) {
4153 mr0 = stl_sc26198getreg(portp, MR0);
4154 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4155 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4156 mr0 |= MR0_SWFRX;
4157 portp->stats.rxxon++;
4158 stl_sc26198wait(portp);
4159 stl_sc26198setreg(portp, MR0, mr0);
4160 } else {
4161 mr0 = stl_sc26198getreg(portp, MR0);
4162 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4163 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4164 mr0 &= ~MR0_SWFRX;
4165 portp->stats.rxxoff++;
4166 stl_sc26198wait(portp);
4167 stl_sc26198setreg(portp, MR0, mr0);
4168 }
4169 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004170 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004171 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172}
4173
4174/*****************************************************************************/
4175
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004176static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177{
4178 unsigned long flags;
4179
Jiri Slabya0564e12006-12-08 02:38:37 -08004180 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181
Jiri Slaby615e4a72006-12-08 02:38:38 -08004182 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 return;
4184
Alan Coxb65b5b52006-06-27 02:54:05 -07004185 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186 BRDENABLE(portp->brdnr, portp->pagenr);
4187 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4188 stl_sc26198setreg(portp, SCCR, portp->crenable);
4189 BRDDISABLE(portp->brdnr);
4190 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004191 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192}
4193
4194/*****************************************************************************/
4195
4196/*
4197 * Return the current state of data flow on this port. This is only
4198 * really interresting when determining if data has fully completed
4199 * transmission or not... The sc26198 interrupt scheme cannot
4200 * determine when all data has actually drained, so we need to
4201 * check the port statusy register to be sure.
4202 */
4203
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004204static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205{
4206 unsigned long flags;
4207 unsigned char sr;
4208
Jiri Slabya0564e12006-12-08 02:38:37 -08004209 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210
Jiri Slaby615e4a72006-12-08 02:38:38 -08004211 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004212 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004214 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215
Alan Coxb65b5b52006-06-27 02:54:05 -07004216 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 BRDENABLE(portp->brdnr, portp->pagenr);
4218 sr = stl_sc26198getreg(portp, SR);
4219 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004220 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221
Jesper Juhl014c2542006-01-15 02:37:08 +01004222 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223}
4224
4225/*****************************************************************************/
4226
4227/*
4228 * Delay for a small amount of time, to give the sc26198 a chance
4229 * to process a command...
4230 */
4231
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004232static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233{
4234 int i;
4235
Jiri Slabya0564e12006-12-08 02:38:37 -08004236 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237
Jiri Slaby615e4a72006-12-08 02:38:38 -08004238 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239 return;
4240
Jiri Slabyc62429d2006-12-08 02:39:14 -08004241 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 stl_sc26198getglobreg(portp, TSTR);
4243}
4244
4245/*****************************************************************************/
4246
4247/*
4248 * If we are TX flow controlled and in IXANY mode then we may
4249 * need to unflow control here. We gotta do this because of the
4250 * automatic flow control modes of the sc26198.
4251 */
4252
Jiri Slaby60be4812006-12-08 02:38:40 -08004253static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254{
4255 unsigned char mr0;
4256
4257 mr0 = stl_sc26198getreg(portp, MR0);
4258 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4259 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4260 stl_sc26198wait(portp);
4261 stl_sc26198setreg(portp, MR0, mr0);
4262 clear_bit(ASYI_TXFLOWED, &portp->istate);
4263}
4264
4265/*****************************************************************************/
4266
4267/*
4268 * Interrupt service routine for sc26198 panels.
4269 */
4270
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004271static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004273 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 unsigned int iack;
4275
Alan Coxb65b5b52006-06-27 02:54:05 -07004276 spin_lock(&brd_lock);
4277
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278/*
4279 * Work around bug in sc26198 chip... Cannot have A6 address
4280 * line of UART high, else iack will be returned as 0.
4281 */
4282 outb(0, (iobase + 1));
4283
4284 iack = inb(iobase + XP_IACK);
4285 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4286
4287 if (iack & IVR_RXDATA)
4288 stl_sc26198rxisr(portp, iack);
4289 else if (iack & IVR_TXDATA)
4290 stl_sc26198txisr(portp);
4291 else
4292 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004293
4294 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295}
4296
4297/*****************************************************************************/
4298
4299/*
4300 * Transmit interrupt handler. This has gotta be fast! Handling TX
4301 * chars is pretty simple, stuff as many as possible from the TX buffer
4302 * into the sc26198 FIFO.
4303 * In practice it is possible that interrupts are enabled but that the
4304 * port has been hung up. Need to handle not having any TX buffer here,
4305 * this is done by using the side effect that head and tail will also
4306 * be NULL if the buffer has been freed.
4307 */
4308
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004309static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310{
Alan Coxd18a7502008-10-13 10:40:07 +01004311 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 unsigned int ioaddr;
4313 unsigned char mr0;
4314 int len, stlen;
4315 char *head, *tail;
4316
Jiri Slabya0564e12006-12-08 02:38:37 -08004317 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
4319 ioaddr = portp->ioaddr;
4320 head = portp->tx.head;
4321 tail = portp->tx.tail;
4322 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4323 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4324 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4325 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004326 tty = tty_port_tty_get(&portp->port);
4327 if (tty) {
4328 tty_wakeup(tty);
4329 tty_kref_put(tty);
4330 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 }
4332
4333 if (len == 0) {
4334 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4335 mr0 = inb(ioaddr + XP_DATA);
4336 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4337 portp->imr &= ~IR_TXRDY;
4338 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4339 outb(portp->imr, (ioaddr + XP_DATA));
4340 clear_bit(ASYI_TXBUSY, &portp->istate);
4341 } else {
4342 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4343 outb(mr0, (ioaddr + XP_DATA));
4344 }
4345 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004346 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004348 stlen = min_t(unsigned int, len,
4349 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 outb(GTXFIFO, (ioaddr + XP_ADDR));
4351 outsb((ioaddr + XP_DATA), tail, stlen);
4352 len -= stlen;
4353 tail += stlen;
4354 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4355 tail = portp->tx.buf;
4356 if (len > 0) {
4357 outsb((ioaddr + XP_DATA), tail, len);
4358 tail += len;
4359 }
4360 portp->tx.tail = tail;
4361 }
4362}
4363
4364/*****************************************************************************/
4365
4366/*
4367 * Receive character interrupt handler. Determine if we have good chars
4368 * or bad chars and then process appropriately. Good chars are easy
4369 * just shove the lot into the RX buffer and set all status byte to 0.
4370 * If a bad RX char then process as required. This routine needs to be
4371 * fast! In practice it is possible that we get an interrupt on a port
4372 * that is closed. This can happen on hangups - since they completely
4373 * shutdown a port not in user context. Need to handle this case.
4374 */
4375
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004376static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377{
4378 struct tty_struct *tty;
4379 unsigned int len, buflen, ioaddr;
4380
Jiri Slabya0564e12006-12-08 02:38:37 -08004381 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382
Alan Coxd18a7502008-10-13 10:40:07 +01004383 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384 ioaddr = portp->ioaddr;
4385 outb(GIBCR, (ioaddr + XP_ADDR));
4386 len = inb(ioaddr + XP_DATA) + 1;
4387
4388 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004389 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004390 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391 outb(GRXFIFO, (ioaddr + XP_ADDR));
4392 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4393 portp->stats.rxlost += len;
4394 portp->stats.rxtotal += len;
4395 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004396 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004398 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004400 tty_prepare_flip_string(tty, &ptr, len);
4401 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 tty_schedule_flip(tty);
4403 portp->stats.rxtotal += len;
4404 }
4405 }
4406 } else {
4407 stl_sc26198rxbadchars(portp);
4408 }
4409
4410/*
4411 * If we are TX flow controlled and in IXANY mode then we may need
4412 * to unflow control here. We gotta do this because of the automatic
4413 * flow control modes of the sc26198.
4414 */
4415 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004416 if ((tty != NULL) &&
4417 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 (tty->termios->c_iflag & IXANY)) {
4419 stl_sc26198txunflow(portp, tty);
4420 }
4421 }
Alan Coxd18a7502008-10-13 10:40:07 +01004422 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423}
4424
4425/*****************************************************************************/
4426
4427/*
4428 * Process an RX bad character.
4429 */
4430
Jiri Slaby60be4812006-12-08 02:38:40 -08004431static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432{
4433 struct tty_struct *tty;
4434 unsigned int ioaddr;
4435
Alan Coxd18a7502008-10-13 10:40:07 +01004436 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437 ioaddr = portp->ioaddr;
4438
4439 if (status & SR_RXPARITY)
4440 portp->stats.rxparity++;
4441 if (status & SR_RXFRAMING)
4442 portp->stats.rxframing++;
4443 if (status & SR_RXOVERRUN)
4444 portp->stats.rxoverrun++;
4445 if (status & SR_RXBREAK)
4446 portp->stats.rxbreaks++;
4447
Jiri Slaby615e4a72006-12-08 02:38:38 -08004448 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449 ((portp->rxignoremsk & status) == 0)) {
4450 if (portp->rxmarkmsk & status) {
4451 if (status & SR_RXBREAK) {
4452 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004453 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454 do_SAK(tty);
4455 BRDENABLE(portp->brdnr, portp->pagenr);
4456 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004457 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004459 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004461 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004463 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004465 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467
Alan Cox33f0f882006-01-09 20:54:13 -08004468 tty_insert_flip_char(tty, ch, status);
4469 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470
4471 if (status == 0)
4472 portp->stats.rxtotal++;
4473 }
Alan Coxd18a7502008-10-13 10:40:07 +01004474 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475}
4476
4477/*****************************************************************************/
4478
4479/*
4480 * Process all characters in the RX FIFO of the UART. Check all char
4481 * status bytes as well, and process as required. We need to check
4482 * all bytes in the FIFO, in case some more enter the FIFO while we
4483 * are here. To get the exact character error type we need to switch
4484 * into CHAR error mode (that is why we need to make sure we empty
4485 * the FIFO).
4486 */
4487
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004488static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489{
4490 unsigned char status, mr1;
4491 char ch;
4492
4493/*
4494 * To get the precise error type for each character we must switch
4495 * back into CHAR error mode.
4496 */
4497 mr1 = stl_sc26198getreg(portp, MR1);
4498 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4499
4500 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4501 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4502 ch = stl_sc26198getreg(portp, RXFIFO);
4503 stl_sc26198rxbadch(portp, status, ch);
4504 }
4505
4506/*
4507 * To get correct interrupt class we must switch back into BLOCK
4508 * error mode.
4509 */
4510 stl_sc26198setreg(portp, MR1, mr1);
4511}
4512
4513/*****************************************************************************/
4514
4515/*
4516 * Other interrupt handler. This includes modem signals, flow
4517 * control actions, etc. Most stuff is left to off-level interrupt
4518 * processing time.
4519 */
4520
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004521static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522{
4523 unsigned char cir, ipr, xisr;
4524
Jiri Slabya0564e12006-12-08 02:38:37 -08004525 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526
4527 cir = stl_sc26198getglobreg(portp, CIR);
4528
4529 switch (cir & CIR_SUBTYPEMASK) {
4530 case CIR_SUBCOS:
4531 ipr = stl_sc26198getreg(portp, IPR);
4532 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004533 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534 portp->stats.modem++;
4535 }
4536 break;
4537 case CIR_SUBXONXOFF:
4538 xisr = stl_sc26198getreg(portp, XISR);
4539 if (xisr & XISR_RXXONGOT) {
4540 set_bit(ASYI_TXFLOWED, &portp->istate);
4541 portp->stats.txxoff++;
4542 }
4543 if (xisr & XISR_RXXOFFGOT) {
4544 clear_bit(ASYI_TXFLOWED, &portp->istate);
4545 portp->stats.txxon++;
4546 }
4547 break;
4548 case CIR_SUBBREAK:
4549 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4550 stl_sc26198rxbadchars(portp);
4551 break;
4552 default:
4553 break;
4554 }
4555}
4556
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004557static void stl_free_isabrds(void)
4558{
4559 struct stlbrd *brdp;
4560 unsigned int i;
4561
4562 for (i = 0; i < stl_nrbrds; i++) {
4563 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4564 continue;
4565
4566 free_irq(brdp->irq, brdp);
4567
4568 stl_cleanup_panels(brdp);
4569
4570 release_region(brdp->ioaddr1, brdp->iosize1);
4571 if (brdp->iosize2 > 0)
4572 release_region(brdp->ioaddr2, brdp->iosize2);
4573
4574 kfree(brdp);
4575 stl_brds[i] = NULL;
4576 }
4577}
4578
Jiri Slaby23b85a12006-12-08 02:38:40 -08004579/*
4580 * Loadable module initialization stuff.
4581 */
4582static int __init stallion_module_init(void)
4583{
Jiri Slaby843b5682006-12-08 02:39:12 -08004584 struct stlbrd *brdp;
4585 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004586 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004587 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004588
4589 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4590
4591 spin_lock_init(&stallion_lock);
4592 spin_lock_init(&brd_lock);
4593
Jiri Slabye4151092007-06-08 13:46:52 -07004594 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4595 if (!stl_serial) {
4596 retval = -ENOMEM;
4597 goto err;
4598 }
4599
4600 stl_serial->owner = THIS_MODULE;
4601 stl_serial->driver_name = stl_drvname;
4602 stl_serial->name = "ttyE";
4603 stl_serial->major = STL_SERIALMAJOR;
4604 stl_serial->minor_start = 0;
4605 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4606 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4607 stl_serial->init_termios = stl_deftermios;
4608 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4609 tty_set_operations(stl_serial, &stl_ops);
4610
4611 retval = tty_register_driver(stl_serial);
4612 if (retval) {
4613 printk("STALLION: failed to register serial driver\n");
4614 goto err_frtty;
4615 }
4616
Jiri Slaby843b5682006-12-08 02:39:12 -08004617/*
4618 * Find any dynamically supported boards. That is via module load
4619 * line options.
4620 */
4621 for (i = stl_nrbrds; i < stl_nargs; i++) {
4622 memset(&conf, 0, sizeof(conf));
4623 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4624 continue;
4625 if ((brdp = stl_allocbrd()) == NULL)
4626 continue;
4627 brdp->brdnr = i;
4628 brdp->brdtype = conf.brdtype;
4629 brdp->ioaddr1 = conf.ioaddr1;
4630 brdp->ioaddr2 = conf.ioaddr2;
4631 brdp->irq = conf.irq;
4632 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004633 stl_brds[brdp->brdnr] = brdp;
4634 if (stl_brdinit(brdp)) {
4635 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004636 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004637 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004638 for (j = 0; j < brdp->nrports; j++)
4639 tty_register_device(stl_serial,
4640 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004641 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004642 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004643 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004644
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004645 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004646 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004647 if (retval && stl_nrbrds == 0) {
4648 printk(KERN_ERR "STALLION: can't register pci driver\n");
4649 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004650 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004651
4652/*
4653 * Set up a character driver for per board stuff. This is mainly used
4654 * to do stats ioctls on the ports.
4655 */
4656 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4657 printk("STALLION: failed to register serial board device\n");
4658
4659 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004660 if (IS_ERR(stallion_class))
4661 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004662 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004663 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4664 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004665
Jiri Slaby23b85a12006-12-08 02:38:40 -08004666 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004667err_unrtty:
4668 tty_unregister_driver(stl_serial);
4669err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004670 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004671err:
4672 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004673}
4674
4675static void __exit stallion_module_exit(void)
4676{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004677 struct stlbrd *brdp;
4678 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004679
4680 pr_debug("cleanup_module()\n");
4681
4682 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4683 stl_drvversion);
4684
4685/*
4686 * Free up all allocated resources used by the ports. This includes
4687 * memory and interrupts. As part of this process we will also do
4688 * a hangup on every open port - to try to flush out any processes
4689 * hanging onto ports.
4690 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004691 for (i = 0; i < stl_nrbrds; i++) {
4692 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4693 continue;
4694 for (j = 0; j < brdp->nrports; j++)
4695 tty_unregister_device(stl_serial,
4696 brdp->brdnr * STL_MAXPORTS + j);
4697 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004698
Jiri Slaby23b85a12006-12-08 02:38:40 -08004699 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004700 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004701 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004702 class_destroy(stallion_class);
4703
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004704 pci_unregister_driver(&stl_pcidriver);
4705
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004706 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004707
4708 tty_unregister_driver(stl_serial);
4709 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004710}
4711
4712module_init(stallion_module_init);
4713module_exit(stallion_module_exit);
4714
4715MODULE_AUTHOR("Greg Ungerer");
4716MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4717MODULE_LICENSE("GPL");