blob: 7612464beeb1dae12df0a442b786dfb267767f47 [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 Slabyca7ed0f2006-12-08 02:38:39 -0800139static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141/*
142 * Per board state flags. Used with the state field of the board struct.
143 * Not really much here!
144 */
145#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800146#define STL_PROBED 0x2
147
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149/*
150 * Define the port structure istate flags. These set of flags are
151 * modified at interrupt time - so setting and reseting them needs
152 * to be atomic. Use the bit clear/setting routines for this.
153 */
154#define ASYI_TXBUSY 1
155#define ASYI_TXLOW 2
156#define ASYI_DCDCHANGE 3
157#define ASYI_TXFLOWED 4
158
159/*
160 * Define an array of board names as printable strings. Handy for
161 * referencing boards when printing trace and stuff.
162 */
163static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
176 NULL,
177 NULL,
178 NULL,
179 NULL,
180 NULL,
181 NULL,
182 NULL,
183 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 "EasyIO",
185 "EC8/32-AT",
186 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800187 NULL,
188 NULL,
189 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 "EC8/32-PCI",
191 "EC8/64-PCI",
192 "EasyIO-PCI",
193};
194
195/*****************************************************************************/
196
197/*
198 * Define some string labels for arguments passed from the module
199 * load line. These allow for easy board definitions, and easy
200 * modification of the io, memory and irq resoucres.
201 */
202static int stl_nargs = 0;
203static char *board0[4];
204static char *board1[4];
205static char *board2[4];
206static char *board3[4];
207
208static char **stl_brdsp[] = {
209 (char **) &board0,
210 (char **) &board1,
211 (char **) &board2,
212 (char **) &board3
213};
214
215/*
216 * Define a set of common board names, and types. This is used to
217 * parse any module arguments.
218 */
219
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800220static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 char *name;
222 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800223} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 { "easyio", BRD_EASYIO },
225 { "eio", BRD_EASYIO },
226 { "20", BRD_EASYIO },
227 { "ec8/32", BRD_ECH },
228 { "ec8/32-at", BRD_ECH },
229 { "ec8/32-isa", BRD_ECH },
230 { "ech", BRD_ECH },
231 { "echat", BRD_ECH },
232 { "21", BRD_ECH },
233 { "ec8/32-mc", BRD_ECHMC },
234 { "ec8/32-mca", BRD_ECHMC },
235 { "echmc", BRD_ECHMC },
236 { "echmca", BRD_ECHMC },
237 { "22", BRD_ECHMC },
238 { "ec8/32-pc", BRD_ECHPCI },
239 { "ec8/32-pci", BRD_ECHPCI },
240 { "26", BRD_ECHPCI },
241 { "ec8/64-pc", BRD_ECH64PCI },
242 { "ec8/64-pci", BRD_ECH64PCI },
243 { "ech-pci", BRD_ECH64PCI },
244 { "echpci", BRD_ECH64PCI },
245 { "echpc", BRD_ECH64PCI },
246 { "27", BRD_ECH64PCI },
247 { "easyio-pc", BRD_EASYIOPCI },
248 { "easyio-pci", BRD_EASYIOPCI },
249 { "eio-pci", BRD_EASYIOPCI },
250 { "eiopci", BRD_EASYIOPCI },
251 { "28", BRD_EASYIOPCI },
252};
253
254/*
255 * Define the module agruments.
256 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258module_param_array(board0, charp, &stl_nargs, 0);
259MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
260module_param_array(board1, charp, &stl_nargs, 0);
261MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
262module_param_array(board2, charp, &stl_nargs, 0);
263MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
264module_param_array(board3, charp, &stl_nargs, 0);
265MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
266
267/*****************************************************************************/
268
269/*
270 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
271 * to the directly accessible io ports of these boards (not the uarts -
272 * they are in cd1400.h and sc26198.h).
273 */
274#define EIO_8PORTRS 0x04
275#define EIO_4PORTRS 0x05
276#define EIO_8PORTDI 0x00
277#define EIO_8PORTM 0x06
278#define EIO_MK3 0x03
279#define EIO_IDBITMASK 0x07
280
281#define EIO_BRDMASK 0xf0
282#define ID_BRD4 0x10
283#define ID_BRD8 0x20
284#define ID_BRD16 0x30
285
286#define EIO_INTRPEND 0x08
287#define EIO_INTEDGE 0x00
288#define EIO_INTLEVEL 0x08
289#define EIO_0WS 0x10
290
291#define ECH_ID 0xa0
292#define ECH_IDBITMASK 0xe0
293#define ECH_BRDENABLE 0x08
294#define ECH_BRDDISABLE 0x00
295#define ECH_INTENABLE 0x01
296#define ECH_INTDISABLE 0x00
297#define ECH_INTLEVEL 0x02
298#define ECH_INTEDGE 0x00
299#define ECH_INTRPEND 0x01
300#define ECH_BRDRESET 0x01
301
302#define ECHMC_INTENABLE 0x01
303#define ECHMC_BRDRESET 0x02
304
305#define ECH_PNLSTATUS 2
306#define ECH_PNL16PORT 0x20
307#define ECH_PNLIDMASK 0x07
308#define ECH_PNLXPID 0x40
309#define ECH_PNLINTRPEND 0x80
310
311#define ECH_ADDR2MASK 0x1e0
312
313/*
314 * Define the vector mapping bits for the programmable interrupt board
315 * hardware. These bits encode the interrupt for the board to use - it
316 * is software selectable (except the EIO-8M).
317 */
318static unsigned char stl_vecmap[] = {
319 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
320 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
321};
322
323/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700324 * Lock ordering is that you may not take stallion_lock holding
325 * brd_lock.
326 */
327
328static spinlock_t brd_lock; /* Guard the board mapping */
329static spinlock_t stallion_lock; /* Guard the tty driver */
330
331/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 * Set up enable and disable macros for the ECH boards. They require
333 * the secondary io address space to be activated and deactivated.
334 * This way all ECH boards can share their secondary io region.
335 * If this is an ECH-PCI board then also need to set the page pointer
336 * to point to the correct page.
337 */
338#define BRDENABLE(brdnr,pagenr) \
339 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
340 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
341 stl_brds[(brdnr)]->ioctrl); \
342 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
343 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
344
345#define BRDDISABLE(brdnr) \
346 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
347 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
348 stl_brds[(brdnr)]->ioctrl);
349
350#define STL_CD1400MAXBAUD 230400
351#define STL_SC26198MAXBAUD 460800
352
353#define STL_BAUDBASE 115200
354#define STL_CLOSEDELAY (5 * HZ / 10)
355
356/*****************************************************************************/
357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358/*
359 * Define the Stallion PCI vendor and device IDs.
360 */
361#ifndef PCI_VENDOR_ID_STALLION
362#define PCI_VENDOR_ID_STALLION 0x124d
363#endif
364#ifndef PCI_DEVICE_ID_ECHPCI832
365#define PCI_DEVICE_ID_ECHPCI832 0x0000
366#endif
367#ifndef PCI_DEVICE_ID_ECHPCI864
368#define PCI_DEVICE_ID_ECHPCI864 0x0002
369#endif
370#ifndef PCI_DEVICE_ID_EIOPCI
371#define PCI_DEVICE_ID_EIOPCI 0x0003
372#endif
373
374/*
375 * Define structure to hold all Stallion PCI boards.
376 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800378static struct pci_device_id stl_pcibrds[] = {
379 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
380 .driver_data = BRD_ECH64PCI },
381 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
382 .driver_data = BRD_EASYIOPCI },
383 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
384 .driver_data = BRD_ECHPCI },
385 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
386 .driver_data = BRD_ECHPCI },
387 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800389MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391/*****************************************************************************/
392
393/*
394 * Define macros to extract a brd/port number from a minor number.
395 */
396#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
397#define MINOR2PORT(min) ((min) & 0x3f)
398
399/*
400 * Define a baud rate table that converts termios baud rate selector
401 * into the actual baud rate value. All baud rate calculations are
402 * based on the actual baud rate required.
403 */
404static unsigned int stl_baudrates[] = {
405 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
406 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
407};
408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409/*****************************************************************************/
410
411/*
412 * Declare all those functions in this driver!
413 */
414
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800416static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800417static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
418static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800419static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421/*
422 * CD1400 uart specific handling functions.
423 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800424static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
425static int stl_cd1400getreg(struct stlport *portp, int regnr);
426static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
427static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
428static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800429static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800430static int stl_cd1400getsignals(struct stlport *portp);
431static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
432static void stl_cd1400ccrwait(struct stlport *portp);
433static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
434static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
435static void stl_cd1400disableintrs(struct stlport *portp);
436static void stl_cd1400sendbreak(struct stlport *portp, int len);
437static void stl_cd1400flowctrl(struct stlport *portp, int state);
438static void stl_cd1400sendflow(struct stlport *portp, int state);
439static void stl_cd1400flush(struct stlport *portp);
440static int stl_cd1400datastate(struct stlport *portp);
441static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
442static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
443static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
444static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
445static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800447static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
449/*
450 * SC26198 uart specific handling functions.
451 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800452static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
453static int stl_sc26198getreg(struct stlport *portp, int regnr);
454static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
455static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
456static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
457static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800458static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800459static int stl_sc26198getsignals(struct stlport *portp);
460static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
461static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
462static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
463static void stl_sc26198disableintrs(struct stlport *portp);
464static void stl_sc26198sendbreak(struct stlport *portp, int len);
465static void stl_sc26198flowctrl(struct stlport *portp, int state);
466static void stl_sc26198sendflow(struct stlport *portp, int state);
467static void stl_sc26198flush(struct stlport *portp);
468static int stl_sc26198datastate(struct stlport *portp);
469static void stl_sc26198wait(struct stlport *portp);
470static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
471static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
472static void stl_sc26198txisr(struct stlport *port);
473static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
474static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
475static void stl_sc26198rxbadchars(struct stlport *portp);
476static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
478/*****************************************************************************/
479
480/*
481 * Generic UART support structure.
482 */
483typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800484 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
485 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800486 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800487 int (*getsignals)(struct stlport *portp);
488 void (*setsignals)(struct stlport *portp, int dtr, int rts);
489 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
490 void (*startrxtx)(struct stlport *portp, int rx, int tx);
491 void (*disableintrs)(struct stlport *portp);
492 void (*sendbreak)(struct stlport *portp, int len);
493 void (*flowctrl)(struct stlport *portp, int state);
494 void (*sendflow)(struct stlport *portp, int state);
495 void (*flush)(struct stlport *portp);
496 int (*datastate)(struct stlport *portp);
497 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498} uart_t;
499
500/*
501 * Define some macros to make calling these functions nice and clean.
502 */
503#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
504#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
505#define stl_setport (* ((uart_t *) portp->uartp)->setport)
506#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
507#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
508#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
509#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
510#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
511#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
512#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
513#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
514#define stl_flush (* ((uart_t *) portp->uartp)->flush)
515#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
516
517/*****************************************************************************/
518
519/*
520 * CD1400 UART specific data initialization.
521 */
522static uart_t stl_cd1400uart = {
523 stl_cd1400panelinit,
524 stl_cd1400portinit,
525 stl_cd1400setport,
526 stl_cd1400getsignals,
527 stl_cd1400setsignals,
528 stl_cd1400enablerxtx,
529 stl_cd1400startrxtx,
530 stl_cd1400disableintrs,
531 stl_cd1400sendbreak,
532 stl_cd1400flowctrl,
533 stl_cd1400sendflow,
534 stl_cd1400flush,
535 stl_cd1400datastate,
536 stl_cd1400eiointr
537};
538
539/*
540 * Define the offsets within the register bank of a cd1400 based panel.
541 * These io address offsets are common to the EasyIO board as well.
542 */
543#define EREG_ADDR 0
544#define EREG_DATA 4
545#define EREG_RXACK 5
546#define EREG_TXACK 6
547#define EREG_MDACK 7
548
549#define EREG_BANKSIZE 8
550
551#define CD1400_CLK 25000000
552#define CD1400_CLK8M 20000000
553
554/*
555 * Define the cd1400 baud rate clocks. These are used when calculating
556 * what clock and divisor to use for the required baud rate. Also
557 * define the maximum baud rate allowed, and the default base baud.
558 */
559static int stl_cd1400clkdivs[] = {
560 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
561};
562
563/*****************************************************************************/
564
565/*
566 * SC26198 UART specific data initization.
567 */
568static uart_t stl_sc26198uart = {
569 stl_sc26198panelinit,
570 stl_sc26198portinit,
571 stl_sc26198setport,
572 stl_sc26198getsignals,
573 stl_sc26198setsignals,
574 stl_sc26198enablerxtx,
575 stl_sc26198startrxtx,
576 stl_sc26198disableintrs,
577 stl_sc26198sendbreak,
578 stl_sc26198flowctrl,
579 stl_sc26198sendflow,
580 stl_sc26198flush,
581 stl_sc26198datastate,
582 stl_sc26198intr
583};
584
585/*
586 * Define the offsets within the register bank of a sc26198 based panel.
587 */
588#define XP_DATA 0
589#define XP_ADDR 1
590#define XP_MODID 2
591#define XP_STATUS 2
592#define XP_IACK 3
593
594#define XP_BANKSIZE 4
595
596/*
597 * Define the sc26198 baud rate table. Offsets within the table
598 * represent the actual baud rate selector of sc26198 registers.
599 */
600static unsigned int sc26198_baudtable[] = {
601 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
602 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
603 230400, 460800, 921600
604};
605
Tobias Klauserfe971072006-01-09 20:54:02 -0800606#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
608/*****************************************************************************/
609
610/*
611 * Define the driver info for a user level control device. Used mainly
612 * to get at port stats - only not using the port device itself.
613 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700614static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 .owner = THIS_MODULE,
616 .ioctl = stl_memioctl,
617};
618
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800619static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 * Check for any arguments passed in on the module load command line.
623 */
624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625/*****************************************************************************/
626
627/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 * Parse the supplied argument string, into the board conf struct.
629 */
630
Jiri Slaby40e82652006-12-08 02:38:41 -0800631static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632{
633 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800634 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Jiri Slabya0564e12006-12-08 02:38:37 -0800636 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
Jiri Slaby615e4a72006-12-08 02:38:38 -0800638 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100639 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800642 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Tobias Klauserfe971072006-01-09 20:54:02 -0800644 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
646 break;
647 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800648 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800650 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 }
652
653 confp->brdtype = stl_brdstr[i].type;
654
655 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800656 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800657 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 i++;
659 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800660 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800661 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 i++;
663 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800664 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800665 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100666 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667}
668
669/*****************************************************************************/
670
671/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 * Allocate a new board structure. Fill out the basic info in it.
673 */
674
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800675static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800677 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800679 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800680 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700681 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800682 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800683 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 }
685
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100687 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688}
689
690/*****************************************************************************/
691
692static int stl_open(struct tty_struct *tty, struct file *filp)
693{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800694 struct stlport *portp;
695 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 unsigned int minordev;
697 int brdnr, panelnr, portnr, rc;
698
Jiri Slabya0564e12006-12-08 02:38:37 -0800699 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
701 minordev = tty->index;
702 brdnr = MINOR2BRD(minordev);
703 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100704 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800706 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100707 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 minordev = MINOR2PORT(minordev);
709 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800710 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 break;
712 if (minordev < brdp->panels[panelnr]->nrports) {
713 portnr = minordev;
714 break;
715 }
716 minordev -= brdp->panels[panelnr]->nrports;
717 }
718 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100719 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800722 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100723 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725/*
726 * On the first open of the device setup the port hardware, and
727 * initialize the per port data structure.
728 */
729 portp->tty = tty;
730 tty->driver_data = portp;
731 portp->refcount++;
732
733 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800734 if (!portp->tx.buf) {
735 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
736 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100737 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 portp->tx.head = portp->tx.buf;
739 portp->tx.tail = portp->tx.buf;
740 }
741 stl_setport(portp, tty->termios);
742 portp->sigs = stl_getsignals(portp);
743 stl_setsignals(portp, 1, 1);
744 stl_enablerxtx(portp, 1, 1);
745 stl_startrxtx(portp, 1, 0);
746 clear_bit(TTY_IO_ERROR, &tty->flags);
747 portp->flags |= ASYNC_INITIALIZED;
748 }
749
750/*
751 * Check if this port is in the middle of closing. If so then wait
752 * until it is closed then return error status, based on flag settings.
753 * The sleep here does not need interrupt protection since the wakeup
754 * for it is done with the same context.
755 */
756 if (portp->flags & ASYNC_CLOSING) {
757 interruptible_sleep_on(&portp->close_wait);
758 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100759 return -EAGAIN;
760 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 }
762
763/*
764 * Based on type of open being done check if it can overlap with any
765 * previous opens still in effect. If we are a normal serial device
766 * then also we might have to wait for carrier.
767 */
768 if (!(filp->f_flags & O_NONBLOCK)) {
769 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100770 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 }
772 portp->flags |= ASYNC_NORMAL_ACTIVE;
773
Jesper Juhl014c2542006-01-15 02:37:08 +0100774 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775}
776
777/*****************************************************************************/
778
779/*
780 * Possibly need to wait for carrier (DCD signal) to come high. Say
781 * maybe because if we are clocal then we don't need to wait...
782 */
783
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800784static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
786 unsigned long flags;
787 int rc, doclocal;
788
Jiri Slabya0564e12006-12-08 02:38:37 -0800789 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 rc = 0;
792 doclocal = 0;
793
Alan Coxb65b5b52006-06-27 02:54:05 -0700794 spin_lock_irqsave(&stallion_lock, flags);
795
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 if (portp->tty->termios->c_cflag & CLOCAL)
797 doclocal++;
798
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 portp->openwaitcnt++;
800 if (! tty_hung_up_p(filp))
801 portp->refcount--;
802
803 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700804 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 stl_setsignals(portp, 1, 1);
806 if (tty_hung_up_p(filp) ||
807 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
808 if (portp->flags & ASYNC_HUP_NOTIFY)
809 rc = -EBUSY;
810 else
811 rc = -ERESTARTSYS;
812 break;
813 }
814 if (((portp->flags & ASYNC_CLOSING) == 0) &&
815 (doclocal || (portp->sigs & TIOCM_CD))) {
816 break;
817 }
818 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;
Jesper Juhl014c2542006-01-15 02:37:08 +01001093 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) &&
1263 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1264 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
1268 rc = 0;
1269
1270 switch (cmd) {
1271 case TIOCGSOFTCAR:
1272 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1273 (unsigned __user *) argp);
1274 break;
1275 case TIOCSSOFTCAR:
1276 if (get_user(ival, (unsigned int __user *) arg))
1277 return -EFAULT;
1278 tty->termios->c_cflag =
1279 (tty->termios->c_cflag & ~CLOCAL) |
1280 (ival ? CLOCAL : 0);
1281 break;
1282 case TIOCGSERIAL:
1283 rc = stl_getserial(portp, argp);
1284 break;
1285 case TIOCSSERIAL:
1286 rc = stl_setserial(portp, argp);
1287 break;
1288 case COM_GETPORTSTATS:
1289 rc = stl_getportstats(portp, argp);
1290 break;
1291 case COM_CLRPORTSTATS:
1292 rc = stl_clrportstats(portp, argp);
1293 break;
1294 case TIOCSERCONFIG:
1295 case TIOCSERGWILD:
1296 case TIOCSERSWILD:
1297 case TIOCSERGETLSR:
1298 case TIOCSERGSTRUCT:
1299 case TIOCSERGETMULTI:
1300 case TIOCSERSETMULTI:
1301 default:
1302 rc = -ENOIOCTLCMD;
1303 break;
1304 }
1305
Jesper Juhl014c2542006-01-15 02:37:08 +01001306 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307}
1308
1309/*****************************************************************************/
1310
Jiri Slaby96b066b2006-12-08 02:38:42 -08001311/*
1312 * Start the transmitter again. Just turn TX interrupts back on.
1313 */
1314
1315static void stl_start(struct tty_struct *tty)
1316{
1317 struct stlport *portp;
1318
1319 pr_debug("stl_start(tty=%p)\n", tty);
1320
1321 if (tty == NULL)
1322 return;
1323 portp = tty->driver_data;
1324 if (portp == NULL)
1325 return;
1326 stl_startrxtx(portp, -1, 1);
1327}
1328
1329/*****************************************************************************/
1330
Alan Cox606d0992006-12-08 02:38:45 -08001331static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001333 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001334 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
Jiri Slabya0564e12006-12-08 02:38:37 -08001336 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Jiri Slaby615e4a72006-12-08 02:38:38 -08001338 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 return;
1340 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001341 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 return;
1343
1344 tiosp = tty->termios;
1345 if ((tiosp->c_cflag == old->c_cflag) &&
1346 (tiosp->c_iflag == old->c_iflag))
1347 return;
1348
1349 stl_setport(portp, tiosp);
1350 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1351 -1);
1352 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1353 tty->hw_stopped = 0;
1354 stl_start(tty);
1355 }
1356 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1357 wake_up_interruptible(&portp->open_wait);
1358}
1359
1360/*****************************************************************************/
1361
1362/*
1363 * Attempt to flow control who ever is sending us data. Based on termios
1364 * settings use software or/and hardware flow control.
1365 */
1366
1367static void stl_throttle(struct tty_struct *tty)
1368{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001369 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
Jiri Slabya0564e12006-12-08 02:38:37 -08001371 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Jiri Slaby615e4a72006-12-08 02:38:38 -08001373 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return;
1375 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001376 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 return;
1378 stl_flowctrl(portp, 0);
1379}
1380
1381/*****************************************************************************/
1382
1383/*
1384 * Unflow control the device sending us data...
1385 */
1386
1387static void stl_unthrottle(struct tty_struct *tty)
1388{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001389 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
Jiri Slabya0564e12006-12-08 02:38:37 -08001391 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Jiri Slaby615e4a72006-12-08 02:38:38 -08001393 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 return;
1395 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001396 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 return;
1398 stl_flowctrl(portp, 1);
1399}
1400
1401/*****************************************************************************/
1402
1403/*
1404 * Stop the transmitter. Basically to do this we will just turn TX
1405 * interrupts off.
1406 */
1407
1408static void stl_stop(struct tty_struct *tty)
1409{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001410 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Jiri Slabya0564e12006-12-08 02:38:37 -08001412 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Jiri Slaby615e4a72006-12-08 02:38:38 -08001414 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 return;
1416 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001417 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 return;
1419 stl_startrxtx(portp, -1, 0);
1420}
1421
1422/*****************************************************************************/
1423
1424/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 * Hangup this port. This is pretty much like closing the port, only
1426 * a little more brutal. No waiting for data to drain. Shutdown the
1427 * port and maybe drop signals.
1428 */
1429
1430static void stl_hangup(struct tty_struct *tty)
1431{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001432 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Jiri Slabya0564e12006-12-08 02:38:37 -08001434 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Jiri Slaby615e4a72006-12-08 02:38:38 -08001436 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 return;
1438 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001439 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 return;
1441
1442 portp->flags &= ~ASYNC_INITIALIZED;
1443 stl_disableintrs(portp);
1444 if (tty->termios->c_cflag & HUPCL)
1445 stl_setsignals(portp, 0, 0);
1446 stl_enablerxtx(portp, 0, 0);
1447 stl_flushbuffer(tty);
1448 portp->istate = 0;
1449 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001450 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001452 portp->tx.buf = NULL;
1453 portp->tx.head = NULL;
1454 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001456 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1458 portp->refcount = 0;
1459 wake_up_interruptible(&portp->open_wait);
1460}
1461
1462/*****************************************************************************/
1463
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464static void stl_breakctl(struct tty_struct *tty, int state)
1465{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001466 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Jiri Slabya0564e12006-12-08 02:38:37 -08001468 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Jiri Slaby615e4a72006-12-08 02:38:38 -08001470 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 return;
1472 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001473 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 return;
1475
1476 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1477}
1478
1479/*****************************************************************************/
1480
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481static void stl_sendxchar(struct tty_struct *tty, char ch)
1482{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001483 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Jiri Slabya0564e12006-12-08 02:38:37 -08001485 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
Jiri Slaby615e4a72006-12-08 02:38:38 -08001487 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 return;
1489 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001490 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 return;
1492
1493 if (ch == STOP_CHAR(tty))
1494 stl_sendflow(portp, 0);
1495 else if (ch == START_CHAR(tty))
1496 stl_sendflow(portp, 1);
1497 else
1498 stl_putchar(tty, ch);
1499}
1500
1501/*****************************************************************************/
1502
1503#define MAXLINE 80
1504
1505/*
1506 * Format info for a specified port. The line is deliberately limited
1507 * to 80 characters. (If it is too long it will be truncated, if too
1508 * short then padded with spaces).
1509 */
1510
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001511static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512{
1513 char *sp;
1514 int sigs, cnt;
1515
1516 sp = pos;
1517 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1518 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1519 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1520
1521 if (portp->stats.rxframing)
1522 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1523 if (portp->stats.rxparity)
1524 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1525 if (portp->stats.rxbreaks)
1526 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1527 if (portp->stats.rxoverrun)
1528 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1529
1530 sigs = stl_getsignals(portp);
1531 cnt = sprintf(sp, "%s%s%s%s%s ",
1532 (sigs & TIOCM_RTS) ? "|RTS" : "",
1533 (sigs & TIOCM_CTS) ? "|CTS" : "",
1534 (sigs & TIOCM_DTR) ? "|DTR" : "",
1535 (sigs & TIOCM_CD) ? "|DCD" : "",
1536 (sigs & TIOCM_DSR) ? "|DSR" : "");
1537 *sp = ' ';
1538 sp += cnt;
1539
1540 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1541 *sp++ = ' ';
1542 if (cnt >= MAXLINE)
1543 pos[(MAXLINE - 2)] = '+';
1544 pos[(MAXLINE - 1)] = '\n';
1545
Jesper Juhl014c2542006-01-15 02:37:08 +01001546 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547}
1548
1549/*****************************************************************************/
1550
1551/*
1552 * Port info, read from the /proc file system.
1553 */
1554
1555static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1556{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001557 struct stlbrd *brdp;
1558 struct stlpanel *panelp;
1559 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 int brdnr, panelnr, portnr, totalport;
1561 int curoff, maxoff;
1562 char *pos;
1563
Jiri Slabya0564e12006-12-08 02:38:37 -08001564 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1565 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
1567 pos = page;
1568 totalport = 0;
1569 curoff = 0;
1570
1571 if (off == 0) {
1572 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1573 stl_drvversion);
1574 while (pos < (page + MAXLINE - 1))
1575 *pos++ = ' ';
1576 *pos++ = '\n';
1577 }
1578 curoff = MAXLINE;
1579
1580/*
1581 * We scan through for each board, panel and port. The offset is
1582 * calculated on the fly, and irrelevant ports are skipped.
1583 */
1584 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1585 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001586 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 continue;
1588 if (brdp->state == 0)
1589 continue;
1590
1591 maxoff = curoff + (brdp->nrports * MAXLINE);
1592 if (off >= maxoff) {
1593 curoff = maxoff;
1594 continue;
1595 }
1596
1597 totalport = brdnr * STL_MAXPORTS;
1598 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1599 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001600 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 continue;
1602
1603 maxoff = curoff + (panelp->nrports * MAXLINE);
1604 if (off >= maxoff) {
1605 curoff = maxoff;
1606 totalport += panelp->nrports;
1607 continue;
1608 }
1609
1610 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1611 totalport++) {
1612 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001613 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 continue;
1615 if (off >= (curoff += MAXLINE))
1616 continue;
1617 if ((pos - page + MAXLINE) > count)
1618 goto stl_readdone;
1619 pos += stl_portinfo(portp, totalport, pos);
1620 }
1621 }
1622 }
1623
1624 *eof = 1;
1625
1626stl_readdone:
1627 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001628 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629}
1630
1631/*****************************************************************************/
1632
1633/*
1634 * All board interrupts are vectored through here first. This code then
1635 * calls off to the approrpriate board interrupt handlers.
1636 */
1637
David Howells7d12e782006-10-05 14:55:46 +01001638static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001640 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Jiri Slabya0564e12006-12-08 02:38:37 -08001642 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
1644 return IRQ_RETVAL((* brdp->isr)(brdp));
1645}
1646
1647/*****************************************************************************/
1648
1649/*
1650 * Interrupt service routine for EasyIO board types.
1651 */
1652
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001653static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001655 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 unsigned int iobase;
1657 int handled = 0;
1658
Alan Coxb65b5b52006-06-27 02:54:05 -07001659 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 panelp = brdp->panels[0];
1661 iobase = panelp->iobase;
1662 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1663 handled = 1;
1664 (* panelp->isr)(panelp, iobase);
1665 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001666 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 return handled;
1668}
1669
1670/*****************************************************************************/
1671
1672/*
1673 * Interrupt service routine for ECH-AT board types.
1674 */
1675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001676static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001678 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 unsigned int ioaddr;
1680 int bnknr;
1681 int handled = 0;
1682
1683 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1684
1685 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1686 handled = 1;
1687 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1688 ioaddr = brdp->bnkstataddr[bnknr];
1689 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1690 panelp = brdp->bnk2panel[bnknr];
1691 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1692 }
1693 }
1694 }
1695
1696 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1697
1698 return handled;
1699}
1700
1701/*****************************************************************************/
1702
1703/*
1704 * Interrupt service routine for ECH-MCA board types.
1705 */
1706
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001707static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001709 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 unsigned int ioaddr;
1711 int bnknr;
1712 int handled = 0;
1713
1714 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1715 handled = 1;
1716 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1717 ioaddr = brdp->bnkstataddr[bnknr];
1718 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1719 panelp = brdp->bnk2panel[bnknr];
1720 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1721 }
1722 }
1723 }
1724 return handled;
1725}
1726
1727/*****************************************************************************/
1728
1729/*
1730 * Interrupt service routine for ECH-PCI board types.
1731 */
1732
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001733static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001735 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 unsigned int ioaddr;
1737 int bnknr, recheck;
1738 int handled = 0;
1739
1740 while (1) {
1741 recheck = 0;
1742 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1743 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1744 ioaddr = brdp->bnkstataddr[bnknr];
1745 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1746 panelp = brdp->bnk2panel[bnknr];
1747 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1748 recheck++;
1749 handled = 1;
1750 }
1751 }
1752 if (! recheck)
1753 break;
1754 }
1755 return handled;
1756}
1757
1758/*****************************************************************************/
1759
1760/*
1761 * Interrupt service routine for ECH-8/64-PCI board types.
1762 */
1763
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001764static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001766 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 unsigned int ioaddr;
1768 int bnknr;
1769 int handled = 0;
1770
1771 while (inb(brdp->ioctrl) & 0x1) {
1772 handled = 1;
1773 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1774 ioaddr = brdp->bnkstataddr[bnknr];
1775 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1776 panelp = brdp->bnk2panel[bnknr];
1777 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1778 }
1779 }
1780 }
1781
1782 return handled;
1783}
1784
1785/*****************************************************************************/
1786
1787/*
1788 * Service an off-level request for some channel.
1789 */
Al Viro3e577a82006-12-06 18:41:45 +00001790static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001792 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 struct tty_struct *tty;
1794 unsigned int oldsigs;
1795
Jiri Slabya0564e12006-12-08 02:38:37 -08001796 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797
Jiri Slaby615e4a72006-12-08 02:38:38 -08001798 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 return;
1800
1801 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001802 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 return;
1804
1805 lock_kernel();
1806 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1807 tty_wakeup(tty);
1808 }
1809 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1810 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1811 oldsigs = portp->sigs;
1812 portp->sigs = stl_getsignals(portp);
1813 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1814 wake_up_interruptible(&portp->open_wait);
1815 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1816 if (portp->flags & ASYNC_CHECK_CD)
1817 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1818 }
1819 }
1820 unlock_kernel();
1821}
1822
1823/*****************************************************************************/
1824
1825/*
1826 * Initialize all the ports on a panel.
1827 */
1828
Jiri Slaby705c1862006-12-08 02:39:11 -08001829static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001831 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 int chipmask, i;
1833
Jiri Slabya0564e12006-12-08 02:38:37 -08001834 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835
1836 chipmask = stl_panelinit(brdp, panelp);
1837
1838/*
1839 * All UART's are initialized (if found!). Now go through and setup
1840 * each ports data structures.
1841 */
1842 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001843 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001844 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001846 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 break;
1848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849
1850 portp->magic = STL_PORTMAGIC;
1851 portp->portnr = i;
1852 portp->brdnr = panelp->brdnr;
1853 portp->panelnr = panelp->panelnr;
1854 portp->uartp = panelp->uartp;
1855 portp->clk = brdp->clk;
1856 portp->baud_base = STL_BAUDBASE;
1857 portp->close_delay = STL_CLOSEDELAY;
1858 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001859 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 init_waitqueue_head(&portp->open_wait);
1861 init_waitqueue_head(&portp->close_wait);
1862 portp->stats.brd = portp->brdnr;
1863 portp->stats.panel = portp->panelnr;
1864 portp->stats.port = portp->portnr;
1865 panelp->ports[i] = portp;
1866 stl_portinit(brdp, panelp, portp);
1867 }
1868
1869 return(0);
1870}
1871
Jiri Slaby3b85b342006-12-08 02:39:10 -08001872static void stl_cleanup_panels(struct stlbrd *brdp)
1873{
1874 struct stlpanel *panelp;
1875 struct stlport *portp;
1876 unsigned int j, k;
1877
1878 for (j = 0; j < STL_MAXPANELS; j++) {
1879 panelp = brdp->panels[j];
1880 if (panelp == NULL)
1881 continue;
1882 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1883 portp = panelp->ports[k];
1884 if (portp == NULL)
1885 continue;
1886 if (portp->tty != NULL)
1887 stl_hangup(portp->tty);
1888 kfree(portp->tx.buf);
1889 kfree(portp);
1890 }
1891 kfree(panelp);
1892 }
1893}
1894
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895/*****************************************************************************/
1896
1897/*
1898 * Try to find and initialize an EasyIO board.
1899 */
1900
Jiri Slaby705c1862006-12-08 02:39:11 -08001901static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001903 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 unsigned int status;
1905 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001906 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907
Jiri Slabya0564e12006-12-08 02:38:37 -08001908 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
1910 brdp->ioctrl = brdp->ioaddr1 + 1;
1911 brdp->iostatus = brdp->ioaddr1 + 2;
1912
1913 status = inb(brdp->iostatus);
1914 if ((status & EIO_IDBITMASK) == EIO_MK3)
1915 brdp->ioctrl++;
1916
1917/*
1918 * Handle board specific stuff now. The real difference is PCI
1919 * or not PCI.
1920 */
1921 if (brdp->brdtype == BRD_EASYIOPCI) {
1922 brdp->iosize1 = 0x80;
1923 brdp->iosize2 = 0x80;
1924 name = "serial(EIO-PCI)";
1925 outb(0x41, (brdp->ioaddr2 + 0x4c));
1926 } else {
1927 brdp->iosize1 = 8;
1928 name = "serial(EIO)";
1929 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1930 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1931 printk("STALLION: invalid irq=%d for brd=%d\n",
1932 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001933 retval = -EINVAL;
1934 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 }
1936 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1937 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1938 brdp->ioctrl);
1939 }
1940
Jiri Slaby3b85b342006-12-08 02:39:10 -08001941 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1943 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1944 "%x conflicts with another device\n", brdp->brdnr,
1945 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001946 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 }
1948
1949 if (brdp->iosize2 > 0)
1950 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1951 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1952 "address %x conflicts with another device\n",
1953 brdp->brdnr, brdp->ioaddr2);
1954 printk(KERN_WARNING "STALLION: Warning, also "
1955 "releasing board %d I/O address %x \n",
1956 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001957 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 }
1959
1960/*
1961 * Everything looks OK, so let's go ahead and probe for the hardware.
1962 */
1963 brdp->clk = CD1400_CLK;
1964 brdp->isr = stl_eiointr;
1965
Jiri Slaby3b85b342006-12-08 02:39:10 -08001966 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 switch (status & EIO_IDBITMASK) {
1968 case EIO_8PORTM:
1969 brdp->clk = CD1400_CLK8M;
1970 /* fall thru */
1971 case EIO_8PORTRS:
1972 case EIO_8PORTDI:
1973 brdp->nrports = 8;
1974 break;
1975 case EIO_4PORTRS:
1976 brdp->nrports = 4;
1977 break;
1978 case EIO_MK3:
1979 switch (status & EIO_BRDMASK) {
1980 case ID_BRD4:
1981 brdp->nrports = 4;
1982 break;
1983 case ID_BRD8:
1984 brdp->nrports = 8;
1985 break;
1986 case ID_BRD16:
1987 brdp->nrports = 16;
1988 break;
1989 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001990 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 }
1992 break;
1993 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001994 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 }
1996
1997/*
1998 * We have verified that the board is actually present, so now we
1999 * can complete the setup.
2000 */
2001
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002002 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002003 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002005 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002006 retval = -ENOMEM;
2007 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
2010 panelp->magic = STL_PANELMAGIC;
2011 panelp->brdnr = brdp->brdnr;
2012 panelp->panelnr = 0;
2013 panelp->nrports = brdp->nrports;
2014 panelp->iobase = brdp->ioaddr1;
2015 panelp->hwid = status;
2016 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002017 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 panelp->isr = stl_sc26198intr;
2019 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002020 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 panelp->isr = stl_cd1400eiointr;
2022 }
2023
2024 brdp->panels[0] = panelp;
2025 brdp->nrpanels = 1;
2026 brdp->state |= BRD_FOUND;
2027 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002028 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 printk("STALLION: failed to register interrupt "
2030 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002031 retval = -ENODEV;
2032 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08002034
2035 return 0;
2036err_fr:
2037 stl_cleanup_panels(brdp);
2038err_rel2:
2039 if (brdp->iosize2 > 0)
2040 release_region(brdp->ioaddr2, brdp->iosize2);
2041err_rel1:
2042 release_region(brdp->ioaddr1, brdp->iosize1);
2043err:
2044 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045}
2046
2047/*****************************************************************************/
2048
2049/*
2050 * Try to find an ECH board and initialize it. This code is capable of
2051 * dealing with all types of ECH board.
2052 */
2053
Jiri Slaby705c1862006-12-08 02:39:11 -08002054static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002056 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 unsigned int status, nxtid, ioaddr, conflict;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002058 int panelnr, banknr, i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 char *name;
2060
Jiri Slabya0564e12006-12-08 02:38:37 -08002061 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
2063 status = 0;
2064 conflict = 0;
2065
2066/*
2067 * Set up the initial board register contents for boards. This varies a
2068 * bit between the different board types. So we need to handle each
2069 * separately. Also do a check that the supplied IRQ is good.
2070 */
2071 switch (brdp->brdtype) {
2072
2073 case BRD_ECH:
2074 brdp->isr = stl_echatintr;
2075 brdp->ioctrl = brdp->ioaddr1 + 1;
2076 brdp->iostatus = brdp->ioaddr1 + 1;
2077 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002078 if ((status & ECH_IDBITMASK) != ECH_ID) {
2079 retval = -ENODEV;
2080 goto err;
2081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2083 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2084 printk("STALLION: invalid irq=%d for brd=%d\n",
2085 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002086 retval = -EINVAL;
2087 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 }
2089 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2090 status |= (stl_vecmap[brdp->irq] << 1);
2091 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2092 brdp->ioctrlval = ECH_INTENABLE |
2093 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2094 for (i = 0; (i < 10); i++)
2095 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2096 brdp->iosize1 = 2;
2097 brdp->iosize2 = 32;
2098 name = "serial(EC8/32)";
2099 outb(status, brdp->ioaddr1);
2100 break;
2101
2102 case BRD_ECHMC:
2103 brdp->isr = stl_echmcaintr;
2104 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2105 brdp->iostatus = brdp->ioctrl;
2106 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002107 if ((status & ECH_IDBITMASK) != ECH_ID) {
2108 retval = -ENODEV;
2109 goto err;
2110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2112 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2113 printk("STALLION: invalid irq=%d for brd=%d\n",
2114 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002115 retval = -EINVAL;
2116 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 }
2118 outb(ECHMC_BRDRESET, brdp->ioctrl);
2119 outb(ECHMC_INTENABLE, brdp->ioctrl);
2120 brdp->iosize1 = 64;
2121 name = "serial(EC8/32-MC)";
2122 break;
2123
2124 case BRD_ECHPCI:
2125 brdp->isr = stl_echpciintr;
2126 brdp->ioctrl = brdp->ioaddr1 + 2;
2127 brdp->iosize1 = 4;
2128 brdp->iosize2 = 8;
2129 name = "serial(EC8/32-PCI)";
2130 break;
2131
2132 case BRD_ECH64PCI:
2133 brdp->isr = stl_echpci64intr;
2134 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2135 outb(0x43, (brdp->ioaddr1 + 0x4c));
2136 brdp->iosize1 = 0x80;
2137 brdp->iosize2 = 0x80;
2138 name = "serial(EC8/64-PCI)";
2139 break;
2140
2141 default:
2142 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002143 retval = -EINVAL;
2144 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 }
2146
2147/*
2148 * Check boards for possible IO address conflicts and return fail status
2149 * if an IO conflict found.
2150 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002151 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2153 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2154 "%x conflicts with another device\n", brdp->brdnr,
2155 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002156 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 }
2158
2159 if (brdp->iosize2 > 0)
2160 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2161 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2162 "address %x conflicts with another device\n",
2163 brdp->brdnr, brdp->ioaddr2);
2164 printk(KERN_WARNING "STALLION: Warning, also "
2165 "releasing board %d I/O address %x \n",
2166 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002167 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 }
2169
2170/*
2171 * Scan through the secondary io address space looking for panels.
2172 * As we find'em allocate and initialize panel structures for each.
2173 */
2174 brdp->clk = CD1400_CLK;
2175 brdp->hwid = status;
2176
2177 ioaddr = brdp->ioaddr2;
2178 banknr = 0;
2179 panelnr = 0;
2180 nxtid = 0;
2181
2182 for (i = 0; (i < STL_MAXPANELS); i++) {
2183 if (brdp->brdtype == BRD_ECHPCI) {
2184 outb(nxtid, brdp->ioctrl);
2185 ioaddr = brdp->ioaddr2;
2186 }
2187 status = inb(ioaddr + ECH_PNLSTATUS);
2188 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002189 goto err_fr;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002190 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002191 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002193 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002194 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 panelp->magic = STL_PANELMAGIC;
2197 panelp->brdnr = brdp->brdnr;
2198 panelp->panelnr = panelnr;
2199 panelp->iobase = ioaddr;
2200 panelp->pagenr = nxtid;
2201 panelp->hwid = status;
2202 brdp->bnk2panel[banknr] = panelp;
2203 brdp->bnkpageaddr[banknr] = nxtid;
2204 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2205
2206 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002207 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 panelp->isr = stl_sc26198intr;
2209 if (status & ECH_PNL16PORT) {
2210 panelp->nrports = 16;
2211 brdp->bnk2panel[banknr] = panelp;
2212 brdp->bnkpageaddr[banknr] = nxtid;
2213 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2214 ECH_PNLSTATUS;
2215 } else {
2216 panelp->nrports = 8;
2217 }
2218 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002219 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 panelp->isr = stl_cd1400echintr;
2221 if (status & ECH_PNL16PORT) {
2222 panelp->nrports = 16;
2223 panelp->ackmask = 0x80;
2224 if (brdp->brdtype != BRD_ECHPCI)
2225 ioaddr += EREG_BANKSIZE;
2226 brdp->bnk2panel[banknr] = panelp;
2227 brdp->bnkpageaddr[banknr] = ++nxtid;
2228 brdp->bnkstataddr[banknr++] = ioaddr +
2229 ECH_PNLSTATUS;
2230 } else {
2231 panelp->nrports = 8;
2232 panelp->ackmask = 0xc0;
2233 }
2234 }
2235
2236 nxtid++;
2237 ioaddr += EREG_BANKSIZE;
2238 brdp->nrports += panelp->nrports;
2239 brdp->panels[panelnr++] = panelp;
2240 if ((brdp->brdtype != BRD_ECHPCI) &&
2241 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
Jiri Slaby3b85b342006-12-08 02:39:10 -08002242 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 }
2244
2245 brdp->nrpanels = panelnr;
2246 brdp->nrbnks = banknr;
2247 if (brdp->brdtype == BRD_ECH)
2248 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2249
2250 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002251 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 printk("STALLION: failed to register interrupt "
2253 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002254 retval = -ENODEV;
2255 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 }
2257
Jiri Slaby3b85b342006-12-08 02:39:10 -08002258 return 0;
2259err_fr:
2260 stl_cleanup_panels(brdp);
2261 if (brdp->iosize2 > 0)
2262 release_region(brdp->ioaddr2, brdp->iosize2);
2263err_rel1:
2264 release_region(brdp->ioaddr1, brdp->iosize1);
2265err:
2266 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267}
2268
2269/*****************************************************************************/
2270
2271/*
2272 * Initialize and configure the specified board.
2273 * Scan through all the boards in the configuration and see what we
2274 * can find. Handle EIO and the ECH boards a little differently here
2275 * since the initial search and setup is very different.
2276 */
2277
Jiri Slaby705c1862006-12-08 02:39:11 -08002278static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002280 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
Jiri Slabya0564e12006-12-08 02:38:37 -08002282 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283
2284 switch (brdp->brdtype) {
2285 case BRD_EASYIO:
2286 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002287 retval = stl_initeio(brdp);
2288 if (retval)
2289 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 break;
2291 case BRD_ECH:
2292 case BRD_ECHMC:
2293 case BRD_ECHPCI:
2294 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002295 retval = stl_initech(brdp);
2296 if (retval)
2297 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 break;
2299 default:
2300 printk("STALLION: board=%d is unknown board type=%d\n",
2301 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002302 retval = -ENODEV;
2303 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 }
2305
2306 stl_brds[brdp->brdnr] = brdp;
2307 if ((brdp->state & BRD_FOUND) == 0) {
2308 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2309 stl_brdnames[brdp->brdtype], brdp->brdnr,
2310 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002311 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 }
2313
2314 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002315 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 stl_initports(brdp, brdp->panels[i]);
2317
2318 printk("STALLION: %s found, board=%d io=%x irq=%d "
2319 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2320 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2321 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002322
2323 return 0;
2324err_free:
2325 free_irq(brdp->irq, brdp);
2326
2327 stl_cleanup_panels(brdp);
2328
2329 release_region(brdp->ioaddr1, brdp->iosize1);
2330 if (brdp->iosize2 > 0)
2331 release_region(brdp->ioaddr2, brdp->iosize2);
2332
2333 stl_brds[brdp->brdnr] = NULL;
2334err:
2335 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336}
2337
2338/*****************************************************************************/
2339
2340/*
2341 * Find the next available board number that is free.
2342 */
2343
Jiri Slaby705c1862006-12-08 02:39:11 -08002344static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345{
2346 int i;
2347
2348 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002349 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 if (i >= stl_nrbrds)
2351 stl_nrbrds = i + 1;
2352 return(i);
2353 }
2354 }
2355 return(-1);
2356}
2357
2358/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359/*
2360 * We have a Stallion board. Allocate a board structure and
2361 * initialize it. Read its IO and IRQ resources from PCI
2362 * configuration space.
2363 */
2364
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002365static int __devinit stl_pciprobe(struct pci_dev *pdev,
2366 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002368 struct stlbrd *brdp;
2369 unsigned int brdtype = ent->driver_data;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002370 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002372 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002373 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002374
2375 dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
2376 pdev->vendor, pdev->device, pdev->class);
2377
Jiri Slaby3b85b342006-12-08 02:39:10 -08002378 retval = pci_enable_device(pdev);
2379 if (retval)
2380 goto err;
2381 brdp = stl_allocbrd();
2382 if (brdp == NULL) {
2383 retval = -ENOMEM;
2384 goto err;
2385 }
2386 brdp->brdnr = stl_getbrdnr();
2387 if (brdp->brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002388 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002390 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
2392 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002393 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394
2395/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 * We have all resources from the board, so let's setup the actual
2397 * board structure now.
2398 */
2399 switch (brdtype) {
2400 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002401 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2402 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 break;
2404 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002405 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2406 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 break;
2408 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002409 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2410 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 break;
2412 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002413 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 break;
2415 }
2416
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002417 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002418 retval = stl_brdinit(brdp);
2419 if (retval)
2420 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002422 pci_set_drvdata(pdev, brdp);
2423
Jiri Slaby3b85b342006-12-08 02:39:10 -08002424 return 0;
2425err_fr:
2426 kfree(brdp);
2427err:
2428 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429}
2430
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002431static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002433 struct stlbrd *brdp = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002435 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002437 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002439 release_region(brdp->ioaddr1, brdp->iosize1);
2440 if (brdp->iosize2 > 0)
2441 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002443 stl_brds[brdp->brdnr] = NULL;
2444 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445}
2446
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002447static struct pci_driver stl_pcidriver = {
2448 .name = "stallion",
2449 .id_table = stl_pcibrds,
2450 .probe = stl_pciprobe,
2451 .remove = __devexit_p(stl_pciremove)
2452};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453
2454/*****************************************************************************/
2455
2456/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 * Return the board stats structure to user app.
2458 */
2459
2460static int stl_getbrdstats(combrd_t __user *bp)
2461{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002462 struct stlbrd *brdp;
2463 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 int i;
2465
2466 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2467 return -EFAULT;
2468 if (stl_brdstats.brd >= STL_MAXBRDS)
2469 return(-ENODEV);
2470 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002471 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 return(-ENODEV);
2473
2474 memset(&stl_brdstats, 0, sizeof(combrd_t));
2475 stl_brdstats.brd = brdp->brdnr;
2476 stl_brdstats.type = brdp->brdtype;
2477 stl_brdstats.hwid = brdp->hwid;
2478 stl_brdstats.state = brdp->state;
2479 stl_brdstats.ioaddr = brdp->ioaddr1;
2480 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2481 stl_brdstats.irq = brdp->irq;
2482 stl_brdstats.nrpanels = brdp->nrpanels;
2483 stl_brdstats.nrports = brdp->nrports;
2484 for (i = 0; (i < brdp->nrpanels); i++) {
2485 panelp = brdp->panels[i];
2486 stl_brdstats.panels[i].panel = i;
2487 stl_brdstats.panels[i].hwid = panelp->hwid;
2488 stl_brdstats.panels[i].nrports = panelp->nrports;
2489 }
2490
2491 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2492}
2493
2494/*****************************************************************************/
2495
2496/*
2497 * Resolve the referenced port number into a port struct pointer.
2498 */
2499
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002500static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002502 struct stlbrd *brdp;
2503 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504
2505 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002506 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002508 if (brdp == NULL)
2509 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002511 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002513 if (panelp == NULL)
2514 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002516 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 return(panelp->ports[portnr]);
2518}
2519
2520/*****************************************************************************/
2521
2522/*
2523 * Return the port stats structure to user app. A NULL port struct
2524 * pointer passed in means that we need to find out from the app
2525 * what port to get stats for (used through board control device).
2526 */
2527
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002528static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529{
2530 unsigned char *head, *tail;
2531 unsigned long flags;
2532
2533 if (!portp) {
2534 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2535 return -EFAULT;
2536 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2537 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002538 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 return(-ENODEV);
2540 }
2541
2542 portp->stats.state = portp->istate;
2543 portp->stats.flags = portp->flags;
2544 portp->stats.hwid = portp->hwid;
2545
2546 portp->stats.ttystate = 0;
2547 portp->stats.cflags = 0;
2548 portp->stats.iflags = 0;
2549 portp->stats.oflags = 0;
2550 portp->stats.lflags = 0;
2551 portp->stats.rxbuffered = 0;
2552
Alan Coxb65b5b52006-06-27 02:54:05 -07002553 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002554 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 if (portp->tty->driver_data == portp) {
2556 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002557 /* No longer available as a statistic */
2558 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002559 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 portp->stats.cflags = portp->tty->termios->c_cflag;
2561 portp->stats.iflags = portp->tty->termios->c_iflag;
2562 portp->stats.oflags = portp->tty->termios->c_oflag;
2563 portp->stats.lflags = portp->tty->termios->c_lflag;
2564 }
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;
2571 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2572 (STL_TXBUFSIZE - (tail - head)));
2573
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)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 return(-ENODEV);
2595 }
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)
2640 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)
2661 return(-ENODEV);
2662 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
2685 return(rc);
2686}
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{
2730 outb((regnr + portp->uartaddr), portp->ioaddr);
2731 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{
2736 outb((regnr + portp->uartaddr), portp->ioaddr);
2737 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;
2769 for (i = 0; (i < nrchips); i++) {
2770 if (brdp->brdtype == BRD_ECHPCI) {
2771 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2772 ioaddr = panelp->iobase;
2773 } else {
2774 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2775 }
2776 uartaddr = (i & 0x01) ? 0x080 : 0;
2777 outb((GFRCR + uartaddr), ioaddr);
2778 outb(0, (ioaddr + EREG_DATA));
2779 outb((CCR + uartaddr), ioaddr);
2780 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2781 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2782 outb((GFRCR + uartaddr), ioaddr);
2783 for (j = 0; (j < CCR_MAXWAIT); j++) {
2784 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2785 break;
2786 }
2787 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2788 printk("STALLION: cd1400 not responding, "
2789 "brd=%d panel=%d chip=%d\n",
2790 panelp->brdnr, panelp->panelnr, i);
2791 continue;
2792 }
2793 chipmask |= (0x1 << i);
2794 outb((PPR + uartaddr), ioaddr);
2795 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2796 }
2797
2798 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002799 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002800 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801}
2802
2803/*****************************************************************************/
2804
2805/*
2806 * Initialize hardware specific port registers.
2807 */
2808
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002809static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810{
Alan Coxb65b5b52006-06-27 02:54:05 -07002811 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002812 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2813 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
Jiri Slaby615e4a72006-12-08 02:38:38 -08002815 if ((brdp == NULL) || (panelp == NULL) ||
2816 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 return;
2818
Alan Coxb65b5b52006-06-27 02:54:05 -07002819 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2821 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2822 portp->uartaddr = (portp->portnr & 0x04) << 5;
2823 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2824
2825 BRDENABLE(portp->brdnr, portp->pagenr);
2826 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2827 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2828 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2829 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002830 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831}
2832
2833/*****************************************************************************/
2834
2835/*
2836 * Wait for the command register to be ready. We will poll this,
2837 * since it won't usually take too long to be ready.
2838 */
2839
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002840static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841{
2842 int i;
2843
2844 for (i = 0; (i < CCR_MAXWAIT); i++) {
2845 if (stl_cd1400getreg(portp, CCR) == 0) {
2846 return;
2847 }
2848 }
2849
2850 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2851 portp->portnr, portp->panelnr, portp->brdnr);
2852}
2853
2854/*****************************************************************************/
2855
2856/*
2857 * Set up the cd1400 registers for a port based on the termios port
2858 * settings.
2859 */
2860
Alan Cox606d0992006-12-08 02:38:45 -08002861static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002863 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 unsigned long flags;
2865 unsigned int clkdiv, baudrate;
2866 unsigned char cor1, cor2, cor3;
2867 unsigned char cor4, cor5, ccr;
2868 unsigned char srer, sreron, sreroff;
2869 unsigned char mcor1, mcor2, rtpr;
2870 unsigned char clk, div;
2871
2872 cor1 = 0;
2873 cor2 = 0;
2874 cor3 = 0;
2875 cor4 = 0;
2876 cor5 = 0;
2877 ccr = 0;
2878 rtpr = 0;
2879 clk = 0;
2880 div = 0;
2881 mcor1 = 0;
2882 mcor2 = 0;
2883 sreron = 0;
2884 sreroff = 0;
2885
2886 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002887 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 return;
2889
2890/*
2891 * Set up the RX char ignore mask with those RX error types we
2892 * can ignore. We can get the cd1400 to help us out a little here,
2893 * it will ignore parity errors and breaks for us.
2894 */
2895 portp->rxignoremsk = 0;
2896 if (tiosp->c_iflag & IGNPAR) {
2897 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2898 cor1 |= COR1_PARIGNORE;
2899 }
2900 if (tiosp->c_iflag & IGNBRK) {
2901 portp->rxignoremsk |= ST_BREAK;
2902 cor4 |= COR4_IGNBRK;
2903 }
2904
2905 portp->rxmarkmsk = ST_OVERRUN;
2906 if (tiosp->c_iflag & (INPCK | PARMRK))
2907 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2908 if (tiosp->c_iflag & BRKINT)
2909 portp->rxmarkmsk |= ST_BREAK;
2910
2911/*
2912 * Go through the char size, parity and stop bits and set all the
2913 * option register appropriately.
2914 */
2915 switch (tiosp->c_cflag & CSIZE) {
2916 case CS5:
2917 cor1 |= COR1_CHL5;
2918 break;
2919 case CS6:
2920 cor1 |= COR1_CHL6;
2921 break;
2922 case CS7:
2923 cor1 |= COR1_CHL7;
2924 break;
2925 default:
2926 cor1 |= COR1_CHL8;
2927 break;
2928 }
2929
2930 if (tiosp->c_cflag & CSTOPB)
2931 cor1 |= COR1_STOP2;
2932 else
2933 cor1 |= COR1_STOP1;
2934
2935 if (tiosp->c_cflag & PARENB) {
2936 if (tiosp->c_cflag & PARODD)
2937 cor1 |= (COR1_PARENB | COR1_PARODD);
2938 else
2939 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2940 } else {
2941 cor1 |= COR1_PARNONE;
2942 }
2943
2944/*
2945 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2946 * space for hardware flow control and the like. This should be set to
2947 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2948 * really be based on VTIME.
2949 */
2950 cor3 |= FIFO_RXTHRESHOLD;
2951 rtpr = 2;
2952
2953/*
2954 * Calculate the baud rate timers. For now we will just assume that
2955 * the input and output baud are the same. Could have used a baud
2956 * table here, but this way we can generate virtually any baud rate
2957 * we like!
2958 */
2959 baudrate = tiosp->c_cflag & CBAUD;
2960 if (baudrate & CBAUDEX) {
2961 baudrate &= ~CBAUDEX;
2962 if ((baudrate < 1) || (baudrate > 4))
2963 tiosp->c_cflag &= ~CBAUDEX;
2964 else
2965 baudrate += 15;
2966 }
2967 baudrate = stl_baudrates[baudrate];
2968 if ((tiosp->c_cflag & CBAUD) == B38400) {
2969 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2970 baudrate = 57600;
2971 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2972 baudrate = 115200;
2973 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2974 baudrate = 230400;
2975 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2976 baudrate = 460800;
2977 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
2978 baudrate = (portp->baud_base / portp->custom_divisor);
2979 }
2980 if (baudrate > STL_CD1400MAXBAUD)
2981 baudrate = STL_CD1400MAXBAUD;
2982
2983 if (baudrate > 0) {
2984 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
2985 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
2986 if (clkdiv < 0x100)
2987 break;
2988 }
2989 div = (unsigned char) clkdiv;
2990 }
2991
2992/*
2993 * Check what form of modem signaling is required and set it up.
2994 */
2995 if ((tiosp->c_cflag & CLOCAL) == 0) {
2996 mcor1 |= MCOR1_DCD;
2997 mcor2 |= MCOR2_DCD;
2998 sreron |= SRER_MODEM;
2999 portp->flags |= ASYNC_CHECK_CD;
3000 } else {
3001 portp->flags &= ~ASYNC_CHECK_CD;
3002 }
3003
3004/*
3005 * Setup cd1400 enhanced modes if we can. In particular we want to
3006 * handle as much of the flow control as possible automatically. As
3007 * well as saving a few CPU cycles it will also greatly improve flow
3008 * control reliability.
3009 */
3010 if (tiosp->c_iflag & IXON) {
3011 cor2 |= COR2_TXIBE;
3012 cor3 |= COR3_SCD12;
3013 if (tiosp->c_iflag & IXANY)
3014 cor2 |= COR2_IXM;
3015 }
3016
3017 if (tiosp->c_cflag & CRTSCTS) {
3018 cor2 |= COR2_CTSAE;
3019 mcor1 |= FIFO_RTSTHRESHOLD;
3020 }
3021
3022/*
3023 * All cd1400 register values calculated so go through and set
3024 * them all up.
3025 */
3026
Jiri Slabya0564e12006-12-08 02:38:37 -08003027 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003029 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003031 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003033 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3034 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3036 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037
Alan Coxb65b5b52006-06-27 02:54:05 -07003038 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 BRDENABLE(portp->brdnr, portp->pagenr);
3040 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3041 srer = stl_cd1400getreg(portp, SRER);
3042 stl_cd1400setreg(portp, SRER, 0);
3043 if (stl_cd1400updatereg(portp, COR1, cor1))
3044 ccr = 1;
3045 if (stl_cd1400updatereg(portp, COR2, cor2))
3046 ccr = 1;
3047 if (stl_cd1400updatereg(portp, COR3, cor3))
3048 ccr = 1;
3049 if (ccr) {
3050 stl_cd1400ccrwait(portp);
3051 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3052 }
3053 stl_cd1400setreg(portp, COR4, cor4);
3054 stl_cd1400setreg(portp, COR5, cor5);
3055 stl_cd1400setreg(portp, MCOR1, mcor1);
3056 stl_cd1400setreg(portp, MCOR2, mcor2);
3057 if (baudrate > 0) {
3058 stl_cd1400setreg(portp, TCOR, clk);
3059 stl_cd1400setreg(portp, TBPR, div);
3060 stl_cd1400setreg(portp, RCOR, clk);
3061 stl_cd1400setreg(portp, RBPR, div);
3062 }
3063 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3064 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3065 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3066 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3067 stl_cd1400setreg(portp, RTPR, rtpr);
3068 mcor1 = stl_cd1400getreg(portp, MSVR1);
3069 if (mcor1 & MSVR1_DCD)
3070 portp->sigs |= TIOCM_CD;
3071 else
3072 portp->sigs &= ~TIOCM_CD;
3073 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3074 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003075 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076}
3077
3078/*****************************************************************************/
3079
3080/*
3081 * Set the state of the DTR and RTS signals.
3082 */
3083
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003084static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085{
3086 unsigned char msvr1, msvr2;
3087 unsigned long flags;
3088
Jiri Slabya0564e12006-12-08 02:38:37 -08003089 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3090 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091
3092 msvr1 = 0;
3093 msvr2 = 0;
3094 if (dtr > 0)
3095 msvr1 = MSVR1_DTR;
3096 if (rts > 0)
3097 msvr2 = MSVR2_RTS;
3098
Alan Coxb65b5b52006-06-27 02:54:05 -07003099 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 BRDENABLE(portp->brdnr, portp->pagenr);
3101 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3102 if (rts >= 0)
3103 stl_cd1400setreg(portp, MSVR2, msvr2);
3104 if (dtr >= 0)
3105 stl_cd1400setreg(portp, MSVR1, msvr1);
3106 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003107 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108}
3109
3110/*****************************************************************************/
3111
3112/*
3113 * Return the state of the signals.
3114 */
3115
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003116static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117{
3118 unsigned char msvr1, msvr2;
3119 unsigned long flags;
3120 int sigs;
3121
Jiri Slabya0564e12006-12-08 02:38:37 -08003122 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123
Alan Coxb65b5b52006-06-27 02:54:05 -07003124 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 BRDENABLE(portp->brdnr, portp->pagenr);
3126 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3127 msvr1 = stl_cd1400getreg(portp, MSVR1);
3128 msvr2 = stl_cd1400getreg(portp, MSVR2);
3129 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003130 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
3132 sigs = 0;
3133 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3134 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3135 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3136 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3137#if 0
3138 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3139 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3140#else
3141 sigs |= TIOCM_DSR;
3142#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003143 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144}
3145
3146/*****************************************************************************/
3147
3148/*
3149 * Enable/Disable the Transmitter and/or Receiver.
3150 */
3151
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003152static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153{
3154 unsigned char ccr;
3155 unsigned long flags;
3156
Jiri Slabya0564e12006-12-08 02:38:37 -08003157 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3158
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 ccr = 0;
3160
3161 if (tx == 0)
3162 ccr |= CCR_TXDISABLE;
3163 else if (tx > 0)
3164 ccr |= CCR_TXENABLE;
3165 if (rx == 0)
3166 ccr |= CCR_RXDISABLE;
3167 else if (rx > 0)
3168 ccr |= CCR_RXENABLE;
3169
Alan Coxb65b5b52006-06-27 02:54:05 -07003170 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 BRDENABLE(portp->brdnr, portp->pagenr);
3172 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3173 stl_cd1400ccrwait(portp);
3174 stl_cd1400setreg(portp, CCR, ccr);
3175 stl_cd1400ccrwait(portp);
3176 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003177 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178}
3179
3180/*****************************************************************************/
3181
3182/*
3183 * Start/stop the Transmitter and/or Receiver.
3184 */
3185
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003186static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187{
3188 unsigned char sreron, sreroff;
3189 unsigned long flags;
3190
Jiri Slabya0564e12006-12-08 02:38:37 -08003191 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
3193 sreron = 0;
3194 sreroff = 0;
3195 if (tx == 0)
3196 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3197 else if (tx == 1)
3198 sreron |= SRER_TXDATA;
3199 else if (tx >= 2)
3200 sreron |= SRER_TXEMPTY;
3201 if (rx == 0)
3202 sreroff |= SRER_RXDATA;
3203 else if (rx > 0)
3204 sreron |= SRER_RXDATA;
3205
Alan Coxb65b5b52006-06-27 02:54:05 -07003206 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 BRDENABLE(portp->brdnr, portp->pagenr);
3208 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3209 stl_cd1400setreg(portp, SRER,
3210 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3211 BRDDISABLE(portp->brdnr);
3212 if (tx > 0)
3213 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003214 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215}
3216
3217/*****************************************************************************/
3218
3219/*
3220 * Disable all interrupts from this port.
3221 */
3222
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003223static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224{
3225 unsigned long flags;
3226
Jiri Slabya0564e12006-12-08 02:38:37 -08003227 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3228
Alan Coxb65b5b52006-06-27 02:54:05 -07003229 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 BRDENABLE(portp->brdnr, portp->pagenr);
3231 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3232 stl_cd1400setreg(portp, SRER, 0);
3233 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003234 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235}
3236
3237/*****************************************************************************/
3238
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003239static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240{
3241 unsigned long flags;
3242
Jiri Slabya0564e12006-12-08 02:38:37 -08003243 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244
Alan Coxb65b5b52006-06-27 02:54:05 -07003245 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246 BRDENABLE(portp->brdnr, portp->pagenr);
3247 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3248 stl_cd1400setreg(portp, SRER,
3249 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3250 SRER_TXEMPTY));
3251 BRDDISABLE(portp->brdnr);
3252 portp->brklen = len;
3253 if (len == 1)
3254 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003255 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256}
3257
3258/*****************************************************************************/
3259
3260/*
3261 * Take flow control actions...
3262 */
3263
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003264static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265{
3266 struct tty_struct *tty;
3267 unsigned long flags;
3268
Jiri Slabya0564e12006-12-08 02:38:37 -08003269 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270
Jiri Slaby615e4a72006-12-08 02:38:38 -08003271 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 return;
3273 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003274 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 return;
3276
Alan Coxb65b5b52006-06-27 02:54:05 -07003277 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 BRDENABLE(portp->brdnr, portp->pagenr);
3279 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3280
3281 if (state) {
3282 if (tty->termios->c_iflag & IXOFF) {
3283 stl_cd1400ccrwait(portp);
3284 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3285 portp->stats.rxxon++;
3286 stl_cd1400ccrwait(portp);
3287 }
3288/*
3289 * Question: should we return RTS to what it was before? It may
3290 * have been set by an ioctl... Suppose not, since if you have
3291 * hardware flow control set then it is pretty silly to go and
3292 * set the RTS line by hand.
3293 */
3294 if (tty->termios->c_cflag & CRTSCTS) {
3295 stl_cd1400setreg(portp, MCOR1,
3296 (stl_cd1400getreg(portp, MCOR1) |
3297 FIFO_RTSTHRESHOLD));
3298 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3299 portp->stats.rxrtson++;
3300 }
3301 } else {
3302 if (tty->termios->c_iflag & IXOFF) {
3303 stl_cd1400ccrwait(portp);
3304 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3305 portp->stats.rxxoff++;
3306 stl_cd1400ccrwait(portp);
3307 }
3308 if (tty->termios->c_cflag & CRTSCTS) {
3309 stl_cd1400setreg(portp, MCOR1,
3310 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3311 stl_cd1400setreg(portp, MSVR2, 0);
3312 portp->stats.rxrtsoff++;
3313 }
3314 }
3315
3316 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003317 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318}
3319
3320/*****************************************************************************/
3321
3322/*
3323 * Send a flow control character...
3324 */
3325
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003326static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327{
3328 struct tty_struct *tty;
3329 unsigned long flags;
3330
Jiri Slabya0564e12006-12-08 02:38:37 -08003331 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332
Jiri Slaby615e4a72006-12-08 02:38:38 -08003333 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334 return;
3335 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003336 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 return;
3338
Alan Coxb65b5b52006-06-27 02:54:05 -07003339 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 BRDENABLE(portp->brdnr, portp->pagenr);
3341 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3342 if (state) {
3343 stl_cd1400ccrwait(portp);
3344 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3345 portp->stats.rxxon++;
3346 stl_cd1400ccrwait(portp);
3347 } else {
3348 stl_cd1400ccrwait(portp);
3349 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3350 portp->stats.rxxoff++;
3351 stl_cd1400ccrwait(portp);
3352 }
3353 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003354 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355}
3356
3357/*****************************************************************************/
3358
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003359static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360{
3361 unsigned long flags;
3362
Jiri Slabya0564e12006-12-08 02:38:37 -08003363 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364
Jiri Slaby615e4a72006-12-08 02:38:38 -08003365 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 return;
3367
Alan Coxb65b5b52006-06-27 02:54:05 -07003368 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369 BRDENABLE(portp->brdnr, portp->pagenr);
3370 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3371 stl_cd1400ccrwait(portp);
3372 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3373 stl_cd1400ccrwait(portp);
3374 portp->tx.tail = portp->tx.head;
3375 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003376 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377}
3378
3379/*****************************************************************************/
3380
3381/*
3382 * Return the current state of data flow on this port. This is only
3383 * really interresting when determining if data has fully completed
3384 * transmission or not... This is easy for the cd1400, it accurately
3385 * maintains the busy port flag.
3386 */
3387
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003388static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389{
Jiri Slabya0564e12006-12-08 02:38:37 -08003390 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391
Jiri Slaby615e4a72006-12-08 02:38:38 -08003392 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003393 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394
Jesper Juhl014c2542006-01-15 02:37:08 +01003395 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396}
3397
3398/*****************************************************************************/
3399
3400/*
3401 * Interrupt service routine for cd1400 EasyIO boards.
3402 */
3403
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003404static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405{
3406 unsigned char svrtype;
3407
Jiri Slabya0564e12006-12-08 02:38:37 -08003408 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
Alan Coxb65b5b52006-06-27 02:54:05 -07003410 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 outb(SVRR, iobase);
3412 svrtype = inb(iobase + EREG_DATA);
3413 if (panelp->nrports > 4) {
3414 outb((SVRR + 0x80), iobase);
3415 svrtype |= inb(iobase + EREG_DATA);
3416 }
3417
3418 if (svrtype & SVRR_RX)
3419 stl_cd1400rxisr(panelp, iobase);
3420 else if (svrtype & SVRR_TX)
3421 stl_cd1400txisr(panelp, iobase);
3422 else if (svrtype & SVRR_MDM)
3423 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003424
3425 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426}
3427
3428/*****************************************************************************/
3429
3430/*
3431 * Interrupt service routine for cd1400 panels.
3432 */
3433
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003434static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435{
3436 unsigned char svrtype;
3437
Jiri Slabya0564e12006-12-08 02:38:37 -08003438 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439
3440 outb(SVRR, iobase);
3441 svrtype = inb(iobase + EREG_DATA);
3442 outb((SVRR + 0x80), iobase);
3443 svrtype |= inb(iobase + EREG_DATA);
3444 if (svrtype & SVRR_RX)
3445 stl_cd1400rxisr(panelp, iobase);
3446 else if (svrtype & SVRR_TX)
3447 stl_cd1400txisr(panelp, iobase);
3448 else if (svrtype & SVRR_MDM)
3449 stl_cd1400mdmisr(panelp, iobase);
3450}
3451
3452
3453/*****************************************************************************/
3454
3455/*
3456 * Unfortunately we need to handle breaks in the TX data stream, since
3457 * this is the only way to generate them on the cd1400.
3458 */
3459
Jiri Slaby60be4812006-12-08 02:38:40 -08003460static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461{
3462 if (portp->brklen == 1) {
3463 outb((COR2 + portp->uartaddr), ioaddr);
3464 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3465 (ioaddr + EREG_DATA));
3466 outb((TDR + portp->uartaddr), ioaddr);
3467 outb(ETC_CMD, (ioaddr + EREG_DATA));
3468 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3469 outb((SRER + portp->uartaddr), ioaddr);
3470 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3471 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003472 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473 } else if (portp->brklen > 1) {
3474 outb((TDR + portp->uartaddr), ioaddr);
3475 outb(ETC_CMD, (ioaddr + EREG_DATA));
3476 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3477 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003478 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 } else {
3480 outb((COR2 + portp->uartaddr), ioaddr);
3481 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3482 (ioaddr + EREG_DATA));
3483 portp->brklen = 0;
3484 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003485 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486}
3487
3488/*****************************************************************************/
3489
3490/*
3491 * Transmit interrupt handler. This has gotta be fast! Handling TX
3492 * chars is pretty simple, stuff as many as possible from the TX buffer
3493 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3494 * are embedded as commands in the data stream. Oh no, had to use a goto!
3495 * This could be optimized more, will do when I get time...
3496 * In practice it is possible that interrupts are enabled but that the
3497 * port has been hung up. Need to handle not having any TX buffer here,
3498 * this is done by using the side effect that head and tail will also
3499 * be NULL if the buffer has been freed.
3500 */
3501
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003502static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003504 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 int len, stlen;
3506 char *head, *tail;
3507 unsigned char ioack, srer;
3508
Jiri Slabya0564e12006-12-08 02:38:37 -08003509 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510
3511 ioack = inb(ioaddr + EREG_TXACK);
3512 if (((ioack & panelp->ackmask) != 0) ||
3513 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3514 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3515 return;
3516 }
3517 portp = panelp->ports[(ioack >> 3)];
3518
3519/*
3520 * Unfortunately we need to handle breaks in the data stream, since
3521 * this is the only way to generate them on the cd1400. Do it now if
3522 * a break is to be sent.
3523 */
3524 if (portp->brklen != 0)
3525 if (stl_cd1400breakisr(portp, ioaddr))
3526 goto stl_txalldone;
3527
3528 head = portp->tx.head;
3529 tail = portp->tx.tail;
3530 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3531 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3532 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3533 set_bit(ASYI_TXLOW, &portp->istate);
3534 schedule_work(&portp->tqueue);
3535 }
3536
3537 if (len == 0) {
3538 outb((SRER + portp->uartaddr), ioaddr);
3539 srer = inb(ioaddr + EREG_DATA);
3540 if (srer & SRER_TXDATA) {
3541 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3542 } else {
3543 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3544 clear_bit(ASYI_TXBUSY, &portp->istate);
3545 }
3546 outb(srer, (ioaddr + EREG_DATA));
3547 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003548 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08003550 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551 outb((TDR + portp->uartaddr), ioaddr);
3552 outsb((ioaddr + EREG_DATA), tail, stlen);
3553 len -= stlen;
3554 tail += stlen;
3555 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3556 tail = portp->tx.buf;
3557 if (len > 0) {
3558 outsb((ioaddr + EREG_DATA), tail, len);
3559 tail += len;
3560 }
3561 portp->tx.tail = tail;
3562 }
3563
3564stl_txalldone:
3565 outb((EOSRR + portp->uartaddr), ioaddr);
3566 outb(0, (ioaddr + EREG_DATA));
3567}
3568
3569/*****************************************************************************/
3570
3571/*
3572 * Receive character interrupt handler. Determine if we have good chars
3573 * or bad chars and then process appropriately. Good chars are easy
3574 * just shove the lot into the RX buffer and set all status byte to 0.
3575 * If a bad RX char then process as required. This routine needs to be
3576 * fast! In practice it is possible that we get an interrupt on a port
3577 * that is closed. This can happen on hangups - since they completely
3578 * shutdown a port not in user context. Need to handle this case.
3579 */
3580
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003581static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003583 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 struct tty_struct *tty;
3585 unsigned int ioack, len, buflen;
3586 unsigned char status;
3587 char ch;
3588
Jiri Slabya0564e12006-12-08 02:38:37 -08003589 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590
3591 ioack = inb(ioaddr + EREG_RXACK);
3592 if ((ioack & panelp->ackmask) != 0) {
3593 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3594 return;
3595 }
3596 portp = panelp->ports[(ioack >> 3)];
3597 tty = portp->tty;
3598
3599 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3600 outb((RDCR + portp->uartaddr), ioaddr);
3601 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003602 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08003603 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604 outb((RDSR + portp->uartaddr), ioaddr);
3605 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3606 portp->stats.rxlost += len;
3607 portp->stats.rxtotal += len;
3608 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003609 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003611 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003613 tty_prepare_flip_string(tty, &ptr, len);
3614 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 tty_schedule_flip(tty);
3616 portp->stats.rxtotal += len;
3617 }
3618 }
3619 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3620 outb((RDSR + portp->uartaddr), ioaddr);
3621 status = inb(ioaddr + EREG_DATA);
3622 ch = inb(ioaddr + EREG_DATA);
3623 if (status & ST_PARITY)
3624 portp->stats.rxparity++;
3625 if (status & ST_FRAMING)
3626 portp->stats.rxframing++;
3627 if (status & ST_OVERRUN)
3628 portp->stats.rxoverrun++;
3629 if (status & ST_BREAK)
3630 portp->stats.rxbreaks++;
3631 if (status & ST_SCHARMASK) {
3632 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3633 portp->stats.txxon++;
3634 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3635 portp->stats.txxoff++;
3636 goto stl_rxalldone;
3637 }
Alan Cox33f0f882006-01-09 20:54:13 -08003638 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 if (portp->rxmarkmsk & status) {
3640 if (status & ST_BREAK) {
3641 status = TTY_BREAK;
3642 if (portp->flags & ASYNC_SAK) {
3643 do_SAK(tty);
3644 BRDENABLE(portp->brdnr, portp->pagenr);
3645 }
3646 } else if (status & ST_PARITY) {
3647 status = TTY_PARITY;
3648 } else if (status & ST_FRAMING) {
3649 status = TTY_FRAME;
3650 } else if(status & ST_OVERRUN) {
3651 status = TTY_OVERRUN;
3652 } else {
3653 status = 0;
3654 }
3655 } else {
3656 status = 0;
3657 }
Alan Cox33f0f882006-01-09 20:54:13 -08003658 tty_insert_flip_char(tty, ch, status);
3659 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 }
3661 } else {
3662 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3663 return;
3664 }
3665
3666stl_rxalldone:
3667 outb((EOSRR + portp->uartaddr), ioaddr);
3668 outb(0, (ioaddr + EREG_DATA));
3669}
3670
3671/*****************************************************************************/
3672
3673/*
3674 * Modem interrupt handler. The is called when the modem signal line
3675 * (DCD) has changed state. Leave most of the work to the off-level
3676 * processing routine.
3677 */
3678
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003679static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003681 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 unsigned int ioack;
3683 unsigned char misr;
3684
Jiri Slabya0564e12006-12-08 02:38:37 -08003685 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686
3687 ioack = inb(ioaddr + EREG_MDACK);
3688 if (((ioack & panelp->ackmask) != 0) ||
3689 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3690 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3691 return;
3692 }
3693 portp = panelp->ports[(ioack >> 3)];
3694
3695 outb((MISR + portp->uartaddr), ioaddr);
3696 misr = inb(ioaddr + EREG_DATA);
3697 if (misr & MISR_DCD) {
3698 set_bit(ASYI_DCDCHANGE, &portp->istate);
3699 schedule_work(&portp->tqueue);
3700 portp->stats.modem++;
3701 }
3702
3703 outb((EOSRR + portp->uartaddr), ioaddr);
3704 outb(0, (ioaddr + EREG_DATA));
3705}
3706
3707/*****************************************************************************/
3708/* SC26198 HARDWARE FUNCTIONS */
3709/*****************************************************************************/
3710
3711/*
3712 * These functions get/set/update the registers of the sc26198 UARTs.
3713 * Access to the sc26198 registers is via an address/data io port pair.
3714 * (Maybe should make this inline...)
3715 */
3716
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003717static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718{
3719 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003720 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721}
3722
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003723static void stl_sc26198setreg(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 outb(value, (portp->ioaddr + XP_DATA));
3727}
3728
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003729static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730{
3731 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3732 if (inb(portp->ioaddr + XP_DATA) != value) {
3733 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003734 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003736 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737}
3738
3739/*****************************************************************************/
3740
3741/*
3742 * Functions to get and set the sc26198 global registers.
3743 */
3744
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003745static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746{
3747 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003748 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749}
3750
3751#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003752static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753{
3754 outb(regnr, (portp->ioaddr + XP_ADDR));
3755 outb(value, (portp->ioaddr + XP_DATA));
3756}
3757#endif
3758
3759/*****************************************************************************/
3760
3761/*
3762 * Inbitialize the UARTs in a panel. We don't care what sort of board
3763 * these ports are on - since the port io registers are almost
3764 * identical when dealing with ports.
3765 */
3766
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003767static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768{
3769 int chipmask, i;
3770 int nrchips, ioaddr;
3771
Jiri Slabya0564e12006-12-08 02:38:37 -08003772 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773
3774 BRDENABLE(panelp->brdnr, panelp->pagenr);
3775
3776/*
3777 * Check that each chip is present and started up OK.
3778 */
3779 chipmask = 0;
3780 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3781 if (brdp->brdtype == BRD_ECHPCI)
3782 outb(panelp->pagenr, brdp->ioctrl);
3783
3784 for (i = 0; (i < nrchips); i++) {
3785 ioaddr = panelp->iobase + (i * 4);
3786 outb(SCCR, (ioaddr + XP_ADDR));
3787 outb(CR_RESETALL, (ioaddr + XP_DATA));
3788 outb(TSTR, (ioaddr + XP_ADDR));
3789 if (inb(ioaddr + XP_DATA) != 0) {
3790 printk("STALLION: sc26198 not responding, "
3791 "brd=%d panel=%d chip=%d\n",
3792 panelp->brdnr, panelp->panelnr, i);
3793 continue;
3794 }
3795 chipmask |= (0x1 << i);
3796 outb(GCCR, (ioaddr + XP_ADDR));
3797 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3798 outb(WDTRCR, (ioaddr + XP_ADDR));
3799 outb(0xff, (ioaddr + XP_DATA));
3800 }
3801
3802 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003803 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804}
3805
3806/*****************************************************************************/
3807
3808/*
3809 * Initialize hardware specific port registers.
3810 */
3811
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003812static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813{
Jiri Slabya0564e12006-12-08 02:38:37 -08003814 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3815 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816
Jiri Slaby615e4a72006-12-08 02:38:38 -08003817 if ((brdp == NULL) || (panelp == NULL) ||
3818 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 return;
3820
3821 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3822 portp->uartaddr = (portp->portnr & 0x07) << 4;
3823 portp->pagenr = panelp->pagenr;
3824 portp->hwid = 0x1;
3825
3826 BRDENABLE(portp->brdnr, portp->pagenr);
3827 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3828 BRDDISABLE(portp->brdnr);
3829}
3830
3831/*****************************************************************************/
3832
3833/*
3834 * Set up the sc26198 registers for a port based on the termios port
3835 * settings.
3836 */
3837
Alan Cox606d0992006-12-08 02:38:45 -08003838static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003840 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 unsigned long flags;
3842 unsigned int baudrate;
3843 unsigned char mr0, mr1, mr2, clk;
3844 unsigned char imron, imroff, iopr, ipr;
3845
3846 mr0 = 0;
3847 mr1 = 0;
3848 mr2 = 0;
3849 clk = 0;
3850 iopr = 0;
3851 imron = 0;
3852 imroff = 0;
3853
3854 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003855 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 return;
3857
3858/*
3859 * Set up the RX char ignore mask with those RX error types we
3860 * can ignore.
3861 */
3862 portp->rxignoremsk = 0;
3863 if (tiosp->c_iflag & IGNPAR)
3864 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3865 SR_RXOVERRUN);
3866 if (tiosp->c_iflag & IGNBRK)
3867 portp->rxignoremsk |= SR_RXBREAK;
3868
3869 portp->rxmarkmsk = SR_RXOVERRUN;
3870 if (tiosp->c_iflag & (INPCK | PARMRK))
3871 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3872 if (tiosp->c_iflag & BRKINT)
3873 portp->rxmarkmsk |= SR_RXBREAK;
3874
3875/*
3876 * Go through the char size, parity and stop bits and set all the
3877 * option register appropriately.
3878 */
3879 switch (tiosp->c_cflag & CSIZE) {
3880 case CS5:
3881 mr1 |= MR1_CS5;
3882 break;
3883 case CS6:
3884 mr1 |= MR1_CS6;
3885 break;
3886 case CS7:
3887 mr1 |= MR1_CS7;
3888 break;
3889 default:
3890 mr1 |= MR1_CS8;
3891 break;
3892 }
3893
3894 if (tiosp->c_cflag & CSTOPB)
3895 mr2 |= MR2_STOP2;
3896 else
3897 mr2 |= MR2_STOP1;
3898
3899 if (tiosp->c_cflag & PARENB) {
3900 if (tiosp->c_cflag & PARODD)
3901 mr1 |= (MR1_PARENB | MR1_PARODD);
3902 else
3903 mr1 |= (MR1_PARENB | MR1_PAREVEN);
3904 } else {
3905 mr1 |= MR1_PARNONE;
3906 }
3907
3908 mr1 |= MR1_ERRBLOCK;
3909
3910/*
3911 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3912 * space for hardware flow control and the like. This should be set to
3913 * VMIN.
3914 */
3915 mr2 |= MR2_RXFIFOHALF;
3916
3917/*
3918 * Calculate the baud rate timers. For now we will just assume that
3919 * the input and output baud are the same. The sc26198 has a fixed
3920 * baud rate table, so only discrete baud rates possible.
3921 */
3922 baudrate = tiosp->c_cflag & CBAUD;
3923 if (baudrate & CBAUDEX) {
3924 baudrate &= ~CBAUDEX;
3925 if ((baudrate < 1) || (baudrate > 4))
3926 tiosp->c_cflag &= ~CBAUDEX;
3927 else
3928 baudrate += 15;
3929 }
3930 baudrate = stl_baudrates[baudrate];
3931 if ((tiosp->c_cflag & CBAUD) == B38400) {
3932 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3933 baudrate = 57600;
3934 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3935 baudrate = 115200;
3936 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3937 baudrate = 230400;
3938 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3939 baudrate = 460800;
3940 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3941 baudrate = (portp->baud_base / portp->custom_divisor);
3942 }
3943 if (baudrate > STL_SC26198MAXBAUD)
3944 baudrate = STL_SC26198MAXBAUD;
3945
3946 if (baudrate > 0) {
3947 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
3948 if (baudrate <= sc26198_baudtable[clk])
3949 break;
3950 }
3951 }
3952
3953/*
3954 * Check what form of modem signaling is required and set it up.
3955 */
3956 if (tiosp->c_cflag & CLOCAL) {
3957 portp->flags &= ~ASYNC_CHECK_CD;
3958 } else {
3959 iopr |= IOPR_DCDCOS;
3960 imron |= IR_IOPORT;
3961 portp->flags |= ASYNC_CHECK_CD;
3962 }
3963
3964/*
3965 * Setup sc26198 enhanced modes if we can. In particular we want to
3966 * handle as much of the flow control as possible automatically. As
3967 * well as saving a few CPU cycles it will also greatly improve flow
3968 * control reliability.
3969 */
3970 if (tiosp->c_iflag & IXON) {
3971 mr0 |= MR0_SWFTX | MR0_SWFT;
3972 imron |= IR_XONXOFF;
3973 } else {
3974 imroff |= IR_XONXOFF;
3975 }
3976 if (tiosp->c_iflag & IXOFF)
3977 mr0 |= MR0_SWFRX;
3978
3979 if (tiosp->c_cflag & CRTSCTS) {
3980 mr2 |= MR2_AUTOCTS;
3981 mr1 |= MR1_AUTORTS;
3982 }
3983
3984/*
3985 * All sc26198 register values calculated so go through and set
3986 * them all up.
3987 */
3988
Jiri Slabya0564e12006-12-08 02:38:37 -08003989 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003991 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3992 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3993 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3995 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
Alan Coxb65b5b52006-06-27 02:54:05 -07003997 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 BRDENABLE(portp->brdnr, portp->pagenr);
3999 stl_sc26198setreg(portp, IMR, 0);
4000 stl_sc26198updatereg(portp, MR0, mr0);
4001 stl_sc26198updatereg(portp, MR1, mr1);
4002 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4003 stl_sc26198updatereg(portp, MR2, mr2);
4004 stl_sc26198updatereg(portp, IOPIOR,
4005 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4006
4007 if (baudrate > 0) {
4008 stl_sc26198setreg(portp, TXCSR, clk);
4009 stl_sc26198setreg(portp, RXCSR, clk);
4010 }
4011
4012 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4013 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4014
4015 ipr = stl_sc26198getreg(portp, IPR);
4016 if (ipr & IPR_DCD)
4017 portp->sigs &= ~TIOCM_CD;
4018 else
4019 portp->sigs |= TIOCM_CD;
4020
4021 portp->imr = (portp->imr & ~imroff) | imron;
4022 stl_sc26198setreg(portp, IMR, portp->imr);
4023 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004024 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025}
4026
4027/*****************************************************************************/
4028
4029/*
4030 * Set the state of the DTR and RTS signals.
4031 */
4032
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004033static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034{
4035 unsigned char iopioron, iopioroff;
4036 unsigned long flags;
4037
Jiri Slabya0564e12006-12-08 02:38:37 -08004038 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4039 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040
4041 iopioron = 0;
4042 iopioroff = 0;
4043 if (dtr == 0)
4044 iopioroff |= IPR_DTR;
4045 else if (dtr > 0)
4046 iopioron |= IPR_DTR;
4047 if (rts == 0)
4048 iopioroff |= IPR_RTS;
4049 else if (rts > 0)
4050 iopioron |= IPR_RTS;
4051
Alan Coxb65b5b52006-06-27 02:54:05 -07004052 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 BRDENABLE(portp->brdnr, portp->pagenr);
4054 stl_sc26198setreg(portp, IOPIOR,
4055 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4056 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004057 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058}
4059
4060/*****************************************************************************/
4061
4062/*
4063 * Return the state of the signals.
4064 */
4065
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004066static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067{
4068 unsigned char ipr;
4069 unsigned long flags;
4070 int sigs;
4071
Jiri Slabya0564e12006-12-08 02:38:37 -08004072 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
Alan Coxb65b5b52006-06-27 02:54:05 -07004074 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 BRDENABLE(portp->brdnr, portp->pagenr);
4076 ipr = stl_sc26198getreg(portp, IPR);
4077 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004078 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
4080 sigs = 0;
4081 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4082 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4083 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4084 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4085 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004086 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087}
4088
4089/*****************************************************************************/
4090
4091/*
4092 * Enable/Disable the Transmitter and/or Receiver.
4093 */
4094
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004095static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096{
4097 unsigned char ccr;
4098 unsigned long flags;
4099
Jiri Slabya0564e12006-12-08 02:38:37 -08004100 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
4102 ccr = portp->crenable;
4103 if (tx == 0)
4104 ccr &= ~CR_TXENABLE;
4105 else if (tx > 0)
4106 ccr |= CR_TXENABLE;
4107 if (rx == 0)
4108 ccr &= ~CR_RXENABLE;
4109 else if (rx > 0)
4110 ccr |= CR_RXENABLE;
4111
Alan Coxb65b5b52006-06-27 02:54:05 -07004112 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 BRDENABLE(portp->brdnr, portp->pagenr);
4114 stl_sc26198setreg(portp, SCCR, ccr);
4115 BRDDISABLE(portp->brdnr);
4116 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004117 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118}
4119
4120/*****************************************************************************/
4121
4122/*
4123 * Start/stop the Transmitter and/or Receiver.
4124 */
4125
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004126static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127{
4128 unsigned char imr;
4129 unsigned long flags;
4130
Jiri Slabya0564e12006-12-08 02:38:37 -08004131 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
4133 imr = portp->imr;
4134 if (tx == 0)
4135 imr &= ~IR_TXRDY;
4136 else if (tx == 1)
4137 imr |= IR_TXRDY;
4138 if (rx == 0)
4139 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4140 else if (rx > 0)
4141 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4142
Alan Coxb65b5b52006-06-27 02:54:05 -07004143 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 BRDENABLE(portp->brdnr, portp->pagenr);
4145 stl_sc26198setreg(portp, IMR, imr);
4146 BRDDISABLE(portp->brdnr);
4147 portp->imr = imr;
4148 if (tx > 0)
4149 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004150 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151}
4152
4153/*****************************************************************************/
4154
4155/*
4156 * Disable all interrupts from this port.
4157 */
4158
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004159static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160{
4161 unsigned long flags;
4162
Jiri Slabya0564e12006-12-08 02:38:37 -08004163 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164
Alan Coxb65b5b52006-06-27 02:54:05 -07004165 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 BRDENABLE(portp->brdnr, portp->pagenr);
4167 portp->imr = 0;
4168 stl_sc26198setreg(portp, IMR, 0);
4169 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004170 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171}
4172
4173/*****************************************************************************/
4174
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004175static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176{
4177 unsigned long flags;
4178
Jiri Slabya0564e12006-12-08 02:38:37 -08004179 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180
Alan Coxb65b5b52006-06-27 02:54:05 -07004181 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 BRDENABLE(portp->brdnr, portp->pagenr);
4183 if (len == 1) {
4184 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4185 portp->stats.txbreaks++;
4186 } else {
4187 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4188 }
4189 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004190 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191}
4192
4193/*****************************************************************************/
4194
4195/*
4196 * Take flow control actions...
4197 */
4198
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004199static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200{
4201 struct tty_struct *tty;
4202 unsigned long flags;
4203 unsigned char mr0;
4204
Jiri Slabya0564e12006-12-08 02:38:37 -08004205 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
Jiri Slaby615e4a72006-12-08 02:38:38 -08004207 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 return;
4209 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004210 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 return;
4212
Alan Coxb65b5b52006-06-27 02:54:05 -07004213 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 BRDENABLE(portp->brdnr, portp->pagenr);
4215
4216 if (state) {
4217 if (tty->termios->c_iflag & IXOFF) {
4218 mr0 = stl_sc26198getreg(portp, MR0);
4219 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4220 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4221 mr0 |= MR0_SWFRX;
4222 portp->stats.rxxon++;
4223 stl_sc26198wait(portp);
4224 stl_sc26198setreg(portp, MR0, mr0);
4225 }
4226/*
4227 * Question: should we return RTS to what it was before? It may
4228 * have been set by an ioctl... Suppose not, since if you have
4229 * hardware flow control set then it is pretty silly to go and
4230 * set the RTS line by hand.
4231 */
4232 if (tty->termios->c_cflag & CRTSCTS) {
4233 stl_sc26198setreg(portp, MR1,
4234 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4235 stl_sc26198setreg(portp, IOPIOR,
4236 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4237 portp->stats.rxrtson++;
4238 }
4239 } else {
4240 if (tty->termios->c_iflag & IXOFF) {
4241 mr0 = stl_sc26198getreg(portp, MR0);
4242 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4243 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4244 mr0 &= ~MR0_SWFRX;
4245 portp->stats.rxxoff++;
4246 stl_sc26198wait(portp);
4247 stl_sc26198setreg(portp, MR0, mr0);
4248 }
4249 if (tty->termios->c_cflag & CRTSCTS) {
4250 stl_sc26198setreg(portp, MR1,
4251 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4252 stl_sc26198setreg(portp, IOPIOR,
4253 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4254 portp->stats.rxrtsoff++;
4255 }
4256 }
4257
4258 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004259 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
4262/*****************************************************************************/
4263
4264/*
4265 * Send a flow control character.
4266 */
4267
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004268static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269{
4270 struct tty_struct *tty;
4271 unsigned long flags;
4272 unsigned char mr0;
4273
Jiri Slabya0564e12006-12-08 02:38:37 -08004274 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275
Jiri Slaby615e4a72006-12-08 02:38:38 -08004276 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277 return;
4278 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004279 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 return;
4281
Alan Coxb65b5b52006-06-27 02:54:05 -07004282 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 BRDENABLE(portp->brdnr, portp->pagenr);
4284 if (state) {
4285 mr0 = stl_sc26198getreg(portp, MR0);
4286 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4287 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4288 mr0 |= MR0_SWFRX;
4289 portp->stats.rxxon++;
4290 stl_sc26198wait(portp);
4291 stl_sc26198setreg(portp, MR0, mr0);
4292 } else {
4293 mr0 = stl_sc26198getreg(portp, MR0);
4294 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4295 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4296 mr0 &= ~MR0_SWFRX;
4297 portp->stats.rxxoff++;
4298 stl_sc26198wait(portp);
4299 stl_sc26198setreg(portp, MR0, mr0);
4300 }
4301 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004302 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303}
4304
4305/*****************************************************************************/
4306
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004307static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308{
4309 unsigned long flags;
4310
Jiri Slabya0564e12006-12-08 02:38:37 -08004311 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
Jiri Slaby615e4a72006-12-08 02:38:38 -08004313 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 return;
4315
Alan Coxb65b5b52006-06-27 02:54:05 -07004316 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 BRDENABLE(portp->brdnr, portp->pagenr);
4318 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4319 stl_sc26198setreg(portp, SCCR, portp->crenable);
4320 BRDDISABLE(portp->brdnr);
4321 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004322 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323}
4324
4325/*****************************************************************************/
4326
4327/*
4328 * Return the current state of data flow on this port. This is only
4329 * really interresting when determining if data has fully completed
4330 * transmission or not... The sc26198 interrupt scheme cannot
4331 * determine when all data has actually drained, so we need to
4332 * check the port statusy register to be sure.
4333 */
4334
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004335static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336{
4337 unsigned long flags;
4338 unsigned char sr;
4339
Jiri Slabya0564e12006-12-08 02:38:37 -08004340 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341
Jiri Slaby615e4a72006-12-08 02:38:38 -08004342 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004343 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004345 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Alan Coxb65b5b52006-06-27 02:54:05 -07004347 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348 BRDENABLE(portp->brdnr, portp->pagenr);
4349 sr = stl_sc26198getreg(portp, SR);
4350 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004351 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
Jesper Juhl014c2542006-01-15 02:37:08 +01004353 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354}
4355
4356/*****************************************************************************/
4357
4358/*
4359 * Delay for a small amount of time, to give the sc26198 a chance
4360 * to process a command...
4361 */
4362
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004363static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364{
4365 int i;
4366
Jiri Slabya0564e12006-12-08 02:38:37 -08004367 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368
Jiri Slaby615e4a72006-12-08 02:38:38 -08004369 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 return;
4371
4372 for (i = 0; (i < 20); i++)
4373 stl_sc26198getglobreg(portp, TSTR);
4374}
4375
4376/*****************************************************************************/
4377
4378/*
4379 * If we are TX flow controlled and in IXANY mode then we may
4380 * need to unflow control here. We gotta do this because of the
4381 * automatic flow control modes of the sc26198.
4382 */
4383
Jiri Slaby60be4812006-12-08 02:38:40 -08004384static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385{
4386 unsigned char mr0;
4387
4388 mr0 = stl_sc26198getreg(portp, MR0);
4389 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4390 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4391 stl_sc26198wait(portp);
4392 stl_sc26198setreg(portp, MR0, mr0);
4393 clear_bit(ASYI_TXFLOWED, &portp->istate);
4394}
4395
4396/*****************************************************************************/
4397
4398/*
4399 * Interrupt service routine for sc26198 panels.
4400 */
4401
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004402static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004404 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 unsigned int iack;
4406
Alan Coxb65b5b52006-06-27 02:54:05 -07004407 spin_lock(&brd_lock);
4408
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409/*
4410 * Work around bug in sc26198 chip... Cannot have A6 address
4411 * line of UART high, else iack will be returned as 0.
4412 */
4413 outb(0, (iobase + 1));
4414
4415 iack = inb(iobase + XP_IACK);
4416 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4417
4418 if (iack & IVR_RXDATA)
4419 stl_sc26198rxisr(portp, iack);
4420 else if (iack & IVR_TXDATA)
4421 stl_sc26198txisr(portp);
4422 else
4423 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004424
4425 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426}
4427
4428/*****************************************************************************/
4429
4430/*
4431 * Transmit interrupt handler. This has gotta be fast! Handling TX
4432 * chars is pretty simple, stuff as many as possible from the TX buffer
4433 * into the sc26198 FIFO.
4434 * In practice it is possible that interrupts are enabled but that the
4435 * port has been hung up. Need to handle not having any TX buffer here,
4436 * this is done by using the side effect that head and tail will also
4437 * be NULL if the buffer has been freed.
4438 */
4439
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004440static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441{
4442 unsigned int ioaddr;
4443 unsigned char mr0;
4444 int len, stlen;
4445 char *head, *tail;
4446
Jiri Slabya0564e12006-12-08 02:38:37 -08004447 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448
4449 ioaddr = portp->ioaddr;
4450 head = portp->tx.head;
4451 tail = portp->tx.tail;
4452 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4453 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4454 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4455 set_bit(ASYI_TXLOW, &portp->istate);
4456 schedule_work(&portp->tqueue);
4457 }
4458
4459 if (len == 0) {
4460 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4461 mr0 = inb(ioaddr + XP_DATA);
4462 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4463 portp->imr &= ~IR_TXRDY;
4464 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4465 outb(portp->imr, (ioaddr + XP_DATA));
4466 clear_bit(ASYI_TXBUSY, &portp->istate);
4467 } else {
4468 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4469 outb(mr0, (ioaddr + XP_DATA));
4470 }
4471 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004472 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08004474 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475 outb(GTXFIFO, (ioaddr + XP_ADDR));
4476 outsb((ioaddr + XP_DATA), tail, stlen);
4477 len -= stlen;
4478 tail += stlen;
4479 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4480 tail = portp->tx.buf;
4481 if (len > 0) {
4482 outsb((ioaddr + XP_DATA), tail, len);
4483 tail += len;
4484 }
4485 portp->tx.tail = tail;
4486 }
4487}
4488
4489/*****************************************************************************/
4490
4491/*
4492 * Receive character interrupt handler. Determine if we have good chars
4493 * or bad chars and then process appropriately. Good chars are easy
4494 * just shove the lot into the RX buffer and set all status byte to 0.
4495 * If a bad RX char then process as required. This routine needs to be
4496 * fast! In practice it is possible that we get an interrupt on a port
4497 * that is closed. This can happen on hangups - since they completely
4498 * shutdown a port not in user context. Need to handle this case.
4499 */
4500
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004501static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502{
4503 struct tty_struct *tty;
4504 unsigned int len, buflen, ioaddr;
4505
Jiri Slabya0564e12006-12-08 02:38:37 -08004506 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507
4508 tty = portp->tty;
4509 ioaddr = portp->ioaddr;
4510 outb(GIBCR, (ioaddr + XP_ADDR));
4511 len = inb(ioaddr + XP_DATA) + 1;
4512
4513 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004514 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08004515 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516 outb(GRXFIFO, (ioaddr + XP_ADDR));
4517 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4518 portp->stats.rxlost += len;
4519 portp->stats.rxtotal += len;
4520 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004521 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004523 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004525 tty_prepare_flip_string(tty, &ptr, len);
4526 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 tty_schedule_flip(tty);
4528 portp->stats.rxtotal += len;
4529 }
4530 }
4531 } else {
4532 stl_sc26198rxbadchars(portp);
4533 }
4534
4535/*
4536 * If we are TX flow controlled and in IXANY mode then we may need
4537 * to unflow control here. We gotta do this because of the automatic
4538 * flow control modes of the sc26198.
4539 */
4540 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004541 if ((tty != NULL) &&
4542 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 (tty->termios->c_iflag & IXANY)) {
4544 stl_sc26198txunflow(portp, tty);
4545 }
4546 }
4547}
4548
4549/*****************************************************************************/
4550
4551/*
4552 * Process an RX bad character.
4553 */
4554
Jiri Slaby60be4812006-12-08 02:38:40 -08004555static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556{
4557 struct tty_struct *tty;
4558 unsigned int ioaddr;
4559
4560 tty = portp->tty;
4561 ioaddr = portp->ioaddr;
4562
4563 if (status & SR_RXPARITY)
4564 portp->stats.rxparity++;
4565 if (status & SR_RXFRAMING)
4566 portp->stats.rxframing++;
4567 if (status & SR_RXOVERRUN)
4568 portp->stats.rxoverrun++;
4569 if (status & SR_RXBREAK)
4570 portp->stats.rxbreaks++;
4571
Jiri Slaby615e4a72006-12-08 02:38:38 -08004572 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 ((portp->rxignoremsk & status) == 0)) {
4574 if (portp->rxmarkmsk & status) {
4575 if (status & SR_RXBREAK) {
4576 status = TTY_BREAK;
4577 if (portp->flags & ASYNC_SAK) {
4578 do_SAK(tty);
4579 BRDENABLE(portp->brdnr, portp->pagenr);
4580 }
4581 } else if (status & SR_RXPARITY) {
4582 status = TTY_PARITY;
4583 } else if (status & SR_RXFRAMING) {
4584 status = TTY_FRAME;
4585 } else if(status & SR_RXOVERRUN) {
4586 status = TTY_OVERRUN;
4587 } else {
4588 status = 0;
4589 }
4590 } else {
4591 status = 0;
4592 }
4593
Alan Cox33f0f882006-01-09 20:54:13 -08004594 tty_insert_flip_char(tty, ch, status);
4595 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596
4597 if (status == 0)
4598 portp->stats.rxtotal++;
4599 }
4600}
4601
4602/*****************************************************************************/
4603
4604/*
4605 * Process all characters in the RX FIFO of the UART. Check all char
4606 * status bytes as well, and process as required. We need to check
4607 * all bytes in the FIFO, in case some more enter the FIFO while we
4608 * are here. To get the exact character error type we need to switch
4609 * into CHAR error mode (that is why we need to make sure we empty
4610 * the FIFO).
4611 */
4612
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004613static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614{
4615 unsigned char status, mr1;
4616 char ch;
4617
4618/*
4619 * To get the precise error type for each character we must switch
4620 * back into CHAR error mode.
4621 */
4622 mr1 = stl_sc26198getreg(portp, MR1);
4623 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4624
4625 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4626 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4627 ch = stl_sc26198getreg(portp, RXFIFO);
4628 stl_sc26198rxbadch(portp, status, ch);
4629 }
4630
4631/*
4632 * To get correct interrupt class we must switch back into BLOCK
4633 * error mode.
4634 */
4635 stl_sc26198setreg(portp, MR1, mr1);
4636}
4637
4638/*****************************************************************************/
4639
4640/*
4641 * Other interrupt handler. This includes modem signals, flow
4642 * control actions, etc. Most stuff is left to off-level interrupt
4643 * processing time.
4644 */
4645
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004646static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647{
4648 unsigned char cir, ipr, xisr;
4649
Jiri Slabya0564e12006-12-08 02:38:37 -08004650 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651
4652 cir = stl_sc26198getglobreg(portp, CIR);
4653
4654 switch (cir & CIR_SUBTYPEMASK) {
4655 case CIR_SUBCOS:
4656 ipr = stl_sc26198getreg(portp, IPR);
4657 if (ipr & IPR_DCDCHANGE) {
4658 set_bit(ASYI_DCDCHANGE, &portp->istate);
4659 schedule_work(&portp->tqueue);
4660 portp->stats.modem++;
4661 }
4662 break;
4663 case CIR_SUBXONXOFF:
4664 xisr = stl_sc26198getreg(portp, XISR);
4665 if (xisr & XISR_RXXONGOT) {
4666 set_bit(ASYI_TXFLOWED, &portp->istate);
4667 portp->stats.txxoff++;
4668 }
4669 if (xisr & XISR_RXXOFFGOT) {
4670 clear_bit(ASYI_TXFLOWED, &portp->istate);
4671 portp->stats.txxon++;
4672 }
4673 break;
4674 case CIR_SUBBREAK:
4675 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4676 stl_sc26198rxbadchars(portp);
4677 break;
4678 default:
4679 break;
4680 }
4681}
4682
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004683static void stl_free_isabrds(void)
4684{
4685 struct stlbrd *brdp;
4686 unsigned int i;
4687
4688 for (i = 0; i < stl_nrbrds; i++) {
4689 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4690 continue;
4691
4692 free_irq(brdp->irq, brdp);
4693
4694 stl_cleanup_panels(brdp);
4695
4696 release_region(brdp->ioaddr1, brdp->iosize1);
4697 if (brdp->iosize2 > 0)
4698 release_region(brdp->ioaddr2, brdp->iosize2);
4699
4700 kfree(brdp);
4701 stl_brds[i] = NULL;
4702 }
4703}
4704
Jiri Slaby23b85a12006-12-08 02:38:40 -08004705/*
4706 * Loadable module initialization stuff.
4707 */
4708static int __init stallion_module_init(void)
4709{
Jiri Slaby843b5682006-12-08 02:39:12 -08004710 struct stlbrd *brdp;
4711 struct stlconf conf;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004712 unsigned int i;
4713 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004714
4715 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4716
4717 spin_lock_init(&stallion_lock);
4718 spin_lock_init(&brd_lock);
4719
Jiri Slaby843b5682006-12-08 02:39:12 -08004720/*
4721 * Find any dynamically supported boards. That is via module load
4722 * line options.
4723 */
4724 for (i = stl_nrbrds; i < stl_nargs; i++) {
4725 memset(&conf, 0, sizeof(conf));
4726 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4727 continue;
4728 if ((brdp = stl_allocbrd()) == NULL)
4729 continue;
4730 brdp->brdnr = i;
4731 brdp->brdtype = conf.brdtype;
4732 brdp->ioaddr1 = conf.ioaddr1;
4733 brdp->ioaddr2 = conf.ioaddr2;
4734 brdp->irq = conf.irq;
4735 brdp->irqtype = conf.irqtype;
4736 if (stl_brdinit(brdp))
4737 kfree(brdp);
4738 else
4739 stl_nrbrds = i + 1;
4740 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004741
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004742 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004743 if (retval && stl_nrbrds == 0)
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004744 goto err;
4745
Jiri Slaby23b85a12006-12-08 02:38:40 -08004746 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004747 if (!stl_serial) {
4748 retval = -ENOMEM;
4749 goto err_pcidr;
4750 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004751
4752/*
4753 * Set up a character driver for per board stuff. This is mainly used
4754 * to do stats ioctls on the ports.
4755 */
4756 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4757 printk("STALLION: failed to register serial board device\n");
4758
4759 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004760 if (IS_ERR(stallion_class)) {
4761 retval = PTR_ERR(stallion_class);
4762 goto err_reg;
4763 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004764 for (i = 0; i < 4; i++)
4765 class_device_create(stallion_class, NULL,
4766 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4767 "staliomem%d", i);
4768
4769 stl_serial->owner = THIS_MODULE;
4770 stl_serial->driver_name = stl_drvname;
4771 stl_serial->name = "ttyE";
4772 stl_serial->major = STL_SERIALMAJOR;
4773 stl_serial->minor_start = 0;
4774 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4775 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4776 stl_serial->init_termios = stl_deftermios;
4777 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4778 tty_set_operations(stl_serial, &stl_ops);
4779
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004780 retval = tty_register_driver(stl_serial);
4781 if (retval) {
Jiri Slaby23b85a12006-12-08 02:38:40 -08004782 printk("STALLION: failed to register serial driver\n");
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004783 goto err_clsdev;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004784 }
4785
4786 return 0;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004787err_clsdev:
4788 for (i = 0; i < 4; i++)
4789 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4790 class_destroy(stallion_class);
4791err_reg:
4792 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
4793 put_tty_driver(stl_serial);
4794err_pcidr:
4795 pci_unregister_driver(&stl_pcidriver);
4796 stl_free_isabrds();
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004797err:
4798 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004799}
4800
4801static void __exit stallion_module_exit(void)
4802{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004803 int i;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004804
4805 pr_debug("cleanup_module()\n");
4806
4807 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4808 stl_drvversion);
4809
4810/*
4811 * Free up all allocated resources used by the ports. This includes
4812 * memory and interrupts. As part of this process we will also do
4813 * a hangup on every open port - to try to flush out any processes
4814 * hanging onto ports.
4815 */
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004816 tty_unregister_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004817 put_tty_driver(stl_serial);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004818
Jiri Slaby23b85a12006-12-08 02:38:40 -08004819 for (i = 0; i < 4; i++)
4820 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4821 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4822 printk("STALLION: failed to un-register serial memory device, "
4823 "errno=%d\n", -i);
4824 class_destroy(stallion_class);
4825
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004826 pci_unregister_driver(&stl_pcidriver);
4827
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004828 stl_free_isabrds();
Jiri Slaby23b85a12006-12-08 02:38:40 -08004829}
4830
4831module_init(stallion_module_init);
4832module_exit(stallion_module_exit);
4833
4834MODULE_AUTHOR("Greg Ungerer");
4835MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4836MODULE_LICENSE("GPL");