blob: 77eef61c46f3aca520977877f8bcb5a8714c80d2 [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;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800836 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 return;
Alan Cox4350f3f2009-01-02 13:46:24 +0000838 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839
Alan Cox4350f3f2009-01-02 13:46:24 +0000840 spin_lock_irqsave(&port->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 if (tty_hung_up_p(filp)) {
Alan Cox4350f3f2009-01-02 13:46:24 +0000842 spin_unlock_irqrestore(&port->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 return;
844 }
Alan Cox4350f3f2009-01-02 13:46:24 +0000845 if (tty->count == 1 && port->count != 1)
846 port->count = 1;
847 if (port->count-- > 1) {
848 spin_unlock_irqrestore(&port->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 return;
850 }
851
Alan Cox4350f3f2009-01-02 13:46:24 +0000852 port->count = 0;
853 port->flags |= ASYNC_CLOSING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
855/*
856 * May want to wait for any data to drain before closing. The BUSY
857 * flag keeps track of whether we are still sending or not - it is
858 * very accurate for the cd1400, not quite so for the sc26198.
859 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
860 */
861 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700862
Alan Cox4350f3f2009-01-02 13:46:24 +0000863 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxb65b5b52006-06-27 02:54:05 -0700864
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
866 tty_wait_until_sent(tty, portp->closing_wait);
867 stl_waituntilsent(tty, (HZ / 2));
868
Alan Coxb65b5b52006-06-27 02:54:05 -0700869
Alan Cox4350f3f2009-01-02 13:46:24 +0000870 spin_lock_irqsave(&port->lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100871 portp->port.flags &= ~ASYNC_INITIALIZED;
Alan Cox4350f3f2009-01-02 13:46:24 +0000872 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxb65b5b52006-06-27 02:54:05 -0700873
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 stl_disableintrs(portp);
875 if (tty->termios->c_cflag & HUPCL)
876 stl_setsignals(portp, 0, 0);
877 stl_enablerxtx(portp, 0, 0);
878 stl_flushbuffer(tty);
879 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800880 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800882 portp->tx.buf = NULL;
883 portp->tx.head = NULL;
884 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 }
886 set_bit(TTY_IO_ERROR, &tty->flags);
887 tty_ldisc_flush(tty);
888
889 tty->closing = 0;
Alan Cox4350f3f2009-01-02 13:46:24 +0000890 tty_port_tty_set(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
Alan Cox4350f3f2009-01-02 13:46:24 +0000892 if (port->blocked_open) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 if (portp->close_delay)
894 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
Alan Coxf8ae4762008-07-16 21:56:37 +0100895 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 }
897
Alan Coxf8ae4762008-07-16 21:56:37 +0100898 portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
Alan Cox4350f3f2009-01-02 13:46:24 +0000899 wake_up_interruptible(&port->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900}
901
902/*****************************************************************************/
903
904/*
905 * Write routine. Take data and stuff it in to the TX ring queue.
906 * If transmit interrupts are not running then start them.
907 */
908
909static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
910{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800911 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 unsigned int len, stlen;
913 unsigned char *chbuf;
914 char *head, *tail;
915
Jiri Slabya0564e12006-12-08 02:38:37 -0800916 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800919 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100920 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800921 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100922 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
924/*
925 * If copying direct from user space we must cater for page faults,
926 * causing us to "sleep" here for a while. To handle this copy in all
927 * the data we need now, into a local buffer. Then when we got it all
928 * copy it into the TX buffer.
929 */
930 chbuf = (unsigned char *) buf;
931
932 head = portp->tx.head;
933 tail = portp->tx.tail;
934 if (head >= tail) {
935 len = STL_TXBUFSIZE - (head - tail) - 1;
936 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
937 } else {
938 len = tail - head - 1;
939 stlen = len;
940 }
941
Jiri Slaby843b5682006-12-08 02:39:12 -0800942 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 count = 0;
944 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800945 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 memcpy(head, chbuf, stlen);
947 len -= stlen;
948 chbuf += stlen;
949 count += stlen;
950 head += stlen;
951 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
952 head = portp->tx.buf;
953 stlen = tail - head;
954 }
955 }
956 portp->tx.head = head;
957
958 clear_bit(ASYI_TXLOW, &portp->istate);
959 stl_startrxtx(portp, -1, 1);
960
Jesper Juhl014c2542006-01-15 02:37:08 +0100961 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962}
963
964/*****************************************************************************/
965
David Howells4a561222008-07-22 11:18:43 +0100966static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800968 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 unsigned int len;
970 char *head, *tail;
971
Jiri Slabya0564e12006-12-08 02:38:37 -0800972 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800975 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +0100976 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800977 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +0100978 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 head = portp->tx.head;
981 tail = portp->tx.tail;
982
983 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
984 len--;
985
986 if (len > 0) {
987 *head++ = ch;
988 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
989 head = portp->tx.buf;
990 }
991 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +0100992 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993}
994
995/*****************************************************************************/
996
997/*
998 * If there are any characters in the buffer then make sure that TX
999 * interrupts are on and get'em out. Normally used after the putchar
1000 * routine has been called.
1001 */
1002
1003static void stl_flushchars(struct tty_struct *tty)
1004{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001005 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006
Jiri Slabya0564e12006-12-08 02:38:37 -08001007 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001010 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001012 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 return;
1014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 stl_startrxtx(portp, -1, 1);
1016}
1017
1018/*****************************************************************************/
1019
1020static int stl_writeroom(struct tty_struct *tty)
1021{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001022 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 char *head, *tail;
1024
Jiri Slabya0564e12006-12-08 02:38:37 -08001025 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001028 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001029 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001030 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001031 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032
1033 head = portp->tx.head;
1034 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001035 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036}
1037
1038/*****************************************************************************/
1039
1040/*
1041 * Return number of chars in the TX buffer. Normally we would just
1042 * calculate the number of chars in the buffer and return that, but if
1043 * the buffer is empty and TX interrupts are still on then we return
1044 * that the buffer still has 1 char in it. This way whoever called us
1045 * will not think that ALL chars have drained - since the UART still
1046 * must have some chars in it (we are busy after all).
1047 */
1048
1049static int stl_charsinbuffer(struct tty_struct *tty)
1050{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001051 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 unsigned int size;
1053 char *head, *tail;
1054
Jiri Slabya0564e12006-12-08 02:38:37 -08001055 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001058 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001059 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001060 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001061 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
1063 head = portp->tx.head;
1064 tail = portp->tx.tail;
1065 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1066 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1067 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001068 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069}
1070
1071/*****************************************************************************/
1072
1073/*
1074 * Generate the serial struct info.
1075 */
1076
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001077static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
1079 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001080 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Jiri Slabya0564e12006-12-08 02:38:37 -08001082 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
1084 memset(&sio, 0, sizeof(struct serial_struct));
1085 sio.line = portp->portnr;
1086 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001087 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 sio.baud_base = portp->baud_base;
1089 sio.close_delay = portp->close_delay;
1090 sio.closing_wait = portp->closing_wait;
1091 sio.custom_divisor = portp->custom_divisor;
1092 sio.hub6 = 0;
1093 if (portp->uartp == &stl_cd1400uart) {
1094 sio.type = PORT_CIRRUS;
1095 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1096 } else {
1097 sio.type = PORT_UNKNOWN;
1098 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1099 }
1100
1101 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001102 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 sio.irq = brdp->irq;
1104
1105 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1106}
1107
1108/*****************************************************************************/
1109
1110/*
1111 * Set port according to the serial struct info.
1112 * At this point we do not do any auto-configure stuff, so we will
1113 * just quietly ignore any requests to change irq, etc.
1114 */
1115
Alan Coxd18a7502008-10-13 10:40:07 +01001116static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117{
Alan Coxd18a7502008-10-13 10:40:07 +01001118 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 struct serial_struct sio;
1120
Jiri Slabya0564e12006-12-08 02:38:37 -08001121 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
1123 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1124 return -EFAULT;
1125 if (!capable(CAP_SYS_ADMIN)) {
1126 if ((sio.baud_base != portp->baud_base) ||
1127 (sio.close_delay != portp->close_delay) ||
1128 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001129 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001130 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 }
1132
Alan Coxf8ae4762008-07-16 21:56:37 +01001133 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 (sio.flags & ASYNC_USR_MASK);
1135 portp->baud_base = sio.baud_base;
1136 portp->close_delay = sio.close_delay;
1137 portp->closing_wait = sio.closing_wait;
1138 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001139 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001140 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141}
1142
1143/*****************************************************************************/
1144
1145static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1146{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001147 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001150 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001151 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001153 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 return stl_getsignals(portp);
1156}
1157
1158static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1159 unsigned int set, unsigned int clear)
1160{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001161 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 int rts = -1, dtr = -1;
1163
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001165 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001166 return -ENODEV;
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 if (set & TIOCM_RTS)
1171 rts = 1;
1172 if (set & TIOCM_DTR)
1173 dtr = 1;
1174 if (clear & TIOCM_RTS)
1175 rts = 0;
1176 if (clear & TIOCM_DTR)
1177 dtr = 0;
1178
1179 stl_setsignals(portp, dtr, rts);
1180 return 0;
1181}
1182
1183static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1184{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001185 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 int rc;
1187 void __user *argp = (void __user *)arg;
1188
Jiri Slabya0564e12006-12-08 02:38:37 -08001189 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1190 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001193 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001194 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001197 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001199 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
1201 rc = 0;
1202
Alan Coxf433c652008-04-30 00:53:23 -07001203 lock_kernel();
1204
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 case TIOCGSERIAL:
1207 rc = stl_getserial(portp, argp);
1208 break;
1209 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001210 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 break;
1212 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001213 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 break;
1215 case COM_CLRPORTSTATS:
1216 rc = stl_clrportstats(portp, argp);
1217 break;
1218 case TIOCSERCONFIG:
1219 case TIOCSERGWILD:
1220 case TIOCSERSWILD:
1221 case TIOCSERGETLSR:
1222 case TIOCSERGSTRUCT:
1223 case TIOCSERGETMULTI:
1224 case TIOCSERSETMULTI:
1225 default:
1226 rc = -ENOIOCTLCMD;
1227 break;
1228 }
Alan Coxf433c652008-04-30 00:53:23 -07001229 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001230 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231}
1232
1233/*****************************************************************************/
1234
Jiri Slaby96b066b2006-12-08 02:38:42 -08001235/*
1236 * Start the transmitter again. Just turn TX interrupts back on.
1237 */
1238
1239static void stl_start(struct tty_struct *tty)
1240{
1241 struct stlport *portp;
1242
1243 pr_debug("stl_start(tty=%p)\n", tty);
1244
Jiri Slaby96b066b2006-12-08 02:38:42 -08001245 portp = tty->driver_data;
1246 if (portp == NULL)
1247 return;
1248 stl_startrxtx(portp, -1, 1);
1249}
1250
1251/*****************************************************************************/
1252
Alan Cox606d0992006-12-08 02:38:45 -08001253static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001255 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001256 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Jiri Slabya0564e12006-12-08 02:38:37 -08001258 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001261 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 return;
1263
1264 tiosp = tty->termios;
1265 if ((tiosp->c_cflag == old->c_cflag) &&
1266 (tiosp->c_iflag == old->c_iflag))
1267 return;
1268
1269 stl_setport(portp, tiosp);
1270 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1271 -1);
1272 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1273 tty->hw_stopped = 0;
1274 stl_start(tty);
1275 }
1276 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001277 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278}
1279
1280/*****************************************************************************/
1281
1282/*
1283 * Attempt to flow control who ever is sending us data. Based on termios
1284 * settings use software or/and hardware flow control.
1285 */
1286
1287static void stl_throttle(struct tty_struct *tty)
1288{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001289 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Jiri Slabya0564e12006-12-08 02:38:37 -08001291 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001294 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 return;
1296 stl_flowctrl(portp, 0);
1297}
1298
1299/*****************************************************************************/
1300
1301/*
1302 * Unflow control the device sending us data...
1303 */
1304
1305static void stl_unthrottle(struct tty_struct *tty)
1306{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001307 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Jiri Slabya0564e12006-12-08 02:38:37 -08001309 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001312 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 return;
1314 stl_flowctrl(portp, 1);
1315}
1316
1317/*****************************************************************************/
1318
1319/*
1320 * Stop the transmitter. Basically to do this we will just turn TX
1321 * interrupts off.
1322 */
1323
1324static void stl_stop(struct tty_struct *tty)
1325{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001326 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
Jiri Slabya0564e12006-12-08 02:38:37 -08001328 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001331 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 return;
1333 stl_startrxtx(portp, -1, 0);
1334}
1335
1336/*****************************************************************************/
1337
1338/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 * Hangup this port. This is pretty much like closing the port, only
1340 * a little more brutal. No waiting for data to drain. Shutdown the
1341 * port and maybe drop signals.
1342 */
1343
1344static void stl_hangup(struct tty_struct *tty)
1345{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001346 struct stlport *portp;
Alan Cox4350f3f2009-01-02 13:46:24 +00001347 struct tty_port *port;
1348 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
Jiri Slabya0564e12006-12-08 02:38:37 -08001350 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001353 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 return;
Alan Cox4350f3f2009-01-02 13:46:24 +00001355 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Alan Cox4350f3f2009-01-02 13:46:24 +00001357 spin_lock_irqsave(&port->lock, flags);
1358 port->flags &= ~ASYNC_INITIALIZED;
1359 spin_unlock_irqrestore(&port->lock, flags);
1360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 stl_disableintrs(portp);
1362 if (tty->termios->c_cflag & HUPCL)
1363 stl_setsignals(portp, 0, 0);
1364 stl_enablerxtx(portp, 0, 0);
1365 stl_flushbuffer(tty);
1366 portp->istate = 0;
1367 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001368 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001370 portp->tx.buf = NULL;
1371 portp->tx.head = NULL;
1372 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 }
Alan Cox4350f3f2009-01-02 13:46:24 +00001374 tty_port_hangup(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375}
1376
1377/*****************************************************************************/
1378
David Howells4a561222008-07-22 11:18:43 +01001379static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001381 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Jiri Slabya0564e12006-12-08 02:38:37 -08001383 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001386 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001387 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
1389 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001390 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391}
1392
1393/*****************************************************************************/
1394
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395static void stl_sendxchar(struct tty_struct *tty, char ch)
1396{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001397 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
Jiri Slabya0564e12006-12-08 02:38:37 -08001399 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001402 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 return;
1404
1405 if (ch == STOP_CHAR(tty))
1406 stl_sendflow(portp, 0);
1407 else if (ch == START_CHAR(tty))
1408 stl_sendflow(portp, 1);
1409 else
1410 stl_putchar(tty, ch);
1411}
1412
1413/*****************************************************************************/
1414
1415#define MAXLINE 80
1416
1417/*
1418 * Format info for a specified port. The line is deliberately limited
1419 * to 80 characters. (If it is too long it will be truncated, if too
1420 * short then padded with spaces).
1421 */
1422
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001423static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424{
1425 char *sp;
1426 int sigs, cnt;
1427
1428 sp = pos;
1429 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1430 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1431 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1432
1433 if (portp->stats.rxframing)
1434 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1435 if (portp->stats.rxparity)
1436 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1437 if (portp->stats.rxbreaks)
1438 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1439 if (portp->stats.rxoverrun)
1440 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1441
1442 sigs = stl_getsignals(portp);
1443 cnt = sprintf(sp, "%s%s%s%s%s ",
1444 (sigs & TIOCM_RTS) ? "|RTS" : "",
1445 (sigs & TIOCM_CTS) ? "|CTS" : "",
1446 (sigs & TIOCM_DTR) ? "|DTR" : "",
1447 (sigs & TIOCM_CD) ? "|DCD" : "",
1448 (sigs & TIOCM_DSR) ? "|DSR" : "");
1449 *sp = ' ';
1450 sp += cnt;
1451
Jiri Slabyc62429d2006-12-08 02:39:14 -08001452 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 *sp++ = ' ';
1454 if (cnt >= MAXLINE)
1455 pos[(MAXLINE - 2)] = '+';
1456 pos[(MAXLINE - 1)] = '\n';
1457
Jesper Juhl014c2542006-01-15 02:37:08 +01001458 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459}
1460
1461/*****************************************************************************/
1462
1463/*
1464 * Port info, read from the /proc file system.
1465 */
1466
1467static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1468{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001469 struct stlbrd *brdp;
1470 struct stlpanel *panelp;
1471 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001472 unsigned int brdnr, panelnr, portnr;
1473 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 char *pos;
1475
Jiri Slabya0564e12006-12-08 02:38:37 -08001476 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1477 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
1479 pos = page;
1480 totalport = 0;
1481 curoff = 0;
1482
1483 if (off == 0) {
1484 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1485 stl_drvversion);
1486 while (pos < (page + MAXLINE - 1))
1487 *pos++ = ' ';
1488 *pos++ = '\n';
1489 }
1490 curoff = MAXLINE;
1491
1492/*
1493 * We scan through for each board, panel and port. The offset is
1494 * calculated on the fly, and irrelevant ports are skipped.
1495 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001496 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001498 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 continue;
1500 if (brdp->state == 0)
1501 continue;
1502
1503 maxoff = curoff + (brdp->nrports * MAXLINE);
1504 if (off >= maxoff) {
1505 curoff = maxoff;
1506 continue;
1507 }
1508
1509 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001510 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001512 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 continue;
1514
1515 maxoff = curoff + (panelp->nrports * MAXLINE);
1516 if (off >= maxoff) {
1517 curoff = maxoff;
1518 totalport += panelp->nrports;
1519 continue;
1520 }
1521
Jiri Slabyc62429d2006-12-08 02:39:14 -08001522 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 totalport++) {
1524 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001525 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 continue;
1527 if (off >= (curoff += MAXLINE))
1528 continue;
1529 if ((pos - page + MAXLINE) > count)
1530 goto stl_readdone;
1531 pos += stl_portinfo(portp, totalport, pos);
1532 }
1533 }
1534 }
1535
1536 *eof = 1;
1537
1538stl_readdone:
1539 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001540 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541}
1542
1543/*****************************************************************************/
1544
1545/*
1546 * All board interrupts are vectored through here first. This code then
1547 * calls off to the approrpriate board interrupt handlers.
1548 */
1549
David Howells7d12e782006-10-05 14:55:46 +01001550static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001552 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Jeff Garzika6f97b22007-10-31 05:20:49 -04001554 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556 return IRQ_RETVAL((* brdp->isr)(brdp));
1557}
1558
1559/*****************************************************************************/
1560
1561/*
1562 * Interrupt service routine for EasyIO board types.
1563 */
1564
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001565static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001567 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 unsigned int iobase;
1569 int handled = 0;
1570
Alan Coxb65b5b52006-06-27 02:54:05 -07001571 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 panelp = brdp->panels[0];
1573 iobase = panelp->iobase;
1574 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1575 handled = 1;
1576 (* panelp->isr)(panelp, iobase);
1577 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001578 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 return handled;
1580}
1581
1582/*****************************************************************************/
1583
1584/*
1585 * Interrupt service routine for ECH-AT board types.
1586 */
1587
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001588static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001590 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001591 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 int handled = 0;
1593
1594 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1595
1596 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1597 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001598 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 ioaddr = brdp->bnkstataddr[bnknr];
1600 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1601 panelp = brdp->bnk2panel[bnknr];
1602 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1603 }
1604 }
1605 }
1606
1607 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1608
1609 return handled;
1610}
1611
1612/*****************************************************************************/
1613
1614/*
1615 * Interrupt service routine for ECH-MCA board types.
1616 */
1617
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001618static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001620 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001621 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 int handled = 0;
1623
1624 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1625 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001626 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 ioaddr = brdp->bnkstataddr[bnknr];
1628 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1629 panelp = brdp->bnk2panel[bnknr];
1630 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1631 }
1632 }
1633 }
1634 return handled;
1635}
1636
1637/*****************************************************************************/
1638
1639/*
1640 * Interrupt service routine for ECH-PCI board types.
1641 */
1642
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001643static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001645 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001646 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 int handled = 0;
1648
1649 while (1) {
1650 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001651 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1653 ioaddr = brdp->bnkstataddr[bnknr];
1654 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1655 panelp = brdp->bnk2panel[bnknr];
1656 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1657 recheck++;
1658 handled = 1;
1659 }
1660 }
1661 if (! recheck)
1662 break;
1663 }
1664 return handled;
1665}
1666
1667/*****************************************************************************/
1668
1669/*
1670 * Interrupt service routine for ECH-8/64-PCI board types.
1671 */
1672
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001673static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001675 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001676 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 int handled = 0;
1678
1679 while (inb(brdp->ioctrl) & 0x1) {
1680 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001681 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 ioaddr = brdp->bnkstataddr[bnknr];
1683 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1684 panelp = brdp->bnk2panel[bnknr];
1685 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1686 }
1687 }
1688 }
1689
1690 return handled;
1691}
1692
1693/*****************************************************************************/
1694
1695/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 * Initialize all the ports on a panel.
1697 */
1698
Jiri Slaby705c1862006-12-08 02:39:11 -08001699static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001701 struct stlport *portp;
1702 unsigned int i;
1703 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
Jiri Slabya0564e12006-12-08 02:38:37 -08001705 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707 chipmask = stl_panelinit(brdp, panelp);
1708
1709/*
1710 * All UART's are initialized (if found!). Now go through and setup
1711 * each ports data structures.
1712 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001713 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001714 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001715 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001717 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 break;
1719 }
Alan Coxd18a7502008-10-13 10:40:07 +01001720 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001721 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 portp->magic = STL_PORTMAGIC;
1723 portp->portnr = i;
1724 portp->brdnr = panelp->brdnr;
1725 portp->panelnr = panelp->panelnr;
1726 portp->uartp = panelp->uartp;
1727 portp->clk = brdp->clk;
1728 portp->baud_base = STL_BAUDBASE;
1729 portp->close_delay = STL_CLOSEDELAY;
1730 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001731 init_waitqueue_head(&portp->port.open_wait);
1732 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 portp->stats.brd = portp->brdnr;
1734 portp->stats.panel = portp->panelnr;
1735 portp->stats.port = portp->portnr;
1736 panelp->ports[i] = portp;
1737 stl_portinit(brdp, panelp, portp);
1738 }
1739
Jiri Slabyc62429d2006-12-08 02:39:14 -08001740 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741}
1742
Jiri Slaby3b85b342006-12-08 02:39:10 -08001743static void stl_cleanup_panels(struct stlbrd *brdp)
1744{
1745 struct stlpanel *panelp;
1746 struct stlport *portp;
1747 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001748 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001749
1750 for (j = 0; j < STL_MAXPANELS; j++) {
1751 panelp = brdp->panels[j];
1752 if (panelp == NULL)
1753 continue;
1754 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1755 portp = panelp->ports[k];
1756 if (portp == NULL)
1757 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001758 tty = tty_port_tty_get(&portp->port);
1759 if (tty != NULL) {
1760 stl_hangup(tty);
1761 tty_kref_put(tty);
1762 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001763 kfree(portp->tx.buf);
1764 kfree(portp);
1765 }
1766 kfree(panelp);
1767 }
1768}
1769
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770/*****************************************************************************/
1771
1772/*
1773 * Try to find and initialize an EasyIO board.
1774 */
1775
Jiri Slaby705c1862006-12-08 02:39:11 -08001776static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001778 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 unsigned int status;
1780 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001781 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
Jiri Slabya0564e12006-12-08 02:38:37 -08001783 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784
1785 brdp->ioctrl = brdp->ioaddr1 + 1;
1786 brdp->iostatus = brdp->ioaddr1 + 2;
1787
1788 status = inb(brdp->iostatus);
1789 if ((status & EIO_IDBITMASK) == EIO_MK3)
1790 brdp->ioctrl++;
1791
1792/*
1793 * Handle board specific stuff now. The real difference is PCI
1794 * or not PCI.
1795 */
1796 if (brdp->brdtype == BRD_EASYIOPCI) {
1797 brdp->iosize1 = 0x80;
1798 brdp->iosize2 = 0x80;
1799 name = "serial(EIO-PCI)";
1800 outb(0x41, (brdp->ioaddr2 + 0x4c));
1801 } else {
1802 brdp->iosize1 = 8;
1803 name = "serial(EIO)";
1804 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1805 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1806 printk("STALLION: invalid irq=%d for brd=%d\n",
1807 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001808 retval = -EINVAL;
1809 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 }
1811 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1812 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1813 brdp->ioctrl);
1814 }
1815
Jiri Slaby3b85b342006-12-08 02:39:10 -08001816 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1818 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1819 "%x conflicts with another device\n", brdp->brdnr,
1820 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001821 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 }
1823
1824 if (brdp->iosize2 > 0)
1825 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1826 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1827 "address %x conflicts with another device\n",
1828 brdp->brdnr, brdp->ioaddr2);
1829 printk(KERN_WARNING "STALLION: Warning, also "
1830 "releasing board %d I/O address %x \n",
1831 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001832 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 }
1834
1835/*
1836 * Everything looks OK, so let's go ahead and probe for the hardware.
1837 */
1838 brdp->clk = CD1400_CLK;
1839 brdp->isr = stl_eiointr;
1840
Jiri Slaby3b85b342006-12-08 02:39:10 -08001841 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 switch (status & EIO_IDBITMASK) {
1843 case EIO_8PORTM:
1844 brdp->clk = CD1400_CLK8M;
1845 /* fall thru */
1846 case EIO_8PORTRS:
1847 case EIO_8PORTDI:
1848 brdp->nrports = 8;
1849 break;
1850 case EIO_4PORTRS:
1851 brdp->nrports = 4;
1852 break;
1853 case EIO_MK3:
1854 switch (status & EIO_BRDMASK) {
1855 case ID_BRD4:
1856 brdp->nrports = 4;
1857 break;
1858 case ID_BRD8:
1859 brdp->nrports = 8;
1860 break;
1861 case ID_BRD16:
1862 brdp->nrports = 16;
1863 break;
1864 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001865 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 }
1867 break;
1868 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001869 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 }
1871
1872/*
1873 * We have verified that the board is actually present, so now we
1874 * can complete the setup.
1875 */
1876
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001877 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001878 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001880 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001881 retval = -ENOMEM;
1882 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
1885 panelp->magic = STL_PANELMAGIC;
1886 panelp->brdnr = brdp->brdnr;
1887 panelp->panelnr = 0;
1888 panelp->nrports = brdp->nrports;
1889 panelp->iobase = brdp->ioaddr1;
1890 panelp->hwid = status;
1891 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001892 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 panelp->isr = stl_sc26198intr;
1894 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001895 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 panelp->isr = stl_cd1400eiointr;
1897 }
1898
1899 brdp->panels[0] = panelp;
1900 brdp->nrpanels = 1;
1901 brdp->state |= BRD_FOUND;
1902 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001903 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 printk("STALLION: failed to register interrupt "
1905 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001906 retval = -ENODEV;
1907 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001909
1910 return 0;
1911err_fr:
1912 stl_cleanup_panels(brdp);
1913err_rel2:
1914 if (brdp->iosize2 > 0)
1915 release_region(brdp->ioaddr2, brdp->iosize2);
1916err_rel1:
1917 release_region(brdp->ioaddr1, brdp->iosize1);
1918err:
1919 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920}
1921
1922/*****************************************************************************/
1923
1924/*
1925 * Try to find an ECH board and initialize it. This code is capable of
1926 * dealing with all types of ECH board.
1927 */
1928
Jiri Slaby705c1862006-12-08 02:39:11 -08001929static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001931 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001932 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1933 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 char *name;
1935
Jiri Slabya0564e12006-12-08 02:38:37 -08001936 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937
1938 status = 0;
1939 conflict = 0;
1940
1941/*
1942 * Set up the initial board register contents for boards. This varies a
1943 * bit between the different board types. So we need to handle each
1944 * separately. Also do a check that the supplied IRQ is good.
1945 */
1946 switch (brdp->brdtype) {
1947
1948 case BRD_ECH:
1949 brdp->isr = stl_echatintr;
1950 brdp->ioctrl = brdp->ioaddr1 + 1;
1951 brdp->iostatus = brdp->ioaddr1 + 1;
1952 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001953 if ((status & ECH_IDBITMASK) != ECH_ID) {
1954 retval = -ENODEV;
1955 goto err;
1956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1958 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1959 printk("STALLION: invalid irq=%d for brd=%d\n",
1960 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001961 retval = -EINVAL;
1962 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 }
1964 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1965 status |= (stl_vecmap[brdp->irq] << 1);
1966 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1967 brdp->ioctrlval = ECH_INTENABLE |
1968 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001969 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1971 brdp->iosize1 = 2;
1972 brdp->iosize2 = 32;
1973 name = "serial(EC8/32)";
1974 outb(status, brdp->ioaddr1);
1975 break;
1976
1977 case BRD_ECHMC:
1978 brdp->isr = stl_echmcaintr;
1979 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1980 brdp->iostatus = brdp->ioctrl;
1981 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001982 if ((status & ECH_IDBITMASK) != ECH_ID) {
1983 retval = -ENODEV;
1984 goto err;
1985 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1987 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1988 printk("STALLION: invalid irq=%d for brd=%d\n",
1989 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001990 retval = -EINVAL;
1991 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 }
1993 outb(ECHMC_BRDRESET, brdp->ioctrl);
1994 outb(ECHMC_INTENABLE, brdp->ioctrl);
1995 brdp->iosize1 = 64;
1996 name = "serial(EC8/32-MC)";
1997 break;
1998
1999 case BRD_ECHPCI:
2000 brdp->isr = stl_echpciintr;
2001 brdp->ioctrl = brdp->ioaddr1 + 2;
2002 brdp->iosize1 = 4;
2003 brdp->iosize2 = 8;
2004 name = "serial(EC8/32-PCI)";
2005 break;
2006
2007 case BRD_ECH64PCI:
2008 brdp->isr = stl_echpci64intr;
2009 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2010 outb(0x43, (brdp->ioaddr1 + 0x4c));
2011 brdp->iosize1 = 0x80;
2012 brdp->iosize2 = 0x80;
2013 name = "serial(EC8/64-PCI)";
2014 break;
2015
2016 default:
2017 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002018 retval = -EINVAL;
2019 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 }
2021
2022/*
2023 * Check boards for possible IO address conflicts and return fail status
2024 * if an IO conflict found.
2025 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002026 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2028 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2029 "%x conflicts with another device\n", brdp->brdnr,
2030 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002031 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 }
2033
2034 if (brdp->iosize2 > 0)
2035 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2036 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2037 "address %x conflicts with another device\n",
2038 brdp->brdnr, brdp->ioaddr2);
2039 printk(KERN_WARNING "STALLION: Warning, also "
2040 "releasing board %d I/O address %x \n",
2041 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002042 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
2044
2045/*
2046 * Scan through the secondary io address space looking for panels.
2047 * As we find'em allocate and initialize panel structures for each.
2048 */
2049 brdp->clk = CD1400_CLK;
2050 brdp->hwid = status;
2051
2052 ioaddr = brdp->ioaddr2;
2053 banknr = 0;
2054 panelnr = 0;
2055 nxtid = 0;
2056
Jiri Slabyc62429d2006-12-08 02:39:14 -08002057 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 if (brdp->brdtype == BRD_ECHPCI) {
2059 outb(nxtid, brdp->ioctrl);
2060 ioaddr = brdp->ioaddr2;
2061 }
2062 status = inb(ioaddr + ECH_PNLSTATUS);
2063 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002064 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002065 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002066 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002068 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002069 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002070 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 panelp->magic = STL_PANELMAGIC;
2073 panelp->brdnr = brdp->brdnr;
2074 panelp->panelnr = panelnr;
2075 panelp->iobase = ioaddr;
2076 panelp->pagenr = nxtid;
2077 panelp->hwid = status;
2078 brdp->bnk2panel[banknr] = panelp;
2079 brdp->bnkpageaddr[banknr] = nxtid;
2080 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2081
2082 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002083 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 panelp->isr = stl_sc26198intr;
2085 if (status & ECH_PNL16PORT) {
2086 panelp->nrports = 16;
2087 brdp->bnk2panel[banknr] = panelp;
2088 brdp->bnkpageaddr[banknr] = nxtid;
2089 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2090 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002091 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002094 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 panelp->isr = stl_cd1400echintr;
2096 if (status & ECH_PNL16PORT) {
2097 panelp->nrports = 16;
2098 panelp->ackmask = 0x80;
2099 if (brdp->brdtype != BRD_ECHPCI)
2100 ioaddr += EREG_BANKSIZE;
2101 brdp->bnk2panel[banknr] = panelp;
2102 brdp->bnkpageaddr[banknr] = ++nxtid;
2103 brdp->bnkstataddr[banknr++] = ioaddr +
2104 ECH_PNLSTATUS;
2105 } else {
2106 panelp->nrports = 8;
2107 panelp->ackmask = 0xc0;
2108 }
2109 }
2110
2111 nxtid++;
2112 ioaddr += EREG_BANKSIZE;
2113 brdp->nrports += panelp->nrports;
2114 brdp->panels[panelnr++] = panelp;
2115 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002116 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2117 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002118 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 }
2121
2122 brdp->nrpanels = panelnr;
2123 brdp->nrbnks = banknr;
2124 if (brdp->brdtype == BRD_ECH)
2125 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2126
2127 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002128 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 printk("STALLION: failed to register interrupt "
2130 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002131 retval = -ENODEV;
2132 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 }
2134
Jiri Slaby3b85b342006-12-08 02:39:10 -08002135 return 0;
2136err_fr:
2137 stl_cleanup_panels(brdp);
2138 if (brdp->iosize2 > 0)
2139 release_region(brdp->ioaddr2, brdp->iosize2);
2140err_rel1:
2141 release_region(brdp->ioaddr1, brdp->iosize1);
2142err:
2143 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144}
2145
2146/*****************************************************************************/
2147
2148/*
2149 * Initialize and configure the specified board.
2150 * Scan through all the boards in the configuration and see what we
2151 * can find. Handle EIO and the ECH boards a little differently here
2152 * since the initial search and setup is very different.
2153 */
2154
Jiri Slaby705c1862006-12-08 02:39:11 -08002155static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002157 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158
Jiri Slabya0564e12006-12-08 02:38:37 -08002159 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
2161 switch (brdp->brdtype) {
2162 case BRD_EASYIO:
2163 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002164 retval = stl_initeio(brdp);
2165 if (retval)
2166 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 break;
2168 case BRD_ECH:
2169 case BRD_ECHMC:
2170 case BRD_ECHPCI:
2171 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002172 retval = stl_initech(brdp);
2173 if (retval)
2174 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 break;
2176 default:
2177 printk("STALLION: board=%d is unknown board type=%d\n",
2178 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002179 retval = -ENODEV;
2180 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 }
2182
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 if ((brdp->state & BRD_FOUND) == 0) {
2184 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2185 stl_brdnames[brdp->brdtype], brdp->brdnr,
2186 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002187 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 }
2189
Jiri Slabyc62429d2006-12-08 02:39:14 -08002190 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002191 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 stl_initports(brdp, brdp->panels[i]);
2193
2194 printk("STALLION: %s found, board=%d io=%x irq=%d "
2195 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2196 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2197 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002198
2199 return 0;
2200err_free:
2201 free_irq(brdp->irq, brdp);
2202
2203 stl_cleanup_panels(brdp);
2204
2205 release_region(brdp->ioaddr1, brdp->iosize1);
2206 if (brdp->iosize2 > 0)
2207 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002208err:
2209 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210}
2211
2212/*****************************************************************************/
2213
2214/*
2215 * Find the next available board number that is free.
2216 */
2217
Jiri Slaby705c1862006-12-08 02:39:11 -08002218static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002220 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Jiri Slabyc62429d2006-12-08 02:39:14 -08002222 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002223 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 if (i >= stl_nrbrds)
2225 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002226 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002228
2229 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230}
2231
2232/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233/*
2234 * We have a Stallion board. Allocate a board structure and
2235 * initialize it. Read its IO and IRQ resources from PCI
2236 * configuration space.
2237 */
2238
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002239static int __devinit stl_pciprobe(struct pci_dev *pdev,
2240 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002242 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002243 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002244 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002246 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002247 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002248
Jiri Slaby3b85b342006-12-08 02:39:10 -08002249 retval = pci_enable_device(pdev);
2250 if (retval)
2251 goto err;
2252 brdp = stl_allocbrd();
2253 if (brdp == NULL) {
2254 retval = -ENOMEM;
2255 goto err;
2256 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002257 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002258 brdnr = stl_getbrdnr();
2259 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002260 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002262 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002263 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002264 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002266 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002267 stl_brds[brdp->brdnr] = brdp;
2268 mutex_unlock(&stl_brdslock);
2269
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002271 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
2273/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 * We have all resources from the board, so let's setup the actual
2275 * board structure now.
2276 */
2277 switch (brdtype) {
2278 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002279 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2280 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 break;
2282 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002283 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2284 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 break;
2286 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002287 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2288 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 break;
2290 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002291 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 break;
2293 }
2294
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002295 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002296 retval = stl_brdinit(brdp);
2297 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002298 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002300 pci_set_drvdata(pdev, brdp);
2301
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002302 for (i = 0; i < brdp->nrports; i++)
2303 tty_register_device(stl_serial,
2304 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2305
Jiri Slaby3b85b342006-12-08 02:39:10 -08002306 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002307err_null:
2308 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002309err_fr:
2310 kfree(brdp);
2311err:
2312 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313}
2314
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002315static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002317 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002318 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002320 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002322 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002324 release_region(brdp->ioaddr1, brdp->iosize1);
2325 if (brdp->iosize2 > 0)
2326 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002328 for (i = 0; i < brdp->nrports; i++)
2329 tty_unregister_device(stl_serial,
2330 brdp->brdnr * STL_MAXPORTS + i);
2331
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002332 stl_brds[brdp->brdnr] = NULL;
2333 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334}
2335
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002336static struct pci_driver stl_pcidriver = {
2337 .name = "stallion",
2338 .id_table = stl_pcibrds,
2339 .probe = stl_pciprobe,
2340 .remove = __devexit_p(stl_pciremove)
2341};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342
2343/*****************************************************************************/
2344
2345/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 * Return the board stats structure to user app.
2347 */
2348
2349static int stl_getbrdstats(combrd_t __user *bp)
2350{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002351 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002352 struct stlbrd *brdp;
2353 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002354 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
2356 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2357 return -EFAULT;
2358 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002359 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002361 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002362 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
2364 memset(&stl_brdstats, 0, sizeof(combrd_t));
2365 stl_brdstats.brd = brdp->brdnr;
2366 stl_brdstats.type = brdp->brdtype;
2367 stl_brdstats.hwid = brdp->hwid;
2368 stl_brdstats.state = brdp->state;
2369 stl_brdstats.ioaddr = brdp->ioaddr1;
2370 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2371 stl_brdstats.irq = brdp->irq;
2372 stl_brdstats.nrpanels = brdp->nrpanels;
2373 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002374 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 panelp = brdp->panels[i];
2376 stl_brdstats.panels[i].panel = i;
2377 stl_brdstats.panels[i].hwid = panelp->hwid;
2378 stl_brdstats.panels[i].nrports = panelp->nrports;
2379 }
2380
2381 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2382}
2383
2384/*****************************************************************************/
2385
2386/*
2387 * Resolve the referenced port number into a port struct pointer.
2388 */
2389
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002390static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002392 struct stlbrd *brdp;
2393 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394
Jiri Slabyc62429d2006-12-08 02:39:14 -08002395 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2396 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002398 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002399 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002400 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002401 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002403 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002404 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002405 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002406 return NULL;
2407 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408}
2409
2410/*****************************************************************************/
2411
2412/*
2413 * Return the port stats structure to user app. A NULL port struct
2414 * pointer passed in means that we need to find out from the app
2415 * what port to get stats for (used through board control device).
2416 */
2417
Alan Coxd18a7502008-10-13 10:40:07 +01002418static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002420 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 unsigned char *head, *tail;
2422 unsigned long flags;
2423
2424 if (!portp) {
2425 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2426 return -EFAULT;
2427 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2428 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002429 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002430 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 }
2432
2433 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002434 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 portp->stats.hwid = portp->hwid;
2436
2437 portp->stats.ttystate = 0;
2438 portp->stats.cflags = 0;
2439 portp->stats.iflags = 0;
2440 portp->stats.oflags = 0;
2441 portp->stats.lflags = 0;
2442 portp->stats.rxbuffered = 0;
2443
Alan Coxb65b5b52006-06-27 02:54:05 -07002444 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002445 if (tty != NULL && portp->port.tty == tty) {
2446 portp->stats.ttystate = tty->flags;
2447 /* No longer available as a statistic */
2448 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2449 if (tty->termios != NULL) {
2450 portp->stats.cflags = tty->termios->c_cflag;
2451 portp->stats.iflags = tty->termios->c_iflag;
2452 portp->stats.oflags = tty->termios->c_oflag;
2453 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 }
Alan Coxd18a7502008-10-13 10:40:07 +01002455 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002456 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457
2458 head = portp->tx.head;
2459 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002460 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2461 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
2463 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2464
2465 return copy_to_user(cp, &portp->stats,
2466 sizeof(comstats_t)) ? -EFAULT : 0;
2467}
2468
2469/*****************************************************************************/
2470
2471/*
2472 * Clear the port stats structure. We also return it zeroed out...
2473 */
2474
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002475static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002477 comstats_t stl_comstats;
2478
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 if (!portp) {
2480 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2481 return -EFAULT;
2482 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2483 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002484 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002485 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 }
2487
2488 memset(&portp->stats, 0, sizeof(comstats_t));
2489 portp->stats.brd = portp->brdnr;
2490 portp->stats.panel = portp->panelnr;
2491 portp->stats.port = portp->portnr;
2492 return copy_to_user(cp, &portp->stats,
2493 sizeof(comstats_t)) ? -EFAULT : 0;
2494}
2495
2496/*****************************************************************************/
2497
2498/*
2499 * Return the entire driver ports structure to a user app.
2500 */
2501
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002502static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002504 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002505 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002507 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 return -EFAULT;
2509 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2510 stl_dummyport.portnr);
2511 if (!portp)
2512 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002513 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514}
2515
2516/*****************************************************************************/
2517
2518/*
2519 * Return the entire driver board structure to a user app.
2520 */
2521
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002522static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002524 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002525 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002527 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002529 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 return -ENODEV;
2531 brdp = stl_brds[stl_dummybrd.brdnr];
2532 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002533 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002534 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535}
2536
2537/*****************************************************************************/
2538
2539/*
2540 * The "staliomem" device is also required to do some special operations
2541 * on the board and/or ports. In this driver it is mostly used for stats
2542 * collection.
2543 */
2544
2545static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2546{
2547 int brdnr, rc;
2548 void __user *argp = (void __user *)arg;
2549
Jiri Slabya0564e12006-12-08 02:38:37 -08002550 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551
2552 brdnr = iminor(ip);
2553 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002554 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 rc = 0;
2556
2557 switch (cmd) {
2558 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002559 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 break;
2561 case COM_CLRPORTSTATS:
2562 rc = stl_clrportstats(NULL, argp);
2563 break;
2564 case COM_GETBRDSTATS:
2565 rc = stl_getbrdstats(argp);
2566 break;
2567 case COM_READPORT:
2568 rc = stl_getportstruct(argp);
2569 break;
2570 case COM_READBOARD:
2571 rc = stl_getbrdstruct(argp);
2572 break;
2573 default:
2574 rc = -ENOIOCTLCMD;
2575 break;
2576 }
2577
Jiri Slabyc62429d2006-12-08 02:39:14 -08002578 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579}
2580
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002581static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 .open = stl_open,
2583 .close = stl_close,
2584 .write = stl_write,
2585 .put_char = stl_putchar,
2586 .flush_chars = stl_flushchars,
2587 .write_room = stl_writeroom,
2588 .chars_in_buffer = stl_charsinbuffer,
2589 .ioctl = stl_ioctl,
2590 .set_termios = stl_settermios,
2591 .throttle = stl_throttle,
2592 .unthrottle = stl_unthrottle,
2593 .stop = stl_stop,
2594 .start = stl_start,
2595 .hangup = stl_hangup,
2596 .flush_buffer = stl_flushbuffer,
2597 .break_ctl = stl_breakctl,
2598 .wait_until_sent = stl_waituntilsent,
2599 .send_xchar = stl_sendxchar,
2600 .read_proc = stl_readproc,
2601 .tiocmget = stl_tiocmget,
2602 .tiocmset = stl_tiocmset,
2603};
2604
Alan Cox31f35932009-01-02 13:45:05 +00002605static const struct tty_port_operations stl_port_ops = {
2606 .carrier_raised = stl_carrier_raised,
Alan Cox4350f3f2009-01-02 13:46:24 +00002607 .raise_dtr_rts = stl_raise_dtr_rts,
Alan Cox31f35932009-01-02 13:45:05 +00002608};
2609
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611/* CD1400 HARDWARE FUNCTIONS */
2612/*****************************************************************************/
2613
2614/*
2615 * These functions get/set/update the registers of the cd1400 UARTs.
2616 * Access to the cd1400 registers is via an address/data io port pair.
2617 * (Maybe should make this inline...)
2618 */
2619
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002620static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621{
2622 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002623 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624}
2625
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002626static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002628 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 outb(value, portp->ioaddr + EREG_DATA);
2630}
2631
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002632static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002634 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 if (inb(portp->ioaddr + EREG_DATA) != value) {
2636 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002637 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002639 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640}
2641
2642/*****************************************************************************/
2643
2644/*
2645 * Inbitialize the UARTs in a panel. We don't care what sort of board
2646 * these ports are on - since the port io registers are almost
2647 * identical when dealing with ports.
2648 */
2649
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002650static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651{
2652 unsigned int gfrcr;
2653 int chipmask, i, j;
2654 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002655 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656
Jiri Slabya0564e12006-12-08 02:38:37 -08002657 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658
Alan Coxb65b5b52006-06-27 02:54:05 -07002659 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 BRDENABLE(panelp->brdnr, panelp->pagenr);
2661
2662/*
2663 * Check that each chip is present and started up OK.
2664 */
2665 chipmask = 0;
2666 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002667 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 if (brdp->brdtype == BRD_ECHPCI) {
2669 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2670 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002671 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 uartaddr = (i & 0x01) ? 0x080 : 0;
2674 outb((GFRCR + uartaddr), ioaddr);
2675 outb(0, (ioaddr + EREG_DATA));
2676 outb((CCR + uartaddr), ioaddr);
2677 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2678 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2679 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002680 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2682 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002683
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2685 printk("STALLION: cd1400 not responding, "
2686 "brd=%d panel=%d chip=%d\n",
2687 panelp->brdnr, panelp->panelnr, i);
2688 continue;
2689 }
2690 chipmask |= (0x1 << i);
2691 outb((PPR + uartaddr), ioaddr);
2692 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2693 }
2694
2695 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002696 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002697 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698}
2699
2700/*****************************************************************************/
2701
2702/*
2703 * Initialize hardware specific port registers.
2704 */
2705
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002706static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707{
Alan Coxb65b5b52006-06-27 02:54:05 -07002708 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002709 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2710 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711
Jiri Slaby615e4a72006-12-08 02:38:38 -08002712 if ((brdp == NULL) || (panelp == NULL) ||
2713 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 return;
2715
Alan Coxb65b5b52006-06-27 02:54:05 -07002716 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2718 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2719 portp->uartaddr = (portp->portnr & 0x04) << 5;
2720 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2721
2722 BRDENABLE(portp->brdnr, portp->pagenr);
2723 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2724 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2725 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2726 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002727 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728}
2729
2730/*****************************************************************************/
2731
2732/*
2733 * Wait for the command register to be ready. We will poll this,
2734 * since it won't usually take too long to be ready.
2735 */
2736
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002737static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738{
2739 int i;
2740
Jiri Slabyc62429d2006-12-08 02:39:14 -08002741 for (i = 0; i < CCR_MAXWAIT; i++)
2742 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
2745 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2746 portp->portnr, portp->panelnr, portp->brdnr);
2747}
2748
2749/*****************************************************************************/
2750
2751/*
2752 * Set up the cd1400 registers for a port based on the termios port
2753 * settings.
2754 */
2755
Alan Cox606d0992006-12-08 02:38:45 -08002756static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002758 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 unsigned long flags;
2760 unsigned int clkdiv, baudrate;
2761 unsigned char cor1, cor2, cor3;
2762 unsigned char cor4, cor5, ccr;
2763 unsigned char srer, sreron, sreroff;
2764 unsigned char mcor1, mcor2, rtpr;
2765 unsigned char clk, div;
2766
2767 cor1 = 0;
2768 cor2 = 0;
2769 cor3 = 0;
2770 cor4 = 0;
2771 cor5 = 0;
2772 ccr = 0;
2773 rtpr = 0;
2774 clk = 0;
2775 div = 0;
2776 mcor1 = 0;
2777 mcor2 = 0;
2778 sreron = 0;
2779 sreroff = 0;
2780
2781 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002782 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 return;
2784
2785/*
2786 * Set up the RX char ignore mask with those RX error types we
2787 * can ignore. We can get the cd1400 to help us out a little here,
2788 * it will ignore parity errors and breaks for us.
2789 */
2790 portp->rxignoremsk = 0;
2791 if (tiosp->c_iflag & IGNPAR) {
2792 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2793 cor1 |= COR1_PARIGNORE;
2794 }
2795 if (tiosp->c_iflag & IGNBRK) {
2796 portp->rxignoremsk |= ST_BREAK;
2797 cor4 |= COR4_IGNBRK;
2798 }
2799
2800 portp->rxmarkmsk = ST_OVERRUN;
2801 if (tiosp->c_iflag & (INPCK | PARMRK))
2802 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2803 if (tiosp->c_iflag & BRKINT)
2804 portp->rxmarkmsk |= ST_BREAK;
2805
2806/*
2807 * Go through the char size, parity and stop bits and set all the
2808 * option register appropriately.
2809 */
2810 switch (tiosp->c_cflag & CSIZE) {
2811 case CS5:
2812 cor1 |= COR1_CHL5;
2813 break;
2814 case CS6:
2815 cor1 |= COR1_CHL6;
2816 break;
2817 case CS7:
2818 cor1 |= COR1_CHL7;
2819 break;
2820 default:
2821 cor1 |= COR1_CHL8;
2822 break;
2823 }
2824
2825 if (tiosp->c_cflag & CSTOPB)
2826 cor1 |= COR1_STOP2;
2827 else
2828 cor1 |= COR1_STOP1;
2829
2830 if (tiosp->c_cflag & PARENB) {
2831 if (tiosp->c_cflag & PARODD)
2832 cor1 |= (COR1_PARENB | COR1_PARODD);
2833 else
2834 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2835 } else {
2836 cor1 |= COR1_PARNONE;
2837 }
2838
2839/*
2840 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2841 * space for hardware flow control and the like. This should be set to
2842 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2843 * really be based on VTIME.
2844 */
2845 cor3 |= FIFO_RXTHRESHOLD;
2846 rtpr = 2;
2847
2848/*
2849 * Calculate the baud rate timers. For now we will just assume that
2850 * the input and output baud are the same. Could have used a baud
2851 * table here, but this way we can generate virtually any baud rate
2852 * we like!
2853 */
2854 baudrate = tiosp->c_cflag & CBAUD;
2855 if (baudrate & CBAUDEX) {
2856 baudrate &= ~CBAUDEX;
2857 if ((baudrate < 1) || (baudrate > 4))
2858 tiosp->c_cflag &= ~CBAUDEX;
2859 else
2860 baudrate += 15;
2861 }
2862 baudrate = stl_baudrates[baudrate];
2863 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002864 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002866 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002868 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002870 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002872 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 baudrate = (portp->baud_base / portp->custom_divisor);
2874 }
2875 if (baudrate > STL_CD1400MAXBAUD)
2876 baudrate = STL_CD1400MAXBAUD;
2877
2878 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002879 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2880 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 if (clkdiv < 0x100)
2882 break;
2883 }
2884 div = (unsigned char) clkdiv;
2885 }
2886
2887/*
2888 * Check what form of modem signaling is required and set it up.
2889 */
2890 if ((tiosp->c_cflag & CLOCAL) == 0) {
2891 mcor1 |= MCOR1_DCD;
2892 mcor2 |= MCOR2_DCD;
2893 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002894 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002895 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002896 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897
2898/*
2899 * Setup cd1400 enhanced modes if we can. In particular we want to
2900 * handle as much of the flow control as possible automatically. As
2901 * well as saving a few CPU cycles it will also greatly improve flow
2902 * control reliability.
2903 */
2904 if (tiosp->c_iflag & IXON) {
2905 cor2 |= COR2_TXIBE;
2906 cor3 |= COR3_SCD12;
2907 if (tiosp->c_iflag & IXANY)
2908 cor2 |= COR2_IXM;
2909 }
2910
2911 if (tiosp->c_cflag & CRTSCTS) {
2912 cor2 |= COR2_CTSAE;
2913 mcor1 |= FIFO_RTSTHRESHOLD;
2914 }
2915
2916/*
2917 * All cd1400 register values calculated so go through and set
2918 * them all up.
2919 */
2920
Jiri Slabya0564e12006-12-08 02:38:37 -08002921 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002923 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002925 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002927 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2928 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2930 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931
Alan Coxb65b5b52006-06-27 02:54:05 -07002932 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 BRDENABLE(portp->brdnr, portp->pagenr);
2934 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2935 srer = stl_cd1400getreg(portp, SRER);
2936 stl_cd1400setreg(portp, SRER, 0);
2937 if (stl_cd1400updatereg(portp, COR1, cor1))
2938 ccr = 1;
2939 if (stl_cd1400updatereg(portp, COR2, cor2))
2940 ccr = 1;
2941 if (stl_cd1400updatereg(portp, COR3, cor3))
2942 ccr = 1;
2943 if (ccr) {
2944 stl_cd1400ccrwait(portp);
2945 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2946 }
2947 stl_cd1400setreg(portp, COR4, cor4);
2948 stl_cd1400setreg(portp, COR5, cor5);
2949 stl_cd1400setreg(portp, MCOR1, mcor1);
2950 stl_cd1400setreg(portp, MCOR2, mcor2);
2951 if (baudrate > 0) {
2952 stl_cd1400setreg(portp, TCOR, clk);
2953 stl_cd1400setreg(portp, TBPR, div);
2954 stl_cd1400setreg(portp, RCOR, clk);
2955 stl_cd1400setreg(portp, RBPR, div);
2956 }
2957 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2958 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2959 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2960 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2961 stl_cd1400setreg(portp, RTPR, rtpr);
2962 mcor1 = stl_cd1400getreg(portp, MSVR1);
2963 if (mcor1 & MSVR1_DCD)
2964 portp->sigs |= TIOCM_CD;
2965 else
2966 portp->sigs &= ~TIOCM_CD;
2967 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2968 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002969 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970}
2971
2972/*****************************************************************************/
2973
2974/*
2975 * Set the state of the DTR and RTS signals.
2976 */
2977
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002978static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979{
2980 unsigned char msvr1, msvr2;
2981 unsigned long flags;
2982
Jiri Slabya0564e12006-12-08 02:38:37 -08002983 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2984 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985
2986 msvr1 = 0;
2987 msvr2 = 0;
2988 if (dtr > 0)
2989 msvr1 = MSVR1_DTR;
2990 if (rts > 0)
2991 msvr2 = MSVR2_RTS;
2992
Alan Coxb65b5b52006-06-27 02:54:05 -07002993 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 BRDENABLE(portp->brdnr, portp->pagenr);
2995 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2996 if (rts >= 0)
2997 stl_cd1400setreg(portp, MSVR2, msvr2);
2998 if (dtr >= 0)
2999 stl_cd1400setreg(portp, MSVR1, msvr1);
3000 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003001 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002}
3003
3004/*****************************************************************************/
3005
3006/*
3007 * Return the state of the signals.
3008 */
3009
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003010static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011{
3012 unsigned char msvr1, msvr2;
3013 unsigned long flags;
3014 int sigs;
3015
Jiri Slabya0564e12006-12-08 02:38:37 -08003016 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017
Alan Coxb65b5b52006-06-27 02:54:05 -07003018 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 BRDENABLE(portp->brdnr, portp->pagenr);
3020 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3021 msvr1 = stl_cd1400getreg(portp, MSVR1);
3022 msvr2 = stl_cd1400getreg(portp, MSVR2);
3023 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003024 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025
3026 sigs = 0;
3027 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3028 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3029 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3030 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3031#if 0
3032 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3033 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3034#else
3035 sigs |= TIOCM_DSR;
3036#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003037 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038}
3039
3040/*****************************************************************************/
3041
3042/*
3043 * Enable/Disable the Transmitter and/or Receiver.
3044 */
3045
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003046static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047{
3048 unsigned char ccr;
3049 unsigned long flags;
3050
Jiri Slabya0564e12006-12-08 02:38:37 -08003051 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3052
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 ccr = 0;
3054
3055 if (tx == 0)
3056 ccr |= CCR_TXDISABLE;
3057 else if (tx > 0)
3058 ccr |= CCR_TXENABLE;
3059 if (rx == 0)
3060 ccr |= CCR_RXDISABLE;
3061 else if (rx > 0)
3062 ccr |= CCR_RXENABLE;
3063
Alan Coxb65b5b52006-06-27 02:54:05 -07003064 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 BRDENABLE(portp->brdnr, portp->pagenr);
3066 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3067 stl_cd1400ccrwait(portp);
3068 stl_cd1400setreg(portp, CCR, ccr);
3069 stl_cd1400ccrwait(portp);
3070 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003071 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072}
3073
3074/*****************************************************************************/
3075
3076/*
3077 * Start/stop the Transmitter and/or Receiver.
3078 */
3079
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003080static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081{
3082 unsigned char sreron, sreroff;
3083 unsigned long flags;
3084
Jiri Slabya0564e12006-12-08 02:38:37 -08003085 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086
3087 sreron = 0;
3088 sreroff = 0;
3089 if (tx == 0)
3090 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3091 else if (tx == 1)
3092 sreron |= SRER_TXDATA;
3093 else if (tx >= 2)
3094 sreron |= SRER_TXEMPTY;
3095 if (rx == 0)
3096 sreroff |= SRER_RXDATA;
3097 else if (rx > 0)
3098 sreron |= SRER_RXDATA;
3099
Alan Coxb65b5b52006-06-27 02:54:05 -07003100 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 BRDENABLE(portp->brdnr, portp->pagenr);
3102 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3103 stl_cd1400setreg(portp, SRER,
3104 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3105 BRDDISABLE(portp->brdnr);
3106 if (tx > 0)
3107 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003108 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109}
3110
3111/*****************************************************************************/
3112
3113/*
3114 * Disable all interrupts from this port.
3115 */
3116
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003117static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118{
3119 unsigned long flags;
3120
Jiri Slabya0564e12006-12-08 02:38:37 -08003121 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3122
Alan Coxb65b5b52006-06-27 02:54:05 -07003123 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 BRDENABLE(portp->brdnr, portp->pagenr);
3125 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3126 stl_cd1400setreg(portp, SRER, 0);
3127 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003128 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129}
3130
3131/*****************************************************************************/
3132
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003133static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134{
3135 unsigned long flags;
3136
Jiri Slabya0564e12006-12-08 02:38:37 -08003137 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138
Alan Coxb65b5b52006-06-27 02:54:05 -07003139 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 BRDENABLE(portp->brdnr, portp->pagenr);
3141 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3142 stl_cd1400setreg(portp, SRER,
3143 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3144 SRER_TXEMPTY));
3145 BRDDISABLE(portp->brdnr);
3146 portp->brklen = len;
3147 if (len == 1)
3148 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003149 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150}
3151
3152/*****************************************************************************/
3153
3154/*
3155 * Take flow control actions...
3156 */
3157
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003158static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159{
3160 struct tty_struct *tty;
3161 unsigned long flags;
3162
Jiri Slabya0564e12006-12-08 02:38:37 -08003163 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Jiri Slaby615e4a72006-12-08 02:38:38 -08003165 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003167 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003168 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169 return;
3170
Alan Coxb65b5b52006-06-27 02:54:05 -07003171 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 BRDENABLE(portp->brdnr, portp->pagenr);
3173 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3174
3175 if (state) {
3176 if (tty->termios->c_iflag & IXOFF) {
3177 stl_cd1400ccrwait(portp);
3178 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3179 portp->stats.rxxon++;
3180 stl_cd1400ccrwait(portp);
3181 }
3182/*
3183 * Question: should we return RTS to what it was before? It may
3184 * have been set by an ioctl... Suppose not, since if you have
3185 * hardware flow control set then it is pretty silly to go and
3186 * set the RTS line by hand.
3187 */
3188 if (tty->termios->c_cflag & CRTSCTS) {
3189 stl_cd1400setreg(portp, MCOR1,
3190 (stl_cd1400getreg(portp, MCOR1) |
3191 FIFO_RTSTHRESHOLD));
3192 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3193 portp->stats.rxrtson++;
3194 }
3195 } else {
3196 if (tty->termios->c_iflag & IXOFF) {
3197 stl_cd1400ccrwait(portp);
3198 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3199 portp->stats.rxxoff++;
3200 stl_cd1400ccrwait(portp);
3201 }
3202 if (tty->termios->c_cflag & CRTSCTS) {
3203 stl_cd1400setreg(portp, MCOR1,
3204 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3205 stl_cd1400setreg(portp, MSVR2, 0);
3206 portp->stats.rxrtsoff++;
3207 }
3208 }
3209
3210 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003211 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003212 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213}
3214
3215/*****************************************************************************/
3216
3217/*
3218 * Send a flow control character...
3219 */
3220
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003221static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222{
3223 struct tty_struct *tty;
3224 unsigned long flags;
3225
Jiri Slabya0564e12006-12-08 02:38:37 -08003226 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227
Jiri Slaby615e4a72006-12-08 02:38:38 -08003228 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003230 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003231 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 return;
3233
Alan Coxb65b5b52006-06-27 02:54:05 -07003234 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 BRDENABLE(portp->brdnr, portp->pagenr);
3236 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3237 if (state) {
3238 stl_cd1400ccrwait(portp);
3239 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3240 portp->stats.rxxon++;
3241 stl_cd1400ccrwait(portp);
3242 } else {
3243 stl_cd1400ccrwait(portp);
3244 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3245 portp->stats.rxxoff++;
3246 stl_cd1400ccrwait(portp);
3247 }
3248 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003249 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003250 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251}
3252
3253/*****************************************************************************/
3254
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003255static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256{
3257 unsigned long flags;
3258
Jiri Slabya0564e12006-12-08 02:38:37 -08003259 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260
Jiri Slaby615e4a72006-12-08 02:38:38 -08003261 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 return;
3263
Alan Coxb65b5b52006-06-27 02:54:05 -07003264 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265 BRDENABLE(portp->brdnr, portp->pagenr);
3266 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3267 stl_cd1400ccrwait(portp);
3268 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3269 stl_cd1400ccrwait(portp);
3270 portp->tx.tail = portp->tx.head;
3271 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003272 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273}
3274
3275/*****************************************************************************/
3276
3277/*
3278 * Return the current state of data flow on this port. This is only
3279 * really interresting when determining if data has fully completed
3280 * transmission or not... This is easy for the cd1400, it accurately
3281 * maintains the busy port flag.
3282 */
3283
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003284static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285{
Jiri Slabya0564e12006-12-08 02:38:37 -08003286 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287
Jiri Slaby615e4a72006-12-08 02:38:38 -08003288 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003289 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290
Jesper Juhl014c2542006-01-15 02:37:08 +01003291 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292}
3293
3294/*****************************************************************************/
3295
3296/*
3297 * Interrupt service routine for cd1400 EasyIO boards.
3298 */
3299
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003300static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301{
3302 unsigned char svrtype;
3303
Jiri Slabya0564e12006-12-08 02:38:37 -08003304 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305
Alan Coxb65b5b52006-06-27 02:54:05 -07003306 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 outb(SVRR, iobase);
3308 svrtype = inb(iobase + EREG_DATA);
3309 if (panelp->nrports > 4) {
3310 outb((SVRR + 0x80), iobase);
3311 svrtype |= inb(iobase + EREG_DATA);
3312 }
3313
3314 if (svrtype & SVRR_RX)
3315 stl_cd1400rxisr(panelp, iobase);
3316 else if (svrtype & SVRR_TX)
3317 stl_cd1400txisr(panelp, iobase);
3318 else if (svrtype & SVRR_MDM)
3319 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003320
3321 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322}
3323
3324/*****************************************************************************/
3325
3326/*
3327 * Interrupt service routine for cd1400 panels.
3328 */
3329
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003330static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331{
3332 unsigned char svrtype;
3333
Jiri Slabya0564e12006-12-08 02:38:37 -08003334 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335
3336 outb(SVRR, iobase);
3337 svrtype = inb(iobase + EREG_DATA);
3338 outb((SVRR + 0x80), iobase);
3339 svrtype |= inb(iobase + EREG_DATA);
3340 if (svrtype & SVRR_RX)
3341 stl_cd1400rxisr(panelp, iobase);
3342 else if (svrtype & SVRR_TX)
3343 stl_cd1400txisr(panelp, iobase);
3344 else if (svrtype & SVRR_MDM)
3345 stl_cd1400mdmisr(panelp, iobase);
3346}
3347
3348
3349/*****************************************************************************/
3350
3351/*
3352 * Unfortunately we need to handle breaks in the TX data stream, since
3353 * this is the only way to generate them on the cd1400.
3354 */
3355
Jiri Slaby60be4812006-12-08 02:38:40 -08003356static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357{
3358 if (portp->brklen == 1) {
3359 outb((COR2 + portp->uartaddr), ioaddr);
3360 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3361 (ioaddr + EREG_DATA));
3362 outb((TDR + portp->uartaddr), ioaddr);
3363 outb(ETC_CMD, (ioaddr + EREG_DATA));
3364 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3365 outb((SRER + portp->uartaddr), ioaddr);
3366 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3367 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003368 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369 } else if (portp->brklen > 1) {
3370 outb((TDR + portp->uartaddr), ioaddr);
3371 outb(ETC_CMD, (ioaddr + EREG_DATA));
3372 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3373 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003374 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 } else {
3376 outb((COR2 + portp->uartaddr), ioaddr);
3377 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3378 (ioaddr + EREG_DATA));
3379 portp->brklen = 0;
3380 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003381 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382}
3383
3384/*****************************************************************************/
3385
3386/*
3387 * Transmit interrupt handler. This has gotta be fast! Handling TX
3388 * chars is pretty simple, stuff as many as possible from the TX buffer
3389 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3390 * are embedded as commands in the data stream. Oh no, had to use a goto!
3391 * This could be optimized more, will do when I get time...
3392 * In practice it is possible that interrupts are enabled but that the
3393 * port has been hung up. Need to handle not having any TX buffer here,
3394 * this is done by using the side effect that head and tail will also
3395 * be NULL if the buffer has been freed.
3396 */
3397
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003398static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003400 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 int len, stlen;
3402 char *head, *tail;
3403 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003404 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
Jiri Slabya0564e12006-12-08 02:38:37 -08003406 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407
3408 ioack = inb(ioaddr + EREG_TXACK);
3409 if (((ioack & panelp->ackmask) != 0) ||
3410 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3411 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3412 return;
3413 }
3414 portp = panelp->ports[(ioack >> 3)];
3415
3416/*
3417 * Unfortunately we need to handle breaks in the data stream, since
3418 * this is the only way to generate them on the cd1400. Do it now if
3419 * a break is to be sent.
3420 */
3421 if (portp->brklen != 0)
3422 if (stl_cd1400breakisr(portp, ioaddr))
3423 goto stl_txalldone;
3424
3425 head = portp->tx.head;
3426 tail = portp->tx.tail;
3427 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3428 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3429 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3430 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003431 tty = tty_port_tty_get(&portp->port);
3432 if (tty) {
3433 tty_wakeup(tty);
3434 tty_kref_put(tty);
3435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 }
3437
3438 if (len == 0) {
3439 outb((SRER + portp->uartaddr), ioaddr);
3440 srer = inb(ioaddr + EREG_DATA);
3441 if (srer & SRER_TXDATA) {
3442 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3443 } else {
3444 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3445 clear_bit(ASYI_TXBUSY, &portp->istate);
3446 }
3447 outb(srer, (ioaddr + EREG_DATA));
3448 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003449 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003451 stlen = min_t(unsigned int, len,
3452 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 outb((TDR + portp->uartaddr), ioaddr);
3454 outsb((ioaddr + EREG_DATA), tail, stlen);
3455 len -= stlen;
3456 tail += stlen;
3457 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3458 tail = portp->tx.buf;
3459 if (len > 0) {
3460 outsb((ioaddr + EREG_DATA), tail, len);
3461 tail += len;
3462 }
3463 portp->tx.tail = tail;
3464 }
3465
3466stl_txalldone:
3467 outb((EOSRR + portp->uartaddr), ioaddr);
3468 outb(0, (ioaddr + EREG_DATA));
3469}
3470
3471/*****************************************************************************/
3472
3473/*
3474 * Receive character interrupt handler. Determine if we have good chars
3475 * or bad chars and then process appropriately. Good chars are easy
3476 * just shove the lot into the RX buffer and set all status byte to 0.
3477 * If a bad RX char then process as required. This routine needs to be
3478 * fast! In practice it is possible that we get an interrupt on a port
3479 * that is closed. This can happen on hangups - since they completely
3480 * shutdown a port not in user context. Need to handle this case.
3481 */
3482
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003483static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003485 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 struct tty_struct *tty;
3487 unsigned int ioack, len, buflen;
3488 unsigned char status;
3489 char ch;
3490
Jiri Slabya0564e12006-12-08 02:38:37 -08003491 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492
3493 ioack = inb(ioaddr + EREG_RXACK);
3494 if ((ioack & panelp->ackmask) != 0) {
3495 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3496 return;
3497 }
3498 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003499 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500
3501 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3502 outb((RDCR + portp->uartaddr), ioaddr);
3503 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003504 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003505 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 outb((RDSR + portp->uartaddr), ioaddr);
3507 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3508 portp->stats.rxlost += len;
3509 portp->stats.rxtotal += len;
3510 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003511 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003513 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003515 tty_prepare_flip_string(tty, &ptr, len);
3516 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517 tty_schedule_flip(tty);
3518 portp->stats.rxtotal += len;
3519 }
3520 }
3521 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3522 outb((RDSR + portp->uartaddr), ioaddr);
3523 status = inb(ioaddr + EREG_DATA);
3524 ch = inb(ioaddr + EREG_DATA);
3525 if (status & ST_PARITY)
3526 portp->stats.rxparity++;
3527 if (status & ST_FRAMING)
3528 portp->stats.rxframing++;
3529 if (status & ST_OVERRUN)
3530 portp->stats.rxoverrun++;
3531 if (status & ST_BREAK)
3532 portp->stats.rxbreaks++;
3533 if (status & ST_SCHARMASK) {
3534 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3535 portp->stats.txxon++;
3536 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3537 portp->stats.txxoff++;
3538 goto stl_rxalldone;
3539 }
Alan Cox33f0f882006-01-09 20:54:13 -08003540 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541 if (portp->rxmarkmsk & status) {
3542 if (status & ST_BREAK) {
3543 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003544 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 do_SAK(tty);
3546 BRDENABLE(portp->brdnr, portp->pagenr);
3547 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003548 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003550 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003552 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003554 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003556 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003558 tty_insert_flip_char(tty, ch, status);
3559 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 }
3561 } else {
3562 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003563 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 return;
3565 }
3566
3567stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003568 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 outb((EOSRR + portp->uartaddr), ioaddr);
3570 outb(0, (ioaddr + EREG_DATA));
3571}
3572
3573/*****************************************************************************/
3574
3575/*
3576 * Modem interrupt handler. The is called when the modem signal line
3577 * (DCD) has changed state. Leave most of the work to the off-level
3578 * processing routine.
3579 */
3580
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003581static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003583 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 unsigned int ioack;
3585 unsigned char misr;
3586
Jiri Slabya0564e12006-12-08 02:38:37 -08003587 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588
3589 ioack = inb(ioaddr + EREG_MDACK);
3590 if (((ioack & panelp->ackmask) != 0) ||
3591 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3592 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3593 return;
3594 }
3595 portp = panelp->ports[(ioack >> 3)];
3596
3597 outb((MISR + portp->uartaddr), ioaddr);
3598 misr = inb(ioaddr + EREG_DATA);
3599 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003600 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 portp->stats.modem++;
3602 }
3603
3604 outb((EOSRR + portp->uartaddr), ioaddr);
3605 outb(0, (ioaddr + EREG_DATA));
3606}
3607
3608/*****************************************************************************/
3609/* SC26198 HARDWARE FUNCTIONS */
3610/*****************************************************************************/
3611
3612/*
3613 * These functions get/set/update the registers of the sc26198 UARTs.
3614 * Access to the sc26198 registers is via an address/data io port pair.
3615 * (Maybe should make this inline...)
3616 */
3617
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003618static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619{
3620 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003621 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622}
3623
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003624static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625{
3626 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3627 outb(value, (portp->ioaddr + XP_DATA));
3628}
3629
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003630static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631{
3632 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3633 if (inb(portp->ioaddr + XP_DATA) != value) {
3634 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003635 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003637 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638}
3639
3640/*****************************************************************************/
3641
3642/*
3643 * Functions to get and set the sc26198 global registers.
3644 */
3645
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003646static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647{
3648 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003649 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650}
3651
3652#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003653static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654{
3655 outb(regnr, (portp->ioaddr + XP_ADDR));
3656 outb(value, (portp->ioaddr + XP_DATA));
3657}
3658#endif
3659
3660/*****************************************************************************/
3661
3662/*
3663 * Inbitialize the UARTs in a panel. We don't care what sort of board
3664 * these ports are on - since the port io registers are almost
3665 * identical when dealing with ports.
3666 */
3667
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003668static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669{
3670 int chipmask, i;
3671 int nrchips, ioaddr;
3672
Jiri Slabya0564e12006-12-08 02:38:37 -08003673 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
3675 BRDENABLE(panelp->brdnr, panelp->pagenr);
3676
3677/*
3678 * Check that each chip is present and started up OK.
3679 */
3680 chipmask = 0;
3681 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3682 if (brdp->brdtype == BRD_ECHPCI)
3683 outb(panelp->pagenr, brdp->ioctrl);
3684
Jiri Slabyc62429d2006-12-08 02:39:14 -08003685 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 ioaddr = panelp->iobase + (i * 4);
3687 outb(SCCR, (ioaddr + XP_ADDR));
3688 outb(CR_RESETALL, (ioaddr + XP_DATA));
3689 outb(TSTR, (ioaddr + XP_ADDR));
3690 if (inb(ioaddr + XP_DATA) != 0) {
3691 printk("STALLION: sc26198 not responding, "
3692 "brd=%d panel=%d chip=%d\n",
3693 panelp->brdnr, panelp->panelnr, i);
3694 continue;
3695 }
3696 chipmask |= (0x1 << i);
3697 outb(GCCR, (ioaddr + XP_ADDR));
3698 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3699 outb(WDTRCR, (ioaddr + XP_ADDR));
3700 outb(0xff, (ioaddr + XP_DATA));
3701 }
3702
3703 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003704 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705}
3706
3707/*****************************************************************************/
3708
3709/*
3710 * Initialize hardware specific port registers.
3711 */
3712
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003713static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714{
Jiri Slabya0564e12006-12-08 02:38:37 -08003715 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3716 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717
Jiri Slaby615e4a72006-12-08 02:38:38 -08003718 if ((brdp == NULL) || (panelp == NULL) ||
3719 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 return;
3721
3722 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3723 portp->uartaddr = (portp->portnr & 0x07) << 4;
3724 portp->pagenr = panelp->pagenr;
3725 portp->hwid = 0x1;
3726
3727 BRDENABLE(portp->brdnr, portp->pagenr);
3728 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3729 BRDDISABLE(portp->brdnr);
3730}
3731
3732/*****************************************************************************/
3733
3734/*
3735 * Set up the sc26198 registers for a port based on the termios port
3736 * settings.
3737 */
3738
Alan Cox606d0992006-12-08 02:38:45 -08003739static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003741 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 unsigned long flags;
3743 unsigned int baudrate;
3744 unsigned char mr0, mr1, mr2, clk;
3745 unsigned char imron, imroff, iopr, ipr;
3746
3747 mr0 = 0;
3748 mr1 = 0;
3749 mr2 = 0;
3750 clk = 0;
3751 iopr = 0;
3752 imron = 0;
3753 imroff = 0;
3754
3755 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003756 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757 return;
3758
3759/*
3760 * Set up the RX char ignore mask with those RX error types we
3761 * can ignore.
3762 */
3763 portp->rxignoremsk = 0;
3764 if (tiosp->c_iflag & IGNPAR)
3765 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3766 SR_RXOVERRUN);
3767 if (tiosp->c_iflag & IGNBRK)
3768 portp->rxignoremsk |= SR_RXBREAK;
3769
3770 portp->rxmarkmsk = SR_RXOVERRUN;
3771 if (tiosp->c_iflag & (INPCK | PARMRK))
3772 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3773 if (tiosp->c_iflag & BRKINT)
3774 portp->rxmarkmsk |= SR_RXBREAK;
3775
3776/*
3777 * Go through the char size, parity and stop bits and set all the
3778 * option register appropriately.
3779 */
3780 switch (tiosp->c_cflag & CSIZE) {
3781 case CS5:
3782 mr1 |= MR1_CS5;
3783 break;
3784 case CS6:
3785 mr1 |= MR1_CS6;
3786 break;
3787 case CS7:
3788 mr1 |= MR1_CS7;
3789 break;
3790 default:
3791 mr1 |= MR1_CS8;
3792 break;
3793 }
3794
3795 if (tiosp->c_cflag & CSTOPB)
3796 mr2 |= MR2_STOP2;
3797 else
3798 mr2 |= MR2_STOP1;
3799
3800 if (tiosp->c_cflag & PARENB) {
3801 if (tiosp->c_cflag & PARODD)
3802 mr1 |= (MR1_PARENB | MR1_PARODD);
3803 else
3804 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003805 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
3808 mr1 |= MR1_ERRBLOCK;
3809
3810/*
3811 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3812 * space for hardware flow control and the like. This should be set to
3813 * VMIN.
3814 */
3815 mr2 |= MR2_RXFIFOHALF;
3816
3817/*
3818 * Calculate the baud rate timers. For now we will just assume that
3819 * the input and output baud are the same. The sc26198 has a fixed
3820 * baud rate table, so only discrete baud rates possible.
3821 */
3822 baudrate = tiosp->c_cflag & CBAUD;
3823 if (baudrate & CBAUDEX) {
3824 baudrate &= ~CBAUDEX;
3825 if ((baudrate < 1) || (baudrate > 4))
3826 tiosp->c_cflag &= ~CBAUDEX;
3827 else
3828 baudrate += 15;
3829 }
3830 baudrate = stl_baudrates[baudrate];
3831 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003832 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003834 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003836 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003838 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003840 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 baudrate = (portp->baud_base / portp->custom_divisor);
3842 }
3843 if (baudrate > STL_SC26198MAXBAUD)
3844 baudrate = STL_SC26198MAXBAUD;
3845
Jiri Slabyc62429d2006-12-08 02:39:14 -08003846 if (baudrate > 0)
3847 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 if (baudrate <= sc26198_baudtable[clk])
3849 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
3851/*
3852 * Check what form of modem signaling is required and set it up.
3853 */
3854 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003855 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 } else {
3857 iopr |= IOPR_DCDCOS;
3858 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003859 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 }
3861
3862/*
3863 * Setup sc26198 enhanced modes if we can. In particular we want to
3864 * handle as much of the flow control as possible automatically. As
3865 * well as saving a few CPU cycles it will also greatly improve flow
3866 * control reliability.
3867 */
3868 if (tiosp->c_iflag & IXON) {
3869 mr0 |= MR0_SWFTX | MR0_SWFT;
3870 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003871 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003873
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 if (tiosp->c_iflag & IXOFF)
3875 mr0 |= MR0_SWFRX;
3876
3877 if (tiosp->c_cflag & CRTSCTS) {
3878 mr2 |= MR2_AUTOCTS;
3879 mr1 |= MR1_AUTORTS;
3880 }
3881
3882/*
3883 * All sc26198 register values calculated so go through and set
3884 * them all up.
3885 */
3886
Jiri Slabya0564e12006-12-08 02:38:37 -08003887 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003889 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3890 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3891 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3893 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
Alan Coxb65b5b52006-06-27 02:54:05 -07003895 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 BRDENABLE(portp->brdnr, portp->pagenr);
3897 stl_sc26198setreg(portp, IMR, 0);
3898 stl_sc26198updatereg(portp, MR0, mr0);
3899 stl_sc26198updatereg(portp, MR1, mr1);
3900 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3901 stl_sc26198updatereg(portp, MR2, mr2);
3902 stl_sc26198updatereg(portp, IOPIOR,
3903 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3904
3905 if (baudrate > 0) {
3906 stl_sc26198setreg(portp, TXCSR, clk);
3907 stl_sc26198setreg(portp, RXCSR, clk);
3908 }
3909
3910 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3911 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3912
3913 ipr = stl_sc26198getreg(portp, IPR);
3914 if (ipr & IPR_DCD)
3915 portp->sigs &= ~TIOCM_CD;
3916 else
3917 portp->sigs |= TIOCM_CD;
3918
3919 portp->imr = (portp->imr & ~imroff) | imron;
3920 stl_sc26198setreg(portp, IMR, portp->imr);
3921 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003922 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923}
3924
3925/*****************************************************************************/
3926
3927/*
3928 * Set the state of the DTR and RTS signals.
3929 */
3930
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003931static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932{
3933 unsigned char iopioron, iopioroff;
3934 unsigned long flags;
3935
Jiri Slabya0564e12006-12-08 02:38:37 -08003936 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3937 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938
3939 iopioron = 0;
3940 iopioroff = 0;
3941 if (dtr == 0)
3942 iopioroff |= IPR_DTR;
3943 else if (dtr > 0)
3944 iopioron |= IPR_DTR;
3945 if (rts == 0)
3946 iopioroff |= IPR_RTS;
3947 else if (rts > 0)
3948 iopioron |= IPR_RTS;
3949
Alan Coxb65b5b52006-06-27 02:54:05 -07003950 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 BRDENABLE(portp->brdnr, portp->pagenr);
3952 stl_sc26198setreg(portp, IOPIOR,
3953 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3954 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003955 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956}
3957
3958/*****************************************************************************/
3959
3960/*
3961 * Return the state of the signals.
3962 */
3963
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003964static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965{
3966 unsigned char ipr;
3967 unsigned long flags;
3968 int sigs;
3969
Jiri Slabya0564e12006-12-08 02:38:37 -08003970 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
Alan Coxb65b5b52006-06-27 02:54:05 -07003972 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 BRDENABLE(portp->brdnr, portp->pagenr);
3974 ipr = stl_sc26198getreg(portp, IPR);
3975 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003976 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
3978 sigs = 0;
3979 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3980 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3981 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3982 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3983 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003984 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985}
3986
3987/*****************************************************************************/
3988
3989/*
3990 * Enable/Disable the Transmitter and/or Receiver.
3991 */
3992
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003993static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994{
3995 unsigned char ccr;
3996 unsigned long flags;
3997
Jiri Slabya0564e12006-12-08 02:38:37 -08003998 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
4000 ccr = portp->crenable;
4001 if (tx == 0)
4002 ccr &= ~CR_TXENABLE;
4003 else if (tx > 0)
4004 ccr |= CR_TXENABLE;
4005 if (rx == 0)
4006 ccr &= ~CR_RXENABLE;
4007 else if (rx > 0)
4008 ccr |= CR_RXENABLE;
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, SCCR, ccr);
4013 BRDDISABLE(portp->brdnr);
4014 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004015 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016}
4017
4018/*****************************************************************************/
4019
4020/*
4021 * Start/stop the Transmitter and/or Receiver.
4022 */
4023
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004024static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025{
4026 unsigned char imr;
4027 unsigned long flags;
4028
Jiri Slabya0564e12006-12-08 02:38:37 -08004029 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030
4031 imr = portp->imr;
4032 if (tx == 0)
4033 imr &= ~IR_TXRDY;
4034 else if (tx == 1)
4035 imr |= IR_TXRDY;
4036 if (rx == 0)
4037 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4038 else if (rx > 0)
4039 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4040
Alan Coxb65b5b52006-06-27 02:54:05 -07004041 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 BRDENABLE(portp->brdnr, portp->pagenr);
4043 stl_sc26198setreg(portp, IMR, imr);
4044 BRDDISABLE(portp->brdnr);
4045 portp->imr = imr;
4046 if (tx > 0)
4047 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004048 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049}
4050
4051/*****************************************************************************/
4052
4053/*
4054 * Disable all interrupts from this port.
4055 */
4056
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004057static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058{
4059 unsigned long flags;
4060
Jiri Slabya0564e12006-12-08 02:38:37 -08004061 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062
Alan Coxb65b5b52006-06-27 02:54:05 -07004063 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 BRDENABLE(portp->brdnr, portp->pagenr);
4065 portp->imr = 0;
4066 stl_sc26198setreg(portp, IMR, 0);
4067 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004068 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069}
4070
4071/*****************************************************************************/
4072
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004073static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074{
4075 unsigned long flags;
4076
Jiri Slabya0564e12006-12-08 02:38:37 -08004077 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Alan Coxb65b5b52006-06-27 02:54:05 -07004079 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 BRDENABLE(portp->brdnr, portp->pagenr);
4081 if (len == 1) {
4082 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4083 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004084 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004086
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004088 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089}
4090
4091/*****************************************************************************/
4092
4093/*
4094 * Take flow control actions...
4095 */
4096
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004097static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098{
4099 struct tty_struct *tty;
4100 unsigned long flags;
4101 unsigned char mr0;
4102
Jiri Slabya0564e12006-12-08 02:38:37 -08004103 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104
Jiri Slaby615e4a72006-12-08 02:38:38 -08004105 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004107 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004108 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 return;
4110
Alan Coxb65b5b52006-06-27 02:54:05 -07004111 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 BRDENABLE(portp->brdnr, portp->pagenr);
4113
4114 if (state) {
4115 if (tty->termios->c_iflag & IXOFF) {
4116 mr0 = stl_sc26198getreg(portp, MR0);
4117 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4118 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4119 mr0 |= MR0_SWFRX;
4120 portp->stats.rxxon++;
4121 stl_sc26198wait(portp);
4122 stl_sc26198setreg(portp, MR0, mr0);
4123 }
4124/*
4125 * Question: should we return RTS to what it was before? It may
4126 * have been set by an ioctl... Suppose not, since if you have
4127 * hardware flow control set then it is pretty silly to go and
4128 * set the RTS line by hand.
4129 */
4130 if (tty->termios->c_cflag & CRTSCTS) {
4131 stl_sc26198setreg(portp, MR1,
4132 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4133 stl_sc26198setreg(portp, IOPIOR,
4134 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4135 portp->stats.rxrtson++;
4136 }
4137 } else {
4138 if (tty->termios->c_iflag & IXOFF) {
4139 mr0 = stl_sc26198getreg(portp, MR0);
4140 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4141 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4142 mr0 &= ~MR0_SWFRX;
4143 portp->stats.rxxoff++;
4144 stl_sc26198wait(portp);
4145 stl_sc26198setreg(portp, MR0, mr0);
4146 }
4147 if (tty->termios->c_cflag & CRTSCTS) {
4148 stl_sc26198setreg(portp, MR1,
4149 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4150 stl_sc26198setreg(portp, IOPIOR,
4151 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4152 portp->stats.rxrtsoff++;
4153 }
4154 }
4155
4156 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004157 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004158 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159}
4160
4161/*****************************************************************************/
4162
4163/*
4164 * Send a flow control character.
4165 */
4166
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004167static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168{
4169 struct tty_struct *tty;
4170 unsigned long flags;
4171 unsigned char mr0;
4172
Jiri Slabya0564e12006-12-08 02:38:37 -08004173 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174
Jiri Slaby615e4a72006-12-08 02:38:38 -08004175 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004177 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004178 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 return;
4180
Alan Coxb65b5b52006-06-27 02:54:05 -07004181 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 BRDENABLE(portp->brdnr, portp->pagenr);
4183 if (state) {
4184 mr0 = stl_sc26198getreg(portp, MR0);
4185 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4186 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4187 mr0 |= MR0_SWFRX;
4188 portp->stats.rxxon++;
4189 stl_sc26198wait(portp);
4190 stl_sc26198setreg(portp, MR0, mr0);
4191 } else {
4192 mr0 = stl_sc26198getreg(portp, MR0);
4193 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4194 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4195 mr0 &= ~MR0_SWFRX;
4196 portp->stats.rxxoff++;
4197 stl_sc26198wait(portp);
4198 stl_sc26198setreg(portp, MR0, mr0);
4199 }
4200 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004201 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004202 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203}
4204
4205/*****************************************************************************/
4206
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004207static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208{
4209 unsigned long flags;
4210
Jiri Slabya0564e12006-12-08 02:38:37 -08004211 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212
Jiri Slaby615e4a72006-12-08 02:38:38 -08004213 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 return;
4215
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 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4219 stl_sc26198setreg(portp, SCCR, portp->crenable);
4220 BRDDISABLE(portp->brdnr);
4221 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004222 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223}
4224
4225/*****************************************************************************/
4226
4227/*
4228 * Return the current state of data flow on this port. This is only
4229 * really interresting when determining if data has fully completed
4230 * transmission or not... The sc26198 interrupt scheme cannot
4231 * determine when all data has actually drained, so we need to
4232 * check the port statusy register to be sure.
4233 */
4234
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004235static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
4237 unsigned long flags;
4238 unsigned char sr;
4239
Jiri Slabya0564e12006-12-08 02:38:37 -08004240 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Jiri Slaby615e4a72006-12-08 02:38:38 -08004242 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004243 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004245 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246
Alan Coxb65b5b52006-06-27 02:54:05 -07004247 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 BRDENABLE(portp->brdnr, portp->pagenr);
4249 sr = stl_sc26198getreg(portp, SR);
4250 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004251 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
Jesper Juhl014c2542006-01-15 02:37:08 +01004253 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254}
4255
4256/*****************************************************************************/
4257
4258/*
4259 * Delay for a small amount of time, to give the sc26198 a chance
4260 * to process a command...
4261 */
4262
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004263static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264{
4265 int i;
4266
Jiri Slabya0564e12006-12-08 02:38:37 -08004267 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268
Jiri Slaby615e4a72006-12-08 02:38:38 -08004269 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270 return;
4271
Jiri Slabyc62429d2006-12-08 02:39:14 -08004272 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 stl_sc26198getglobreg(portp, TSTR);
4274}
4275
4276/*****************************************************************************/
4277
4278/*
4279 * If we are TX flow controlled and in IXANY mode then we may
4280 * need to unflow control here. We gotta do this because of the
4281 * automatic flow control modes of the sc26198.
4282 */
4283
Jiri Slaby60be4812006-12-08 02:38:40 -08004284static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285{
4286 unsigned char mr0;
4287
4288 mr0 = stl_sc26198getreg(portp, MR0);
4289 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4290 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4291 stl_sc26198wait(portp);
4292 stl_sc26198setreg(portp, MR0, mr0);
4293 clear_bit(ASYI_TXFLOWED, &portp->istate);
4294}
4295
4296/*****************************************************************************/
4297
4298/*
4299 * Interrupt service routine for sc26198 panels.
4300 */
4301
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004302static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004304 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 unsigned int iack;
4306
Alan Coxb65b5b52006-06-27 02:54:05 -07004307 spin_lock(&brd_lock);
4308
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309/*
4310 * Work around bug in sc26198 chip... Cannot have A6 address
4311 * line of UART high, else iack will be returned as 0.
4312 */
4313 outb(0, (iobase + 1));
4314
4315 iack = inb(iobase + XP_IACK);
4316 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4317
4318 if (iack & IVR_RXDATA)
4319 stl_sc26198rxisr(portp, iack);
4320 else if (iack & IVR_TXDATA)
4321 stl_sc26198txisr(portp);
4322 else
4323 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004324
4325 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326}
4327
4328/*****************************************************************************/
4329
4330/*
4331 * Transmit interrupt handler. This has gotta be fast! Handling TX
4332 * chars is pretty simple, stuff as many as possible from the TX buffer
4333 * into the sc26198 FIFO.
4334 * In practice it is possible that interrupts are enabled but that the
4335 * port has been hung up. Need to handle not having any TX buffer here,
4336 * this is done by using the side effect that head and tail will also
4337 * be NULL if the buffer has been freed.
4338 */
4339
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004340static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341{
Alan Coxd18a7502008-10-13 10:40:07 +01004342 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 unsigned int ioaddr;
4344 unsigned char mr0;
4345 int len, stlen;
4346 char *head, *tail;
4347
Jiri Slabya0564e12006-12-08 02:38:37 -08004348 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349
4350 ioaddr = portp->ioaddr;
4351 head = portp->tx.head;
4352 tail = portp->tx.tail;
4353 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4354 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4355 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4356 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004357 tty = tty_port_tty_get(&portp->port);
4358 if (tty) {
4359 tty_wakeup(tty);
4360 tty_kref_put(tty);
4361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362 }
4363
4364 if (len == 0) {
4365 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4366 mr0 = inb(ioaddr + XP_DATA);
4367 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4368 portp->imr &= ~IR_TXRDY;
4369 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4370 outb(portp->imr, (ioaddr + XP_DATA));
4371 clear_bit(ASYI_TXBUSY, &portp->istate);
4372 } else {
4373 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4374 outb(mr0, (ioaddr + XP_DATA));
4375 }
4376 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004377 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004379 stlen = min_t(unsigned int, len,
4380 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381 outb(GTXFIFO, (ioaddr + XP_ADDR));
4382 outsb((ioaddr + XP_DATA), tail, stlen);
4383 len -= stlen;
4384 tail += stlen;
4385 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4386 tail = portp->tx.buf;
4387 if (len > 0) {
4388 outsb((ioaddr + XP_DATA), tail, len);
4389 tail += len;
4390 }
4391 portp->tx.tail = tail;
4392 }
4393}
4394
4395/*****************************************************************************/
4396
4397/*
4398 * Receive character interrupt handler. Determine if we have good chars
4399 * or bad chars and then process appropriately. Good chars are easy
4400 * just shove the lot into the RX buffer and set all status byte to 0.
4401 * If a bad RX char then process as required. This routine needs to be
4402 * fast! In practice it is possible that we get an interrupt on a port
4403 * that is closed. This can happen on hangups - since they completely
4404 * shutdown a port not in user context. Need to handle this case.
4405 */
4406
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004407static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408{
4409 struct tty_struct *tty;
4410 unsigned int len, buflen, ioaddr;
4411
Jiri Slabya0564e12006-12-08 02:38:37 -08004412 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413
Alan Coxd18a7502008-10-13 10:40:07 +01004414 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 ioaddr = portp->ioaddr;
4416 outb(GIBCR, (ioaddr + XP_ADDR));
4417 len = inb(ioaddr + XP_DATA) + 1;
4418
4419 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004420 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004421 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 outb(GRXFIFO, (ioaddr + XP_ADDR));
4423 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4424 portp->stats.rxlost += len;
4425 portp->stats.rxtotal += len;
4426 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004427 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004429 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004431 tty_prepare_flip_string(tty, &ptr, len);
4432 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 tty_schedule_flip(tty);
4434 portp->stats.rxtotal += len;
4435 }
4436 }
4437 } else {
4438 stl_sc26198rxbadchars(portp);
4439 }
4440
4441/*
4442 * If we are TX flow controlled and in IXANY mode then we may need
4443 * to unflow control here. We gotta do this because of the automatic
4444 * flow control modes of the sc26198.
4445 */
4446 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004447 if ((tty != NULL) &&
4448 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449 (tty->termios->c_iflag & IXANY)) {
4450 stl_sc26198txunflow(portp, tty);
4451 }
4452 }
Alan Coxd18a7502008-10-13 10:40:07 +01004453 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454}
4455
4456/*****************************************************************************/
4457
4458/*
4459 * Process an RX bad character.
4460 */
4461
Jiri Slaby60be4812006-12-08 02:38:40 -08004462static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463{
4464 struct tty_struct *tty;
4465 unsigned int ioaddr;
4466
Alan Coxd18a7502008-10-13 10:40:07 +01004467 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468 ioaddr = portp->ioaddr;
4469
4470 if (status & SR_RXPARITY)
4471 portp->stats.rxparity++;
4472 if (status & SR_RXFRAMING)
4473 portp->stats.rxframing++;
4474 if (status & SR_RXOVERRUN)
4475 portp->stats.rxoverrun++;
4476 if (status & SR_RXBREAK)
4477 portp->stats.rxbreaks++;
4478
Jiri Slaby615e4a72006-12-08 02:38:38 -08004479 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480 ((portp->rxignoremsk & status) == 0)) {
4481 if (portp->rxmarkmsk & status) {
4482 if (status & SR_RXBREAK) {
4483 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004484 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 do_SAK(tty);
4486 BRDENABLE(portp->brdnr, portp->pagenr);
4487 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004488 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004490 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004492 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004494 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004496 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498
Alan Cox33f0f882006-01-09 20:54:13 -08004499 tty_insert_flip_char(tty, ch, status);
4500 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501
4502 if (status == 0)
4503 portp->stats.rxtotal++;
4504 }
Alan Coxd18a7502008-10-13 10:40:07 +01004505 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506}
4507
4508/*****************************************************************************/
4509
4510/*
4511 * Process all characters in the RX FIFO of the UART. Check all char
4512 * status bytes as well, and process as required. We need to check
4513 * all bytes in the FIFO, in case some more enter the FIFO while we
4514 * are here. To get the exact character error type we need to switch
4515 * into CHAR error mode (that is why we need to make sure we empty
4516 * the FIFO).
4517 */
4518
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004519static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520{
4521 unsigned char status, mr1;
4522 char ch;
4523
4524/*
4525 * To get the precise error type for each character we must switch
4526 * back into CHAR error mode.
4527 */
4528 mr1 = stl_sc26198getreg(portp, MR1);
4529 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4530
4531 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4532 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4533 ch = stl_sc26198getreg(portp, RXFIFO);
4534 stl_sc26198rxbadch(portp, status, ch);
4535 }
4536
4537/*
4538 * To get correct interrupt class we must switch back into BLOCK
4539 * error mode.
4540 */
4541 stl_sc26198setreg(portp, MR1, mr1);
4542}
4543
4544/*****************************************************************************/
4545
4546/*
4547 * Other interrupt handler. This includes modem signals, flow
4548 * control actions, etc. Most stuff is left to off-level interrupt
4549 * processing time.
4550 */
4551
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004552static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553{
4554 unsigned char cir, ipr, xisr;
4555
Jiri Slabya0564e12006-12-08 02:38:37 -08004556 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557
4558 cir = stl_sc26198getglobreg(portp, CIR);
4559
4560 switch (cir & CIR_SUBTYPEMASK) {
4561 case CIR_SUBCOS:
4562 ipr = stl_sc26198getreg(portp, IPR);
4563 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004564 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565 portp->stats.modem++;
4566 }
4567 break;
4568 case CIR_SUBXONXOFF:
4569 xisr = stl_sc26198getreg(portp, XISR);
4570 if (xisr & XISR_RXXONGOT) {
4571 set_bit(ASYI_TXFLOWED, &portp->istate);
4572 portp->stats.txxoff++;
4573 }
4574 if (xisr & XISR_RXXOFFGOT) {
4575 clear_bit(ASYI_TXFLOWED, &portp->istate);
4576 portp->stats.txxon++;
4577 }
4578 break;
4579 case CIR_SUBBREAK:
4580 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4581 stl_sc26198rxbadchars(portp);
4582 break;
4583 default:
4584 break;
4585 }
4586}
4587
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004588static void stl_free_isabrds(void)
4589{
4590 struct stlbrd *brdp;
4591 unsigned int i;
4592
4593 for (i = 0; i < stl_nrbrds; i++) {
4594 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4595 continue;
4596
4597 free_irq(brdp->irq, brdp);
4598
4599 stl_cleanup_panels(brdp);
4600
4601 release_region(brdp->ioaddr1, brdp->iosize1);
4602 if (brdp->iosize2 > 0)
4603 release_region(brdp->ioaddr2, brdp->iosize2);
4604
4605 kfree(brdp);
4606 stl_brds[i] = NULL;
4607 }
4608}
4609
Jiri Slaby23b85a12006-12-08 02:38:40 -08004610/*
4611 * Loadable module initialization stuff.
4612 */
4613static int __init stallion_module_init(void)
4614{
Jiri Slaby843b5682006-12-08 02:39:12 -08004615 struct stlbrd *brdp;
4616 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004617 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004618 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004619
4620 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4621
4622 spin_lock_init(&stallion_lock);
4623 spin_lock_init(&brd_lock);
4624
Jiri Slabye4151092007-06-08 13:46:52 -07004625 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4626 if (!stl_serial) {
4627 retval = -ENOMEM;
4628 goto err;
4629 }
4630
4631 stl_serial->owner = THIS_MODULE;
4632 stl_serial->driver_name = stl_drvname;
4633 stl_serial->name = "ttyE";
4634 stl_serial->major = STL_SERIALMAJOR;
4635 stl_serial->minor_start = 0;
4636 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4637 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4638 stl_serial->init_termios = stl_deftermios;
4639 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4640 tty_set_operations(stl_serial, &stl_ops);
4641
4642 retval = tty_register_driver(stl_serial);
4643 if (retval) {
4644 printk("STALLION: failed to register serial driver\n");
4645 goto err_frtty;
4646 }
4647
Jiri Slaby843b5682006-12-08 02:39:12 -08004648/*
4649 * Find any dynamically supported boards. That is via module load
4650 * line options.
4651 */
4652 for (i = stl_nrbrds; i < stl_nargs; i++) {
4653 memset(&conf, 0, sizeof(conf));
4654 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4655 continue;
4656 if ((brdp = stl_allocbrd()) == NULL)
4657 continue;
4658 brdp->brdnr = i;
4659 brdp->brdtype = conf.brdtype;
4660 brdp->ioaddr1 = conf.ioaddr1;
4661 brdp->ioaddr2 = conf.ioaddr2;
4662 brdp->irq = conf.irq;
4663 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004664 stl_brds[brdp->brdnr] = brdp;
4665 if (stl_brdinit(brdp)) {
4666 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004667 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004668 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004669 for (j = 0; j < brdp->nrports; j++)
4670 tty_register_device(stl_serial,
4671 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004672 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004673 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004674 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004675
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004676 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004677 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004678 if (retval && stl_nrbrds == 0) {
4679 printk(KERN_ERR "STALLION: can't register pci driver\n");
4680 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004681 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004682
4683/*
4684 * Set up a character driver for per board stuff. This is mainly used
4685 * to do stats ioctls on the ports.
4686 */
4687 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4688 printk("STALLION: failed to register serial board device\n");
4689
4690 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004691 if (IS_ERR(stallion_class))
4692 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004693 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004694 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4695 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004696
Jiri Slaby23b85a12006-12-08 02:38:40 -08004697 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004698err_unrtty:
4699 tty_unregister_driver(stl_serial);
4700err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004701 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004702err:
4703 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004704}
4705
4706static void __exit stallion_module_exit(void)
4707{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004708 struct stlbrd *brdp;
4709 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004710
4711 pr_debug("cleanup_module()\n");
4712
4713 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4714 stl_drvversion);
4715
4716/*
4717 * Free up all allocated resources used by the ports. This includes
4718 * memory and interrupts. As part of this process we will also do
4719 * a hangup on every open port - to try to flush out any processes
4720 * hanging onto ports.
4721 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004722 for (i = 0; i < stl_nrbrds; i++) {
4723 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4724 continue;
4725 for (j = 0; j < brdp->nrports; j++)
4726 tty_unregister_device(stl_serial,
4727 brdp->brdnr * STL_MAXPORTS + j);
4728 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004729
Jiri Slaby23b85a12006-12-08 02:38:40 -08004730 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004731 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004732 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004733 class_destroy(stallion_class);
4734
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004735 pci_unregister_driver(&stl_pcidriver);
4736
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004737 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004738
4739 tty_unregister_driver(stl_serial);
4740 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004741}
4742
4743module_init(stallion_module_init);
4744module_exit(stallion_module_exit);
4745
4746MODULE_AUTHOR("Greg Ungerer");
4747MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4748MODULE_LICENSE("GPL");