blob: 2db2e9fbb5c6476296a9ed3fb8bb67d8416be7ea [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 {
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 int brdtype;
67 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/*
124 * Define global stats structures. Not used often, and can be
125 * re-used for each stats call.
126 */
127static comstats_t stl_comstats;
128static combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800129static struct stlbrd stl_dummybrd;
130static struct stlport stl_dummyport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
132/*
133 * Define global place to put buffer overflow characters.
134 */
135static char stl_unwanted[SC26198_RXFIFOSIZE];
136
137/*****************************************************************************/
138
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800139static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800140static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
142/*
143 * Per board state flags. Used with the state field of the board struct.
144 * Not really much here!
145 */
146#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800147#define STL_PROBED 0x2
148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150/*
151 * Define the port structure istate flags. These set of flags are
152 * modified at interrupt time - so setting and reseting them needs
153 * to be atomic. Use the bit clear/setting routines for this.
154 */
155#define ASYI_TXBUSY 1
156#define ASYI_TXLOW 2
157#define ASYI_DCDCHANGE 3
158#define ASYI_TXFLOWED 4
159
160/*
161 * Define an array of board names as printable strings. Handy for
162 * referencing boards when printing trace and stuff.
163 */
164static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
176 NULL,
177 NULL,
178 NULL,
179 NULL,
180 NULL,
181 NULL,
182 NULL,
183 NULL,
184 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 "EasyIO",
186 "EC8/32-AT",
187 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800188 NULL,
189 NULL,
190 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 "EC8/32-PCI",
192 "EC8/64-PCI",
193 "EasyIO-PCI",
194};
195
196/*****************************************************************************/
197
198/*
199 * Define some string labels for arguments passed from the module
200 * load line. These allow for easy board definitions, and easy
201 * modification of the io, memory and irq resoucres.
202 */
203static int stl_nargs = 0;
204static char *board0[4];
205static char *board1[4];
206static char *board2[4];
207static char *board3[4];
208
209static char **stl_brdsp[] = {
210 (char **) &board0,
211 (char **) &board1,
212 (char **) &board2,
213 (char **) &board3
214};
215
216/*
217 * Define a set of common board names, and types. This is used to
218 * parse any module arguments.
219 */
220
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800221static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 char *name;
223 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800224} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 { "easyio", BRD_EASYIO },
226 { "eio", BRD_EASYIO },
227 { "20", BRD_EASYIO },
228 { "ec8/32", BRD_ECH },
229 { "ec8/32-at", BRD_ECH },
230 { "ec8/32-isa", BRD_ECH },
231 { "ech", BRD_ECH },
232 { "echat", BRD_ECH },
233 { "21", BRD_ECH },
234 { "ec8/32-mc", BRD_ECHMC },
235 { "ec8/32-mca", BRD_ECHMC },
236 { "echmc", BRD_ECHMC },
237 { "echmca", BRD_ECHMC },
238 { "22", BRD_ECHMC },
239 { "ec8/32-pc", BRD_ECHPCI },
240 { "ec8/32-pci", BRD_ECHPCI },
241 { "26", BRD_ECHPCI },
242 { "ec8/64-pc", BRD_ECH64PCI },
243 { "ec8/64-pci", BRD_ECH64PCI },
244 { "ech-pci", BRD_ECH64PCI },
245 { "echpci", BRD_ECH64PCI },
246 { "echpc", BRD_ECH64PCI },
247 { "27", BRD_ECH64PCI },
248 { "easyio-pc", BRD_EASYIOPCI },
249 { "easyio-pci", BRD_EASYIOPCI },
250 { "eio-pci", BRD_EASYIOPCI },
251 { "eiopci", BRD_EASYIOPCI },
252 { "28", BRD_EASYIOPCI },
253};
254
255/*
256 * Define the module agruments.
257 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259module_param_array(board0, charp, &stl_nargs, 0);
260MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
261module_param_array(board1, charp, &stl_nargs, 0);
262MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
263module_param_array(board2, charp, &stl_nargs, 0);
264MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
265module_param_array(board3, charp, &stl_nargs, 0);
266MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
267
268/*****************************************************************************/
269
270/*
271 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
272 * to the directly accessible io ports of these boards (not the uarts -
273 * they are in cd1400.h and sc26198.h).
274 */
275#define EIO_8PORTRS 0x04
276#define EIO_4PORTRS 0x05
277#define EIO_8PORTDI 0x00
278#define EIO_8PORTM 0x06
279#define EIO_MK3 0x03
280#define EIO_IDBITMASK 0x07
281
282#define EIO_BRDMASK 0xf0
283#define ID_BRD4 0x10
284#define ID_BRD8 0x20
285#define ID_BRD16 0x30
286
287#define EIO_INTRPEND 0x08
288#define EIO_INTEDGE 0x00
289#define EIO_INTLEVEL 0x08
290#define EIO_0WS 0x10
291
292#define ECH_ID 0xa0
293#define ECH_IDBITMASK 0xe0
294#define ECH_BRDENABLE 0x08
295#define ECH_BRDDISABLE 0x00
296#define ECH_INTENABLE 0x01
297#define ECH_INTDISABLE 0x00
298#define ECH_INTLEVEL 0x02
299#define ECH_INTEDGE 0x00
300#define ECH_INTRPEND 0x01
301#define ECH_BRDRESET 0x01
302
303#define ECHMC_INTENABLE 0x01
304#define ECHMC_BRDRESET 0x02
305
306#define ECH_PNLSTATUS 2
307#define ECH_PNL16PORT 0x20
308#define ECH_PNLIDMASK 0x07
309#define ECH_PNLXPID 0x40
310#define ECH_PNLINTRPEND 0x80
311
312#define ECH_ADDR2MASK 0x1e0
313
314/*
315 * Define the vector mapping bits for the programmable interrupt board
316 * hardware. These bits encode the interrupt for the board to use - it
317 * is software selectable (except the EIO-8M).
318 */
319static unsigned char stl_vecmap[] = {
320 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
321 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
322};
323
324/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700325 * Lock ordering is that you may not take stallion_lock holding
326 * brd_lock.
327 */
328
329static spinlock_t brd_lock; /* Guard the board mapping */
330static spinlock_t stallion_lock; /* Guard the tty driver */
331
332/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 * Set up enable and disable macros for the ECH boards. They require
334 * the secondary io address space to be activated and deactivated.
335 * This way all ECH boards can share their secondary io region.
336 * If this is an ECH-PCI board then also need to set the page pointer
337 * to point to the correct page.
338 */
339#define BRDENABLE(brdnr,pagenr) \
340 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
341 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
342 stl_brds[(brdnr)]->ioctrl); \
343 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
344 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
345
346#define BRDDISABLE(brdnr) \
347 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
348 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
349 stl_brds[(brdnr)]->ioctrl);
350
351#define STL_CD1400MAXBAUD 230400
352#define STL_SC26198MAXBAUD 460800
353
354#define STL_BAUDBASE 115200
355#define STL_CLOSEDELAY (5 * HZ / 10)
356
357/*****************************************************************************/
358
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359/*
360 * Define the Stallion PCI vendor and device IDs.
361 */
362#ifndef PCI_VENDOR_ID_STALLION
363#define PCI_VENDOR_ID_STALLION 0x124d
364#endif
365#ifndef PCI_DEVICE_ID_ECHPCI832
366#define PCI_DEVICE_ID_ECHPCI832 0x0000
367#endif
368#ifndef PCI_DEVICE_ID_ECHPCI864
369#define PCI_DEVICE_ID_ECHPCI864 0x0002
370#endif
371#ifndef PCI_DEVICE_ID_EIOPCI
372#define PCI_DEVICE_ID_EIOPCI 0x0003
373#endif
374
375/*
376 * Define structure to hold all Stallion PCI boards.
377 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800379static struct pci_device_id stl_pcibrds[] = {
380 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
381 .driver_data = BRD_ECH64PCI },
382 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
383 .driver_data = BRD_EASYIOPCI },
384 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
385 .driver_data = BRD_ECHPCI },
386 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
387 .driver_data = BRD_ECHPCI },
388 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800390MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
392/*****************************************************************************/
393
394/*
395 * Define macros to extract a brd/port number from a minor number.
396 */
397#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
398#define MINOR2PORT(min) ((min) & 0x3f)
399
400/*
401 * Define a baud rate table that converts termios baud rate selector
402 * into the actual baud rate value. All baud rate calculations are
403 * based on the actual baud rate required.
404 */
405static unsigned int stl_baudrates[] = {
406 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
407 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
408};
409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410/*****************************************************************************/
411
412/*
413 * Declare all those functions in this driver!
414 */
415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800417static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800418static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
419static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800420static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422/*
423 * CD1400 uart specific handling functions.
424 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800425static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
426static int stl_cd1400getreg(struct stlport *portp, int regnr);
427static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
428static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
429static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800430static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800431static int stl_cd1400getsignals(struct stlport *portp);
432static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
433static void stl_cd1400ccrwait(struct stlport *portp);
434static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
435static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
436static void stl_cd1400disableintrs(struct stlport *portp);
437static void stl_cd1400sendbreak(struct stlport *portp, int len);
438static void stl_cd1400flowctrl(struct stlport *portp, int state);
439static void stl_cd1400sendflow(struct stlport *portp, int state);
440static void stl_cd1400flush(struct stlport *portp);
441static int stl_cd1400datastate(struct stlport *portp);
442static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
443static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
444static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
445static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
446static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800448static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
450/*
451 * SC26198 uart specific handling functions.
452 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800453static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
454static int stl_sc26198getreg(struct stlport *portp, int regnr);
455static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
456static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
457static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
458static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800459static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800460static int stl_sc26198getsignals(struct stlport *portp);
461static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
462static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
463static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
464static void stl_sc26198disableintrs(struct stlport *portp);
465static void stl_sc26198sendbreak(struct stlport *portp, int len);
466static void stl_sc26198flowctrl(struct stlport *portp, int state);
467static void stl_sc26198sendflow(struct stlport *portp, int state);
468static void stl_sc26198flush(struct stlport *portp);
469static int stl_sc26198datastate(struct stlport *portp);
470static void stl_sc26198wait(struct stlport *portp);
471static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
472static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
473static void stl_sc26198txisr(struct stlport *port);
474static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
475static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
476static void stl_sc26198rxbadchars(struct stlport *portp);
477static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479/*****************************************************************************/
480
481/*
482 * Generic UART support structure.
483 */
484typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800485 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
486 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800487 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800488 int (*getsignals)(struct stlport *portp);
489 void (*setsignals)(struct stlport *portp, int dtr, int rts);
490 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
491 void (*startrxtx)(struct stlport *portp, int rx, int tx);
492 void (*disableintrs)(struct stlport *portp);
493 void (*sendbreak)(struct stlport *portp, int len);
494 void (*flowctrl)(struct stlport *portp, int state);
495 void (*sendflow)(struct stlport *portp, int state);
496 void (*flush)(struct stlport *portp);
497 int (*datastate)(struct stlport *portp);
498 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499} uart_t;
500
501/*
502 * Define some macros to make calling these functions nice and clean.
503 */
504#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
505#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
506#define stl_setport (* ((uart_t *) portp->uartp)->setport)
507#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
508#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
509#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
510#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
511#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
512#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
513#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
514#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
515#define stl_flush (* ((uart_t *) portp->uartp)->flush)
516#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
517
518/*****************************************************************************/
519
520/*
521 * CD1400 UART specific data initialization.
522 */
523static uart_t stl_cd1400uart = {
524 stl_cd1400panelinit,
525 stl_cd1400portinit,
526 stl_cd1400setport,
527 stl_cd1400getsignals,
528 stl_cd1400setsignals,
529 stl_cd1400enablerxtx,
530 stl_cd1400startrxtx,
531 stl_cd1400disableintrs,
532 stl_cd1400sendbreak,
533 stl_cd1400flowctrl,
534 stl_cd1400sendflow,
535 stl_cd1400flush,
536 stl_cd1400datastate,
537 stl_cd1400eiointr
538};
539
540/*
541 * Define the offsets within the register bank of a cd1400 based panel.
542 * These io address offsets are common to the EasyIO board as well.
543 */
544#define EREG_ADDR 0
545#define EREG_DATA 4
546#define EREG_RXACK 5
547#define EREG_TXACK 6
548#define EREG_MDACK 7
549
550#define EREG_BANKSIZE 8
551
552#define CD1400_CLK 25000000
553#define CD1400_CLK8M 20000000
554
555/*
556 * Define the cd1400 baud rate clocks. These are used when calculating
557 * what clock and divisor to use for the required baud rate. Also
558 * define the maximum baud rate allowed, and the default base baud.
559 */
560static int stl_cd1400clkdivs[] = {
561 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
562};
563
564/*****************************************************************************/
565
566/*
567 * SC26198 UART specific data initization.
568 */
569static uart_t stl_sc26198uart = {
570 stl_sc26198panelinit,
571 stl_sc26198portinit,
572 stl_sc26198setport,
573 stl_sc26198getsignals,
574 stl_sc26198setsignals,
575 stl_sc26198enablerxtx,
576 stl_sc26198startrxtx,
577 stl_sc26198disableintrs,
578 stl_sc26198sendbreak,
579 stl_sc26198flowctrl,
580 stl_sc26198sendflow,
581 stl_sc26198flush,
582 stl_sc26198datastate,
583 stl_sc26198intr
584};
585
586/*
587 * Define the offsets within the register bank of a sc26198 based panel.
588 */
589#define XP_DATA 0
590#define XP_ADDR 1
591#define XP_MODID 2
592#define XP_STATUS 2
593#define XP_IACK 3
594
595#define XP_BANKSIZE 4
596
597/*
598 * Define the sc26198 baud rate table. Offsets within the table
599 * represent the actual baud rate selector of sc26198 registers.
600 */
601static unsigned int sc26198_baudtable[] = {
602 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
603 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
604 230400, 460800, 921600
605};
606
Tobias Klauserfe971072006-01-09 20:54:02 -0800607#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
609/*****************************************************************************/
610
611/*
612 * Define the driver info for a user level control device. Used mainly
613 * to get at port stats - only not using the port device itself.
614 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700615static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 .owner = THIS_MODULE,
617 .ioctl = stl_memioctl,
618};
619
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800620static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 * Check for any arguments passed in on the module load command line.
624 */
625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626/*****************************************************************************/
627
628/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 * Parse the supplied argument string, into the board conf struct.
630 */
631
Jiri Slaby40e82652006-12-08 02:38:41 -0800632static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
634 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800635 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Jiri Slabya0564e12006-12-08 02:38:37 -0800637 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Jiri Slaby615e4a72006-12-08 02:38:38 -0800639 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100640 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
Jiri Slabyc62429d2006-12-08 02:39:14 -0800642 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800643 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Jiri Slabyc62429d2006-12-08 02:39:14 -0800645 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
647 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800648
Tobias Klauserfe971072006-01-09 20:54:02 -0800649 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800651 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 }
653
654 confp->brdtype = stl_brdstr[i].type;
655
656 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800657 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800658 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 i++;
660 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800661 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800662 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 i++;
664 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800665 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800666 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100667 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668}
669
670/*****************************************************************************/
671
672/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 * Allocate a new board structure. Fill out the basic info in it.
674 */
675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800676static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800678 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800680 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800681 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700682 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800683 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800684 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100688 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689}
690
691/*****************************************************************************/
692
693static int stl_open(struct tty_struct *tty, struct file *filp)
694{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800695 struct stlport *portp;
696 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 unsigned int minordev;
698 int brdnr, panelnr, portnr, rc;
699
Jiri Slabya0564e12006-12-08 02:38:37 -0800700 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
702 minordev = tty->index;
703 brdnr = MINOR2BRD(minordev);
704 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100705 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800707 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100708 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800710 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800711 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 break;
713 if (minordev < brdp->panels[panelnr]->nrports) {
714 portnr = minordev;
715 break;
716 }
717 minordev -= brdp->panels[panelnr]->nrports;
718 }
719 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100720 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
722 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800723 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100724 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726/*
727 * On the first open of the device setup the port hardware, and
728 * initialize the per port data structure.
729 */
730 portp->tty = tty;
731 tty->driver_data = portp;
732 portp->refcount++;
733
734 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800735 if (!portp->tx.buf) {
736 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
737 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100738 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 portp->tx.head = portp->tx.buf;
740 portp->tx.tail = portp->tx.buf;
741 }
742 stl_setport(portp, tty->termios);
743 portp->sigs = stl_getsignals(portp);
744 stl_setsignals(portp, 1, 1);
745 stl_enablerxtx(portp, 1, 1);
746 stl_startrxtx(portp, 1, 0);
747 clear_bit(TTY_IO_ERROR, &tty->flags);
748 portp->flags |= ASYNC_INITIALIZED;
749 }
750
751/*
752 * Check if this port is in the middle of closing. If so then wait
753 * until it is closed then return error status, based on flag settings.
754 * The sleep here does not need interrupt protection since the wakeup
755 * for it is done with the same context.
756 */
757 if (portp->flags & ASYNC_CLOSING) {
758 interruptible_sleep_on(&portp->close_wait);
759 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100760 return -EAGAIN;
761 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 }
763
764/*
765 * Based on type of open being done check if it can overlap with any
766 * previous opens still in effect. If we are a normal serial device
767 * then also we might have to wait for carrier.
768 */
Jiri Slabyc62429d2006-12-08 02:39:14 -0800769 if (!(filp->f_flags & O_NONBLOCK))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100771 return rc;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800772
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 portp->flags |= ASYNC_NORMAL_ACTIVE;
774
Jesper Juhl014c2542006-01-15 02:37:08 +0100775 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776}
777
778/*****************************************************************************/
779
780/*
781 * Possibly need to wait for carrier (DCD signal) to come high. Say
782 * maybe because if we are clocal then we don't need to wait...
783 */
784
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800785static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
787 unsigned long flags;
788 int rc, doclocal;
789
Jiri Slabya0564e12006-12-08 02:38:37 -0800790 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 rc = 0;
793 doclocal = 0;
794
Alan Coxb65b5b52006-06-27 02:54:05 -0700795 spin_lock_irqsave(&stallion_lock, flags);
796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 if (portp->tty->termios->c_cflag & CLOCAL)
798 doclocal++;
799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 portp->openwaitcnt++;
801 if (! tty_hung_up_p(filp))
802 portp->refcount--;
803
804 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700805 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 stl_setsignals(portp, 1, 1);
807 if (tty_hung_up_p(filp) ||
808 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
809 if (portp->flags & ASYNC_HUP_NOTIFY)
810 rc = -EBUSY;
811 else
812 rc = -ERESTARTSYS;
813 break;
814 }
815 if (((portp->flags & ASYNC_CLOSING) == 0) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -0800816 (doclocal || (portp->sigs & TIOCM_CD)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 if (signal_pending(current)) {
819 rc = -ERESTARTSYS;
820 break;
821 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700822 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 interruptible_sleep_on(&portp->open_wait);
824 }
825
826 if (! tty_hung_up_p(filp))
827 portp->refcount++;
828 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700829 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
Jesper Juhl014c2542006-01-15 02:37:08 +0100831 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832}
833
834/*****************************************************************************/
835
Jiri Slaby96b066b2006-12-08 02:38:42 -0800836static void stl_flushbuffer(struct tty_struct *tty)
837{
838 struct stlport *portp;
839
840 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
841
842 if (tty == NULL)
843 return;
844 portp = tty->driver_data;
845 if (portp == NULL)
846 return;
847
848 stl_flush(portp);
849 tty_wakeup(tty);
850}
851
852/*****************************************************************************/
853
854static void stl_waituntilsent(struct tty_struct *tty, int timeout)
855{
856 struct stlport *portp;
857 unsigned long tend;
858
859 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
860
861 if (tty == NULL)
862 return;
863 portp = tty->driver_data;
864 if (portp == NULL)
865 return;
866
867 if (timeout == 0)
868 timeout = HZ;
869 tend = jiffies + timeout;
870
871 while (stl_datastate(portp)) {
872 if (signal_pending(current))
873 break;
874 msleep_interruptible(20);
875 if (time_after_eq(jiffies, tend))
876 break;
877 }
878}
879
880/*****************************************************************************/
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882static void stl_close(struct tty_struct *tty, struct file *filp)
883{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800884 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 unsigned long flags;
886
Jiri Slabya0564e12006-12-08 02:38:37 -0800887 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
889 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800890 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 return;
892
Alan Coxb65b5b52006-06-27 02:54:05 -0700893 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700895 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 return;
897 }
898 if ((tty->count == 1) && (portp->refcount != 1))
899 portp->refcount = 1;
900 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700901 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 return;
903 }
904
905 portp->refcount = 0;
906 portp->flags |= ASYNC_CLOSING;
907
908/*
909 * May want to wait for any data to drain before closing. The BUSY
910 * flag keeps track of whether we are still sending or not - it is
911 * very accurate for the cd1400, not quite so for the sc26198.
912 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
913 */
914 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700915
916 spin_unlock_irqrestore(&stallion_lock, flags);
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
919 tty_wait_until_sent(tty, portp->closing_wait);
920 stl_waituntilsent(tty, (HZ / 2));
921
Alan Coxb65b5b52006-06-27 02:54:05 -0700922
923 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700925 spin_unlock_irqrestore(&stallion_lock, flags);
926
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 stl_disableintrs(portp);
928 if (tty->termios->c_cflag & HUPCL)
929 stl_setsignals(portp, 0, 0);
930 stl_enablerxtx(portp, 0, 0);
931 stl_flushbuffer(tty);
932 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800933 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800935 portp->tx.buf = NULL;
936 portp->tx.head = NULL;
937 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
939 set_bit(TTY_IO_ERROR, &tty->flags);
940 tty_ldisc_flush(tty);
941
942 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800943 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
945 if (portp->openwaitcnt) {
946 if (portp->close_delay)
947 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
948 wake_up_interruptible(&portp->open_wait);
949 }
950
951 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
952 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953}
954
955/*****************************************************************************/
956
957/*
958 * Write routine. Take data and stuff it in to the TX ring queue.
959 * If transmit interrupts are not running then start them.
960 */
961
962static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
963{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800964 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 unsigned int len, stlen;
966 unsigned char *chbuf;
967 char *head, *tail;
968
Jiri Slabya0564e12006-12-08 02:38:37 -0800969 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800972 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100973 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800974 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100975 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976
977/*
978 * If copying direct from user space we must cater for page faults,
979 * causing us to "sleep" here for a while. To handle this copy in all
980 * the data we need now, into a local buffer. Then when we got it all
981 * copy it into the TX buffer.
982 */
983 chbuf = (unsigned char *) buf;
984
985 head = portp->tx.head;
986 tail = portp->tx.tail;
987 if (head >= tail) {
988 len = STL_TXBUFSIZE - (head - tail) - 1;
989 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
990 } else {
991 len = tail - head - 1;
992 stlen = len;
993 }
994
Jiri Slaby843b5682006-12-08 02:39:12 -0800995 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 count = 0;
997 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800998 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 memcpy(head, chbuf, stlen);
1000 len -= stlen;
1001 chbuf += stlen;
1002 count += stlen;
1003 head += stlen;
1004 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1005 head = portp->tx.buf;
1006 stlen = tail - head;
1007 }
1008 }
1009 portp->tx.head = head;
1010
1011 clear_bit(ASYI_TXLOW, &portp->istate);
1012 stl_startrxtx(portp, -1, 1);
1013
Jesper Juhl014c2542006-01-15 02:37:08 +01001014 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015}
1016
1017/*****************************************************************************/
1018
1019static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1020{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001021 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 unsigned int len;
1023 char *head, *tail;
1024
Jiri Slabya0564e12006-12-08 02:38:37 -08001025 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Jiri Slaby615e4a72006-12-08 02:38:38 -08001027 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 return;
1029 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001030 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001032 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 return;
1034
1035 head = portp->tx.head;
1036 tail = portp->tx.tail;
1037
1038 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1039 len--;
1040
1041 if (len > 0) {
1042 *head++ = ch;
1043 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1044 head = portp->tx.buf;
1045 }
1046 portp->tx.head = head;
1047}
1048
1049/*****************************************************************************/
1050
1051/*
1052 * If there are any characters in the buffer then make sure that TX
1053 * interrupts are on and get'em out. Normally used after the putchar
1054 * routine has been called.
1055 */
1056
1057static void stl_flushchars(struct tty_struct *tty)
1058{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001059 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Jiri Slabya0564e12006-12-08 02:38:37 -08001061 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Jiri Slaby615e4a72006-12-08 02:38:38 -08001063 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 return;
1065 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001066 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001068 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 return;
1070
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 stl_startrxtx(portp, -1, 1);
1072}
1073
1074/*****************************************************************************/
1075
1076static int stl_writeroom(struct tty_struct *tty)
1077{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001078 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 char *head, *tail;
1080
Jiri Slabya0564e12006-12-08 02:38:37 -08001081 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Jiri Slaby615e4a72006-12-08 02:38:38 -08001083 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001084 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001086 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001087 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001088 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001089 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
1091 head = portp->tx.head;
1092 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001093 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094}
1095
1096/*****************************************************************************/
1097
1098/*
1099 * Return number of chars in the TX buffer. Normally we would just
1100 * calculate the number of chars in the buffer and return that, but if
1101 * the buffer is empty and TX interrupts are still on then we return
1102 * that the buffer still has 1 char in it. This way whoever called us
1103 * will not think that ALL chars have drained - since the UART still
1104 * must have some chars in it (we are busy after all).
1105 */
1106
1107static int stl_charsinbuffer(struct tty_struct *tty)
1108{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001109 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 unsigned int size;
1111 char *head, *tail;
1112
Jiri Slabya0564e12006-12-08 02:38:37 -08001113 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
Jiri Slaby615e4a72006-12-08 02:38:38 -08001115 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001116 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001118 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001119 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001120 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001121 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
1123 head = portp->tx.head;
1124 tail = portp->tx.tail;
1125 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1126 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1127 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001128 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129}
1130
1131/*****************************************************************************/
1132
1133/*
1134 * Generate the serial struct info.
1135 */
1136
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001137static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138{
1139 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001140 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Jiri Slabya0564e12006-12-08 02:38:37 -08001142 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
1144 memset(&sio, 0, sizeof(struct serial_struct));
1145 sio.line = portp->portnr;
1146 sio.port = portp->ioaddr;
1147 sio.flags = portp->flags;
1148 sio.baud_base = portp->baud_base;
1149 sio.close_delay = portp->close_delay;
1150 sio.closing_wait = portp->closing_wait;
1151 sio.custom_divisor = portp->custom_divisor;
1152 sio.hub6 = 0;
1153 if (portp->uartp == &stl_cd1400uart) {
1154 sio.type = PORT_CIRRUS;
1155 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1156 } else {
1157 sio.type = PORT_UNKNOWN;
1158 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1159 }
1160
1161 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001162 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 sio.irq = brdp->irq;
1164
1165 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1166}
1167
1168/*****************************************************************************/
1169
1170/*
1171 * Set port according to the serial struct info.
1172 * At this point we do not do any auto-configure stuff, so we will
1173 * just quietly ignore any requests to change irq, etc.
1174 */
1175
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001176static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177{
1178 struct serial_struct sio;
1179
Jiri Slabya0564e12006-12-08 02:38:37 -08001180 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1183 return -EFAULT;
1184 if (!capable(CAP_SYS_ADMIN)) {
1185 if ((sio.baud_base != portp->baud_base) ||
1186 (sio.close_delay != portp->close_delay) ||
1187 ((sio.flags & ~ASYNC_USR_MASK) !=
1188 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001189 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 }
1191
1192 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1193 (sio.flags & ASYNC_USR_MASK);
1194 portp->baud_base = sio.baud_base;
1195 portp->close_delay = sio.close_delay;
1196 portp->closing_wait = sio.closing_wait;
1197 portp->custom_divisor = sio.custom_divisor;
1198 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001199 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200}
1201
1202/*****************************************************************************/
1203
1204static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1205{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001206 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Jiri Slaby615e4a72006-12-08 02:38:38 -08001208 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001209 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001211 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001212 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001214 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 return stl_getsignals(portp);
1217}
1218
1219static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1220 unsigned int set, unsigned int clear)
1221{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001222 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 int rts = -1, dtr = -1;
1224
Jiri Slaby615e4a72006-12-08 02:38:38 -08001225 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001226 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001228 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001229 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001231 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
1233 if (set & TIOCM_RTS)
1234 rts = 1;
1235 if (set & TIOCM_DTR)
1236 dtr = 1;
1237 if (clear & TIOCM_RTS)
1238 rts = 0;
1239 if (clear & TIOCM_DTR)
1240 dtr = 0;
1241
1242 stl_setsignals(portp, dtr, rts);
1243 return 0;
1244}
1245
1246static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1247{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001248 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 unsigned int ival;
1250 int rc;
1251 void __user *argp = (void __user *)arg;
1252
Jiri Slabya0564e12006-12-08 02:38:37 -08001253 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1254 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Jiri Slaby615e4a72006-12-08 02:38:38 -08001256 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001257 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001259 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001260 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001263 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001265 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
1267 rc = 0;
1268
1269 switch (cmd) {
1270 case TIOCGSOFTCAR:
1271 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1272 (unsigned __user *) argp);
1273 break;
1274 case TIOCSSOFTCAR:
1275 if (get_user(ival, (unsigned int __user *) arg))
1276 return -EFAULT;
1277 tty->termios->c_cflag =
1278 (tty->termios->c_cflag & ~CLOCAL) |
1279 (ival ? CLOCAL : 0);
1280 break;
1281 case TIOCGSERIAL:
1282 rc = stl_getserial(portp, argp);
1283 break;
1284 case TIOCSSERIAL:
1285 rc = stl_setserial(portp, argp);
1286 break;
1287 case COM_GETPORTSTATS:
1288 rc = stl_getportstats(portp, argp);
1289 break;
1290 case COM_CLRPORTSTATS:
1291 rc = stl_clrportstats(portp, argp);
1292 break;
1293 case TIOCSERCONFIG:
1294 case TIOCSERGWILD:
1295 case TIOCSERSWILD:
1296 case TIOCSERGETLSR:
1297 case TIOCSERGSTRUCT:
1298 case TIOCSERGETMULTI:
1299 case TIOCSERSETMULTI:
1300 default:
1301 rc = -ENOIOCTLCMD;
1302 break;
1303 }
1304
Jesper Juhl014c2542006-01-15 02:37:08 +01001305 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306}
1307
1308/*****************************************************************************/
1309
Jiri Slaby96b066b2006-12-08 02:38:42 -08001310/*
1311 * Start the transmitter again. Just turn TX interrupts back on.
1312 */
1313
1314static void stl_start(struct tty_struct *tty)
1315{
1316 struct stlport *portp;
1317
1318 pr_debug("stl_start(tty=%p)\n", tty);
1319
1320 if (tty == NULL)
1321 return;
1322 portp = tty->driver_data;
1323 if (portp == NULL)
1324 return;
1325 stl_startrxtx(portp, -1, 1);
1326}
1327
1328/*****************************************************************************/
1329
Alan Cox606d0992006-12-08 02:38:45 -08001330static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001332 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001333 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Jiri Slabya0564e12006-12-08 02:38:37 -08001335 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Jiri Slaby615e4a72006-12-08 02:38:38 -08001337 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 return;
1339 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001340 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 return;
1342
1343 tiosp = tty->termios;
1344 if ((tiosp->c_cflag == old->c_cflag) &&
1345 (tiosp->c_iflag == old->c_iflag))
1346 return;
1347
1348 stl_setport(portp, tiosp);
1349 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1350 -1);
1351 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1352 tty->hw_stopped = 0;
1353 stl_start(tty);
1354 }
1355 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1356 wake_up_interruptible(&portp->open_wait);
1357}
1358
1359/*****************************************************************************/
1360
1361/*
1362 * Attempt to flow control who ever is sending us data. Based on termios
1363 * settings use software or/and hardware flow control.
1364 */
1365
1366static void stl_throttle(struct tty_struct *tty)
1367{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001368 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Jiri Slabya0564e12006-12-08 02:38:37 -08001370 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Jiri Slaby615e4a72006-12-08 02:38:38 -08001372 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 return;
1374 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001375 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 return;
1377 stl_flowctrl(portp, 0);
1378}
1379
1380/*****************************************************************************/
1381
1382/*
1383 * Unflow control the device sending us data...
1384 */
1385
1386static void stl_unthrottle(struct tty_struct *tty)
1387{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001388 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Jiri Slabya0564e12006-12-08 02:38:37 -08001390 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Jiri Slaby615e4a72006-12-08 02:38:38 -08001392 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 return;
1394 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001395 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 return;
1397 stl_flowctrl(portp, 1);
1398}
1399
1400/*****************************************************************************/
1401
1402/*
1403 * Stop the transmitter. Basically to do this we will just turn TX
1404 * interrupts off.
1405 */
1406
1407static void stl_stop(struct tty_struct *tty)
1408{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001409 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Jiri Slabya0564e12006-12-08 02:38:37 -08001411 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
Jiri Slaby615e4a72006-12-08 02:38:38 -08001413 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 return;
1415 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001416 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 return;
1418 stl_startrxtx(portp, -1, 0);
1419}
1420
1421/*****************************************************************************/
1422
1423/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 * Hangup this port. This is pretty much like closing the port, only
1425 * a little more brutal. No waiting for data to drain. Shutdown the
1426 * port and maybe drop signals.
1427 */
1428
1429static void stl_hangup(struct tty_struct *tty)
1430{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001431 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
Jiri Slabya0564e12006-12-08 02:38:37 -08001433 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Jiri Slaby615e4a72006-12-08 02:38:38 -08001435 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 return;
1437 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001438 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 return;
1440
1441 portp->flags &= ~ASYNC_INITIALIZED;
1442 stl_disableintrs(portp);
1443 if (tty->termios->c_cflag & HUPCL)
1444 stl_setsignals(portp, 0, 0);
1445 stl_enablerxtx(portp, 0, 0);
1446 stl_flushbuffer(tty);
1447 portp->istate = 0;
1448 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001449 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001451 portp->tx.buf = NULL;
1452 portp->tx.head = NULL;
1453 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001455 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1457 portp->refcount = 0;
1458 wake_up_interruptible(&portp->open_wait);
1459}
1460
1461/*****************************************************************************/
1462
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463static void stl_breakctl(struct tty_struct *tty, int state)
1464{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001465 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Jiri Slabya0564e12006-12-08 02:38:37 -08001467 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Jiri Slaby615e4a72006-12-08 02:38:38 -08001469 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 return;
1471 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001472 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 return;
1474
1475 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1476}
1477
1478/*****************************************************************************/
1479
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480static void stl_sendxchar(struct tty_struct *tty, char ch)
1481{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001482 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
Jiri Slabya0564e12006-12-08 02:38:37 -08001484 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
Jiri Slaby615e4a72006-12-08 02:38:38 -08001486 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 return;
1488 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001489 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 return;
1491
1492 if (ch == STOP_CHAR(tty))
1493 stl_sendflow(portp, 0);
1494 else if (ch == START_CHAR(tty))
1495 stl_sendflow(portp, 1);
1496 else
1497 stl_putchar(tty, ch);
1498}
1499
1500/*****************************************************************************/
1501
1502#define MAXLINE 80
1503
1504/*
1505 * Format info for a specified port. The line is deliberately limited
1506 * to 80 characters. (If it is too long it will be truncated, if too
1507 * short then padded with spaces).
1508 */
1509
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001510static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511{
1512 char *sp;
1513 int sigs, cnt;
1514
1515 sp = pos;
1516 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1517 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1518 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1519
1520 if (portp->stats.rxframing)
1521 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1522 if (portp->stats.rxparity)
1523 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1524 if (portp->stats.rxbreaks)
1525 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1526 if (portp->stats.rxoverrun)
1527 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1528
1529 sigs = stl_getsignals(portp);
1530 cnt = sprintf(sp, "%s%s%s%s%s ",
1531 (sigs & TIOCM_RTS) ? "|RTS" : "",
1532 (sigs & TIOCM_CTS) ? "|CTS" : "",
1533 (sigs & TIOCM_DTR) ? "|DTR" : "",
1534 (sigs & TIOCM_CD) ? "|DCD" : "",
1535 (sigs & TIOCM_DSR) ? "|DSR" : "");
1536 *sp = ' ';
1537 sp += cnt;
1538
Jiri Slabyc62429d2006-12-08 02:39:14 -08001539 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 *sp++ = ' ';
1541 if (cnt >= MAXLINE)
1542 pos[(MAXLINE - 2)] = '+';
1543 pos[(MAXLINE - 1)] = '\n';
1544
Jesper Juhl014c2542006-01-15 02:37:08 +01001545 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546}
1547
1548/*****************************************************************************/
1549
1550/*
1551 * Port info, read from the /proc file system.
1552 */
1553
1554static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1555{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001556 struct stlbrd *brdp;
1557 struct stlpanel *panelp;
1558 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 int brdnr, panelnr, portnr, totalport;
1560 int curoff, maxoff;
1561 char *pos;
1562
Jiri Slabya0564e12006-12-08 02:38:37 -08001563 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1564 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
1566 pos = page;
1567 totalport = 0;
1568 curoff = 0;
1569
1570 if (off == 0) {
1571 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1572 stl_drvversion);
1573 while (pos < (page + MAXLINE - 1))
1574 *pos++ = ' ';
1575 *pos++ = '\n';
1576 }
1577 curoff = MAXLINE;
1578
1579/*
1580 * We scan through for each board, panel and port. The offset is
1581 * calculated on the fly, and irrelevant ports are skipped.
1582 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001583 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001585 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 continue;
1587 if (brdp->state == 0)
1588 continue;
1589
1590 maxoff = curoff + (brdp->nrports * MAXLINE);
1591 if (off >= maxoff) {
1592 curoff = maxoff;
1593 continue;
1594 }
1595
1596 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001597 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001599 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 continue;
1601
1602 maxoff = curoff + (panelp->nrports * MAXLINE);
1603 if (off >= maxoff) {
1604 curoff = maxoff;
1605 totalport += panelp->nrports;
1606 continue;
1607 }
1608
Jiri Slabyc62429d2006-12-08 02:39:14 -08001609 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 totalport++) {
1611 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001612 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 continue;
1614 if (off >= (curoff += MAXLINE))
1615 continue;
1616 if ((pos - page + MAXLINE) > count)
1617 goto stl_readdone;
1618 pos += stl_portinfo(portp, totalport, pos);
1619 }
1620 }
1621 }
1622
1623 *eof = 1;
1624
1625stl_readdone:
1626 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001627 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628}
1629
1630/*****************************************************************************/
1631
1632/*
1633 * All board interrupts are vectored through here first. This code then
1634 * calls off to the approrpriate board interrupt handlers.
1635 */
1636
David Howells7d12e782006-10-05 14:55:46 +01001637static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001639 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
Jiri Slabya0564e12006-12-08 02:38:37 -08001641 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
1643 return IRQ_RETVAL((* brdp->isr)(brdp));
1644}
1645
1646/*****************************************************************************/
1647
1648/*
1649 * Interrupt service routine for EasyIO board types.
1650 */
1651
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001652static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001654 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 unsigned int iobase;
1656 int handled = 0;
1657
Alan Coxb65b5b52006-06-27 02:54:05 -07001658 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 panelp = brdp->panels[0];
1660 iobase = panelp->iobase;
1661 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1662 handled = 1;
1663 (* panelp->isr)(panelp, iobase);
1664 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001665 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 return handled;
1667}
1668
1669/*****************************************************************************/
1670
1671/*
1672 * Interrupt service routine for ECH-AT board types.
1673 */
1674
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001675static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001677 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 unsigned int ioaddr;
1679 int bnknr;
1680 int handled = 0;
1681
1682 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1683
1684 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1685 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001686 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 ioaddr = brdp->bnkstataddr[bnknr];
1688 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1689 panelp = brdp->bnk2panel[bnknr];
1690 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1691 }
1692 }
1693 }
1694
1695 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1696
1697 return handled;
1698}
1699
1700/*****************************************************************************/
1701
1702/*
1703 * Interrupt service routine for ECH-MCA board types.
1704 */
1705
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001706static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001708 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 unsigned int ioaddr;
1710 int bnknr;
1711 int handled = 0;
1712
1713 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1714 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001715 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 ioaddr = brdp->bnkstataddr[bnknr];
1717 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1718 panelp = brdp->bnk2panel[bnknr];
1719 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1720 }
1721 }
1722 }
1723 return handled;
1724}
1725
1726/*****************************************************************************/
1727
1728/*
1729 * Interrupt service routine for ECH-PCI board types.
1730 */
1731
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001732static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001734 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 unsigned int ioaddr;
1736 int bnknr, recheck;
1737 int handled = 0;
1738
1739 while (1) {
1740 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001741 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1743 ioaddr = brdp->bnkstataddr[bnknr];
1744 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1745 panelp = brdp->bnk2panel[bnknr];
1746 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1747 recheck++;
1748 handled = 1;
1749 }
1750 }
1751 if (! recheck)
1752 break;
1753 }
1754 return handled;
1755}
1756
1757/*****************************************************************************/
1758
1759/*
1760 * Interrupt service routine for ECH-8/64-PCI board types.
1761 */
1762
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001763static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001765 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 unsigned int ioaddr;
1767 int bnknr;
1768 int handled = 0;
1769
1770 while (inb(brdp->ioctrl) & 0x1) {
1771 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001772 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 ioaddr = brdp->bnkstataddr[bnknr];
1774 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1775 panelp = brdp->bnk2panel[bnknr];
1776 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1777 }
1778 }
1779 }
1780
1781 return handled;
1782}
1783
1784/*****************************************************************************/
1785
1786/*
1787 * Service an off-level request for some channel.
1788 */
Al Viro3e577a82006-12-06 18:41:45 +00001789static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001791 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 struct tty_struct *tty;
1793 unsigned int oldsigs;
1794
Jiri Slabya0564e12006-12-08 02:38:37 -08001795 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796
Jiri Slaby615e4a72006-12-08 02:38:38 -08001797 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 return;
1799
1800 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001801 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 return;
1803
1804 lock_kernel();
Jiri Slabyc62429d2006-12-08 02:39:14 -08001805 if (test_bit(ASYI_TXLOW, &portp->istate))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 tty_wakeup(tty);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001807
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1809 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1810 oldsigs = portp->sigs;
1811 portp->sigs = stl_getsignals(portp);
1812 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1813 wake_up_interruptible(&portp->open_wait);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001814 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 if (portp->flags & ASYNC_CHECK_CD)
1816 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 }
1818 unlock_kernel();
1819}
1820
1821/*****************************************************************************/
1822
1823/*
1824 * Initialize all the ports on a panel.
1825 */
1826
Jiri Slaby705c1862006-12-08 02:39:11 -08001827static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001829 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 int chipmask, i;
1831
Jiri Slabya0564e12006-12-08 02:38:37 -08001832 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
1834 chipmask = stl_panelinit(brdp, panelp);
1835
1836/*
1837 * All UART's are initialized (if found!). Now go through and setup
1838 * each ports data structures.
1839 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001840 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001841 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001842 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001844 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 break;
1846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847
1848 portp->magic = STL_PORTMAGIC;
1849 portp->portnr = i;
1850 portp->brdnr = panelp->brdnr;
1851 portp->panelnr = panelp->panelnr;
1852 portp->uartp = panelp->uartp;
1853 portp->clk = brdp->clk;
1854 portp->baud_base = STL_BAUDBASE;
1855 portp->close_delay = STL_CLOSEDELAY;
1856 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001857 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 init_waitqueue_head(&portp->open_wait);
1859 init_waitqueue_head(&portp->close_wait);
1860 portp->stats.brd = portp->brdnr;
1861 portp->stats.panel = portp->panelnr;
1862 portp->stats.port = portp->portnr;
1863 panelp->ports[i] = portp;
1864 stl_portinit(brdp, panelp, portp);
1865 }
1866
Jiri Slabyc62429d2006-12-08 02:39:14 -08001867 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868}
1869
Jiri Slaby3b85b342006-12-08 02:39:10 -08001870static void stl_cleanup_panels(struct stlbrd *brdp)
1871{
1872 struct stlpanel *panelp;
1873 struct stlport *portp;
1874 unsigned int j, k;
1875
1876 for (j = 0; j < STL_MAXPANELS; j++) {
1877 panelp = brdp->panels[j];
1878 if (panelp == NULL)
1879 continue;
1880 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1881 portp = panelp->ports[k];
1882 if (portp == NULL)
1883 continue;
1884 if (portp->tty != NULL)
1885 stl_hangup(portp->tty);
1886 kfree(portp->tx.buf);
1887 kfree(portp);
1888 }
1889 kfree(panelp);
1890 }
1891}
1892
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893/*****************************************************************************/
1894
1895/*
1896 * Try to find and initialize an EasyIO board.
1897 */
1898
Jiri Slaby705c1862006-12-08 02:39:11 -08001899static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001901 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 unsigned int status;
1903 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001904 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
Jiri Slabya0564e12006-12-08 02:38:37 -08001906 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907
1908 brdp->ioctrl = brdp->ioaddr1 + 1;
1909 brdp->iostatus = brdp->ioaddr1 + 2;
1910
1911 status = inb(brdp->iostatus);
1912 if ((status & EIO_IDBITMASK) == EIO_MK3)
1913 brdp->ioctrl++;
1914
1915/*
1916 * Handle board specific stuff now. The real difference is PCI
1917 * or not PCI.
1918 */
1919 if (brdp->brdtype == BRD_EASYIOPCI) {
1920 brdp->iosize1 = 0x80;
1921 brdp->iosize2 = 0x80;
1922 name = "serial(EIO-PCI)";
1923 outb(0x41, (brdp->ioaddr2 + 0x4c));
1924 } else {
1925 brdp->iosize1 = 8;
1926 name = "serial(EIO)";
1927 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1928 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1929 printk("STALLION: invalid irq=%d for brd=%d\n",
1930 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001931 retval = -EINVAL;
1932 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 }
1934 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1935 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1936 brdp->ioctrl);
1937 }
1938
Jiri Slaby3b85b342006-12-08 02:39:10 -08001939 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1941 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1942 "%x conflicts with another device\n", brdp->brdnr,
1943 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001944 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 }
1946
1947 if (brdp->iosize2 > 0)
1948 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1949 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1950 "address %x conflicts with another device\n",
1951 brdp->brdnr, brdp->ioaddr2);
1952 printk(KERN_WARNING "STALLION: Warning, also "
1953 "releasing board %d I/O address %x \n",
1954 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001955 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 }
1957
1958/*
1959 * Everything looks OK, so let's go ahead and probe for the hardware.
1960 */
1961 brdp->clk = CD1400_CLK;
1962 brdp->isr = stl_eiointr;
1963
Jiri Slaby3b85b342006-12-08 02:39:10 -08001964 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 switch (status & EIO_IDBITMASK) {
1966 case EIO_8PORTM:
1967 brdp->clk = CD1400_CLK8M;
1968 /* fall thru */
1969 case EIO_8PORTRS:
1970 case EIO_8PORTDI:
1971 brdp->nrports = 8;
1972 break;
1973 case EIO_4PORTRS:
1974 brdp->nrports = 4;
1975 break;
1976 case EIO_MK3:
1977 switch (status & EIO_BRDMASK) {
1978 case ID_BRD4:
1979 brdp->nrports = 4;
1980 break;
1981 case ID_BRD8:
1982 brdp->nrports = 8;
1983 break;
1984 case ID_BRD16:
1985 brdp->nrports = 16;
1986 break;
1987 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001988 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 }
1990 break;
1991 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001992 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 }
1994
1995/*
1996 * We have verified that the board is actually present, so now we
1997 * can complete the setup.
1998 */
1999
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002000 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002001 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002003 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002004 retval = -ENOMEM;
2005 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
2008 panelp->magic = STL_PANELMAGIC;
2009 panelp->brdnr = brdp->brdnr;
2010 panelp->panelnr = 0;
2011 panelp->nrports = brdp->nrports;
2012 panelp->iobase = brdp->ioaddr1;
2013 panelp->hwid = status;
2014 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002015 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 panelp->isr = stl_sc26198intr;
2017 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002018 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 panelp->isr = stl_cd1400eiointr;
2020 }
2021
2022 brdp->panels[0] = panelp;
2023 brdp->nrpanels = 1;
2024 brdp->state |= BRD_FOUND;
2025 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002026 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 printk("STALLION: failed to register interrupt "
2028 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002029 retval = -ENODEV;
2030 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08002032
2033 return 0;
2034err_fr:
2035 stl_cleanup_panels(brdp);
2036err_rel2:
2037 if (brdp->iosize2 > 0)
2038 release_region(brdp->ioaddr2, brdp->iosize2);
2039err_rel1:
2040 release_region(brdp->ioaddr1, brdp->iosize1);
2041err:
2042 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
2045/*****************************************************************************/
2046
2047/*
2048 * Try to find an ECH board and initialize it. This code is capable of
2049 * dealing with all types of ECH board.
2050 */
2051
Jiri Slaby705c1862006-12-08 02:39:11 -08002052static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002054 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 unsigned int status, nxtid, ioaddr, conflict;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002056 int panelnr, banknr, i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 char *name;
2058
Jiri Slabya0564e12006-12-08 02:38:37 -08002059 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060
2061 status = 0;
2062 conflict = 0;
2063
2064/*
2065 * Set up the initial board register contents for boards. This varies a
2066 * bit between the different board types. So we need to handle each
2067 * separately. Also do a check that the supplied IRQ is good.
2068 */
2069 switch (brdp->brdtype) {
2070
2071 case BRD_ECH:
2072 brdp->isr = stl_echatintr;
2073 brdp->ioctrl = brdp->ioaddr1 + 1;
2074 brdp->iostatus = brdp->ioaddr1 + 1;
2075 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002076 if ((status & ECH_IDBITMASK) != ECH_ID) {
2077 retval = -ENODEV;
2078 goto err;
2079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2081 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2082 printk("STALLION: invalid irq=%d for brd=%d\n",
2083 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002084 retval = -EINVAL;
2085 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 }
2087 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2088 status |= (stl_vecmap[brdp->irq] << 1);
2089 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2090 brdp->ioctrlval = ECH_INTENABLE |
2091 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002092 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2094 brdp->iosize1 = 2;
2095 brdp->iosize2 = 32;
2096 name = "serial(EC8/32)";
2097 outb(status, brdp->ioaddr1);
2098 break;
2099
2100 case BRD_ECHMC:
2101 brdp->isr = stl_echmcaintr;
2102 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2103 brdp->iostatus = brdp->ioctrl;
2104 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002105 if ((status & ECH_IDBITMASK) != ECH_ID) {
2106 retval = -ENODEV;
2107 goto err;
2108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2110 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2111 printk("STALLION: invalid irq=%d for brd=%d\n",
2112 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002113 retval = -EINVAL;
2114 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 }
2116 outb(ECHMC_BRDRESET, brdp->ioctrl);
2117 outb(ECHMC_INTENABLE, brdp->ioctrl);
2118 brdp->iosize1 = 64;
2119 name = "serial(EC8/32-MC)";
2120 break;
2121
2122 case BRD_ECHPCI:
2123 brdp->isr = stl_echpciintr;
2124 brdp->ioctrl = brdp->ioaddr1 + 2;
2125 brdp->iosize1 = 4;
2126 brdp->iosize2 = 8;
2127 name = "serial(EC8/32-PCI)";
2128 break;
2129
2130 case BRD_ECH64PCI:
2131 brdp->isr = stl_echpci64intr;
2132 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2133 outb(0x43, (brdp->ioaddr1 + 0x4c));
2134 brdp->iosize1 = 0x80;
2135 brdp->iosize2 = 0x80;
2136 name = "serial(EC8/64-PCI)";
2137 break;
2138
2139 default:
2140 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002141 retval = -EINVAL;
2142 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 }
2144
2145/*
2146 * Check boards for possible IO address conflicts and return fail status
2147 * if an IO conflict found.
2148 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002149 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2151 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2152 "%x conflicts with another device\n", brdp->brdnr,
2153 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002154 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 }
2156
2157 if (brdp->iosize2 > 0)
2158 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2159 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2160 "address %x conflicts with another device\n",
2161 brdp->brdnr, brdp->ioaddr2);
2162 printk(KERN_WARNING "STALLION: Warning, also "
2163 "releasing board %d I/O address %x \n",
2164 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002165 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 }
2167
2168/*
2169 * Scan through the secondary io address space looking for panels.
2170 * As we find'em allocate and initialize panel structures for each.
2171 */
2172 brdp->clk = CD1400_CLK;
2173 brdp->hwid = status;
2174
2175 ioaddr = brdp->ioaddr2;
2176 banknr = 0;
2177 panelnr = 0;
2178 nxtid = 0;
2179
Jiri Slabyc62429d2006-12-08 02:39:14 -08002180 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 if (brdp->brdtype == BRD_ECHPCI) {
2182 outb(nxtid, brdp->ioctrl);
2183 ioaddr = brdp->ioaddr2;
2184 }
2185 status = inb(ioaddr + ECH_PNLSTATUS);
2186 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002187 goto err_fr;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002188 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002189 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002191 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002192 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 panelp->magic = STL_PANELMAGIC;
2195 panelp->brdnr = brdp->brdnr;
2196 panelp->panelnr = panelnr;
2197 panelp->iobase = ioaddr;
2198 panelp->pagenr = nxtid;
2199 panelp->hwid = status;
2200 brdp->bnk2panel[banknr] = panelp;
2201 brdp->bnkpageaddr[banknr] = nxtid;
2202 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2203
2204 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002205 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 panelp->isr = stl_sc26198intr;
2207 if (status & ECH_PNL16PORT) {
2208 panelp->nrports = 16;
2209 brdp->bnk2panel[banknr] = panelp;
2210 brdp->bnkpageaddr[banknr] = nxtid;
2211 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2212 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002213 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002216 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 panelp->isr = stl_cd1400echintr;
2218 if (status & ECH_PNL16PORT) {
2219 panelp->nrports = 16;
2220 panelp->ackmask = 0x80;
2221 if (brdp->brdtype != BRD_ECHPCI)
2222 ioaddr += EREG_BANKSIZE;
2223 brdp->bnk2panel[banknr] = panelp;
2224 brdp->bnkpageaddr[banknr] = ++nxtid;
2225 brdp->bnkstataddr[banknr++] = ioaddr +
2226 ECH_PNLSTATUS;
2227 } else {
2228 panelp->nrports = 8;
2229 panelp->ackmask = 0xc0;
2230 }
2231 }
2232
2233 nxtid++;
2234 ioaddr += EREG_BANKSIZE;
2235 brdp->nrports += panelp->nrports;
2236 brdp->panels[panelnr++] = panelp;
2237 if ((brdp->brdtype != BRD_ECHPCI) &&
2238 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
Jiri Slaby3b85b342006-12-08 02:39:10 -08002239 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 }
2241
2242 brdp->nrpanels = panelnr;
2243 brdp->nrbnks = banknr;
2244 if (brdp->brdtype == BRD_ECH)
2245 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2246
2247 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002248 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 printk("STALLION: failed to register interrupt "
2250 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002251 retval = -ENODEV;
2252 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 }
2254
Jiri Slaby3b85b342006-12-08 02:39:10 -08002255 return 0;
2256err_fr:
2257 stl_cleanup_panels(brdp);
2258 if (brdp->iosize2 > 0)
2259 release_region(brdp->ioaddr2, brdp->iosize2);
2260err_rel1:
2261 release_region(brdp->ioaddr1, brdp->iosize1);
2262err:
2263 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264}
2265
2266/*****************************************************************************/
2267
2268/*
2269 * Initialize and configure the specified board.
2270 * Scan through all the boards in the configuration and see what we
2271 * can find. Handle EIO and the ECH boards a little differently here
2272 * since the initial search and setup is very different.
2273 */
2274
Jiri Slaby705c1862006-12-08 02:39:11 -08002275static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002277 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Jiri Slabya0564e12006-12-08 02:38:37 -08002279 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280
2281 switch (brdp->brdtype) {
2282 case BRD_EASYIO:
2283 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002284 retval = stl_initeio(brdp);
2285 if (retval)
2286 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 break;
2288 case BRD_ECH:
2289 case BRD_ECHMC:
2290 case BRD_ECHPCI:
2291 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002292 retval = stl_initech(brdp);
2293 if (retval)
2294 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 break;
2296 default:
2297 printk("STALLION: board=%d is unknown board type=%d\n",
2298 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002299 retval = -ENODEV;
2300 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 }
2302
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 if ((brdp->state & BRD_FOUND) == 0) {
2304 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2305 stl_brdnames[brdp->brdtype], brdp->brdnr,
2306 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002307 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 }
2309
Jiri Slabyc62429d2006-12-08 02:39:14 -08002310 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002311 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 stl_initports(brdp, brdp->panels[i]);
2313
2314 printk("STALLION: %s found, board=%d io=%x irq=%d "
2315 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2316 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2317 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002318
2319 return 0;
2320err_free:
2321 free_irq(brdp->irq, brdp);
2322
2323 stl_cleanup_panels(brdp);
2324
2325 release_region(brdp->ioaddr1, brdp->iosize1);
2326 if (brdp->iosize2 > 0)
2327 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002328err:
2329 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330}
2331
2332/*****************************************************************************/
2333
2334/*
2335 * Find the next available board number that is free.
2336 */
2337
Jiri Slaby705c1862006-12-08 02:39:11 -08002338static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339{
2340 int i;
2341
Jiri Slabyc62429d2006-12-08 02:39:14 -08002342 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002343 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 if (i >= stl_nrbrds)
2345 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002346 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002348
2349 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350}
2351
2352/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353/*
2354 * We have a Stallion board. Allocate a board structure and
2355 * initialize it. Read its IO and IRQ resources from PCI
2356 * configuration space.
2357 */
2358
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002359static int __devinit stl_pciprobe(struct pci_dev *pdev,
2360 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002362 struct stlbrd *brdp;
2363 unsigned int brdtype = ent->driver_data;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002364 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002366 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002367 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002368
2369 dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
2370 pdev->vendor, pdev->device, pdev->class);
2371
Jiri Slaby3b85b342006-12-08 02:39:10 -08002372 retval = pci_enable_device(pdev);
2373 if (retval)
2374 goto err;
2375 brdp = stl_allocbrd();
2376 if (brdp == NULL) {
2377 retval = -ENOMEM;
2378 goto err;
2379 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002380 mutex_lock(&stl_brdslock);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002381 brdp->brdnr = stl_getbrdnr();
2382 if (brdp->brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002383 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002385 mutex_unlock(&stl_brdslock);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002386 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002388 stl_brds[brdp->brdnr] = brdp;
2389 mutex_unlock(&stl_brdslock);
2390
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002392 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393
2394/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 * We have all resources from the board, so let's setup the actual
2396 * board structure now.
2397 */
2398 switch (brdtype) {
2399 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002400 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2401 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 break;
2403 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002404 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2405 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 break;
2407 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002408 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2409 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 break;
2411 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002412 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 break;
2414 }
2415
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002416 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002417 retval = stl_brdinit(brdp);
2418 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002419 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002421 pci_set_drvdata(pdev, brdp);
2422
Jiri Slaby3b85b342006-12-08 02:39:10 -08002423 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002424err_null:
2425 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002426err_fr:
2427 kfree(brdp);
2428err:
2429 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430}
2431
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002432static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002434 struct stlbrd *brdp = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002436 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002438 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002440 release_region(brdp->ioaddr1, brdp->iosize1);
2441 if (brdp->iosize2 > 0)
2442 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002444 stl_brds[brdp->brdnr] = NULL;
2445 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446}
2447
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002448static struct pci_driver stl_pcidriver = {
2449 .name = "stallion",
2450 .id_table = stl_pcibrds,
2451 .probe = stl_pciprobe,
2452 .remove = __devexit_p(stl_pciremove)
2453};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
2455/*****************************************************************************/
2456
2457/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 * Return the board stats structure to user app.
2459 */
2460
2461static int stl_getbrdstats(combrd_t __user *bp)
2462{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002463 struct stlbrd *brdp;
2464 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 int i;
2466
2467 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2468 return -EFAULT;
2469 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002470 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002472 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002473 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
2475 memset(&stl_brdstats, 0, sizeof(combrd_t));
2476 stl_brdstats.brd = brdp->brdnr;
2477 stl_brdstats.type = brdp->brdtype;
2478 stl_brdstats.hwid = brdp->hwid;
2479 stl_brdstats.state = brdp->state;
2480 stl_brdstats.ioaddr = brdp->ioaddr1;
2481 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2482 stl_brdstats.irq = brdp->irq;
2483 stl_brdstats.nrpanels = brdp->nrpanels;
2484 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002485 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 panelp = brdp->panels[i];
2487 stl_brdstats.panels[i].panel = i;
2488 stl_brdstats.panels[i].hwid = panelp->hwid;
2489 stl_brdstats.panels[i].nrports = panelp->nrports;
2490 }
2491
2492 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2493}
2494
2495/*****************************************************************************/
2496
2497/*
2498 * Resolve the referenced port number into a port struct pointer.
2499 */
2500
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002501static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002503 struct stlbrd *brdp;
2504 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505
Jiri Slabyc62429d2006-12-08 02:39:14 -08002506 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2507 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002509 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002510 return NULL;
2511 if (panelnr < 0 || panelnr >= brdp->nrpanels)
2512 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002514 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002515 return NULL;
2516 if (portnr < 0 || portnr >= panelp->nrports)
2517 return NULL;
2518 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519}
2520
2521/*****************************************************************************/
2522
2523/*
2524 * Return the port stats structure to user app. A NULL port struct
2525 * pointer passed in means that we need to find out from the app
2526 * what port to get stats for (used through board control device).
2527 */
2528
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002529static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530{
2531 unsigned char *head, *tail;
2532 unsigned long flags;
2533
2534 if (!portp) {
2535 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2536 return -EFAULT;
2537 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2538 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002539 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002540 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 }
2542
2543 portp->stats.state = portp->istate;
2544 portp->stats.flags = portp->flags;
2545 portp->stats.hwid = portp->hwid;
2546
2547 portp->stats.ttystate = 0;
2548 portp->stats.cflags = 0;
2549 portp->stats.iflags = 0;
2550 portp->stats.oflags = 0;
2551 portp->stats.lflags = 0;
2552 portp->stats.rxbuffered = 0;
2553
Alan Coxb65b5b52006-06-27 02:54:05 -07002554 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002555 if (portp->tty != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 if (portp->tty->driver_data == portp) {
2557 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002558 /* No longer available as a statistic */
2559 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002560 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 portp->stats.cflags = portp->tty->termios->c_cflag;
2562 portp->stats.iflags = portp->tty->termios->c_iflag;
2563 portp->stats.oflags = portp->tty->termios->c_oflag;
2564 portp->stats.lflags = portp->tty->termios->c_lflag;
2565 }
2566 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002567 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
2569 head = portp->tx.head;
2570 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002571 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2572 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
2574 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2575
2576 return copy_to_user(cp, &portp->stats,
2577 sizeof(comstats_t)) ? -EFAULT : 0;
2578}
2579
2580/*****************************************************************************/
2581
2582/*
2583 * Clear the port stats structure. We also return it zeroed out...
2584 */
2585
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002586static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587{
2588 if (!portp) {
2589 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2590 return -EFAULT;
2591 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2592 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002593 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002594 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 }
2596
2597 memset(&portp->stats, 0, sizeof(comstats_t));
2598 portp->stats.brd = portp->brdnr;
2599 portp->stats.panel = portp->panelnr;
2600 portp->stats.port = portp->portnr;
2601 return copy_to_user(cp, &portp->stats,
2602 sizeof(comstats_t)) ? -EFAULT : 0;
2603}
2604
2605/*****************************************************************************/
2606
2607/*
2608 * Return the entire driver ports structure to a user app.
2609 */
2610
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002611static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002613 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002615 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 return -EFAULT;
2617 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2618 stl_dummyport.portnr);
2619 if (!portp)
2620 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002621 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622}
2623
2624/*****************************************************************************/
2625
2626/*
2627 * Return the entire driver board structure to a user app.
2628 */
2629
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002630static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002632 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002634 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 return -EFAULT;
2636 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2637 return -ENODEV;
2638 brdp = stl_brds[stl_dummybrd.brdnr];
2639 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002640 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002641 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642}
2643
2644/*****************************************************************************/
2645
2646/*
2647 * The "staliomem" device is also required to do some special operations
2648 * on the board and/or ports. In this driver it is mostly used for stats
2649 * collection.
2650 */
2651
2652static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2653{
2654 int brdnr, rc;
2655 void __user *argp = (void __user *)arg;
2656
Jiri Slabya0564e12006-12-08 02:38:37 -08002657 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658
2659 brdnr = iminor(ip);
2660 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002661 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 rc = 0;
2663
2664 switch (cmd) {
2665 case COM_GETPORTSTATS:
2666 rc = stl_getportstats(NULL, argp);
2667 break;
2668 case COM_CLRPORTSTATS:
2669 rc = stl_clrportstats(NULL, argp);
2670 break;
2671 case COM_GETBRDSTATS:
2672 rc = stl_getbrdstats(argp);
2673 break;
2674 case COM_READPORT:
2675 rc = stl_getportstruct(argp);
2676 break;
2677 case COM_READBOARD:
2678 rc = stl_getbrdstruct(argp);
2679 break;
2680 default:
2681 rc = -ENOIOCTLCMD;
2682 break;
2683 }
2684
Jiri Slabyc62429d2006-12-08 02:39:14 -08002685 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686}
2687
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002688static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 .open = stl_open,
2690 .close = stl_close,
2691 .write = stl_write,
2692 .put_char = stl_putchar,
2693 .flush_chars = stl_flushchars,
2694 .write_room = stl_writeroom,
2695 .chars_in_buffer = stl_charsinbuffer,
2696 .ioctl = stl_ioctl,
2697 .set_termios = stl_settermios,
2698 .throttle = stl_throttle,
2699 .unthrottle = stl_unthrottle,
2700 .stop = stl_stop,
2701 .start = stl_start,
2702 .hangup = stl_hangup,
2703 .flush_buffer = stl_flushbuffer,
2704 .break_ctl = stl_breakctl,
2705 .wait_until_sent = stl_waituntilsent,
2706 .send_xchar = stl_sendxchar,
2707 .read_proc = stl_readproc,
2708 .tiocmget = stl_tiocmget,
2709 .tiocmset = stl_tiocmset,
2710};
2711
2712/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713/* CD1400 HARDWARE FUNCTIONS */
2714/*****************************************************************************/
2715
2716/*
2717 * These functions get/set/update the registers of the cd1400 UARTs.
2718 * Access to the cd1400 registers is via an address/data io port pair.
2719 * (Maybe should make this inline...)
2720 */
2721
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002722static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723{
2724 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002725 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726}
2727
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002728static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002730 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 outb(value, portp->ioaddr + EREG_DATA);
2732}
2733
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002734static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002736 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 if (inb(portp->ioaddr + EREG_DATA) != value) {
2738 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002739 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002741 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742}
2743
2744/*****************************************************************************/
2745
2746/*
2747 * Inbitialize the UARTs in a panel. We don't care what sort of board
2748 * these ports are on - since the port io registers are almost
2749 * identical when dealing with ports.
2750 */
2751
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002752static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753{
2754 unsigned int gfrcr;
2755 int chipmask, i, j;
2756 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002757 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
Jiri Slabya0564e12006-12-08 02:38:37 -08002759 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760
Alan Coxb65b5b52006-06-27 02:54:05 -07002761 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 BRDENABLE(panelp->brdnr, panelp->pagenr);
2763
2764/*
2765 * Check that each chip is present and started up OK.
2766 */
2767 chipmask = 0;
2768 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002769 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 if (brdp->brdtype == BRD_ECHPCI) {
2771 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2772 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002773 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 uartaddr = (i & 0x01) ? 0x080 : 0;
2776 outb((GFRCR + uartaddr), ioaddr);
2777 outb(0, (ioaddr + EREG_DATA));
2778 outb((CCR + uartaddr), ioaddr);
2779 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2780 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2781 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002782 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2784 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002785
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2787 printk("STALLION: cd1400 not responding, "
2788 "brd=%d panel=%d chip=%d\n",
2789 panelp->brdnr, panelp->panelnr, i);
2790 continue;
2791 }
2792 chipmask |= (0x1 << i);
2793 outb((PPR + uartaddr), ioaddr);
2794 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2795 }
2796
2797 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002798 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002799 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800}
2801
2802/*****************************************************************************/
2803
2804/*
2805 * Initialize hardware specific port registers.
2806 */
2807
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002808static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809{
Alan Coxb65b5b52006-06-27 02:54:05 -07002810 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002811 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2812 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
Jiri Slaby615e4a72006-12-08 02:38:38 -08002814 if ((brdp == NULL) || (panelp == NULL) ||
2815 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 return;
2817
Alan Coxb65b5b52006-06-27 02:54:05 -07002818 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2820 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2821 portp->uartaddr = (portp->portnr & 0x04) << 5;
2822 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2823
2824 BRDENABLE(portp->brdnr, portp->pagenr);
2825 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2826 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2827 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2828 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002829 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830}
2831
2832/*****************************************************************************/
2833
2834/*
2835 * Wait for the command register to be ready. We will poll this,
2836 * since it won't usually take too long to be ready.
2837 */
2838
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002839static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840{
2841 int i;
2842
Jiri Slabyc62429d2006-12-08 02:39:14 -08002843 for (i = 0; i < CCR_MAXWAIT; i++)
2844 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846
2847 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2848 portp->portnr, portp->panelnr, portp->brdnr);
2849}
2850
2851/*****************************************************************************/
2852
2853/*
2854 * Set up the cd1400 registers for a port based on the termios port
2855 * settings.
2856 */
2857
Alan Cox606d0992006-12-08 02:38:45 -08002858static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002860 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 unsigned long flags;
2862 unsigned int clkdiv, baudrate;
2863 unsigned char cor1, cor2, cor3;
2864 unsigned char cor4, cor5, ccr;
2865 unsigned char srer, sreron, sreroff;
2866 unsigned char mcor1, mcor2, rtpr;
2867 unsigned char clk, div;
2868
2869 cor1 = 0;
2870 cor2 = 0;
2871 cor3 = 0;
2872 cor4 = 0;
2873 cor5 = 0;
2874 ccr = 0;
2875 rtpr = 0;
2876 clk = 0;
2877 div = 0;
2878 mcor1 = 0;
2879 mcor2 = 0;
2880 sreron = 0;
2881 sreroff = 0;
2882
2883 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002884 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885 return;
2886
2887/*
2888 * Set up the RX char ignore mask with those RX error types we
2889 * can ignore. We can get the cd1400 to help us out a little here,
2890 * it will ignore parity errors and breaks for us.
2891 */
2892 portp->rxignoremsk = 0;
2893 if (tiosp->c_iflag & IGNPAR) {
2894 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2895 cor1 |= COR1_PARIGNORE;
2896 }
2897 if (tiosp->c_iflag & IGNBRK) {
2898 portp->rxignoremsk |= ST_BREAK;
2899 cor4 |= COR4_IGNBRK;
2900 }
2901
2902 portp->rxmarkmsk = ST_OVERRUN;
2903 if (tiosp->c_iflag & (INPCK | PARMRK))
2904 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2905 if (tiosp->c_iflag & BRKINT)
2906 portp->rxmarkmsk |= ST_BREAK;
2907
2908/*
2909 * Go through the char size, parity and stop bits and set all the
2910 * option register appropriately.
2911 */
2912 switch (tiosp->c_cflag & CSIZE) {
2913 case CS5:
2914 cor1 |= COR1_CHL5;
2915 break;
2916 case CS6:
2917 cor1 |= COR1_CHL6;
2918 break;
2919 case CS7:
2920 cor1 |= COR1_CHL7;
2921 break;
2922 default:
2923 cor1 |= COR1_CHL8;
2924 break;
2925 }
2926
2927 if (tiosp->c_cflag & CSTOPB)
2928 cor1 |= COR1_STOP2;
2929 else
2930 cor1 |= COR1_STOP1;
2931
2932 if (tiosp->c_cflag & PARENB) {
2933 if (tiosp->c_cflag & PARODD)
2934 cor1 |= (COR1_PARENB | COR1_PARODD);
2935 else
2936 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2937 } else {
2938 cor1 |= COR1_PARNONE;
2939 }
2940
2941/*
2942 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2943 * space for hardware flow control and the like. This should be set to
2944 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2945 * really be based on VTIME.
2946 */
2947 cor3 |= FIFO_RXTHRESHOLD;
2948 rtpr = 2;
2949
2950/*
2951 * Calculate the baud rate timers. For now we will just assume that
2952 * the input and output baud are the same. Could have used a baud
2953 * table here, but this way we can generate virtually any baud rate
2954 * we like!
2955 */
2956 baudrate = tiosp->c_cflag & CBAUD;
2957 if (baudrate & CBAUDEX) {
2958 baudrate &= ~CBAUDEX;
2959 if ((baudrate < 1) || (baudrate > 4))
2960 tiosp->c_cflag &= ~CBAUDEX;
2961 else
2962 baudrate += 15;
2963 }
2964 baudrate = stl_baudrates[baudrate];
2965 if ((tiosp->c_cflag & CBAUD) == B38400) {
2966 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2967 baudrate = 57600;
2968 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2969 baudrate = 115200;
2970 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2971 baudrate = 230400;
2972 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2973 baudrate = 460800;
2974 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
2975 baudrate = (portp->baud_base / portp->custom_divisor);
2976 }
2977 if (baudrate > STL_CD1400MAXBAUD)
2978 baudrate = STL_CD1400MAXBAUD;
2979
2980 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002981 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2982 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 if (clkdiv < 0x100)
2984 break;
2985 }
2986 div = (unsigned char) clkdiv;
2987 }
2988
2989/*
2990 * Check what form of modem signaling is required and set it up.
2991 */
2992 if ((tiosp->c_cflag & CLOCAL) == 0) {
2993 mcor1 |= MCOR1_DCD;
2994 mcor2 |= MCOR2_DCD;
2995 sreron |= SRER_MODEM;
2996 portp->flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002997 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 portp->flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999
3000/*
3001 * Setup cd1400 enhanced modes if we can. In particular we want to
3002 * handle as much of the flow control as possible automatically. As
3003 * well as saving a few CPU cycles it will also greatly improve flow
3004 * control reliability.
3005 */
3006 if (tiosp->c_iflag & IXON) {
3007 cor2 |= COR2_TXIBE;
3008 cor3 |= COR3_SCD12;
3009 if (tiosp->c_iflag & IXANY)
3010 cor2 |= COR2_IXM;
3011 }
3012
3013 if (tiosp->c_cflag & CRTSCTS) {
3014 cor2 |= COR2_CTSAE;
3015 mcor1 |= FIFO_RTSTHRESHOLD;
3016 }
3017
3018/*
3019 * All cd1400 register values calculated so go through and set
3020 * them all up.
3021 */
3022
Jiri Slabya0564e12006-12-08 02:38:37 -08003023 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003025 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003027 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003029 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3030 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3032 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
Alan Coxb65b5b52006-06-27 02:54:05 -07003034 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 BRDENABLE(portp->brdnr, portp->pagenr);
3036 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3037 srer = stl_cd1400getreg(portp, SRER);
3038 stl_cd1400setreg(portp, SRER, 0);
3039 if (stl_cd1400updatereg(portp, COR1, cor1))
3040 ccr = 1;
3041 if (stl_cd1400updatereg(portp, COR2, cor2))
3042 ccr = 1;
3043 if (stl_cd1400updatereg(portp, COR3, cor3))
3044 ccr = 1;
3045 if (ccr) {
3046 stl_cd1400ccrwait(portp);
3047 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3048 }
3049 stl_cd1400setreg(portp, COR4, cor4);
3050 stl_cd1400setreg(portp, COR5, cor5);
3051 stl_cd1400setreg(portp, MCOR1, mcor1);
3052 stl_cd1400setreg(portp, MCOR2, mcor2);
3053 if (baudrate > 0) {
3054 stl_cd1400setreg(portp, TCOR, clk);
3055 stl_cd1400setreg(portp, TBPR, div);
3056 stl_cd1400setreg(portp, RCOR, clk);
3057 stl_cd1400setreg(portp, RBPR, div);
3058 }
3059 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3060 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3061 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3062 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3063 stl_cd1400setreg(portp, RTPR, rtpr);
3064 mcor1 = stl_cd1400getreg(portp, MSVR1);
3065 if (mcor1 & MSVR1_DCD)
3066 portp->sigs |= TIOCM_CD;
3067 else
3068 portp->sigs &= ~TIOCM_CD;
3069 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
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 * Set the state of the DTR and RTS signals.
3078 */
3079
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003080static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081{
3082 unsigned char msvr1, msvr2;
3083 unsigned long flags;
3084
Jiri Slabya0564e12006-12-08 02:38:37 -08003085 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3086 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
3088 msvr1 = 0;
3089 msvr2 = 0;
3090 if (dtr > 0)
3091 msvr1 = MSVR1_DTR;
3092 if (rts > 0)
3093 msvr2 = MSVR2_RTS;
3094
Alan Coxb65b5b52006-06-27 02:54:05 -07003095 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 BRDENABLE(portp->brdnr, portp->pagenr);
3097 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3098 if (rts >= 0)
3099 stl_cd1400setreg(portp, MSVR2, msvr2);
3100 if (dtr >= 0)
3101 stl_cd1400setreg(portp, MSVR1, msvr1);
3102 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003103 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104}
3105
3106/*****************************************************************************/
3107
3108/*
3109 * Return the state of the signals.
3110 */
3111
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003112static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113{
3114 unsigned char msvr1, msvr2;
3115 unsigned long flags;
3116 int sigs;
3117
Jiri Slabya0564e12006-12-08 02:38:37 -08003118 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
Alan Coxb65b5b52006-06-27 02:54:05 -07003120 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 BRDENABLE(portp->brdnr, portp->pagenr);
3122 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3123 msvr1 = stl_cd1400getreg(portp, MSVR1);
3124 msvr2 = stl_cd1400getreg(portp, MSVR2);
3125 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003126 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
3128 sigs = 0;
3129 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3130 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3131 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3132 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3133#if 0
3134 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3135 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3136#else
3137 sigs |= TIOCM_DSR;
3138#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003139 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140}
3141
3142/*****************************************************************************/
3143
3144/*
3145 * Enable/Disable the Transmitter and/or Receiver.
3146 */
3147
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003148static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149{
3150 unsigned char ccr;
3151 unsigned long flags;
3152
Jiri Slabya0564e12006-12-08 02:38:37 -08003153 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3154
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 ccr = 0;
3156
3157 if (tx == 0)
3158 ccr |= CCR_TXDISABLE;
3159 else if (tx > 0)
3160 ccr |= CCR_TXENABLE;
3161 if (rx == 0)
3162 ccr |= CCR_RXDISABLE;
3163 else if (rx > 0)
3164 ccr |= CCR_RXENABLE;
3165
Alan Coxb65b5b52006-06-27 02:54:05 -07003166 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 BRDENABLE(portp->brdnr, portp->pagenr);
3168 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3169 stl_cd1400ccrwait(portp);
3170 stl_cd1400setreg(portp, CCR, ccr);
3171 stl_cd1400ccrwait(portp);
3172 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003173 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174}
3175
3176/*****************************************************************************/
3177
3178/*
3179 * Start/stop the Transmitter and/or Receiver.
3180 */
3181
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003182static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183{
3184 unsigned char sreron, sreroff;
3185 unsigned long flags;
3186
Jiri Slabya0564e12006-12-08 02:38:37 -08003187 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188
3189 sreron = 0;
3190 sreroff = 0;
3191 if (tx == 0)
3192 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3193 else if (tx == 1)
3194 sreron |= SRER_TXDATA;
3195 else if (tx >= 2)
3196 sreron |= SRER_TXEMPTY;
3197 if (rx == 0)
3198 sreroff |= SRER_RXDATA;
3199 else if (rx > 0)
3200 sreron |= SRER_RXDATA;
3201
Alan Coxb65b5b52006-06-27 02:54:05 -07003202 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 BRDENABLE(portp->brdnr, portp->pagenr);
3204 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3205 stl_cd1400setreg(portp, SRER,
3206 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3207 BRDDISABLE(portp->brdnr);
3208 if (tx > 0)
3209 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003210 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211}
3212
3213/*****************************************************************************/
3214
3215/*
3216 * Disable all interrupts from this port.
3217 */
3218
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003219static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220{
3221 unsigned long flags;
3222
Jiri Slabya0564e12006-12-08 02:38:37 -08003223 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3224
Alan Coxb65b5b52006-06-27 02:54:05 -07003225 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 BRDENABLE(portp->brdnr, portp->pagenr);
3227 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3228 stl_cd1400setreg(portp, SRER, 0);
3229 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003230 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231}
3232
3233/*****************************************************************************/
3234
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003235static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236{
3237 unsigned long flags;
3238
Jiri Slabya0564e12006-12-08 02:38:37 -08003239 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240
Alan Coxb65b5b52006-06-27 02:54:05 -07003241 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242 BRDENABLE(portp->brdnr, portp->pagenr);
3243 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3244 stl_cd1400setreg(portp, SRER,
3245 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3246 SRER_TXEMPTY));
3247 BRDDISABLE(portp->brdnr);
3248 portp->brklen = len;
3249 if (len == 1)
3250 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003251 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252}
3253
3254/*****************************************************************************/
3255
3256/*
3257 * Take flow control actions...
3258 */
3259
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003260static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261{
3262 struct tty_struct *tty;
3263 unsigned long flags;
3264
Jiri Slabya0564e12006-12-08 02:38:37 -08003265 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266
Jiri Slaby615e4a72006-12-08 02:38:38 -08003267 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268 return;
3269 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003270 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271 return;
3272
Alan Coxb65b5b52006-06-27 02:54:05 -07003273 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 BRDENABLE(portp->brdnr, portp->pagenr);
3275 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3276
3277 if (state) {
3278 if (tty->termios->c_iflag & IXOFF) {
3279 stl_cd1400ccrwait(portp);
3280 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3281 portp->stats.rxxon++;
3282 stl_cd1400ccrwait(portp);
3283 }
3284/*
3285 * Question: should we return RTS to what it was before? It may
3286 * have been set by an ioctl... Suppose not, since if you have
3287 * hardware flow control set then it is pretty silly to go and
3288 * set the RTS line by hand.
3289 */
3290 if (tty->termios->c_cflag & CRTSCTS) {
3291 stl_cd1400setreg(portp, MCOR1,
3292 (stl_cd1400getreg(portp, MCOR1) |
3293 FIFO_RTSTHRESHOLD));
3294 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3295 portp->stats.rxrtson++;
3296 }
3297 } else {
3298 if (tty->termios->c_iflag & IXOFF) {
3299 stl_cd1400ccrwait(portp);
3300 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3301 portp->stats.rxxoff++;
3302 stl_cd1400ccrwait(portp);
3303 }
3304 if (tty->termios->c_cflag & CRTSCTS) {
3305 stl_cd1400setreg(portp, MCOR1,
3306 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3307 stl_cd1400setreg(portp, MSVR2, 0);
3308 portp->stats.rxrtsoff++;
3309 }
3310 }
3311
3312 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003313 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314}
3315
3316/*****************************************************************************/
3317
3318/*
3319 * Send a flow control character...
3320 */
3321
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003322static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323{
3324 struct tty_struct *tty;
3325 unsigned long flags;
3326
Jiri Slabya0564e12006-12-08 02:38:37 -08003327 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
Jiri Slaby615e4a72006-12-08 02:38:38 -08003329 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330 return;
3331 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003332 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333 return;
3334
Alan Coxb65b5b52006-06-27 02:54:05 -07003335 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 BRDENABLE(portp->brdnr, portp->pagenr);
3337 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3338 if (state) {
3339 stl_cd1400ccrwait(portp);
3340 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3341 portp->stats.rxxon++;
3342 stl_cd1400ccrwait(portp);
3343 } else {
3344 stl_cd1400ccrwait(portp);
3345 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3346 portp->stats.rxxoff++;
3347 stl_cd1400ccrwait(portp);
3348 }
3349 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003350 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351}
3352
3353/*****************************************************************************/
3354
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003355static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356{
3357 unsigned long flags;
3358
Jiri Slabya0564e12006-12-08 02:38:37 -08003359 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360
Jiri Slaby615e4a72006-12-08 02:38:38 -08003361 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 return;
3363
Alan Coxb65b5b52006-06-27 02:54:05 -07003364 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 BRDENABLE(portp->brdnr, portp->pagenr);
3366 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3367 stl_cd1400ccrwait(portp);
3368 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3369 stl_cd1400ccrwait(portp);
3370 portp->tx.tail = portp->tx.head;
3371 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003372 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373}
3374
3375/*****************************************************************************/
3376
3377/*
3378 * Return the current state of data flow on this port. This is only
3379 * really interresting when determining if data has fully completed
3380 * transmission or not... This is easy for the cd1400, it accurately
3381 * maintains the busy port flag.
3382 */
3383
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003384static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385{
Jiri Slabya0564e12006-12-08 02:38:37 -08003386 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387
Jiri Slaby615e4a72006-12-08 02:38:38 -08003388 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003389 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
Jesper Juhl014c2542006-01-15 02:37:08 +01003391 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392}
3393
3394/*****************************************************************************/
3395
3396/*
3397 * Interrupt service routine for cd1400 EasyIO boards.
3398 */
3399
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003400static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401{
3402 unsigned char svrtype;
3403
Jiri Slabya0564e12006-12-08 02:38:37 -08003404 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
Alan Coxb65b5b52006-06-27 02:54:05 -07003406 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 outb(SVRR, iobase);
3408 svrtype = inb(iobase + EREG_DATA);
3409 if (panelp->nrports > 4) {
3410 outb((SVRR + 0x80), iobase);
3411 svrtype |= inb(iobase + EREG_DATA);
3412 }
3413
3414 if (svrtype & SVRR_RX)
3415 stl_cd1400rxisr(panelp, iobase);
3416 else if (svrtype & SVRR_TX)
3417 stl_cd1400txisr(panelp, iobase);
3418 else if (svrtype & SVRR_MDM)
3419 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003420
3421 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422}
3423
3424/*****************************************************************************/
3425
3426/*
3427 * Interrupt service routine for cd1400 panels.
3428 */
3429
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003430static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431{
3432 unsigned char svrtype;
3433
Jiri Slabya0564e12006-12-08 02:38:37 -08003434 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435
3436 outb(SVRR, iobase);
3437 svrtype = inb(iobase + EREG_DATA);
3438 outb((SVRR + 0x80), iobase);
3439 svrtype |= inb(iobase + EREG_DATA);
3440 if (svrtype & SVRR_RX)
3441 stl_cd1400rxisr(panelp, iobase);
3442 else if (svrtype & SVRR_TX)
3443 stl_cd1400txisr(panelp, iobase);
3444 else if (svrtype & SVRR_MDM)
3445 stl_cd1400mdmisr(panelp, iobase);
3446}
3447
3448
3449/*****************************************************************************/
3450
3451/*
3452 * Unfortunately we need to handle breaks in the TX data stream, since
3453 * this is the only way to generate them on the cd1400.
3454 */
3455
Jiri Slaby60be4812006-12-08 02:38:40 -08003456static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457{
3458 if (portp->brklen == 1) {
3459 outb((COR2 + portp->uartaddr), ioaddr);
3460 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3461 (ioaddr + EREG_DATA));
3462 outb((TDR + portp->uartaddr), ioaddr);
3463 outb(ETC_CMD, (ioaddr + EREG_DATA));
3464 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3465 outb((SRER + portp->uartaddr), ioaddr);
3466 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3467 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003468 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 } else if (portp->brklen > 1) {
3470 outb((TDR + portp->uartaddr), ioaddr);
3471 outb(ETC_CMD, (ioaddr + EREG_DATA));
3472 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3473 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003474 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475 } else {
3476 outb((COR2 + portp->uartaddr), ioaddr);
3477 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3478 (ioaddr + EREG_DATA));
3479 portp->brklen = 0;
3480 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003481 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482}
3483
3484/*****************************************************************************/
3485
3486/*
3487 * Transmit interrupt handler. This has gotta be fast! Handling TX
3488 * chars is pretty simple, stuff as many as possible from the TX buffer
3489 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3490 * are embedded as commands in the data stream. Oh no, had to use a goto!
3491 * This could be optimized more, will do when I get time...
3492 * In practice it is possible that interrupts are enabled but that the
3493 * port has been hung up. Need to handle not having any TX buffer here,
3494 * this is done by using the side effect that head and tail will also
3495 * be NULL if the buffer has been freed.
3496 */
3497
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003498static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003500 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 int len, stlen;
3502 char *head, *tail;
3503 unsigned char ioack, srer;
3504
Jiri Slabya0564e12006-12-08 02:38:37 -08003505 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506
3507 ioack = inb(ioaddr + EREG_TXACK);
3508 if (((ioack & panelp->ackmask) != 0) ||
3509 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3510 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3511 return;
3512 }
3513 portp = panelp->ports[(ioack >> 3)];
3514
3515/*
3516 * Unfortunately we need to handle breaks in the data stream, since
3517 * this is the only way to generate them on the cd1400. Do it now if
3518 * a break is to be sent.
3519 */
3520 if (portp->brklen != 0)
3521 if (stl_cd1400breakisr(portp, ioaddr))
3522 goto stl_txalldone;
3523
3524 head = portp->tx.head;
3525 tail = portp->tx.tail;
3526 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3527 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3528 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3529 set_bit(ASYI_TXLOW, &portp->istate);
3530 schedule_work(&portp->tqueue);
3531 }
3532
3533 if (len == 0) {
3534 outb((SRER + portp->uartaddr), ioaddr);
3535 srer = inb(ioaddr + EREG_DATA);
3536 if (srer & SRER_TXDATA) {
3537 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3538 } else {
3539 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3540 clear_bit(ASYI_TXBUSY, &portp->istate);
3541 }
3542 outb(srer, (ioaddr + EREG_DATA));
3543 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003544 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08003546 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547 outb((TDR + portp->uartaddr), ioaddr);
3548 outsb((ioaddr + EREG_DATA), tail, stlen);
3549 len -= stlen;
3550 tail += stlen;
3551 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3552 tail = portp->tx.buf;
3553 if (len > 0) {
3554 outsb((ioaddr + EREG_DATA), tail, len);
3555 tail += len;
3556 }
3557 portp->tx.tail = tail;
3558 }
3559
3560stl_txalldone:
3561 outb((EOSRR + portp->uartaddr), ioaddr);
3562 outb(0, (ioaddr + EREG_DATA));
3563}
3564
3565/*****************************************************************************/
3566
3567/*
3568 * Receive character interrupt handler. Determine if we have good chars
3569 * or bad chars and then process appropriately. Good chars are easy
3570 * just shove the lot into the RX buffer and set all status byte to 0.
3571 * If a bad RX char then process as required. This routine needs to be
3572 * fast! In practice it is possible that we get an interrupt on a port
3573 * that is closed. This can happen on hangups - since they completely
3574 * shutdown a port not in user context. Need to handle this case.
3575 */
3576
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003577static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003579 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580 struct tty_struct *tty;
3581 unsigned int ioack, len, buflen;
3582 unsigned char status;
3583 char ch;
3584
Jiri Slabya0564e12006-12-08 02:38:37 -08003585 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586
3587 ioack = inb(ioaddr + EREG_RXACK);
3588 if ((ioack & panelp->ackmask) != 0) {
3589 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3590 return;
3591 }
3592 portp = panelp->ports[(ioack >> 3)];
3593 tty = portp->tty;
3594
3595 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3596 outb((RDCR + portp->uartaddr), ioaddr);
3597 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003598 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08003599 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 outb((RDSR + portp->uartaddr), ioaddr);
3601 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3602 portp->stats.rxlost += len;
3603 portp->stats.rxtotal += len;
3604 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003605 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003607 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003609 tty_prepare_flip_string(tty, &ptr, len);
3610 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 tty_schedule_flip(tty);
3612 portp->stats.rxtotal += len;
3613 }
3614 }
3615 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3616 outb((RDSR + portp->uartaddr), ioaddr);
3617 status = inb(ioaddr + EREG_DATA);
3618 ch = inb(ioaddr + EREG_DATA);
3619 if (status & ST_PARITY)
3620 portp->stats.rxparity++;
3621 if (status & ST_FRAMING)
3622 portp->stats.rxframing++;
3623 if (status & ST_OVERRUN)
3624 portp->stats.rxoverrun++;
3625 if (status & ST_BREAK)
3626 portp->stats.rxbreaks++;
3627 if (status & ST_SCHARMASK) {
3628 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3629 portp->stats.txxon++;
3630 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3631 portp->stats.txxoff++;
3632 goto stl_rxalldone;
3633 }
Alan Cox33f0f882006-01-09 20:54:13 -08003634 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 if (portp->rxmarkmsk & status) {
3636 if (status & ST_BREAK) {
3637 status = TTY_BREAK;
3638 if (portp->flags & ASYNC_SAK) {
3639 do_SAK(tty);
3640 BRDENABLE(portp->brdnr, portp->pagenr);
3641 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003642 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003644 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003646 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003648 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003650 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003652 tty_insert_flip_char(tty, ch, status);
3653 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654 }
3655 } else {
3656 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3657 return;
3658 }
3659
3660stl_rxalldone:
3661 outb((EOSRR + portp->uartaddr), ioaddr);
3662 outb(0, (ioaddr + EREG_DATA));
3663}
3664
3665/*****************************************************************************/
3666
3667/*
3668 * Modem interrupt handler. The is called when the modem signal line
3669 * (DCD) has changed state. Leave most of the work to the off-level
3670 * processing routine.
3671 */
3672
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003673static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003675 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676 unsigned int ioack;
3677 unsigned char misr;
3678
Jiri Slabya0564e12006-12-08 02:38:37 -08003679 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680
3681 ioack = inb(ioaddr + EREG_MDACK);
3682 if (((ioack & panelp->ackmask) != 0) ||
3683 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3684 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3685 return;
3686 }
3687 portp = panelp->ports[(ioack >> 3)];
3688
3689 outb((MISR + portp->uartaddr), ioaddr);
3690 misr = inb(ioaddr + EREG_DATA);
3691 if (misr & MISR_DCD) {
3692 set_bit(ASYI_DCDCHANGE, &portp->istate);
3693 schedule_work(&portp->tqueue);
3694 portp->stats.modem++;
3695 }
3696
3697 outb((EOSRR + portp->uartaddr), ioaddr);
3698 outb(0, (ioaddr + EREG_DATA));
3699}
3700
3701/*****************************************************************************/
3702/* SC26198 HARDWARE FUNCTIONS */
3703/*****************************************************************************/
3704
3705/*
3706 * These functions get/set/update the registers of the sc26198 UARTs.
3707 * Access to the sc26198 registers is via an address/data io port pair.
3708 * (Maybe should make this inline...)
3709 */
3710
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003711static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712{
3713 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003714 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715}
3716
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003717static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718{
3719 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3720 outb(value, (portp->ioaddr + XP_DATA));
3721}
3722
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003723static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724{
3725 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3726 if (inb(portp->ioaddr + XP_DATA) != value) {
3727 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003728 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003730 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731}
3732
3733/*****************************************************************************/
3734
3735/*
3736 * Functions to get and set the sc26198 global registers.
3737 */
3738
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003739static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740{
3741 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003742 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743}
3744
3745#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003746static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747{
3748 outb(regnr, (portp->ioaddr + XP_ADDR));
3749 outb(value, (portp->ioaddr + XP_DATA));
3750}
3751#endif
3752
3753/*****************************************************************************/
3754
3755/*
3756 * Inbitialize the UARTs in a panel. We don't care what sort of board
3757 * these ports are on - since the port io registers are almost
3758 * identical when dealing with ports.
3759 */
3760
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003761static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762{
3763 int chipmask, i;
3764 int nrchips, ioaddr;
3765
Jiri Slabya0564e12006-12-08 02:38:37 -08003766 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767
3768 BRDENABLE(panelp->brdnr, panelp->pagenr);
3769
3770/*
3771 * Check that each chip is present and started up OK.
3772 */
3773 chipmask = 0;
3774 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3775 if (brdp->brdtype == BRD_ECHPCI)
3776 outb(panelp->pagenr, brdp->ioctrl);
3777
Jiri Slabyc62429d2006-12-08 02:39:14 -08003778 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 ioaddr = panelp->iobase + (i * 4);
3780 outb(SCCR, (ioaddr + XP_ADDR));
3781 outb(CR_RESETALL, (ioaddr + XP_DATA));
3782 outb(TSTR, (ioaddr + XP_ADDR));
3783 if (inb(ioaddr + XP_DATA) != 0) {
3784 printk("STALLION: sc26198 not responding, "
3785 "brd=%d panel=%d chip=%d\n",
3786 panelp->brdnr, panelp->panelnr, i);
3787 continue;
3788 }
3789 chipmask |= (0x1 << i);
3790 outb(GCCR, (ioaddr + XP_ADDR));
3791 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3792 outb(WDTRCR, (ioaddr + XP_ADDR));
3793 outb(0xff, (ioaddr + XP_DATA));
3794 }
3795
3796 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003797 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798}
3799
3800/*****************************************************************************/
3801
3802/*
3803 * Initialize hardware specific port registers.
3804 */
3805
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003806static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807{
Jiri Slabya0564e12006-12-08 02:38:37 -08003808 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3809 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810
Jiri Slaby615e4a72006-12-08 02:38:38 -08003811 if ((brdp == NULL) || (panelp == NULL) ||
3812 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 return;
3814
3815 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3816 portp->uartaddr = (portp->portnr & 0x07) << 4;
3817 portp->pagenr = panelp->pagenr;
3818 portp->hwid = 0x1;
3819
3820 BRDENABLE(portp->brdnr, portp->pagenr);
3821 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3822 BRDDISABLE(portp->brdnr);
3823}
3824
3825/*****************************************************************************/
3826
3827/*
3828 * Set up the sc26198 registers for a port based on the termios port
3829 * settings.
3830 */
3831
Alan Cox606d0992006-12-08 02:38:45 -08003832static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003834 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 unsigned long flags;
3836 unsigned int baudrate;
3837 unsigned char mr0, mr1, mr2, clk;
3838 unsigned char imron, imroff, iopr, ipr;
3839
3840 mr0 = 0;
3841 mr1 = 0;
3842 mr2 = 0;
3843 clk = 0;
3844 iopr = 0;
3845 imron = 0;
3846 imroff = 0;
3847
3848 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003849 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850 return;
3851
3852/*
3853 * Set up the RX char ignore mask with those RX error types we
3854 * can ignore.
3855 */
3856 portp->rxignoremsk = 0;
3857 if (tiosp->c_iflag & IGNPAR)
3858 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3859 SR_RXOVERRUN);
3860 if (tiosp->c_iflag & IGNBRK)
3861 portp->rxignoremsk |= SR_RXBREAK;
3862
3863 portp->rxmarkmsk = SR_RXOVERRUN;
3864 if (tiosp->c_iflag & (INPCK | PARMRK))
3865 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3866 if (tiosp->c_iflag & BRKINT)
3867 portp->rxmarkmsk |= SR_RXBREAK;
3868
3869/*
3870 * Go through the char size, parity and stop bits and set all the
3871 * option register appropriately.
3872 */
3873 switch (tiosp->c_cflag & CSIZE) {
3874 case CS5:
3875 mr1 |= MR1_CS5;
3876 break;
3877 case CS6:
3878 mr1 |= MR1_CS6;
3879 break;
3880 case CS7:
3881 mr1 |= MR1_CS7;
3882 break;
3883 default:
3884 mr1 |= MR1_CS8;
3885 break;
3886 }
3887
3888 if (tiosp->c_cflag & CSTOPB)
3889 mr2 |= MR2_STOP2;
3890 else
3891 mr2 |= MR2_STOP1;
3892
3893 if (tiosp->c_cflag & PARENB) {
3894 if (tiosp->c_cflag & PARODD)
3895 mr1 |= (MR1_PARENB | MR1_PARODD);
3896 else
3897 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003898 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900
3901 mr1 |= MR1_ERRBLOCK;
3902
3903/*
3904 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3905 * space for hardware flow control and the like. This should be set to
3906 * VMIN.
3907 */
3908 mr2 |= MR2_RXFIFOHALF;
3909
3910/*
3911 * Calculate the baud rate timers. For now we will just assume that
3912 * the input and output baud are the same. The sc26198 has a fixed
3913 * baud rate table, so only discrete baud rates possible.
3914 */
3915 baudrate = tiosp->c_cflag & CBAUD;
3916 if (baudrate & CBAUDEX) {
3917 baudrate &= ~CBAUDEX;
3918 if ((baudrate < 1) || (baudrate > 4))
3919 tiosp->c_cflag &= ~CBAUDEX;
3920 else
3921 baudrate += 15;
3922 }
3923 baudrate = stl_baudrates[baudrate];
3924 if ((tiosp->c_cflag & CBAUD) == B38400) {
3925 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3926 baudrate = 57600;
3927 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3928 baudrate = 115200;
3929 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3930 baudrate = 230400;
3931 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3932 baudrate = 460800;
3933 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3934 baudrate = (portp->baud_base / portp->custom_divisor);
3935 }
3936 if (baudrate > STL_SC26198MAXBAUD)
3937 baudrate = STL_SC26198MAXBAUD;
3938
Jiri Slabyc62429d2006-12-08 02:39:14 -08003939 if (baudrate > 0)
3940 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 if (baudrate <= sc26198_baudtable[clk])
3942 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943
3944/*
3945 * Check what form of modem signaling is required and set it up.
3946 */
3947 if (tiosp->c_cflag & CLOCAL) {
3948 portp->flags &= ~ASYNC_CHECK_CD;
3949 } else {
3950 iopr |= IOPR_DCDCOS;
3951 imron |= IR_IOPORT;
3952 portp->flags |= ASYNC_CHECK_CD;
3953 }
3954
3955/*
3956 * Setup sc26198 enhanced modes if we can. In particular we want to
3957 * handle as much of the flow control as possible automatically. As
3958 * well as saving a few CPU cycles it will also greatly improve flow
3959 * control reliability.
3960 */
3961 if (tiosp->c_iflag & IXON) {
3962 mr0 |= MR0_SWFTX | MR0_SWFT;
3963 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003964 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003966
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 if (tiosp->c_iflag & IXOFF)
3968 mr0 |= MR0_SWFRX;
3969
3970 if (tiosp->c_cflag & CRTSCTS) {
3971 mr2 |= MR2_AUTOCTS;
3972 mr1 |= MR1_AUTORTS;
3973 }
3974
3975/*
3976 * All sc26198 register values calculated so go through and set
3977 * them all up.
3978 */
3979
Jiri Slabya0564e12006-12-08 02:38:37 -08003980 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003982 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3983 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3984 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3986 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
Alan Coxb65b5b52006-06-27 02:54:05 -07003988 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 BRDENABLE(portp->brdnr, portp->pagenr);
3990 stl_sc26198setreg(portp, IMR, 0);
3991 stl_sc26198updatereg(portp, MR0, mr0);
3992 stl_sc26198updatereg(portp, MR1, mr1);
3993 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3994 stl_sc26198updatereg(portp, MR2, mr2);
3995 stl_sc26198updatereg(portp, IOPIOR,
3996 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3997
3998 if (baudrate > 0) {
3999 stl_sc26198setreg(portp, TXCSR, clk);
4000 stl_sc26198setreg(portp, RXCSR, clk);
4001 }
4002
4003 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4004 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4005
4006 ipr = stl_sc26198getreg(portp, IPR);
4007 if (ipr & IPR_DCD)
4008 portp->sigs &= ~TIOCM_CD;
4009 else
4010 portp->sigs |= TIOCM_CD;
4011
4012 portp->imr = (portp->imr & ~imroff) | imron;
4013 stl_sc26198setreg(portp, IMR, portp->imr);
4014 BRDDISABLE(portp->brdnr);
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 * Set the state of the DTR and RTS signals.
4022 */
4023
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004024static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025{
4026 unsigned char iopioron, iopioroff;
4027 unsigned long flags;
4028
Jiri Slabya0564e12006-12-08 02:38:37 -08004029 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4030 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
4032 iopioron = 0;
4033 iopioroff = 0;
4034 if (dtr == 0)
4035 iopioroff |= IPR_DTR;
4036 else if (dtr > 0)
4037 iopioron |= IPR_DTR;
4038 if (rts == 0)
4039 iopioroff |= IPR_RTS;
4040 else if (rts > 0)
4041 iopioron |= IPR_RTS;
4042
Alan Coxb65b5b52006-06-27 02:54:05 -07004043 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 BRDENABLE(portp->brdnr, portp->pagenr);
4045 stl_sc26198setreg(portp, IOPIOR,
4046 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4047 BRDDISABLE(portp->brdnr);
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 * Return the state of the signals.
4055 */
4056
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004057static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058{
4059 unsigned char ipr;
4060 unsigned long flags;
4061 int sigs;
4062
Jiri Slabya0564e12006-12-08 02:38:37 -08004063 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064
Alan Coxb65b5b52006-06-27 02:54:05 -07004065 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 BRDENABLE(portp->brdnr, portp->pagenr);
4067 ipr = stl_sc26198getreg(portp, IPR);
4068 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004069 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
4071 sigs = 0;
4072 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4073 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4074 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4075 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4076 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004077 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078}
4079
4080/*****************************************************************************/
4081
4082/*
4083 * Enable/Disable the Transmitter and/or Receiver.
4084 */
4085
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004086static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087{
4088 unsigned char ccr;
4089 unsigned long flags;
4090
Jiri Slabya0564e12006-12-08 02:38:37 -08004091 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092
4093 ccr = portp->crenable;
4094 if (tx == 0)
4095 ccr &= ~CR_TXENABLE;
4096 else if (tx > 0)
4097 ccr |= CR_TXENABLE;
4098 if (rx == 0)
4099 ccr &= ~CR_RXENABLE;
4100 else if (rx > 0)
4101 ccr |= CR_RXENABLE;
4102
Alan Coxb65b5b52006-06-27 02:54:05 -07004103 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 BRDENABLE(portp->brdnr, portp->pagenr);
4105 stl_sc26198setreg(portp, SCCR, ccr);
4106 BRDDISABLE(portp->brdnr);
4107 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004108 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109}
4110
4111/*****************************************************************************/
4112
4113/*
4114 * Start/stop the Transmitter and/or Receiver.
4115 */
4116
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004117static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118{
4119 unsigned char imr;
4120 unsigned long flags;
4121
Jiri Slabya0564e12006-12-08 02:38:37 -08004122 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
4124 imr = portp->imr;
4125 if (tx == 0)
4126 imr &= ~IR_TXRDY;
4127 else if (tx == 1)
4128 imr |= IR_TXRDY;
4129 if (rx == 0)
4130 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4131 else if (rx > 0)
4132 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4133
Alan Coxb65b5b52006-06-27 02:54:05 -07004134 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 BRDENABLE(portp->brdnr, portp->pagenr);
4136 stl_sc26198setreg(portp, IMR, imr);
4137 BRDDISABLE(portp->brdnr);
4138 portp->imr = imr;
4139 if (tx > 0)
4140 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004141 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142}
4143
4144/*****************************************************************************/
4145
4146/*
4147 * Disable all interrupts from this port.
4148 */
4149
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004150static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151{
4152 unsigned long flags;
4153
Jiri Slabya0564e12006-12-08 02:38:37 -08004154 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
Alan Coxb65b5b52006-06-27 02:54:05 -07004156 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 BRDENABLE(portp->brdnr, portp->pagenr);
4158 portp->imr = 0;
4159 stl_sc26198setreg(portp, IMR, 0);
4160 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004161 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162}
4163
4164/*****************************************************************************/
4165
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004166static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167{
4168 unsigned long flags;
4169
Jiri Slabya0564e12006-12-08 02:38:37 -08004170 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171
Alan Coxb65b5b52006-06-27 02:54:05 -07004172 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 BRDENABLE(portp->brdnr, portp->pagenr);
4174 if (len == 1) {
4175 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4176 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004177 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004179
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004181 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182}
4183
4184/*****************************************************************************/
4185
4186/*
4187 * Take flow control actions...
4188 */
4189
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004190static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191{
4192 struct tty_struct *tty;
4193 unsigned long flags;
4194 unsigned char mr0;
4195
Jiri Slabya0564e12006-12-08 02:38:37 -08004196 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197
Jiri Slaby615e4a72006-12-08 02:38:38 -08004198 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 return;
4200 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004201 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 return;
4203
Alan Coxb65b5b52006-06-27 02:54:05 -07004204 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 BRDENABLE(portp->brdnr, portp->pagenr);
4206
4207 if (state) {
4208 if (tty->termios->c_iflag & IXOFF) {
4209 mr0 = stl_sc26198getreg(portp, MR0);
4210 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4211 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4212 mr0 |= MR0_SWFRX;
4213 portp->stats.rxxon++;
4214 stl_sc26198wait(portp);
4215 stl_sc26198setreg(portp, MR0, mr0);
4216 }
4217/*
4218 * Question: should we return RTS to what it was before? It may
4219 * have been set by an ioctl... Suppose not, since if you have
4220 * hardware flow control set then it is pretty silly to go and
4221 * set the RTS line by hand.
4222 */
4223 if (tty->termios->c_cflag & CRTSCTS) {
4224 stl_sc26198setreg(portp, MR1,
4225 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4226 stl_sc26198setreg(portp, IOPIOR,
4227 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4228 portp->stats.rxrtson++;
4229 }
4230 } else {
4231 if (tty->termios->c_iflag & IXOFF) {
4232 mr0 = stl_sc26198getreg(portp, MR0);
4233 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4234 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4235 mr0 &= ~MR0_SWFRX;
4236 portp->stats.rxxoff++;
4237 stl_sc26198wait(portp);
4238 stl_sc26198setreg(portp, MR0, mr0);
4239 }
4240 if (tty->termios->c_cflag & CRTSCTS) {
4241 stl_sc26198setreg(portp, MR1,
4242 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4243 stl_sc26198setreg(portp, IOPIOR,
4244 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4245 portp->stats.rxrtsoff++;
4246 }
4247 }
4248
4249 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004250 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251}
4252
4253/*****************************************************************************/
4254
4255/*
4256 * Send a flow control character.
4257 */
4258
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004259static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260{
4261 struct tty_struct *tty;
4262 unsigned long flags;
4263 unsigned char mr0;
4264
Jiri Slabya0564e12006-12-08 02:38:37 -08004265 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266
Jiri Slaby615e4a72006-12-08 02:38:38 -08004267 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 return;
4269 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004270 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 return;
4272
Alan Coxb65b5b52006-06-27 02:54:05 -07004273 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 BRDENABLE(portp->brdnr, portp->pagenr);
4275 if (state) {
4276 mr0 = stl_sc26198getreg(portp, MR0);
4277 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4278 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4279 mr0 |= MR0_SWFRX;
4280 portp->stats.rxxon++;
4281 stl_sc26198wait(portp);
4282 stl_sc26198setreg(portp, MR0, mr0);
4283 } else {
4284 mr0 = stl_sc26198getreg(portp, MR0);
4285 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4286 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4287 mr0 &= ~MR0_SWFRX;
4288 portp->stats.rxxoff++;
4289 stl_sc26198wait(portp);
4290 stl_sc26198setreg(portp, MR0, mr0);
4291 }
4292 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004293 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294}
4295
4296/*****************************************************************************/
4297
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004298static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299{
4300 unsigned long flags;
4301
Jiri Slabya0564e12006-12-08 02:38:37 -08004302 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303
Jiri Slaby615e4a72006-12-08 02:38:38 -08004304 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 return;
4306
Alan Coxb65b5b52006-06-27 02:54:05 -07004307 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 BRDENABLE(portp->brdnr, portp->pagenr);
4309 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4310 stl_sc26198setreg(portp, SCCR, portp->crenable);
4311 BRDDISABLE(portp->brdnr);
4312 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004313 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314}
4315
4316/*****************************************************************************/
4317
4318/*
4319 * Return the current state of data flow on this port. This is only
4320 * really interresting when determining if data has fully completed
4321 * transmission or not... The sc26198 interrupt scheme cannot
4322 * determine when all data has actually drained, so we need to
4323 * check the port statusy register to be sure.
4324 */
4325
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004326static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327{
4328 unsigned long flags;
4329 unsigned char sr;
4330
Jiri Slabya0564e12006-12-08 02:38:37 -08004331 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332
Jiri Slaby615e4a72006-12-08 02:38:38 -08004333 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004334 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004336 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
Alan Coxb65b5b52006-06-27 02:54:05 -07004338 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 BRDENABLE(portp->brdnr, portp->pagenr);
4340 sr = stl_sc26198getreg(portp, SR);
4341 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004342 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Jesper Juhl014c2542006-01-15 02:37:08 +01004344 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345}
4346
4347/*****************************************************************************/
4348
4349/*
4350 * Delay for a small amount of time, to give the sc26198 a chance
4351 * to process a command...
4352 */
4353
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004354static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355{
4356 int i;
4357
Jiri Slabya0564e12006-12-08 02:38:37 -08004358 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359
Jiri Slaby615e4a72006-12-08 02:38:38 -08004360 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361 return;
4362
Jiri Slabyc62429d2006-12-08 02:39:14 -08004363 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364 stl_sc26198getglobreg(portp, TSTR);
4365}
4366
4367/*****************************************************************************/
4368
4369/*
4370 * If we are TX flow controlled and in IXANY mode then we may
4371 * need to unflow control here. We gotta do this because of the
4372 * automatic flow control modes of the sc26198.
4373 */
4374
Jiri Slaby60be4812006-12-08 02:38:40 -08004375static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376{
4377 unsigned char mr0;
4378
4379 mr0 = stl_sc26198getreg(portp, MR0);
4380 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4381 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4382 stl_sc26198wait(portp);
4383 stl_sc26198setreg(portp, MR0, mr0);
4384 clear_bit(ASYI_TXFLOWED, &portp->istate);
4385}
4386
4387/*****************************************************************************/
4388
4389/*
4390 * Interrupt service routine for sc26198 panels.
4391 */
4392
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004393static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004395 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 unsigned int iack;
4397
Alan Coxb65b5b52006-06-27 02:54:05 -07004398 spin_lock(&brd_lock);
4399
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400/*
4401 * Work around bug in sc26198 chip... Cannot have A6 address
4402 * line of UART high, else iack will be returned as 0.
4403 */
4404 outb(0, (iobase + 1));
4405
4406 iack = inb(iobase + XP_IACK);
4407 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4408
4409 if (iack & IVR_RXDATA)
4410 stl_sc26198rxisr(portp, iack);
4411 else if (iack & IVR_TXDATA)
4412 stl_sc26198txisr(portp);
4413 else
4414 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004415
4416 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417}
4418
4419/*****************************************************************************/
4420
4421/*
4422 * Transmit interrupt handler. This has gotta be fast! Handling TX
4423 * chars is pretty simple, stuff as many as possible from the TX buffer
4424 * into the sc26198 FIFO.
4425 * In practice it is possible that interrupts are enabled but that the
4426 * port has been hung up. Need to handle not having any TX buffer here,
4427 * this is done by using the side effect that head and tail will also
4428 * be NULL if the buffer has been freed.
4429 */
4430
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004431static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432{
4433 unsigned int ioaddr;
4434 unsigned char mr0;
4435 int len, stlen;
4436 char *head, *tail;
4437
Jiri Slabya0564e12006-12-08 02:38:37 -08004438 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439
4440 ioaddr = portp->ioaddr;
4441 head = portp->tx.head;
4442 tail = portp->tx.tail;
4443 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4444 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4445 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4446 set_bit(ASYI_TXLOW, &portp->istate);
4447 schedule_work(&portp->tqueue);
4448 }
4449
4450 if (len == 0) {
4451 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4452 mr0 = inb(ioaddr + XP_DATA);
4453 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4454 portp->imr &= ~IR_TXRDY;
4455 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4456 outb(portp->imr, (ioaddr + XP_DATA));
4457 clear_bit(ASYI_TXBUSY, &portp->istate);
4458 } else {
4459 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4460 outb(mr0, (ioaddr + XP_DATA));
4461 }
4462 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004463 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08004465 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 outb(GTXFIFO, (ioaddr + XP_ADDR));
4467 outsb((ioaddr + XP_DATA), tail, stlen);
4468 len -= stlen;
4469 tail += stlen;
4470 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4471 tail = portp->tx.buf;
4472 if (len > 0) {
4473 outsb((ioaddr + XP_DATA), tail, len);
4474 tail += len;
4475 }
4476 portp->tx.tail = tail;
4477 }
4478}
4479
4480/*****************************************************************************/
4481
4482/*
4483 * Receive character interrupt handler. Determine if we have good chars
4484 * or bad chars and then process appropriately. Good chars are easy
4485 * just shove the lot into the RX buffer and set all status byte to 0.
4486 * If a bad RX char then process as required. This routine needs to be
4487 * fast! In practice it is possible that we get an interrupt on a port
4488 * that is closed. This can happen on hangups - since they completely
4489 * shutdown a port not in user context. Need to handle this case.
4490 */
4491
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004492static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493{
4494 struct tty_struct *tty;
4495 unsigned int len, buflen, ioaddr;
4496
Jiri Slabya0564e12006-12-08 02:38:37 -08004497 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498
4499 tty = portp->tty;
4500 ioaddr = portp->ioaddr;
4501 outb(GIBCR, (ioaddr + XP_ADDR));
4502 len = inb(ioaddr + XP_DATA) + 1;
4503
4504 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004505 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08004506 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 outb(GRXFIFO, (ioaddr + XP_ADDR));
4508 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4509 portp->stats.rxlost += len;
4510 portp->stats.rxtotal += len;
4511 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004512 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004514 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004516 tty_prepare_flip_string(tty, &ptr, len);
4517 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518 tty_schedule_flip(tty);
4519 portp->stats.rxtotal += len;
4520 }
4521 }
4522 } else {
4523 stl_sc26198rxbadchars(portp);
4524 }
4525
4526/*
4527 * If we are TX flow controlled and in IXANY mode then we may need
4528 * to unflow control here. We gotta do this because of the automatic
4529 * flow control modes of the sc26198.
4530 */
4531 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004532 if ((tty != NULL) &&
4533 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534 (tty->termios->c_iflag & IXANY)) {
4535 stl_sc26198txunflow(portp, tty);
4536 }
4537 }
4538}
4539
4540/*****************************************************************************/
4541
4542/*
4543 * Process an RX bad character.
4544 */
4545
Jiri Slaby60be4812006-12-08 02:38:40 -08004546static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547{
4548 struct tty_struct *tty;
4549 unsigned int ioaddr;
4550
4551 tty = portp->tty;
4552 ioaddr = portp->ioaddr;
4553
4554 if (status & SR_RXPARITY)
4555 portp->stats.rxparity++;
4556 if (status & SR_RXFRAMING)
4557 portp->stats.rxframing++;
4558 if (status & SR_RXOVERRUN)
4559 portp->stats.rxoverrun++;
4560 if (status & SR_RXBREAK)
4561 portp->stats.rxbreaks++;
4562
Jiri Slaby615e4a72006-12-08 02:38:38 -08004563 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564 ((portp->rxignoremsk & status) == 0)) {
4565 if (portp->rxmarkmsk & status) {
4566 if (status & SR_RXBREAK) {
4567 status = TTY_BREAK;
4568 if (portp->flags & ASYNC_SAK) {
4569 do_SAK(tty);
4570 BRDENABLE(portp->brdnr, portp->pagenr);
4571 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004572 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004574 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004576 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004578 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004580 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582
Alan Cox33f0f882006-01-09 20:54:13 -08004583 tty_insert_flip_char(tty, ch, status);
4584 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585
4586 if (status == 0)
4587 portp->stats.rxtotal++;
4588 }
4589}
4590
4591/*****************************************************************************/
4592
4593/*
4594 * Process all characters in the RX FIFO of the UART. Check all char
4595 * status bytes as well, and process as required. We need to check
4596 * all bytes in the FIFO, in case some more enter the FIFO while we
4597 * are here. To get the exact character error type we need to switch
4598 * into CHAR error mode (that is why we need to make sure we empty
4599 * the FIFO).
4600 */
4601
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004602static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603{
4604 unsigned char status, mr1;
4605 char ch;
4606
4607/*
4608 * To get the precise error type for each character we must switch
4609 * back into CHAR error mode.
4610 */
4611 mr1 = stl_sc26198getreg(portp, MR1);
4612 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4613
4614 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4615 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4616 ch = stl_sc26198getreg(portp, RXFIFO);
4617 stl_sc26198rxbadch(portp, status, ch);
4618 }
4619
4620/*
4621 * To get correct interrupt class we must switch back into BLOCK
4622 * error mode.
4623 */
4624 stl_sc26198setreg(portp, MR1, mr1);
4625}
4626
4627/*****************************************************************************/
4628
4629/*
4630 * Other interrupt handler. This includes modem signals, flow
4631 * control actions, etc. Most stuff is left to off-level interrupt
4632 * processing time.
4633 */
4634
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004635static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636{
4637 unsigned char cir, ipr, xisr;
4638
Jiri Slabya0564e12006-12-08 02:38:37 -08004639 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004640
4641 cir = stl_sc26198getglobreg(portp, CIR);
4642
4643 switch (cir & CIR_SUBTYPEMASK) {
4644 case CIR_SUBCOS:
4645 ipr = stl_sc26198getreg(portp, IPR);
4646 if (ipr & IPR_DCDCHANGE) {
4647 set_bit(ASYI_DCDCHANGE, &portp->istate);
4648 schedule_work(&portp->tqueue);
4649 portp->stats.modem++;
4650 }
4651 break;
4652 case CIR_SUBXONXOFF:
4653 xisr = stl_sc26198getreg(portp, XISR);
4654 if (xisr & XISR_RXXONGOT) {
4655 set_bit(ASYI_TXFLOWED, &portp->istate);
4656 portp->stats.txxoff++;
4657 }
4658 if (xisr & XISR_RXXOFFGOT) {
4659 clear_bit(ASYI_TXFLOWED, &portp->istate);
4660 portp->stats.txxon++;
4661 }
4662 break;
4663 case CIR_SUBBREAK:
4664 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4665 stl_sc26198rxbadchars(portp);
4666 break;
4667 default:
4668 break;
4669 }
4670}
4671
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004672static void stl_free_isabrds(void)
4673{
4674 struct stlbrd *brdp;
4675 unsigned int i;
4676
4677 for (i = 0; i < stl_nrbrds; i++) {
4678 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4679 continue;
4680
4681 free_irq(brdp->irq, brdp);
4682
4683 stl_cleanup_panels(brdp);
4684
4685 release_region(brdp->ioaddr1, brdp->iosize1);
4686 if (brdp->iosize2 > 0)
4687 release_region(brdp->ioaddr2, brdp->iosize2);
4688
4689 kfree(brdp);
4690 stl_brds[i] = NULL;
4691 }
4692}
4693
Jiri Slaby23b85a12006-12-08 02:38:40 -08004694/*
4695 * Loadable module initialization stuff.
4696 */
4697static int __init stallion_module_init(void)
4698{
Jiri Slaby843b5682006-12-08 02:39:12 -08004699 struct stlbrd *brdp;
4700 struct stlconf conf;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004701 unsigned int i;
4702 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004703
4704 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4705
4706 spin_lock_init(&stallion_lock);
4707 spin_lock_init(&brd_lock);
4708
Jiri Slaby843b5682006-12-08 02:39:12 -08004709/*
4710 * Find any dynamically supported boards. That is via module load
4711 * line options.
4712 */
4713 for (i = stl_nrbrds; i < stl_nargs; i++) {
4714 memset(&conf, 0, sizeof(conf));
4715 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4716 continue;
4717 if ((brdp = stl_allocbrd()) == NULL)
4718 continue;
4719 brdp->brdnr = i;
4720 brdp->brdtype = conf.brdtype;
4721 brdp->ioaddr1 = conf.ioaddr1;
4722 brdp->ioaddr2 = conf.ioaddr2;
4723 brdp->irq = conf.irq;
4724 brdp->irqtype = conf.irqtype;
4725 if (stl_brdinit(brdp))
4726 kfree(brdp);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004727 else {
4728 stl_brds[brdp->brdnr] = brdp;
Jiri Slaby843b5682006-12-08 02:39:12 -08004729 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004730 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004731 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004732
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004733 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004734 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004735 if (retval && stl_nrbrds == 0)
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004736 goto err;
4737
Jiri Slaby23b85a12006-12-08 02:38:40 -08004738 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004739 if (!stl_serial) {
4740 retval = -ENOMEM;
4741 goto err_pcidr;
4742 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004743
4744/*
4745 * Set up a character driver for per board stuff. This is mainly used
4746 * to do stats ioctls on the ports.
4747 */
4748 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4749 printk("STALLION: failed to register serial board device\n");
4750
4751 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004752 if (IS_ERR(stallion_class)) {
4753 retval = PTR_ERR(stallion_class);
4754 goto err_reg;
4755 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004756 for (i = 0; i < 4; i++)
4757 class_device_create(stallion_class, NULL,
4758 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4759 "staliomem%d", i);
4760
4761 stl_serial->owner = THIS_MODULE;
4762 stl_serial->driver_name = stl_drvname;
4763 stl_serial->name = "ttyE";
4764 stl_serial->major = STL_SERIALMAJOR;
4765 stl_serial->minor_start = 0;
4766 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4767 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4768 stl_serial->init_termios = stl_deftermios;
4769 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4770 tty_set_operations(stl_serial, &stl_ops);
4771
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004772 retval = tty_register_driver(stl_serial);
4773 if (retval) {
Jiri Slaby23b85a12006-12-08 02:38:40 -08004774 printk("STALLION: failed to register serial driver\n");
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004775 goto err_clsdev;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004776 }
4777
4778 return 0;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004779err_clsdev:
4780 for (i = 0; i < 4; i++)
4781 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4782 class_destroy(stallion_class);
4783err_reg:
4784 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
4785 put_tty_driver(stl_serial);
4786err_pcidr:
4787 pci_unregister_driver(&stl_pcidriver);
4788 stl_free_isabrds();
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004789err:
4790 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004791}
4792
4793static void __exit stallion_module_exit(void)
4794{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004795 int i;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004796
4797 pr_debug("cleanup_module()\n");
4798
4799 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4800 stl_drvversion);
4801
4802/*
4803 * Free up all allocated resources used by the ports. This includes
4804 * memory and interrupts. As part of this process we will also do
4805 * a hangup on every open port - to try to flush out any processes
4806 * hanging onto ports.
4807 */
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004808 tty_unregister_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004809 put_tty_driver(stl_serial);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004810
Jiri Slaby23b85a12006-12-08 02:38:40 -08004811 for (i = 0; i < 4; i++)
4812 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4813 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4814 printk("STALLION: failed to un-register serial memory device, "
4815 "errno=%d\n", -i);
4816 class_destroy(stallion_class);
4817
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004818 pci_unregister_driver(&stl_pcidriver);
4819
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004820 stl_free_isabrds();
Jiri Slaby23b85a12006-12-08 02:38:40 -08004821}
4822
4823module_init(stallion_module_init);
4824module_exit(stallion_module_exit);
4825
4826MODULE_AUTHOR("Greg Ungerer");
4827MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4828MODULE_LICENSE("GPL");