blob: 4ccf4a5834c9fcdc79899fdb5aaa7e4f7c122989 [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
146
147/*
148 * Define the port structure istate flags. These set of flags are
149 * modified at interrupt time - so setting and reseting them needs
150 * to be atomic. Use the bit clear/setting routines for this.
151 */
152#define ASYI_TXBUSY 1
153#define ASYI_TXLOW 2
154#define ASYI_DCDCHANGE 3
155#define ASYI_TXFLOWED 4
156
157/*
158 * Define an array of board names as printable strings. Handy for
159 * referencing boards when printing trace and stuff.
160 */
161static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800162 NULL,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
176 NULL,
177 NULL,
178 NULL,
179 NULL,
180 NULL,
181 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 "EasyIO",
183 "EC8/32-AT",
184 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800185 NULL,
186 NULL,
187 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 "EC8/32-PCI",
189 "EC8/64-PCI",
190 "EasyIO-PCI",
191};
192
193/*****************************************************************************/
194
195/*
196 * Define some string labels for arguments passed from the module
197 * load line. These allow for easy board definitions, and easy
198 * modification of the io, memory and irq resoucres.
199 */
200static int stl_nargs = 0;
201static char *board0[4];
202static char *board1[4];
203static char *board2[4];
204static char *board3[4];
205
206static char **stl_brdsp[] = {
207 (char **) &board0,
208 (char **) &board1,
209 (char **) &board2,
210 (char **) &board3
211};
212
213/*
214 * Define a set of common board names, and types. This is used to
215 * parse any module arguments.
216 */
217
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800218static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 char *name;
220 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800221} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 { "easyio", BRD_EASYIO },
223 { "eio", BRD_EASYIO },
224 { "20", BRD_EASYIO },
225 { "ec8/32", BRD_ECH },
226 { "ec8/32-at", BRD_ECH },
227 { "ec8/32-isa", BRD_ECH },
228 { "ech", BRD_ECH },
229 { "echat", BRD_ECH },
230 { "21", BRD_ECH },
231 { "ec8/32-mc", BRD_ECHMC },
232 { "ec8/32-mca", BRD_ECHMC },
233 { "echmc", BRD_ECHMC },
234 { "echmca", BRD_ECHMC },
235 { "22", BRD_ECHMC },
236 { "ec8/32-pc", BRD_ECHPCI },
237 { "ec8/32-pci", BRD_ECHPCI },
238 { "26", BRD_ECHPCI },
239 { "ec8/64-pc", BRD_ECH64PCI },
240 { "ec8/64-pci", BRD_ECH64PCI },
241 { "ech-pci", BRD_ECH64PCI },
242 { "echpci", BRD_ECH64PCI },
243 { "echpc", BRD_ECH64PCI },
244 { "27", BRD_ECH64PCI },
245 { "easyio-pc", BRD_EASYIOPCI },
246 { "easyio-pci", BRD_EASYIOPCI },
247 { "eio-pci", BRD_EASYIOPCI },
248 { "eiopci", BRD_EASYIOPCI },
249 { "28", BRD_EASYIOPCI },
250};
251
252/*
253 * Define the module agruments.
254 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
256module_param_array(board0, charp, &stl_nargs, 0);
257MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
258module_param_array(board1, charp, &stl_nargs, 0);
259MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
260module_param_array(board2, charp, &stl_nargs, 0);
261MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
262module_param_array(board3, charp, &stl_nargs, 0);
263MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
264
265/*****************************************************************************/
266
267/*
268 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
269 * to the directly accessible io ports of these boards (not the uarts -
270 * they are in cd1400.h and sc26198.h).
271 */
272#define EIO_8PORTRS 0x04
273#define EIO_4PORTRS 0x05
274#define EIO_8PORTDI 0x00
275#define EIO_8PORTM 0x06
276#define EIO_MK3 0x03
277#define EIO_IDBITMASK 0x07
278
279#define EIO_BRDMASK 0xf0
280#define ID_BRD4 0x10
281#define ID_BRD8 0x20
282#define ID_BRD16 0x30
283
284#define EIO_INTRPEND 0x08
285#define EIO_INTEDGE 0x00
286#define EIO_INTLEVEL 0x08
287#define EIO_0WS 0x10
288
289#define ECH_ID 0xa0
290#define ECH_IDBITMASK 0xe0
291#define ECH_BRDENABLE 0x08
292#define ECH_BRDDISABLE 0x00
293#define ECH_INTENABLE 0x01
294#define ECH_INTDISABLE 0x00
295#define ECH_INTLEVEL 0x02
296#define ECH_INTEDGE 0x00
297#define ECH_INTRPEND 0x01
298#define ECH_BRDRESET 0x01
299
300#define ECHMC_INTENABLE 0x01
301#define ECHMC_BRDRESET 0x02
302
303#define ECH_PNLSTATUS 2
304#define ECH_PNL16PORT 0x20
305#define ECH_PNLIDMASK 0x07
306#define ECH_PNLXPID 0x40
307#define ECH_PNLINTRPEND 0x80
308
309#define ECH_ADDR2MASK 0x1e0
310
311/*
312 * Define the vector mapping bits for the programmable interrupt board
313 * hardware. These bits encode the interrupt for the board to use - it
314 * is software selectable (except the EIO-8M).
315 */
316static unsigned char stl_vecmap[] = {
317 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
318 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
319};
320
321/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700322 * Lock ordering is that you may not take stallion_lock holding
323 * brd_lock.
324 */
325
326static spinlock_t brd_lock; /* Guard the board mapping */
327static spinlock_t stallion_lock; /* Guard the tty driver */
328
329/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 * Set up enable and disable macros for the ECH boards. They require
331 * the secondary io address space to be activated and deactivated.
332 * This way all ECH boards can share their secondary io region.
333 * If this is an ECH-PCI board then also need to set the page pointer
334 * to point to the correct page.
335 */
336#define BRDENABLE(brdnr,pagenr) \
337 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
338 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
339 stl_brds[(brdnr)]->ioctrl); \
340 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
341 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
342
343#define BRDDISABLE(brdnr) \
344 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
345 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
346 stl_brds[(brdnr)]->ioctrl);
347
348#define STL_CD1400MAXBAUD 230400
349#define STL_SC26198MAXBAUD 460800
350
351#define STL_BAUDBASE 115200
352#define STL_CLOSEDELAY (5 * HZ / 10)
353
354/*****************************************************************************/
355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356/*
357 * Define the Stallion PCI vendor and device IDs.
358 */
359#ifndef PCI_VENDOR_ID_STALLION
360#define PCI_VENDOR_ID_STALLION 0x124d
361#endif
362#ifndef PCI_DEVICE_ID_ECHPCI832
363#define PCI_DEVICE_ID_ECHPCI832 0x0000
364#endif
365#ifndef PCI_DEVICE_ID_ECHPCI864
366#define PCI_DEVICE_ID_ECHPCI864 0x0002
367#endif
368#ifndef PCI_DEVICE_ID_EIOPCI
369#define PCI_DEVICE_ID_EIOPCI 0x0003
370#endif
371
372/*
373 * Define structure to hold all Stallion PCI boards.
374 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800376static struct pci_device_id stl_pcibrds[] = {
377 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
378 .driver_data = BRD_ECH64PCI },
379 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
380 .driver_data = BRD_EASYIOPCI },
381 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
382 .driver_data = BRD_ECHPCI },
383 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
384 .driver_data = BRD_ECHPCI },
385 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800387MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
389/*****************************************************************************/
390
391/*
392 * Define macros to extract a brd/port number from a minor number.
393 */
394#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
395#define MINOR2PORT(min) ((min) & 0x3f)
396
397/*
398 * Define a baud rate table that converts termios baud rate selector
399 * into the actual baud rate value. All baud rate calculations are
400 * based on the actual baud rate required.
401 */
402static unsigned int stl_baudrates[] = {
403 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
404 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
405};
406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407/*****************************************************************************/
408
409/*
410 * Declare all those functions in this driver!
411 */
412
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800414static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800415static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
416static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800417static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419/*
420 * CD1400 uart specific handling functions.
421 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800422static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
423static int stl_cd1400getreg(struct stlport *portp, int regnr);
424static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
425static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
426static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800427static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800428static int stl_cd1400getsignals(struct stlport *portp);
429static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
430static void stl_cd1400ccrwait(struct stlport *portp);
431static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
432static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
433static void stl_cd1400disableintrs(struct stlport *portp);
434static void stl_cd1400sendbreak(struct stlport *portp, int len);
435static void stl_cd1400flowctrl(struct stlport *portp, int state);
436static void stl_cd1400sendflow(struct stlport *portp, int state);
437static void stl_cd1400flush(struct stlport *portp);
438static int stl_cd1400datastate(struct stlport *portp);
439static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
440static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
441static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
442static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
443static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800445static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
447/*
448 * SC26198 uart specific handling functions.
449 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800450static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
451static int stl_sc26198getreg(struct stlport *portp, int regnr);
452static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
453static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
454static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
455static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800456static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800457static int stl_sc26198getsignals(struct stlport *portp);
458static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
459static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
460static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
461static void stl_sc26198disableintrs(struct stlport *portp);
462static void stl_sc26198sendbreak(struct stlport *portp, int len);
463static void stl_sc26198flowctrl(struct stlport *portp, int state);
464static void stl_sc26198sendflow(struct stlport *portp, int state);
465static void stl_sc26198flush(struct stlport *portp);
466static int stl_sc26198datastate(struct stlport *portp);
467static void stl_sc26198wait(struct stlport *portp);
468static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
469static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
470static void stl_sc26198txisr(struct stlport *port);
471static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
472static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
473static void stl_sc26198rxbadchars(struct stlport *portp);
474static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
476/*****************************************************************************/
477
478/*
479 * Generic UART support structure.
480 */
481typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800482 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
483 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800484 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800485 int (*getsignals)(struct stlport *portp);
486 void (*setsignals)(struct stlport *portp, int dtr, int rts);
487 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
488 void (*startrxtx)(struct stlport *portp, int rx, int tx);
489 void (*disableintrs)(struct stlport *portp);
490 void (*sendbreak)(struct stlport *portp, int len);
491 void (*flowctrl)(struct stlport *portp, int state);
492 void (*sendflow)(struct stlport *portp, int state);
493 void (*flush)(struct stlport *portp);
494 int (*datastate)(struct stlport *portp);
495 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496} uart_t;
497
498/*
499 * Define some macros to make calling these functions nice and clean.
500 */
501#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
502#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
503#define stl_setport (* ((uart_t *) portp->uartp)->setport)
504#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
505#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
506#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
507#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
508#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
509#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
510#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
511#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
512#define stl_flush (* ((uart_t *) portp->uartp)->flush)
513#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
514
515/*****************************************************************************/
516
517/*
518 * CD1400 UART specific data initialization.
519 */
520static uart_t stl_cd1400uart = {
521 stl_cd1400panelinit,
522 stl_cd1400portinit,
523 stl_cd1400setport,
524 stl_cd1400getsignals,
525 stl_cd1400setsignals,
526 stl_cd1400enablerxtx,
527 stl_cd1400startrxtx,
528 stl_cd1400disableintrs,
529 stl_cd1400sendbreak,
530 stl_cd1400flowctrl,
531 stl_cd1400sendflow,
532 stl_cd1400flush,
533 stl_cd1400datastate,
534 stl_cd1400eiointr
535};
536
537/*
538 * Define the offsets within the register bank of a cd1400 based panel.
539 * These io address offsets are common to the EasyIO board as well.
540 */
541#define EREG_ADDR 0
542#define EREG_DATA 4
543#define EREG_RXACK 5
544#define EREG_TXACK 6
545#define EREG_MDACK 7
546
547#define EREG_BANKSIZE 8
548
549#define CD1400_CLK 25000000
550#define CD1400_CLK8M 20000000
551
552/*
553 * Define the cd1400 baud rate clocks. These are used when calculating
554 * what clock and divisor to use for the required baud rate. Also
555 * define the maximum baud rate allowed, and the default base baud.
556 */
557static int stl_cd1400clkdivs[] = {
558 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
559};
560
561/*****************************************************************************/
562
563/*
564 * SC26198 UART specific data initization.
565 */
566static uart_t stl_sc26198uart = {
567 stl_sc26198panelinit,
568 stl_sc26198portinit,
569 stl_sc26198setport,
570 stl_sc26198getsignals,
571 stl_sc26198setsignals,
572 stl_sc26198enablerxtx,
573 stl_sc26198startrxtx,
574 stl_sc26198disableintrs,
575 stl_sc26198sendbreak,
576 stl_sc26198flowctrl,
577 stl_sc26198sendflow,
578 stl_sc26198flush,
579 stl_sc26198datastate,
580 stl_sc26198intr
581};
582
583/*
584 * Define the offsets within the register bank of a sc26198 based panel.
585 */
586#define XP_DATA 0
587#define XP_ADDR 1
588#define XP_MODID 2
589#define XP_STATUS 2
590#define XP_IACK 3
591
592#define XP_BANKSIZE 4
593
594/*
595 * Define the sc26198 baud rate table. Offsets within the table
596 * represent the actual baud rate selector of sc26198 registers.
597 */
598static unsigned int sc26198_baudtable[] = {
599 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
600 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
601 230400, 460800, 921600
602};
603
Tobias Klauserfe971072006-01-09 20:54:02 -0800604#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
606/*****************************************************************************/
607
608/*
609 * Define the driver info for a user level control device. Used mainly
610 * to get at port stats - only not using the port device itself.
611 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700612static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 .owner = THIS_MODULE,
614 .ioctl = stl_memioctl,
615};
616
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800617static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
619/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 * Check for any arguments passed in on the module load command line.
621 */
622
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623/*****************************************************************************/
624
625/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 * Parse the supplied argument string, into the board conf struct.
627 */
628
Jiri Slaby40e82652006-12-08 02:38:41 -0800629static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
631 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800632 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
Jiri Slabya0564e12006-12-08 02:38:37 -0800634 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Jiri Slaby615e4a72006-12-08 02:38:38 -0800636 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100637 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
639 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800640 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
Tobias Klauserfe971072006-01-09 20:54:02 -0800642 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
644 break;
645 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800646 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800648 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 }
650
651 confp->brdtype = stl_brdstr[i].type;
652
653 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800654 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800655 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 i++;
657 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800658 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800659 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 i++;
661 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800662 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800663 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100664 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
667/*****************************************************************************/
668
669/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 * Allocate a new board structure. Fill out the basic info in it.
671 */
672
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800673static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800675 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800677 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800678 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700679 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800680 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800681 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 }
683
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100685 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686}
687
688/*****************************************************************************/
689
690static int stl_open(struct tty_struct *tty, struct file *filp)
691{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800692 struct stlport *portp;
693 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 unsigned int minordev;
695 int brdnr, panelnr, portnr, rc;
696
Jiri Slabya0564e12006-12-08 02:38:37 -0800697 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
699 minordev = tty->index;
700 brdnr = MINOR2BRD(minordev);
701 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100702 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800704 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100705 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 minordev = MINOR2PORT(minordev);
707 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800708 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 break;
710 if (minordev < brdp->panels[panelnr]->nrports) {
711 portnr = minordev;
712 break;
713 }
714 minordev -= brdp->panels[panelnr]->nrports;
715 }
716 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100717 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
719 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800720 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100721 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
723/*
724 * On the first open of the device setup the port hardware, and
725 * initialize the per port data structure.
726 */
727 portp->tty = tty;
728 tty->driver_data = portp;
729 portp->refcount++;
730
731 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800732 if (!portp->tx.buf) {
733 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
734 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100735 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 portp->tx.head = portp->tx.buf;
737 portp->tx.tail = portp->tx.buf;
738 }
739 stl_setport(portp, tty->termios);
740 portp->sigs = stl_getsignals(portp);
741 stl_setsignals(portp, 1, 1);
742 stl_enablerxtx(portp, 1, 1);
743 stl_startrxtx(portp, 1, 0);
744 clear_bit(TTY_IO_ERROR, &tty->flags);
745 portp->flags |= ASYNC_INITIALIZED;
746 }
747
748/*
749 * Check if this port is in the middle of closing. If so then wait
750 * until it is closed then return error status, based on flag settings.
751 * The sleep here does not need interrupt protection since the wakeup
752 * for it is done with the same context.
753 */
754 if (portp->flags & ASYNC_CLOSING) {
755 interruptible_sleep_on(&portp->close_wait);
756 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100757 return -EAGAIN;
758 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 }
760
761/*
762 * Based on type of open being done check if it can overlap with any
763 * previous opens still in effect. If we are a normal serial device
764 * then also we might have to wait for carrier.
765 */
766 if (!(filp->f_flags & O_NONBLOCK)) {
767 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100768 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 }
770 portp->flags |= ASYNC_NORMAL_ACTIVE;
771
Jesper Juhl014c2542006-01-15 02:37:08 +0100772 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773}
774
775/*****************************************************************************/
776
777/*
778 * Possibly need to wait for carrier (DCD signal) to come high. Say
779 * maybe because if we are clocal then we don't need to wait...
780 */
781
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800782static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
784 unsigned long flags;
785 int rc, doclocal;
786
Jiri Slabya0564e12006-12-08 02:38:37 -0800787 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
789 rc = 0;
790 doclocal = 0;
791
Alan Coxb65b5b52006-06-27 02:54:05 -0700792 spin_lock_irqsave(&stallion_lock, flags);
793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 if (portp->tty->termios->c_cflag & CLOCAL)
795 doclocal++;
796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 portp->openwaitcnt++;
798 if (! tty_hung_up_p(filp))
799 portp->refcount--;
800
801 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700802 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 stl_setsignals(portp, 1, 1);
804 if (tty_hung_up_p(filp) ||
805 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
806 if (portp->flags & ASYNC_HUP_NOTIFY)
807 rc = -EBUSY;
808 else
809 rc = -ERESTARTSYS;
810 break;
811 }
812 if (((portp->flags & ASYNC_CLOSING) == 0) &&
813 (doclocal || (portp->sigs & TIOCM_CD))) {
814 break;
815 }
816 if (signal_pending(current)) {
817 rc = -ERESTARTSYS;
818 break;
819 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700820 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 interruptible_sleep_on(&portp->open_wait);
822 }
823
824 if (! tty_hung_up_p(filp))
825 portp->refcount++;
826 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700827 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
Jesper Juhl014c2542006-01-15 02:37:08 +0100829 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830}
831
832/*****************************************************************************/
833
Jiri Slaby96b066b2006-12-08 02:38:42 -0800834static void stl_flushbuffer(struct tty_struct *tty)
835{
836 struct stlport *portp;
837
838 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
839
840 if (tty == NULL)
841 return;
842 portp = tty->driver_data;
843 if (portp == NULL)
844 return;
845
846 stl_flush(portp);
847 tty_wakeup(tty);
848}
849
850/*****************************************************************************/
851
852static void stl_waituntilsent(struct tty_struct *tty, int timeout)
853{
854 struct stlport *portp;
855 unsigned long tend;
856
857 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
858
859 if (tty == NULL)
860 return;
861 portp = tty->driver_data;
862 if (portp == NULL)
863 return;
864
865 if (timeout == 0)
866 timeout = HZ;
867 tend = jiffies + timeout;
868
869 while (stl_datastate(portp)) {
870 if (signal_pending(current))
871 break;
872 msleep_interruptible(20);
873 if (time_after_eq(jiffies, tend))
874 break;
875 }
876}
877
878/*****************************************************************************/
879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880static void stl_close(struct tty_struct *tty, struct file *filp)
881{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800882 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 unsigned long flags;
884
Jiri Slabya0564e12006-12-08 02:38:37 -0800885 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800888 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 return;
890
Alan Coxb65b5b52006-06-27 02:54:05 -0700891 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700893 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 return;
895 }
896 if ((tty->count == 1) && (portp->refcount != 1))
897 portp->refcount = 1;
898 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700899 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 return;
901 }
902
903 portp->refcount = 0;
904 portp->flags |= ASYNC_CLOSING;
905
906/*
907 * May want to wait for any data to drain before closing. The BUSY
908 * flag keeps track of whether we are still sending or not - it is
909 * very accurate for the cd1400, not quite so for the sc26198.
910 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
911 */
912 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700913
914 spin_unlock_irqrestore(&stallion_lock, flags);
915
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
917 tty_wait_until_sent(tty, portp->closing_wait);
918 stl_waituntilsent(tty, (HZ / 2));
919
Alan Coxb65b5b52006-06-27 02:54:05 -0700920
921 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700923 spin_unlock_irqrestore(&stallion_lock, flags);
924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 stl_disableintrs(portp);
926 if (tty->termios->c_cflag & HUPCL)
927 stl_setsignals(portp, 0, 0);
928 stl_enablerxtx(portp, 0, 0);
929 stl_flushbuffer(tty);
930 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800931 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800933 portp->tx.buf = NULL;
934 portp->tx.head = NULL;
935 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 }
937 set_bit(TTY_IO_ERROR, &tty->flags);
938 tty_ldisc_flush(tty);
939
940 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800941 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
943 if (portp->openwaitcnt) {
944 if (portp->close_delay)
945 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
946 wake_up_interruptible(&portp->open_wait);
947 }
948
949 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
950 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951}
952
953/*****************************************************************************/
954
955/*
956 * Write routine. Take data and stuff it in to the TX ring queue.
957 * If transmit interrupts are not running then start them.
958 */
959
960static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
961{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800962 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 unsigned int len, stlen;
964 unsigned char *chbuf;
965 char *head, *tail;
966
Jiri Slabya0564e12006-12-08 02:38:37 -0800967 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800970 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100971 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800972 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100973 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
975/*
976 * If copying direct from user space we must cater for page faults,
977 * causing us to "sleep" here for a while. To handle this copy in all
978 * the data we need now, into a local buffer. Then when we got it all
979 * copy it into the TX buffer.
980 */
981 chbuf = (unsigned char *) buf;
982
983 head = portp->tx.head;
984 tail = portp->tx.tail;
985 if (head >= tail) {
986 len = STL_TXBUFSIZE - (head - tail) - 1;
987 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
988 } else {
989 len = tail - head - 1;
990 stlen = len;
991 }
992
Jiri Slaby843b5682006-12-08 02:39:12 -0800993 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 count = 0;
995 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800996 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 memcpy(head, chbuf, stlen);
998 len -= stlen;
999 chbuf += stlen;
1000 count += stlen;
1001 head += stlen;
1002 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1003 head = portp->tx.buf;
1004 stlen = tail - head;
1005 }
1006 }
1007 portp->tx.head = head;
1008
1009 clear_bit(ASYI_TXLOW, &portp->istate);
1010 stl_startrxtx(portp, -1, 1);
1011
Jesper Juhl014c2542006-01-15 02:37:08 +01001012 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013}
1014
1015/*****************************************************************************/
1016
1017static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1018{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001019 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 unsigned int len;
1021 char *head, *tail;
1022
Jiri Slabya0564e12006-12-08 02:38:37 -08001023 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
Jiri Slaby615e4a72006-12-08 02:38:38 -08001025 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 return;
1027 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001028 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001030 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 return;
1032
1033 head = portp->tx.head;
1034 tail = portp->tx.tail;
1035
1036 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1037 len--;
1038
1039 if (len > 0) {
1040 *head++ = ch;
1041 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1042 head = portp->tx.buf;
1043 }
1044 portp->tx.head = head;
1045}
1046
1047/*****************************************************************************/
1048
1049/*
1050 * If there are any characters in the buffer then make sure that TX
1051 * interrupts are on and get'em out. Normally used after the putchar
1052 * routine has been called.
1053 */
1054
1055static void stl_flushchars(struct tty_struct *tty)
1056{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001057 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Jiri Slabya0564e12006-12-08 02:38:37 -08001059 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Jiri Slaby615e4a72006-12-08 02:38:38 -08001061 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 return;
1063 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001064 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001066 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 return;
1068
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 stl_startrxtx(portp, -1, 1);
1070}
1071
1072/*****************************************************************************/
1073
1074static int stl_writeroom(struct tty_struct *tty)
1075{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001076 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 char *head, *tail;
1078
Jiri Slabya0564e12006-12-08 02:38:37 -08001079 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
Jiri Slaby615e4a72006-12-08 02:38:38 -08001081 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001082 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001084 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001085 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001086 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001087 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
1089 head = portp->tx.head;
1090 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001091 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092}
1093
1094/*****************************************************************************/
1095
1096/*
1097 * Return number of chars in the TX buffer. Normally we would just
1098 * calculate the number of chars in the buffer and return that, but if
1099 * the buffer is empty and TX interrupts are still on then we return
1100 * that the buffer still has 1 char in it. This way whoever called us
1101 * will not think that ALL chars have drained - since the UART still
1102 * must have some chars in it (we are busy after all).
1103 */
1104
1105static int stl_charsinbuffer(struct tty_struct *tty)
1106{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001107 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 unsigned int size;
1109 char *head, *tail;
1110
Jiri Slabya0564e12006-12-08 02:38:37 -08001111 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Jiri Slaby615e4a72006-12-08 02:38:38 -08001113 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001114 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001116 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001117 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001118 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001119 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
1121 head = portp->tx.head;
1122 tail = portp->tx.tail;
1123 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1124 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1125 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001126 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127}
1128
1129/*****************************************************************************/
1130
1131/*
1132 * Generate the serial struct info.
1133 */
1134
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001135static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
1137 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001138 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Jiri Slabya0564e12006-12-08 02:38:37 -08001140 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
1142 memset(&sio, 0, sizeof(struct serial_struct));
1143 sio.line = portp->portnr;
1144 sio.port = portp->ioaddr;
1145 sio.flags = portp->flags;
1146 sio.baud_base = portp->baud_base;
1147 sio.close_delay = portp->close_delay;
1148 sio.closing_wait = portp->closing_wait;
1149 sio.custom_divisor = portp->custom_divisor;
1150 sio.hub6 = 0;
1151 if (portp->uartp == &stl_cd1400uart) {
1152 sio.type = PORT_CIRRUS;
1153 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1154 } else {
1155 sio.type = PORT_UNKNOWN;
1156 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1157 }
1158
1159 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001160 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 sio.irq = brdp->irq;
1162
1163 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1164}
1165
1166/*****************************************************************************/
1167
1168/*
1169 * Set port according to the serial struct info.
1170 * At this point we do not do any auto-configure stuff, so we will
1171 * just quietly ignore any requests to change irq, etc.
1172 */
1173
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001174static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175{
1176 struct serial_struct sio;
1177
Jiri Slabya0564e12006-12-08 02:38:37 -08001178 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
1180 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1181 return -EFAULT;
1182 if (!capable(CAP_SYS_ADMIN)) {
1183 if ((sio.baud_base != portp->baud_base) ||
1184 (sio.close_delay != portp->close_delay) ||
1185 ((sio.flags & ~ASYNC_USR_MASK) !=
1186 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001187 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
1189
1190 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1191 (sio.flags & ASYNC_USR_MASK);
1192 portp->baud_base = sio.baud_base;
1193 portp->close_delay = sio.close_delay;
1194 portp->closing_wait = sio.closing_wait;
1195 portp->custom_divisor = sio.custom_divisor;
1196 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001197 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198}
1199
1200/*****************************************************************************/
1201
1202static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1203{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001204 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Jiri Slaby615e4a72006-12-08 02:38:38 -08001206 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001207 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001209 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001210 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001212 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
1214 return stl_getsignals(portp);
1215}
1216
1217static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1218 unsigned int set, unsigned int clear)
1219{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001220 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 int rts = -1, dtr = -1;
1222
Jiri Slaby615e4a72006-12-08 02:38:38 -08001223 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001224 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001226 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001227 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001229 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 if (set & TIOCM_RTS)
1232 rts = 1;
1233 if (set & TIOCM_DTR)
1234 dtr = 1;
1235 if (clear & TIOCM_RTS)
1236 rts = 0;
1237 if (clear & TIOCM_DTR)
1238 dtr = 0;
1239
1240 stl_setsignals(portp, dtr, rts);
1241 return 0;
1242}
1243
1244static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1245{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001246 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 unsigned int ival;
1248 int rc;
1249 void __user *argp = (void __user *)arg;
1250
Jiri Slabya0564e12006-12-08 02:38:37 -08001251 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1252 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
Jiri Slaby615e4a72006-12-08 02:38:38 -08001254 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001255 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001257 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001258 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
1260 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1261 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1262 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001263 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 }
1265
1266 rc = 0;
1267
1268 switch (cmd) {
1269 case TIOCGSOFTCAR:
1270 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1271 (unsigned __user *) argp);
1272 break;
1273 case TIOCSSOFTCAR:
1274 if (get_user(ival, (unsigned int __user *) arg))
1275 return -EFAULT;
1276 tty->termios->c_cflag =
1277 (tty->termios->c_cflag & ~CLOCAL) |
1278 (ival ? CLOCAL : 0);
1279 break;
1280 case TIOCGSERIAL:
1281 rc = stl_getserial(portp, argp);
1282 break;
1283 case TIOCSSERIAL:
1284 rc = stl_setserial(portp, argp);
1285 break;
1286 case COM_GETPORTSTATS:
1287 rc = stl_getportstats(portp, argp);
1288 break;
1289 case COM_CLRPORTSTATS:
1290 rc = stl_clrportstats(portp, argp);
1291 break;
1292 case TIOCSERCONFIG:
1293 case TIOCSERGWILD:
1294 case TIOCSERSWILD:
1295 case TIOCSERGETLSR:
1296 case TIOCSERGSTRUCT:
1297 case TIOCSERGETMULTI:
1298 case TIOCSERSETMULTI:
1299 default:
1300 rc = -ENOIOCTLCMD;
1301 break;
1302 }
1303
Jesper Juhl014c2542006-01-15 02:37:08 +01001304 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305}
1306
1307/*****************************************************************************/
1308
Jiri Slaby96b066b2006-12-08 02:38:42 -08001309/*
1310 * Start the transmitter again. Just turn TX interrupts back on.
1311 */
1312
1313static void stl_start(struct tty_struct *tty)
1314{
1315 struct stlport *portp;
1316
1317 pr_debug("stl_start(tty=%p)\n", tty);
1318
1319 if (tty == NULL)
1320 return;
1321 portp = tty->driver_data;
1322 if (portp == NULL)
1323 return;
1324 stl_startrxtx(portp, -1, 1);
1325}
1326
1327/*****************************************************************************/
1328
Alan Cox606d0992006-12-08 02:38:45 -08001329static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001331 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001332 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333
Jiri Slabya0564e12006-12-08 02:38:37 -08001334 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
Jiri Slaby615e4a72006-12-08 02:38:38 -08001336 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 return;
1338 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001339 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 return;
1341
1342 tiosp = tty->termios;
1343 if ((tiosp->c_cflag == old->c_cflag) &&
1344 (tiosp->c_iflag == old->c_iflag))
1345 return;
1346
1347 stl_setport(portp, tiosp);
1348 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1349 -1);
1350 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1351 tty->hw_stopped = 0;
1352 stl_start(tty);
1353 }
1354 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1355 wake_up_interruptible(&portp->open_wait);
1356}
1357
1358/*****************************************************************************/
1359
1360/*
1361 * Attempt to flow control who ever is sending us data. Based on termios
1362 * settings use software or/and hardware flow control.
1363 */
1364
1365static void stl_throttle(struct tty_struct *tty)
1366{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001367 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Jiri Slabya0564e12006-12-08 02:38:37 -08001369 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
Jiri Slaby615e4a72006-12-08 02:38:38 -08001371 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 return;
1373 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001374 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 return;
1376 stl_flowctrl(portp, 0);
1377}
1378
1379/*****************************************************************************/
1380
1381/*
1382 * Unflow control the device sending us data...
1383 */
1384
1385static void stl_unthrottle(struct tty_struct *tty)
1386{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001387 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Jiri Slabya0564e12006-12-08 02:38:37 -08001389 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
Jiri Slaby615e4a72006-12-08 02:38:38 -08001391 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 return;
1393 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001394 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 return;
1396 stl_flowctrl(portp, 1);
1397}
1398
1399/*****************************************************************************/
1400
1401/*
1402 * Stop the transmitter. Basically to do this we will just turn TX
1403 * interrupts off.
1404 */
1405
1406static void stl_stop(struct tty_struct *tty)
1407{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001408 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409
Jiri Slabya0564e12006-12-08 02:38:37 -08001410 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Jiri Slaby615e4a72006-12-08 02:38:38 -08001412 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 return;
1414 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001415 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 return;
1417 stl_startrxtx(portp, -1, 0);
1418}
1419
1420/*****************************************************************************/
1421
1422/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 * Hangup this port. This is pretty much like closing the port, only
1424 * a little more brutal. No waiting for data to drain. Shutdown the
1425 * port and maybe drop signals.
1426 */
1427
1428static void stl_hangup(struct tty_struct *tty)
1429{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001430 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
Jiri Slabya0564e12006-12-08 02:38:37 -08001432 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Jiri Slaby615e4a72006-12-08 02:38:38 -08001434 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 return;
1436 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001437 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 return;
1439
1440 portp->flags &= ~ASYNC_INITIALIZED;
1441 stl_disableintrs(portp);
1442 if (tty->termios->c_cflag & HUPCL)
1443 stl_setsignals(portp, 0, 0);
1444 stl_enablerxtx(portp, 0, 0);
1445 stl_flushbuffer(tty);
1446 portp->istate = 0;
1447 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001448 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001450 portp->tx.buf = NULL;
1451 portp->tx.head = NULL;
1452 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001454 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1456 portp->refcount = 0;
1457 wake_up_interruptible(&portp->open_wait);
1458}
1459
1460/*****************************************************************************/
1461
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462static void stl_breakctl(struct tty_struct *tty, int state)
1463{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001464 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
Jiri Slabya0564e12006-12-08 02:38:37 -08001466 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Jiri Slaby615e4a72006-12-08 02:38:38 -08001468 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 return;
1470 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001471 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 return;
1473
1474 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1475}
1476
1477/*****************************************************************************/
1478
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479static void stl_sendxchar(struct tty_struct *tty, char ch)
1480{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001481 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
Jiri Slabya0564e12006-12-08 02:38:37 -08001483 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Jiri Slaby615e4a72006-12-08 02:38:38 -08001485 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 return;
1487 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001488 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 return;
1490
1491 if (ch == STOP_CHAR(tty))
1492 stl_sendflow(portp, 0);
1493 else if (ch == START_CHAR(tty))
1494 stl_sendflow(portp, 1);
1495 else
1496 stl_putchar(tty, ch);
1497}
1498
1499/*****************************************************************************/
1500
1501#define MAXLINE 80
1502
1503/*
1504 * Format info for a specified port. The line is deliberately limited
1505 * to 80 characters. (If it is too long it will be truncated, if too
1506 * short then padded with spaces).
1507 */
1508
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001509static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510{
1511 char *sp;
1512 int sigs, cnt;
1513
1514 sp = pos;
1515 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1516 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1517 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1518
1519 if (portp->stats.rxframing)
1520 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1521 if (portp->stats.rxparity)
1522 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1523 if (portp->stats.rxbreaks)
1524 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1525 if (portp->stats.rxoverrun)
1526 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1527
1528 sigs = stl_getsignals(portp);
1529 cnt = sprintf(sp, "%s%s%s%s%s ",
1530 (sigs & TIOCM_RTS) ? "|RTS" : "",
1531 (sigs & TIOCM_CTS) ? "|CTS" : "",
1532 (sigs & TIOCM_DTR) ? "|DTR" : "",
1533 (sigs & TIOCM_CD) ? "|DCD" : "",
1534 (sigs & TIOCM_DSR) ? "|DSR" : "");
1535 *sp = ' ';
1536 sp += cnt;
1537
1538 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1539 *sp++ = ' ';
1540 if (cnt >= MAXLINE)
1541 pos[(MAXLINE - 2)] = '+';
1542 pos[(MAXLINE - 1)] = '\n';
1543
Jesper Juhl014c2542006-01-15 02:37:08 +01001544 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545}
1546
1547/*****************************************************************************/
1548
1549/*
1550 * Port info, read from the /proc file system.
1551 */
1552
1553static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1554{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001555 struct stlbrd *brdp;
1556 struct stlpanel *panelp;
1557 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 int brdnr, panelnr, portnr, totalport;
1559 int curoff, maxoff;
1560 char *pos;
1561
Jiri Slabya0564e12006-12-08 02:38:37 -08001562 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1563 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
1565 pos = page;
1566 totalport = 0;
1567 curoff = 0;
1568
1569 if (off == 0) {
1570 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1571 stl_drvversion);
1572 while (pos < (page + MAXLINE - 1))
1573 *pos++ = ' ';
1574 *pos++ = '\n';
1575 }
1576 curoff = MAXLINE;
1577
1578/*
1579 * We scan through for each board, panel and port. The offset is
1580 * calculated on the fly, and irrelevant ports are skipped.
1581 */
1582 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1583 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001584 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 continue;
1586 if (brdp->state == 0)
1587 continue;
1588
1589 maxoff = curoff + (brdp->nrports * MAXLINE);
1590 if (off >= maxoff) {
1591 curoff = maxoff;
1592 continue;
1593 }
1594
1595 totalport = brdnr * STL_MAXPORTS;
1596 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1597 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001598 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 continue;
1600
1601 maxoff = curoff + (panelp->nrports * MAXLINE);
1602 if (off >= maxoff) {
1603 curoff = maxoff;
1604 totalport += panelp->nrports;
1605 continue;
1606 }
1607
1608 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1609 totalport++) {
1610 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001611 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 continue;
1613 if (off >= (curoff += MAXLINE))
1614 continue;
1615 if ((pos - page + MAXLINE) > count)
1616 goto stl_readdone;
1617 pos += stl_portinfo(portp, totalport, pos);
1618 }
1619 }
1620 }
1621
1622 *eof = 1;
1623
1624stl_readdone:
1625 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001626 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627}
1628
1629/*****************************************************************************/
1630
1631/*
1632 * All board interrupts are vectored through here first. This code then
1633 * calls off to the approrpriate board interrupt handlers.
1634 */
1635
David Howells7d12e782006-10-05 14:55:46 +01001636static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001638 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639
Jiri Slabya0564e12006-12-08 02:38:37 -08001640 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
1642 return IRQ_RETVAL((* brdp->isr)(brdp));
1643}
1644
1645/*****************************************************************************/
1646
1647/*
1648 * Interrupt service routine for EasyIO board types.
1649 */
1650
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001651static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001653 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 unsigned int iobase;
1655 int handled = 0;
1656
Alan Coxb65b5b52006-06-27 02:54:05 -07001657 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 panelp = brdp->panels[0];
1659 iobase = panelp->iobase;
1660 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1661 handled = 1;
1662 (* panelp->isr)(panelp, iobase);
1663 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001664 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 return handled;
1666}
1667
1668/*****************************************************************************/
1669
1670/*
1671 * Interrupt service routine for ECH-AT board types.
1672 */
1673
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001674static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001676 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 unsigned int ioaddr;
1678 int bnknr;
1679 int handled = 0;
1680
1681 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1682
1683 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1684 handled = 1;
1685 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1686 ioaddr = brdp->bnkstataddr[bnknr];
1687 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1688 panelp = brdp->bnk2panel[bnknr];
1689 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1690 }
1691 }
1692 }
1693
1694 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1695
1696 return handled;
1697}
1698
1699/*****************************************************************************/
1700
1701/*
1702 * Interrupt service routine for ECH-MCA board types.
1703 */
1704
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001705static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001707 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 unsigned int ioaddr;
1709 int bnknr;
1710 int handled = 0;
1711
1712 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1713 handled = 1;
1714 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1715 ioaddr = brdp->bnkstataddr[bnknr];
1716 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1717 panelp = brdp->bnk2panel[bnknr];
1718 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1719 }
1720 }
1721 }
1722 return handled;
1723}
1724
1725/*****************************************************************************/
1726
1727/*
1728 * Interrupt service routine for ECH-PCI board types.
1729 */
1730
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001731static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001733 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 unsigned int ioaddr;
1735 int bnknr, recheck;
1736 int handled = 0;
1737
1738 while (1) {
1739 recheck = 0;
1740 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1741 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1742 ioaddr = brdp->bnkstataddr[bnknr];
1743 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1744 panelp = brdp->bnk2panel[bnknr];
1745 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1746 recheck++;
1747 handled = 1;
1748 }
1749 }
1750 if (! recheck)
1751 break;
1752 }
1753 return handled;
1754}
1755
1756/*****************************************************************************/
1757
1758/*
1759 * Interrupt service routine for ECH-8/64-PCI board types.
1760 */
1761
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001762static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001764 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 unsigned int ioaddr;
1766 int bnknr;
1767 int handled = 0;
1768
1769 while (inb(brdp->ioctrl) & 0x1) {
1770 handled = 1;
1771 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1772 ioaddr = brdp->bnkstataddr[bnknr];
1773 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1774 panelp = brdp->bnk2panel[bnknr];
1775 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1776 }
1777 }
1778 }
1779
1780 return handled;
1781}
1782
1783/*****************************************************************************/
1784
1785/*
1786 * Service an off-level request for some channel.
1787 */
Al Viro3e577a82006-12-06 18:41:45 +00001788static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001790 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 struct tty_struct *tty;
1792 unsigned int oldsigs;
1793
Jiri Slabya0564e12006-12-08 02:38:37 -08001794 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795
Jiri Slaby615e4a72006-12-08 02:38:38 -08001796 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 return;
1798
1799 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001800 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 return;
1802
1803 lock_kernel();
1804 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1805 tty_wakeup(tty);
1806 }
1807 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1808 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1809 oldsigs = portp->sigs;
1810 portp->sigs = stl_getsignals(portp);
1811 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1812 wake_up_interruptible(&portp->open_wait);
1813 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1814 if (portp->flags & ASYNC_CHECK_CD)
1815 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1816 }
1817 }
1818 unlock_kernel();
1819}
1820
1821/*****************************************************************************/
1822
1823/*
1824 * Initialize all the ports on a panel.
1825 */
1826
Jiri Slaby705c1862006-12-08 02:39:11 -08001827static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001829 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 int chipmask, i;
1831
Jiri Slabya0564e12006-12-08 02:38:37 -08001832 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
1834 chipmask = stl_panelinit(brdp, panelp);
1835
1836/*
1837 * All UART's are initialized (if found!). Now go through and setup
1838 * each ports data structures.
1839 */
1840 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001841 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001842 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001844 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 break;
1846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847
1848 portp->magic = STL_PORTMAGIC;
1849 portp->portnr = i;
1850 portp->brdnr = panelp->brdnr;
1851 portp->panelnr = panelp->panelnr;
1852 portp->uartp = panelp->uartp;
1853 portp->clk = brdp->clk;
1854 portp->baud_base = STL_BAUDBASE;
1855 portp->close_delay = STL_CLOSEDELAY;
1856 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001857 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 init_waitqueue_head(&portp->open_wait);
1859 init_waitqueue_head(&portp->close_wait);
1860 portp->stats.brd = portp->brdnr;
1861 portp->stats.panel = portp->panelnr;
1862 portp->stats.port = portp->portnr;
1863 panelp->ports[i] = portp;
1864 stl_portinit(brdp, panelp, portp);
1865 }
1866
1867 return(0);
1868}
1869
Jiri Slaby3b85b342006-12-08 02:39:10 -08001870static void stl_cleanup_panels(struct stlbrd *brdp)
1871{
1872 struct stlpanel *panelp;
1873 struct stlport *portp;
1874 unsigned int j, k;
1875
1876 for (j = 0; j < STL_MAXPANELS; j++) {
1877 panelp = brdp->panels[j];
1878 if (panelp == NULL)
1879 continue;
1880 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1881 portp = panelp->ports[k];
1882 if (portp == NULL)
1883 continue;
1884 if (portp->tty != NULL)
1885 stl_hangup(portp->tty);
1886 kfree(portp->tx.buf);
1887 kfree(portp);
1888 }
1889 kfree(panelp);
1890 }
1891}
1892
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893/*****************************************************************************/
1894
1895/*
1896 * Try to find and initialize an EasyIO board.
1897 */
1898
Jiri Slaby705c1862006-12-08 02:39:11 -08001899static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001901 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 unsigned int status;
1903 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001904 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
Jiri Slabya0564e12006-12-08 02:38:37 -08001906 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907
1908 brdp->ioctrl = brdp->ioaddr1 + 1;
1909 brdp->iostatus = brdp->ioaddr1 + 2;
1910
1911 status = inb(brdp->iostatus);
1912 if ((status & EIO_IDBITMASK) == EIO_MK3)
1913 brdp->ioctrl++;
1914
1915/*
1916 * Handle board specific stuff now. The real difference is PCI
1917 * or not PCI.
1918 */
1919 if (brdp->brdtype == BRD_EASYIOPCI) {
1920 brdp->iosize1 = 0x80;
1921 brdp->iosize2 = 0x80;
1922 name = "serial(EIO-PCI)";
1923 outb(0x41, (brdp->ioaddr2 + 0x4c));
1924 } else {
1925 brdp->iosize1 = 8;
1926 name = "serial(EIO)";
1927 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1928 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1929 printk("STALLION: invalid irq=%d for brd=%d\n",
1930 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001931 retval = -EINVAL;
1932 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 }
1934 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1935 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1936 brdp->ioctrl);
1937 }
1938
Jiri Slaby3b85b342006-12-08 02:39:10 -08001939 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1941 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1942 "%x conflicts with another device\n", brdp->brdnr,
1943 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001944 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 }
1946
1947 if (brdp->iosize2 > 0)
1948 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1949 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1950 "address %x conflicts with another device\n",
1951 brdp->brdnr, brdp->ioaddr2);
1952 printk(KERN_WARNING "STALLION: Warning, also "
1953 "releasing board %d I/O address %x \n",
1954 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001955 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 }
1957
1958/*
1959 * Everything looks OK, so let's go ahead and probe for the hardware.
1960 */
1961 brdp->clk = CD1400_CLK;
1962 brdp->isr = stl_eiointr;
1963
Jiri Slaby3b85b342006-12-08 02:39:10 -08001964 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 switch (status & EIO_IDBITMASK) {
1966 case EIO_8PORTM:
1967 brdp->clk = CD1400_CLK8M;
1968 /* fall thru */
1969 case EIO_8PORTRS:
1970 case EIO_8PORTDI:
1971 brdp->nrports = 8;
1972 break;
1973 case EIO_4PORTRS:
1974 brdp->nrports = 4;
1975 break;
1976 case EIO_MK3:
1977 switch (status & EIO_BRDMASK) {
1978 case ID_BRD4:
1979 brdp->nrports = 4;
1980 break;
1981 case ID_BRD8:
1982 brdp->nrports = 8;
1983 break;
1984 case ID_BRD16:
1985 brdp->nrports = 16;
1986 break;
1987 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001988 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 }
1990 break;
1991 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001992 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 }
1994
1995/*
1996 * We have verified that the board is actually present, so now we
1997 * can complete the setup.
1998 */
1999
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002000 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002001 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002003 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002004 retval = -ENOMEM;
2005 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
2008 panelp->magic = STL_PANELMAGIC;
2009 panelp->brdnr = brdp->brdnr;
2010 panelp->panelnr = 0;
2011 panelp->nrports = brdp->nrports;
2012 panelp->iobase = brdp->ioaddr1;
2013 panelp->hwid = status;
2014 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002015 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 panelp->isr = stl_sc26198intr;
2017 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002018 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 panelp->isr = stl_cd1400eiointr;
2020 }
2021
2022 brdp->panels[0] = panelp;
2023 brdp->nrpanels = 1;
2024 brdp->state |= BRD_FOUND;
2025 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002026 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 printk("STALLION: failed to register interrupt "
2028 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002029 retval = -ENODEV;
2030 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08002032
2033 return 0;
2034err_fr:
2035 stl_cleanup_panels(brdp);
2036err_rel2:
2037 if (brdp->iosize2 > 0)
2038 release_region(brdp->ioaddr2, brdp->iosize2);
2039err_rel1:
2040 release_region(brdp->ioaddr1, brdp->iosize1);
2041err:
2042 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
2045/*****************************************************************************/
2046
2047/*
2048 * Try to find an ECH board and initialize it. This code is capable of
2049 * dealing with all types of ECH board.
2050 */
2051
Jiri Slaby705c1862006-12-08 02:39:11 -08002052static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002054 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 unsigned int status, nxtid, ioaddr, conflict;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002056 int panelnr, banknr, i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 char *name;
2058
Jiri Slabya0564e12006-12-08 02:38:37 -08002059 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060
2061 status = 0;
2062 conflict = 0;
2063
2064/*
2065 * Set up the initial board register contents for boards. This varies a
2066 * bit between the different board types. So we need to handle each
2067 * separately. Also do a check that the supplied IRQ is good.
2068 */
2069 switch (brdp->brdtype) {
2070
2071 case BRD_ECH:
2072 brdp->isr = stl_echatintr;
2073 brdp->ioctrl = brdp->ioaddr1 + 1;
2074 brdp->iostatus = brdp->ioaddr1 + 1;
2075 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002076 if ((status & ECH_IDBITMASK) != ECH_ID) {
2077 retval = -ENODEV;
2078 goto err;
2079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2081 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2082 printk("STALLION: invalid irq=%d for brd=%d\n",
2083 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002084 retval = -EINVAL;
2085 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 }
2087 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2088 status |= (stl_vecmap[brdp->irq] << 1);
2089 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2090 brdp->ioctrlval = ECH_INTENABLE |
2091 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2092 for (i = 0; (i < 10); i++)
2093 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2094 brdp->iosize1 = 2;
2095 brdp->iosize2 = 32;
2096 name = "serial(EC8/32)";
2097 outb(status, brdp->ioaddr1);
2098 break;
2099
2100 case BRD_ECHMC:
2101 brdp->isr = stl_echmcaintr;
2102 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2103 brdp->iostatus = brdp->ioctrl;
2104 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002105 if ((status & ECH_IDBITMASK) != ECH_ID) {
2106 retval = -ENODEV;
2107 goto err;
2108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2110 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2111 printk("STALLION: invalid irq=%d for brd=%d\n",
2112 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002113 retval = -EINVAL;
2114 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 }
2116 outb(ECHMC_BRDRESET, brdp->ioctrl);
2117 outb(ECHMC_INTENABLE, brdp->ioctrl);
2118 brdp->iosize1 = 64;
2119 name = "serial(EC8/32-MC)";
2120 break;
2121
2122 case BRD_ECHPCI:
2123 brdp->isr = stl_echpciintr;
2124 brdp->ioctrl = brdp->ioaddr1 + 2;
2125 brdp->iosize1 = 4;
2126 brdp->iosize2 = 8;
2127 name = "serial(EC8/32-PCI)";
2128 break;
2129
2130 case BRD_ECH64PCI:
2131 brdp->isr = stl_echpci64intr;
2132 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2133 outb(0x43, (brdp->ioaddr1 + 0x4c));
2134 brdp->iosize1 = 0x80;
2135 brdp->iosize2 = 0x80;
2136 name = "serial(EC8/64-PCI)";
2137 break;
2138
2139 default:
2140 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002141 retval = -EINVAL;
2142 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 }
2144
2145/*
2146 * Check boards for possible IO address conflicts and return fail status
2147 * if an IO conflict found.
2148 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002149 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2151 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2152 "%x conflicts with another device\n", brdp->brdnr,
2153 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002154 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 }
2156
2157 if (brdp->iosize2 > 0)
2158 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2159 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2160 "address %x conflicts with another device\n",
2161 brdp->brdnr, brdp->ioaddr2);
2162 printk(KERN_WARNING "STALLION: Warning, also "
2163 "releasing board %d I/O address %x \n",
2164 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002165 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 }
2167
2168/*
2169 * Scan through the secondary io address space looking for panels.
2170 * As we find'em allocate and initialize panel structures for each.
2171 */
2172 brdp->clk = CD1400_CLK;
2173 brdp->hwid = status;
2174
2175 ioaddr = brdp->ioaddr2;
2176 banknr = 0;
2177 panelnr = 0;
2178 nxtid = 0;
2179
2180 for (i = 0; (i < STL_MAXPANELS); i++) {
2181 if (brdp->brdtype == BRD_ECHPCI) {
2182 outb(nxtid, brdp->ioctrl);
2183 ioaddr = brdp->ioaddr2;
2184 }
2185 status = inb(ioaddr + ECH_PNLSTATUS);
2186 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002187 goto err_fr;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002188 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002189 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002191 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002192 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 panelp->magic = STL_PANELMAGIC;
2195 panelp->brdnr = brdp->brdnr;
2196 panelp->panelnr = panelnr;
2197 panelp->iobase = ioaddr;
2198 panelp->pagenr = nxtid;
2199 panelp->hwid = status;
2200 brdp->bnk2panel[banknr] = panelp;
2201 brdp->bnkpageaddr[banknr] = nxtid;
2202 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2203
2204 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002205 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 panelp->isr = stl_sc26198intr;
2207 if (status & ECH_PNL16PORT) {
2208 panelp->nrports = 16;
2209 brdp->bnk2panel[banknr] = panelp;
2210 brdp->bnkpageaddr[banknr] = nxtid;
2211 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2212 ECH_PNLSTATUS;
2213 } else {
2214 panelp->nrports = 8;
2215 }
2216 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002217 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 panelp->isr = stl_cd1400echintr;
2219 if (status & ECH_PNL16PORT) {
2220 panelp->nrports = 16;
2221 panelp->ackmask = 0x80;
2222 if (brdp->brdtype != BRD_ECHPCI)
2223 ioaddr += EREG_BANKSIZE;
2224 brdp->bnk2panel[banknr] = panelp;
2225 brdp->bnkpageaddr[banknr] = ++nxtid;
2226 brdp->bnkstataddr[banknr++] = ioaddr +
2227 ECH_PNLSTATUS;
2228 } else {
2229 panelp->nrports = 8;
2230 panelp->ackmask = 0xc0;
2231 }
2232 }
2233
2234 nxtid++;
2235 ioaddr += EREG_BANKSIZE;
2236 brdp->nrports += panelp->nrports;
2237 brdp->panels[panelnr++] = panelp;
2238 if ((brdp->brdtype != BRD_ECHPCI) &&
2239 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
Jiri Slaby3b85b342006-12-08 02:39:10 -08002240 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 }
2242
2243 brdp->nrpanels = panelnr;
2244 brdp->nrbnks = banknr;
2245 if (brdp->brdtype == BRD_ECH)
2246 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2247
2248 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002249 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 printk("STALLION: failed to register interrupt "
2251 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002252 retval = -ENODEV;
2253 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
2255
Jiri Slaby3b85b342006-12-08 02:39:10 -08002256 return 0;
2257err_fr:
2258 stl_cleanup_panels(brdp);
2259 if (brdp->iosize2 > 0)
2260 release_region(brdp->ioaddr2, brdp->iosize2);
2261err_rel1:
2262 release_region(brdp->ioaddr1, brdp->iosize1);
2263err:
2264 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265}
2266
2267/*****************************************************************************/
2268
2269/*
2270 * Initialize and configure the specified board.
2271 * Scan through all the boards in the configuration and see what we
2272 * can find. Handle EIO and the ECH boards a little differently here
2273 * since the initial search and setup is very different.
2274 */
2275
Jiri Slaby705c1862006-12-08 02:39:11 -08002276static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002278 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Jiri Slabya0564e12006-12-08 02:38:37 -08002280 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
2282 switch (brdp->brdtype) {
2283 case BRD_EASYIO:
2284 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002285 retval = stl_initeio(brdp);
2286 if (retval)
2287 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 break;
2289 case BRD_ECH:
2290 case BRD_ECHMC:
2291 case BRD_ECHPCI:
2292 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002293 retval = stl_initech(brdp);
2294 if (retval)
2295 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 break;
2297 default:
2298 printk("STALLION: board=%d is unknown board type=%d\n",
2299 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002300 retval = -ENODEV;
2301 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 }
2303
2304 stl_brds[brdp->brdnr] = brdp;
2305 if ((brdp->state & BRD_FOUND) == 0) {
2306 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2307 stl_brdnames[brdp->brdtype], brdp->brdnr,
2308 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002309 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 }
2311
2312 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002313 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 stl_initports(brdp, brdp->panels[i]);
2315
2316 printk("STALLION: %s found, board=%d io=%x irq=%d "
2317 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2318 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2319 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002320
2321 return 0;
2322err_free:
2323 free_irq(brdp->irq, brdp);
2324
2325 stl_cleanup_panels(brdp);
2326
2327 release_region(brdp->ioaddr1, brdp->iosize1);
2328 if (brdp->iosize2 > 0)
2329 release_region(brdp->ioaddr2, brdp->iosize2);
2330
2331 stl_brds[brdp->brdnr] = NULL;
2332err:
2333 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334}
2335
2336/*****************************************************************************/
2337
2338/*
2339 * Find the next available board number that is free.
2340 */
2341
Jiri Slaby705c1862006-12-08 02:39:11 -08002342static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343{
2344 int i;
2345
2346 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002347 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 if (i >= stl_nrbrds)
2349 stl_nrbrds = i + 1;
2350 return(i);
2351 }
2352 }
2353 return(-1);
2354}
2355
2356/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357/*
2358 * We have a Stallion board. Allocate a board structure and
2359 * initialize it. Read its IO and IRQ resources from PCI
2360 * configuration space.
2361 */
2362
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002363static int __devinit stl_pciprobe(struct pci_dev *pdev,
2364 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002366 struct stlbrd *brdp;
2367 unsigned int brdtype = ent->driver_data;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002368 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002370 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002371 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002372
2373 dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
2374 pdev->vendor, pdev->device, pdev->class);
2375
Jiri Slaby3b85b342006-12-08 02:39:10 -08002376 retval = pci_enable_device(pdev);
2377 if (retval)
2378 goto err;
2379 brdp = stl_allocbrd();
2380 if (brdp == NULL) {
2381 retval = -ENOMEM;
2382 goto err;
2383 }
2384 brdp->brdnr = stl_getbrdnr();
2385 if (brdp->brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002386 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002388 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 }
2390 brdp->brdtype = brdtype;
2391
2392/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 * We have all resources from the board, so let's setup the actual
2394 * board structure now.
2395 */
2396 switch (brdtype) {
2397 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002398 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2399 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 break;
2401 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002402 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2403 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 break;
2405 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002406 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2407 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 break;
2409 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002410 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 break;
2412 }
2413
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002414 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002415 retval = stl_brdinit(brdp);
2416 if (retval)
2417 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002419 pci_set_drvdata(pdev, brdp);
2420
Jiri Slaby3b85b342006-12-08 02:39:10 -08002421 return 0;
2422err_fr:
2423 kfree(brdp);
2424err:
2425 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426}
2427
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002428static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002430 struct stlbrd *brdp = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002432 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002434 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002436 release_region(brdp->ioaddr1, brdp->iosize1);
2437 if (brdp->iosize2 > 0)
2438 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002440 stl_brds[brdp->brdnr] = NULL;
2441 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442}
2443
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002444static struct pci_driver stl_pcidriver = {
2445 .name = "stallion",
2446 .id_table = stl_pcibrds,
2447 .probe = stl_pciprobe,
2448 .remove = __devexit_p(stl_pciremove)
2449};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
2451/*****************************************************************************/
2452
2453/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 * Return the board stats structure to user app.
2455 */
2456
2457static int stl_getbrdstats(combrd_t __user *bp)
2458{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002459 struct stlbrd *brdp;
2460 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 int i;
2462
2463 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2464 return -EFAULT;
2465 if (stl_brdstats.brd >= STL_MAXBRDS)
2466 return(-ENODEV);
2467 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002468 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 return(-ENODEV);
2470
2471 memset(&stl_brdstats, 0, sizeof(combrd_t));
2472 stl_brdstats.brd = brdp->brdnr;
2473 stl_brdstats.type = brdp->brdtype;
2474 stl_brdstats.hwid = brdp->hwid;
2475 stl_brdstats.state = brdp->state;
2476 stl_brdstats.ioaddr = brdp->ioaddr1;
2477 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2478 stl_brdstats.irq = brdp->irq;
2479 stl_brdstats.nrpanels = brdp->nrpanels;
2480 stl_brdstats.nrports = brdp->nrports;
2481 for (i = 0; (i < brdp->nrpanels); i++) {
2482 panelp = brdp->panels[i];
2483 stl_brdstats.panels[i].panel = i;
2484 stl_brdstats.panels[i].hwid = panelp->hwid;
2485 stl_brdstats.panels[i].nrports = panelp->nrports;
2486 }
2487
2488 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2489}
2490
2491/*****************************************************************************/
2492
2493/*
2494 * Resolve the referenced port number into a port struct pointer.
2495 */
2496
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002497static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002499 struct stlbrd *brdp;
2500 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501
2502 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002503 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002505 if (brdp == NULL)
2506 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002508 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002510 if (panelp == NULL)
2511 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002513 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 return(panelp->ports[portnr]);
2515}
2516
2517/*****************************************************************************/
2518
2519/*
2520 * Return the port stats structure to user app. A NULL port struct
2521 * pointer passed in means that we need to find out from the app
2522 * what port to get stats for (used through board control device).
2523 */
2524
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002525static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526{
2527 unsigned char *head, *tail;
2528 unsigned long flags;
2529
2530 if (!portp) {
2531 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2532 return -EFAULT;
2533 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2534 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002535 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 return(-ENODEV);
2537 }
2538
2539 portp->stats.state = portp->istate;
2540 portp->stats.flags = portp->flags;
2541 portp->stats.hwid = portp->hwid;
2542
2543 portp->stats.ttystate = 0;
2544 portp->stats.cflags = 0;
2545 portp->stats.iflags = 0;
2546 portp->stats.oflags = 0;
2547 portp->stats.lflags = 0;
2548 portp->stats.rxbuffered = 0;
2549
Alan Coxb65b5b52006-06-27 02:54:05 -07002550 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002551 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552 if (portp->tty->driver_data == portp) {
2553 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002554 /* No longer available as a statistic */
2555 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002556 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 portp->stats.cflags = portp->tty->termios->c_cflag;
2558 portp->stats.iflags = portp->tty->termios->c_iflag;
2559 portp->stats.oflags = portp->tty->termios->c_oflag;
2560 portp->stats.lflags = portp->tty->termios->c_lflag;
2561 }
2562 }
2563 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002564 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
2566 head = portp->tx.head;
2567 tail = portp->tx.tail;
2568 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2569 (STL_TXBUFSIZE - (tail - head)));
2570
2571 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2572
2573 return copy_to_user(cp, &portp->stats,
2574 sizeof(comstats_t)) ? -EFAULT : 0;
2575}
2576
2577/*****************************************************************************/
2578
2579/*
2580 * Clear the port stats structure. We also return it zeroed out...
2581 */
2582
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002583static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584{
2585 if (!portp) {
2586 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2587 return -EFAULT;
2588 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2589 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002590 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 return(-ENODEV);
2592 }
2593
2594 memset(&portp->stats, 0, sizeof(comstats_t));
2595 portp->stats.brd = portp->brdnr;
2596 portp->stats.panel = portp->panelnr;
2597 portp->stats.port = portp->portnr;
2598 return copy_to_user(cp, &portp->stats,
2599 sizeof(comstats_t)) ? -EFAULT : 0;
2600}
2601
2602/*****************************************************************************/
2603
2604/*
2605 * Return the entire driver ports structure to a user app.
2606 */
2607
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002608static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002610 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002612 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 return -EFAULT;
2614 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2615 stl_dummyport.portnr);
2616 if (!portp)
2617 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002618 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619}
2620
2621/*****************************************************************************/
2622
2623/*
2624 * Return the entire driver board structure to a user app.
2625 */
2626
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002627static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002629 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002631 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 return -EFAULT;
2633 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2634 return -ENODEV;
2635 brdp = stl_brds[stl_dummybrd.brdnr];
2636 if (!brdp)
2637 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002638 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639}
2640
2641/*****************************************************************************/
2642
2643/*
2644 * The "staliomem" device is also required to do some special operations
2645 * on the board and/or ports. In this driver it is mostly used for stats
2646 * collection.
2647 */
2648
2649static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2650{
2651 int brdnr, rc;
2652 void __user *argp = (void __user *)arg;
2653
Jiri Slabya0564e12006-12-08 02:38:37 -08002654 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655
2656 brdnr = iminor(ip);
2657 if (brdnr >= STL_MAXBRDS)
2658 return(-ENODEV);
2659 rc = 0;
2660
2661 switch (cmd) {
2662 case COM_GETPORTSTATS:
2663 rc = stl_getportstats(NULL, argp);
2664 break;
2665 case COM_CLRPORTSTATS:
2666 rc = stl_clrportstats(NULL, argp);
2667 break;
2668 case COM_GETBRDSTATS:
2669 rc = stl_getbrdstats(argp);
2670 break;
2671 case COM_READPORT:
2672 rc = stl_getportstruct(argp);
2673 break;
2674 case COM_READBOARD:
2675 rc = stl_getbrdstruct(argp);
2676 break;
2677 default:
2678 rc = -ENOIOCTLCMD;
2679 break;
2680 }
2681
2682 return(rc);
2683}
2684
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002685static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 .open = stl_open,
2687 .close = stl_close,
2688 .write = stl_write,
2689 .put_char = stl_putchar,
2690 .flush_chars = stl_flushchars,
2691 .write_room = stl_writeroom,
2692 .chars_in_buffer = stl_charsinbuffer,
2693 .ioctl = stl_ioctl,
2694 .set_termios = stl_settermios,
2695 .throttle = stl_throttle,
2696 .unthrottle = stl_unthrottle,
2697 .stop = stl_stop,
2698 .start = stl_start,
2699 .hangup = stl_hangup,
2700 .flush_buffer = stl_flushbuffer,
2701 .break_ctl = stl_breakctl,
2702 .wait_until_sent = stl_waituntilsent,
2703 .send_xchar = stl_sendxchar,
2704 .read_proc = stl_readproc,
2705 .tiocmget = stl_tiocmget,
2706 .tiocmset = stl_tiocmset,
2707};
2708
2709/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710/* CD1400 HARDWARE FUNCTIONS */
2711/*****************************************************************************/
2712
2713/*
2714 * These functions get/set/update the registers of the cd1400 UARTs.
2715 * Access to the cd1400 registers is via an address/data io port pair.
2716 * (Maybe should make this inline...)
2717 */
2718
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002719static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720{
2721 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002722 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723}
2724
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002725static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726{
2727 outb((regnr + portp->uartaddr), portp->ioaddr);
2728 outb(value, portp->ioaddr + EREG_DATA);
2729}
2730
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002731static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732{
2733 outb((regnr + portp->uartaddr), portp->ioaddr);
2734 if (inb(portp->ioaddr + EREG_DATA) != value) {
2735 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002736 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002738 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739}
2740
2741/*****************************************************************************/
2742
2743/*
2744 * Inbitialize the UARTs in a panel. We don't care what sort of board
2745 * these ports are on - since the port io registers are almost
2746 * identical when dealing with ports.
2747 */
2748
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002749static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750{
2751 unsigned int gfrcr;
2752 int chipmask, i, j;
2753 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002754 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755
Jiri Slabya0564e12006-12-08 02:38:37 -08002756 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
Alan Coxb65b5b52006-06-27 02:54:05 -07002758 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 BRDENABLE(panelp->brdnr, panelp->pagenr);
2760
2761/*
2762 * Check that each chip is present and started up OK.
2763 */
2764 chipmask = 0;
2765 nrchips = panelp->nrports / CD1400_PORTS;
2766 for (i = 0; (i < nrchips); i++) {
2767 if (brdp->brdtype == BRD_ECHPCI) {
2768 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2769 ioaddr = panelp->iobase;
2770 } else {
2771 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2772 }
2773 uartaddr = (i & 0x01) ? 0x080 : 0;
2774 outb((GFRCR + uartaddr), ioaddr);
2775 outb(0, (ioaddr + EREG_DATA));
2776 outb((CCR + uartaddr), ioaddr);
2777 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2778 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2779 outb((GFRCR + uartaddr), ioaddr);
2780 for (j = 0; (j < CCR_MAXWAIT); j++) {
2781 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2782 break;
2783 }
2784 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2785 printk("STALLION: cd1400 not responding, "
2786 "brd=%d panel=%d chip=%d\n",
2787 panelp->brdnr, panelp->panelnr, i);
2788 continue;
2789 }
2790 chipmask |= (0x1 << i);
2791 outb((PPR + uartaddr), ioaddr);
2792 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2793 }
2794
2795 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002796 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002797 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798}
2799
2800/*****************************************************************************/
2801
2802/*
2803 * Initialize hardware specific port registers.
2804 */
2805
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002806static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807{
Alan Coxb65b5b52006-06-27 02:54:05 -07002808 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002809 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2810 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811
Jiri Slaby615e4a72006-12-08 02:38:38 -08002812 if ((brdp == NULL) || (panelp == NULL) ||
2813 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 return;
2815
Alan Coxb65b5b52006-06-27 02:54:05 -07002816 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2818 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2819 portp->uartaddr = (portp->portnr & 0x04) << 5;
2820 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2821
2822 BRDENABLE(portp->brdnr, portp->pagenr);
2823 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2824 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2825 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2826 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002827 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828}
2829
2830/*****************************************************************************/
2831
2832/*
2833 * Wait for the command register to be ready. We will poll this,
2834 * since it won't usually take too long to be ready.
2835 */
2836
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002837static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838{
2839 int i;
2840
2841 for (i = 0; (i < CCR_MAXWAIT); i++) {
2842 if (stl_cd1400getreg(portp, CCR) == 0) {
2843 return;
2844 }
2845 }
2846
2847 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2848 portp->portnr, portp->panelnr, portp->brdnr);
2849}
2850
2851/*****************************************************************************/
2852
2853/*
2854 * Set up the cd1400 registers for a port based on the termios port
2855 * settings.
2856 */
2857
Alan Cox606d0992006-12-08 02:38:45 -08002858static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002860 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 unsigned long flags;
2862 unsigned int clkdiv, baudrate;
2863 unsigned char cor1, cor2, cor3;
2864 unsigned char cor4, cor5, ccr;
2865 unsigned char srer, sreron, sreroff;
2866 unsigned char mcor1, mcor2, rtpr;
2867 unsigned char clk, div;
2868
2869 cor1 = 0;
2870 cor2 = 0;
2871 cor3 = 0;
2872 cor4 = 0;
2873 cor5 = 0;
2874 ccr = 0;
2875 rtpr = 0;
2876 clk = 0;
2877 div = 0;
2878 mcor1 = 0;
2879 mcor2 = 0;
2880 sreron = 0;
2881 sreroff = 0;
2882
2883 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002884 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885 return;
2886
2887/*
2888 * Set up the RX char ignore mask with those RX error types we
2889 * can ignore. We can get the cd1400 to help us out a little here,
2890 * it will ignore parity errors and breaks for us.
2891 */
2892 portp->rxignoremsk = 0;
2893 if (tiosp->c_iflag & IGNPAR) {
2894 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2895 cor1 |= COR1_PARIGNORE;
2896 }
2897 if (tiosp->c_iflag & IGNBRK) {
2898 portp->rxignoremsk |= ST_BREAK;
2899 cor4 |= COR4_IGNBRK;
2900 }
2901
2902 portp->rxmarkmsk = ST_OVERRUN;
2903 if (tiosp->c_iflag & (INPCK | PARMRK))
2904 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2905 if (tiosp->c_iflag & BRKINT)
2906 portp->rxmarkmsk |= ST_BREAK;
2907
2908/*
2909 * Go through the char size, parity and stop bits and set all the
2910 * option register appropriately.
2911 */
2912 switch (tiosp->c_cflag & CSIZE) {
2913 case CS5:
2914 cor1 |= COR1_CHL5;
2915 break;
2916 case CS6:
2917 cor1 |= COR1_CHL6;
2918 break;
2919 case CS7:
2920 cor1 |= COR1_CHL7;
2921 break;
2922 default:
2923 cor1 |= COR1_CHL8;
2924 break;
2925 }
2926
2927 if (tiosp->c_cflag & CSTOPB)
2928 cor1 |= COR1_STOP2;
2929 else
2930 cor1 |= COR1_STOP1;
2931
2932 if (tiosp->c_cflag & PARENB) {
2933 if (tiosp->c_cflag & PARODD)
2934 cor1 |= (COR1_PARENB | COR1_PARODD);
2935 else
2936 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2937 } else {
2938 cor1 |= COR1_PARNONE;
2939 }
2940
2941/*
2942 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2943 * space for hardware flow control and the like. This should be set to
2944 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2945 * really be based on VTIME.
2946 */
2947 cor3 |= FIFO_RXTHRESHOLD;
2948 rtpr = 2;
2949
2950/*
2951 * Calculate the baud rate timers. For now we will just assume that
2952 * the input and output baud are the same. Could have used a baud
2953 * table here, but this way we can generate virtually any baud rate
2954 * we like!
2955 */
2956 baudrate = tiosp->c_cflag & CBAUD;
2957 if (baudrate & CBAUDEX) {
2958 baudrate &= ~CBAUDEX;
2959 if ((baudrate < 1) || (baudrate > 4))
2960 tiosp->c_cflag &= ~CBAUDEX;
2961 else
2962 baudrate += 15;
2963 }
2964 baudrate = stl_baudrates[baudrate];
2965 if ((tiosp->c_cflag & CBAUD) == B38400) {
2966 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2967 baudrate = 57600;
2968 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2969 baudrate = 115200;
2970 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2971 baudrate = 230400;
2972 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2973 baudrate = 460800;
2974 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
2975 baudrate = (portp->baud_base / portp->custom_divisor);
2976 }
2977 if (baudrate > STL_CD1400MAXBAUD)
2978 baudrate = STL_CD1400MAXBAUD;
2979
2980 if (baudrate > 0) {
2981 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
2982 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
2983 if (clkdiv < 0x100)
2984 break;
2985 }
2986 div = (unsigned char) clkdiv;
2987 }
2988
2989/*
2990 * Check what form of modem signaling is required and set it up.
2991 */
2992 if ((tiosp->c_cflag & CLOCAL) == 0) {
2993 mcor1 |= MCOR1_DCD;
2994 mcor2 |= MCOR2_DCD;
2995 sreron |= SRER_MODEM;
2996 portp->flags |= ASYNC_CHECK_CD;
2997 } else {
2998 portp->flags &= ~ASYNC_CHECK_CD;
2999 }
3000
3001/*
3002 * Setup cd1400 enhanced modes if we can. In particular we want to
3003 * handle as much of the flow control as possible automatically. As
3004 * well as saving a few CPU cycles it will also greatly improve flow
3005 * control reliability.
3006 */
3007 if (tiosp->c_iflag & IXON) {
3008 cor2 |= COR2_TXIBE;
3009 cor3 |= COR3_SCD12;
3010 if (tiosp->c_iflag & IXANY)
3011 cor2 |= COR2_IXM;
3012 }
3013
3014 if (tiosp->c_cflag & CRTSCTS) {
3015 cor2 |= COR2_CTSAE;
3016 mcor1 |= FIFO_RTSTHRESHOLD;
3017 }
3018
3019/*
3020 * All cd1400 register values calculated so go through and set
3021 * them all up.
3022 */
3023
Jiri Slabya0564e12006-12-08 02:38:37 -08003024 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003026 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003028 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003030 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3031 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3033 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
Alan Coxb65b5b52006-06-27 02:54:05 -07003035 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 BRDENABLE(portp->brdnr, portp->pagenr);
3037 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3038 srer = stl_cd1400getreg(portp, SRER);
3039 stl_cd1400setreg(portp, SRER, 0);
3040 if (stl_cd1400updatereg(portp, COR1, cor1))
3041 ccr = 1;
3042 if (stl_cd1400updatereg(portp, COR2, cor2))
3043 ccr = 1;
3044 if (stl_cd1400updatereg(portp, COR3, cor3))
3045 ccr = 1;
3046 if (ccr) {
3047 stl_cd1400ccrwait(portp);
3048 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3049 }
3050 stl_cd1400setreg(portp, COR4, cor4);
3051 stl_cd1400setreg(portp, COR5, cor5);
3052 stl_cd1400setreg(portp, MCOR1, mcor1);
3053 stl_cd1400setreg(portp, MCOR2, mcor2);
3054 if (baudrate > 0) {
3055 stl_cd1400setreg(portp, TCOR, clk);
3056 stl_cd1400setreg(portp, TBPR, div);
3057 stl_cd1400setreg(portp, RCOR, clk);
3058 stl_cd1400setreg(portp, RBPR, div);
3059 }
3060 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3061 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3062 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3063 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3064 stl_cd1400setreg(portp, RTPR, rtpr);
3065 mcor1 = stl_cd1400getreg(portp, MSVR1);
3066 if (mcor1 & MSVR1_DCD)
3067 portp->sigs |= TIOCM_CD;
3068 else
3069 portp->sigs &= ~TIOCM_CD;
3070 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3071 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003072 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073}
3074
3075/*****************************************************************************/
3076
3077/*
3078 * Set the state of the DTR and RTS signals.
3079 */
3080
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003081static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082{
3083 unsigned char msvr1, msvr2;
3084 unsigned long flags;
3085
Jiri Slabya0564e12006-12-08 02:38:37 -08003086 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3087 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088
3089 msvr1 = 0;
3090 msvr2 = 0;
3091 if (dtr > 0)
3092 msvr1 = MSVR1_DTR;
3093 if (rts > 0)
3094 msvr2 = MSVR2_RTS;
3095
Alan Coxb65b5b52006-06-27 02:54:05 -07003096 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 BRDENABLE(portp->brdnr, portp->pagenr);
3098 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3099 if (rts >= 0)
3100 stl_cd1400setreg(portp, MSVR2, msvr2);
3101 if (dtr >= 0)
3102 stl_cd1400setreg(portp, MSVR1, msvr1);
3103 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003104 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105}
3106
3107/*****************************************************************************/
3108
3109/*
3110 * Return the state of the signals.
3111 */
3112
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003113static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114{
3115 unsigned char msvr1, msvr2;
3116 unsigned long flags;
3117 int sigs;
3118
Jiri Slabya0564e12006-12-08 02:38:37 -08003119 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120
Alan Coxb65b5b52006-06-27 02:54:05 -07003121 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 BRDENABLE(portp->brdnr, portp->pagenr);
3123 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3124 msvr1 = stl_cd1400getreg(portp, MSVR1);
3125 msvr2 = stl_cd1400getreg(portp, MSVR2);
3126 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003127 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
3129 sigs = 0;
3130 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3131 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3132 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3133 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3134#if 0
3135 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3136 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3137#else
3138 sigs |= TIOCM_DSR;
3139#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003140 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141}
3142
3143/*****************************************************************************/
3144
3145/*
3146 * Enable/Disable the Transmitter and/or Receiver.
3147 */
3148
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003149static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150{
3151 unsigned char ccr;
3152 unsigned long flags;
3153
Jiri Slabya0564e12006-12-08 02:38:37 -08003154 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3155
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 ccr = 0;
3157
3158 if (tx == 0)
3159 ccr |= CCR_TXDISABLE;
3160 else if (tx > 0)
3161 ccr |= CCR_TXENABLE;
3162 if (rx == 0)
3163 ccr |= CCR_RXDISABLE;
3164 else if (rx > 0)
3165 ccr |= CCR_RXENABLE;
3166
Alan Coxb65b5b52006-06-27 02:54:05 -07003167 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 BRDENABLE(portp->brdnr, portp->pagenr);
3169 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3170 stl_cd1400ccrwait(portp);
3171 stl_cd1400setreg(portp, CCR, ccr);
3172 stl_cd1400ccrwait(portp);
3173 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003174 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175}
3176
3177/*****************************************************************************/
3178
3179/*
3180 * Start/stop the Transmitter and/or Receiver.
3181 */
3182
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003183static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184{
3185 unsigned char sreron, sreroff;
3186 unsigned long flags;
3187
Jiri Slabya0564e12006-12-08 02:38:37 -08003188 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189
3190 sreron = 0;
3191 sreroff = 0;
3192 if (tx == 0)
3193 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3194 else if (tx == 1)
3195 sreron |= SRER_TXDATA;
3196 else if (tx >= 2)
3197 sreron |= SRER_TXEMPTY;
3198 if (rx == 0)
3199 sreroff |= SRER_RXDATA;
3200 else if (rx > 0)
3201 sreron |= SRER_RXDATA;
3202
Alan Coxb65b5b52006-06-27 02:54:05 -07003203 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204 BRDENABLE(portp->brdnr, portp->pagenr);
3205 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3206 stl_cd1400setreg(portp, SRER,
3207 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3208 BRDDISABLE(portp->brdnr);
3209 if (tx > 0)
3210 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003211 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212}
3213
3214/*****************************************************************************/
3215
3216/*
3217 * Disable all interrupts from this port.
3218 */
3219
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003220static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221{
3222 unsigned long flags;
3223
Jiri Slabya0564e12006-12-08 02:38:37 -08003224 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3225
Alan Coxb65b5b52006-06-27 02:54:05 -07003226 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227 BRDENABLE(portp->brdnr, portp->pagenr);
3228 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3229 stl_cd1400setreg(portp, SRER, 0);
3230 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003231 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232}
3233
3234/*****************************************************************************/
3235
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003236static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237{
3238 unsigned long flags;
3239
Jiri Slabya0564e12006-12-08 02:38:37 -08003240 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241
Alan Coxb65b5b52006-06-27 02:54:05 -07003242 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 BRDENABLE(portp->brdnr, portp->pagenr);
3244 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3245 stl_cd1400setreg(portp, SRER,
3246 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3247 SRER_TXEMPTY));
3248 BRDDISABLE(portp->brdnr);
3249 portp->brklen = len;
3250 if (len == 1)
3251 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003252 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253}
3254
3255/*****************************************************************************/
3256
3257/*
3258 * Take flow control actions...
3259 */
3260
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003261static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262{
3263 struct tty_struct *tty;
3264 unsigned long flags;
3265
Jiri Slabya0564e12006-12-08 02:38:37 -08003266 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267
Jiri Slaby615e4a72006-12-08 02:38:38 -08003268 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 return;
3270 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003271 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 return;
3273
Alan Coxb65b5b52006-06-27 02:54:05 -07003274 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 BRDENABLE(portp->brdnr, portp->pagenr);
3276 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3277
3278 if (state) {
3279 if (tty->termios->c_iflag & IXOFF) {
3280 stl_cd1400ccrwait(portp);
3281 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3282 portp->stats.rxxon++;
3283 stl_cd1400ccrwait(portp);
3284 }
3285/*
3286 * Question: should we return RTS to what it was before? It may
3287 * have been set by an ioctl... Suppose not, since if you have
3288 * hardware flow control set then it is pretty silly to go and
3289 * set the RTS line by hand.
3290 */
3291 if (tty->termios->c_cflag & CRTSCTS) {
3292 stl_cd1400setreg(portp, MCOR1,
3293 (stl_cd1400getreg(portp, MCOR1) |
3294 FIFO_RTSTHRESHOLD));
3295 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3296 portp->stats.rxrtson++;
3297 }
3298 } else {
3299 if (tty->termios->c_iflag & IXOFF) {
3300 stl_cd1400ccrwait(portp);
3301 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3302 portp->stats.rxxoff++;
3303 stl_cd1400ccrwait(portp);
3304 }
3305 if (tty->termios->c_cflag & CRTSCTS) {
3306 stl_cd1400setreg(portp, MCOR1,
3307 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3308 stl_cd1400setreg(portp, MSVR2, 0);
3309 portp->stats.rxrtsoff++;
3310 }
3311 }
3312
3313 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003314 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315}
3316
3317/*****************************************************************************/
3318
3319/*
3320 * Send a flow control character...
3321 */
3322
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003323static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324{
3325 struct tty_struct *tty;
3326 unsigned long flags;
3327
Jiri Slabya0564e12006-12-08 02:38:37 -08003328 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329
Jiri Slaby615e4a72006-12-08 02:38:38 -08003330 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331 return;
3332 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003333 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334 return;
3335
Alan Coxb65b5b52006-06-27 02:54:05 -07003336 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 BRDENABLE(portp->brdnr, portp->pagenr);
3338 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3339 if (state) {
3340 stl_cd1400ccrwait(portp);
3341 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3342 portp->stats.rxxon++;
3343 stl_cd1400ccrwait(portp);
3344 } else {
3345 stl_cd1400ccrwait(portp);
3346 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3347 portp->stats.rxxoff++;
3348 stl_cd1400ccrwait(portp);
3349 }
3350 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003351 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352}
3353
3354/*****************************************************************************/
3355
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003356static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357{
3358 unsigned long flags;
3359
Jiri Slabya0564e12006-12-08 02:38:37 -08003360 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361
Jiri Slaby615e4a72006-12-08 02:38:38 -08003362 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363 return;
3364
Alan Coxb65b5b52006-06-27 02:54:05 -07003365 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 BRDENABLE(portp->brdnr, portp->pagenr);
3367 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3368 stl_cd1400ccrwait(portp);
3369 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3370 stl_cd1400ccrwait(portp);
3371 portp->tx.tail = portp->tx.head;
3372 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003373 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374}
3375
3376/*****************************************************************************/
3377
3378/*
3379 * Return the current state of data flow on this port. This is only
3380 * really interresting when determining if data has fully completed
3381 * transmission or not... This is easy for the cd1400, it accurately
3382 * maintains the busy port flag.
3383 */
3384
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003385static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386{
Jiri Slabya0564e12006-12-08 02:38:37 -08003387 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388
Jiri Slaby615e4a72006-12-08 02:38:38 -08003389 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003390 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391
Jesper Juhl014c2542006-01-15 02:37:08 +01003392 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393}
3394
3395/*****************************************************************************/
3396
3397/*
3398 * Interrupt service routine for cd1400 EasyIO boards.
3399 */
3400
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003401static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402{
3403 unsigned char svrtype;
3404
Jiri Slabya0564e12006-12-08 02:38:37 -08003405 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
Alan Coxb65b5b52006-06-27 02:54:05 -07003407 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408 outb(SVRR, iobase);
3409 svrtype = inb(iobase + EREG_DATA);
3410 if (panelp->nrports > 4) {
3411 outb((SVRR + 0x80), iobase);
3412 svrtype |= inb(iobase + EREG_DATA);
3413 }
3414
3415 if (svrtype & SVRR_RX)
3416 stl_cd1400rxisr(panelp, iobase);
3417 else if (svrtype & SVRR_TX)
3418 stl_cd1400txisr(panelp, iobase);
3419 else if (svrtype & SVRR_MDM)
3420 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003421
3422 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423}
3424
3425/*****************************************************************************/
3426
3427/*
3428 * Interrupt service routine for cd1400 panels.
3429 */
3430
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003431static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432{
3433 unsigned char svrtype;
3434
Jiri Slabya0564e12006-12-08 02:38:37 -08003435 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436
3437 outb(SVRR, iobase);
3438 svrtype = inb(iobase + EREG_DATA);
3439 outb((SVRR + 0x80), iobase);
3440 svrtype |= inb(iobase + EREG_DATA);
3441 if (svrtype & SVRR_RX)
3442 stl_cd1400rxisr(panelp, iobase);
3443 else if (svrtype & SVRR_TX)
3444 stl_cd1400txisr(panelp, iobase);
3445 else if (svrtype & SVRR_MDM)
3446 stl_cd1400mdmisr(panelp, iobase);
3447}
3448
3449
3450/*****************************************************************************/
3451
3452/*
3453 * Unfortunately we need to handle breaks in the TX data stream, since
3454 * this is the only way to generate them on the cd1400.
3455 */
3456
Jiri Slaby60be4812006-12-08 02:38:40 -08003457static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458{
3459 if (portp->brklen == 1) {
3460 outb((COR2 + portp->uartaddr), ioaddr);
3461 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3462 (ioaddr + EREG_DATA));
3463 outb((TDR + portp->uartaddr), ioaddr);
3464 outb(ETC_CMD, (ioaddr + EREG_DATA));
3465 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3466 outb((SRER + portp->uartaddr), ioaddr);
3467 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3468 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003469 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 } else if (portp->brklen > 1) {
3471 outb((TDR + portp->uartaddr), ioaddr);
3472 outb(ETC_CMD, (ioaddr + EREG_DATA));
3473 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3474 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003475 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 } else {
3477 outb((COR2 + portp->uartaddr), ioaddr);
3478 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3479 (ioaddr + EREG_DATA));
3480 portp->brklen = 0;
3481 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003482 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483}
3484
3485/*****************************************************************************/
3486
3487/*
3488 * Transmit interrupt handler. This has gotta be fast! Handling TX
3489 * chars is pretty simple, stuff as many as possible from the TX buffer
3490 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3491 * are embedded as commands in the data stream. Oh no, had to use a goto!
3492 * This could be optimized more, will do when I get time...
3493 * In practice it is possible that interrupts are enabled but that the
3494 * port has been hung up. Need to handle not having any TX buffer here,
3495 * this is done by using the side effect that head and tail will also
3496 * be NULL if the buffer has been freed.
3497 */
3498
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003499static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003501 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 int len, stlen;
3503 char *head, *tail;
3504 unsigned char ioack, srer;
3505
Jiri Slabya0564e12006-12-08 02:38:37 -08003506 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507
3508 ioack = inb(ioaddr + EREG_TXACK);
3509 if (((ioack & panelp->ackmask) != 0) ||
3510 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3511 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3512 return;
3513 }
3514 portp = panelp->ports[(ioack >> 3)];
3515
3516/*
3517 * Unfortunately we need to handle breaks in the data stream, since
3518 * this is the only way to generate them on the cd1400. Do it now if
3519 * a break is to be sent.
3520 */
3521 if (portp->brklen != 0)
3522 if (stl_cd1400breakisr(portp, ioaddr))
3523 goto stl_txalldone;
3524
3525 head = portp->tx.head;
3526 tail = portp->tx.tail;
3527 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3528 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3529 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3530 set_bit(ASYI_TXLOW, &portp->istate);
3531 schedule_work(&portp->tqueue);
3532 }
3533
3534 if (len == 0) {
3535 outb((SRER + portp->uartaddr), ioaddr);
3536 srer = inb(ioaddr + EREG_DATA);
3537 if (srer & SRER_TXDATA) {
3538 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3539 } else {
3540 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3541 clear_bit(ASYI_TXBUSY, &portp->istate);
3542 }
3543 outb(srer, (ioaddr + EREG_DATA));
3544 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003545 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08003547 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 outb((TDR + portp->uartaddr), ioaddr);
3549 outsb((ioaddr + EREG_DATA), tail, stlen);
3550 len -= stlen;
3551 tail += stlen;
3552 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3553 tail = portp->tx.buf;
3554 if (len > 0) {
3555 outsb((ioaddr + EREG_DATA), tail, len);
3556 tail += len;
3557 }
3558 portp->tx.tail = tail;
3559 }
3560
3561stl_txalldone:
3562 outb((EOSRR + portp->uartaddr), ioaddr);
3563 outb(0, (ioaddr + EREG_DATA));
3564}
3565
3566/*****************************************************************************/
3567
3568/*
3569 * Receive character interrupt handler. Determine if we have good chars
3570 * or bad chars and then process appropriately. Good chars are easy
3571 * just shove the lot into the RX buffer and set all status byte to 0.
3572 * If a bad RX char then process as required. This routine needs to be
3573 * fast! In practice it is possible that we get an interrupt on a port
3574 * that is closed. This can happen on hangups - since they completely
3575 * shutdown a port not in user context. Need to handle this case.
3576 */
3577
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003578static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003580 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 struct tty_struct *tty;
3582 unsigned int ioack, len, buflen;
3583 unsigned char status;
3584 char ch;
3585
Jiri Slabya0564e12006-12-08 02:38:37 -08003586 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
3588 ioack = inb(ioaddr + EREG_RXACK);
3589 if ((ioack & panelp->ackmask) != 0) {
3590 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3591 return;
3592 }
3593 portp = panelp->ports[(ioack >> 3)];
3594 tty = portp->tty;
3595
3596 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3597 outb((RDCR + portp->uartaddr), ioaddr);
3598 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003599 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08003600 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 outb((RDSR + portp->uartaddr), ioaddr);
3602 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3603 portp->stats.rxlost += len;
3604 portp->stats.rxtotal += len;
3605 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003606 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003608 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003610 tty_prepare_flip_string(tty, &ptr, len);
3611 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 tty_schedule_flip(tty);
3613 portp->stats.rxtotal += len;
3614 }
3615 }
3616 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3617 outb((RDSR + portp->uartaddr), ioaddr);
3618 status = inb(ioaddr + EREG_DATA);
3619 ch = inb(ioaddr + EREG_DATA);
3620 if (status & ST_PARITY)
3621 portp->stats.rxparity++;
3622 if (status & ST_FRAMING)
3623 portp->stats.rxframing++;
3624 if (status & ST_OVERRUN)
3625 portp->stats.rxoverrun++;
3626 if (status & ST_BREAK)
3627 portp->stats.rxbreaks++;
3628 if (status & ST_SCHARMASK) {
3629 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3630 portp->stats.txxon++;
3631 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3632 portp->stats.txxoff++;
3633 goto stl_rxalldone;
3634 }
Alan Cox33f0f882006-01-09 20:54:13 -08003635 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 if (portp->rxmarkmsk & status) {
3637 if (status & ST_BREAK) {
3638 status = TTY_BREAK;
3639 if (portp->flags & ASYNC_SAK) {
3640 do_SAK(tty);
3641 BRDENABLE(portp->brdnr, portp->pagenr);
3642 }
3643 } else if (status & ST_PARITY) {
3644 status = TTY_PARITY;
3645 } else if (status & ST_FRAMING) {
3646 status = TTY_FRAME;
3647 } else if(status & ST_OVERRUN) {
3648 status = TTY_OVERRUN;
3649 } else {
3650 status = 0;
3651 }
3652 } else {
3653 status = 0;
3654 }
Alan Cox33f0f882006-01-09 20:54:13 -08003655 tty_insert_flip_char(tty, ch, status);
3656 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 }
3658 } else {
3659 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3660 return;
3661 }
3662
3663stl_rxalldone:
3664 outb((EOSRR + portp->uartaddr), ioaddr);
3665 outb(0, (ioaddr + EREG_DATA));
3666}
3667
3668/*****************************************************************************/
3669
3670/*
3671 * Modem interrupt handler. The is called when the modem signal line
3672 * (DCD) has changed state. Leave most of the work to the off-level
3673 * processing routine.
3674 */
3675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003676static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003678 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 unsigned int ioack;
3680 unsigned char misr;
3681
Jiri Slabya0564e12006-12-08 02:38:37 -08003682 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683
3684 ioack = inb(ioaddr + EREG_MDACK);
3685 if (((ioack & panelp->ackmask) != 0) ||
3686 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3687 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3688 return;
3689 }
3690 portp = panelp->ports[(ioack >> 3)];
3691
3692 outb((MISR + portp->uartaddr), ioaddr);
3693 misr = inb(ioaddr + EREG_DATA);
3694 if (misr & MISR_DCD) {
3695 set_bit(ASYI_DCDCHANGE, &portp->istate);
3696 schedule_work(&portp->tqueue);
3697 portp->stats.modem++;
3698 }
3699
3700 outb((EOSRR + portp->uartaddr), ioaddr);
3701 outb(0, (ioaddr + EREG_DATA));
3702}
3703
3704/*****************************************************************************/
3705/* SC26198 HARDWARE FUNCTIONS */
3706/*****************************************************************************/
3707
3708/*
3709 * These functions get/set/update the registers of the sc26198 UARTs.
3710 * Access to the sc26198 registers is via an address/data io port pair.
3711 * (Maybe should make this inline...)
3712 */
3713
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003714static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715{
3716 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003717 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718}
3719
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003720static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721{
3722 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3723 outb(value, (portp->ioaddr + XP_DATA));
3724}
3725
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003726static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727{
3728 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3729 if (inb(portp->ioaddr + XP_DATA) != value) {
3730 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003731 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003733 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734}
3735
3736/*****************************************************************************/
3737
3738/*
3739 * Functions to get and set the sc26198 global registers.
3740 */
3741
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003742static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743{
3744 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003745 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746}
3747
3748#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003749static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750{
3751 outb(regnr, (portp->ioaddr + XP_ADDR));
3752 outb(value, (portp->ioaddr + XP_DATA));
3753}
3754#endif
3755
3756/*****************************************************************************/
3757
3758/*
3759 * Inbitialize the UARTs in a panel. We don't care what sort of board
3760 * these ports are on - since the port io registers are almost
3761 * identical when dealing with ports.
3762 */
3763
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003764static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765{
3766 int chipmask, i;
3767 int nrchips, ioaddr;
3768
Jiri Slabya0564e12006-12-08 02:38:37 -08003769 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770
3771 BRDENABLE(panelp->brdnr, panelp->pagenr);
3772
3773/*
3774 * Check that each chip is present and started up OK.
3775 */
3776 chipmask = 0;
3777 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3778 if (brdp->brdtype == BRD_ECHPCI)
3779 outb(panelp->pagenr, brdp->ioctrl);
3780
3781 for (i = 0; (i < nrchips); i++) {
3782 ioaddr = panelp->iobase + (i * 4);
3783 outb(SCCR, (ioaddr + XP_ADDR));
3784 outb(CR_RESETALL, (ioaddr + XP_DATA));
3785 outb(TSTR, (ioaddr + XP_ADDR));
3786 if (inb(ioaddr + XP_DATA) != 0) {
3787 printk("STALLION: sc26198 not responding, "
3788 "brd=%d panel=%d chip=%d\n",
3789 panelp->brdnr, panelp->panelnr, i);
3790 continue;
3791 }
3792 chipmask |= (0x1 << i);
3793 outb(GCCR, (ioaddr + XP_ADDR));
3794 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3795 outb(WDTRCR, (ioaddr + XP_ADDR));
3796 outb(0xff, (ioaddr + XP_DATA));
3797 }
3798
3799 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003800 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801}
3802
3803/*****************************************************************************/
3804
3805/*
3806 * Initialize hardware specific port registers.
3807 */
3808
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003809static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810{
Jiri Slabya0564e12006-12-08 02:38:37 -08003811 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3812 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813
Jiri Slaby615e4a72006-12-08 02:38:38 -08003814 if ((brdp == NULL) || (panelp == NULL) ||
3815 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 return;
3817
3818 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3819 portp->uartaddr = (portp->portnr & 0x07) << 4;
3820 portp->pagenr = panelp->pagenr;
3821 portp->hwid = 0x1;
3822
3823 BRDENABLE(portp->brdnr, portp->pagenr);
3824 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3825 BRDDISABLE(portp->brdnr);
3826}
3827
3828/*****************************************************************************/
3829
3830/*
3831 * Set up the sc26198 registers for a port based on the termios port
3832 * settings.
3833 */
3834
Alan Cox606d0992006-12-08 02:38:45 -08003835static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003837 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 unsigned long flags;
3839 unsigned int baudrate;
3840 unsigned char mr0, mr1, mr2, clk;
3841 unsigned char imron, imroff, iopr, ipr;
3842
3843 mr0 = 0;
3844 mr1 = 0;
3845 mr2 = 0;
3846 clk = 0;
3847 iopr = 0;
3848 imron = 0;
3849 imroff = 0;
3850
3851 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003852 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 return;
3854
3855/*
3856 * Set up the RX char ignore mask with those RX error types we
3857 * can ignore.
3858 */
3859 portp->rxignoremsk = 0;
3860 if (tiosp->c_iflag & IGNPAR)
3861 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3862 SR_RXOVERRUN);
3863 if (tiosp->c_iflag & IGNBRK)
3864 portp->rxignoremsk |= SR_RXBREAK;
3865
3866 portp->rxmarkmsk = SR_RXOVERRUN;
3867 if (tiosp->c_iflag & (INPCK | PARMRK))
3868 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3869 if (tiosp->c_iflag & BRKINT)
3870 portp->rxmarkmsk |= SR_RXBREAK;
3871
3872/*
3873 * Go through the char size, parity and stop bits and set all the
3874 * option register appropriately.
3875 */
3876 switch (tiosp->c_cflag & CSIZE) {
3877 case CS5:
3878 mr1 |= MR1_CS5;
3879 break;
3880 case CS6:
3881 mr1 |= MR1_CS6;
3882 break;
3883 case CS7:
3884 mr1 |= MR1_CS7;
3885 break;
3886 default:
3887 mr1 |= MR1_CS8;
3888 break;
3889 }
3890
3891 if (tiosp->c_cflag & CSTOPB)
3892 mr2 |= MR2_STOP2;
3893 else
3894 mr2 |= MR2_STOP1;
3895
3896 if (tiosp->c_cflag & PARENB) {
3897 if (tiosp->c_cflag & PARODD)
3898 mr1 |= (MR1_PARENB | MR1_PARODD);
3899 else
3900 mr1 |= (MR1_PARENB | MR1_PAREVEN);
3901 } else {
3902 mr1 |= MR1_PARNONE;
3903 }
3904
3905 mr1 |= MR1_ERRBLOCK;
3906
3907/*
3908 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3909 * space for hardware flow control and the like. This should be set to
3910 * VMIN.
3911 */
3912 mr2 |= MR2_RXFIFOHALF;
3913
3914/*
3915 * Calculate the baud rate timers. For now we will just assume that
3916 * the input and output baud are the same. The sc26198 has a fixed
3917 * baud rate table, so only discrete baud rates possible.
3918 */
3919 baudrate = tiosp->c_cflag & CBAUD;
3920 if (baudrate & CBAUDEX) {
3921 baudrate &= ~CBAUDEX;
3922 if ((baudrate < 1) || (baudrate > 4))
3923 tiosp->c_cflag &= ~CBAUDEX;
3924 else
3925 baudrate += 15;
3926 }
3927 baudrate = stl_baudrates[baudrate];
3928 if ((tiosp->c_cflag & CBAUD) == B38400) {
3929 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3930 baudrate = 57600;
3931 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3932 baudrate = 115200;
3933 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3934 baudrate = 230400;
3935 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3936 baudrate = 460800;
3937 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3938 baudrate = (portp->baud_base / portp->custom_divisor);
3939 }
3940 if (baudrate > STL_SC26198MAXBAUD)
3941 baudrate = STL_SC26198MAXBAUD;
3942
3943 if (baudrate > 0) {
3944 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
3945 if (baudrate <= sc26198_baudtable[clk])
3946 break;
3947 }
3948 }
3949
3950/*
3951 * Check what form of modem signaling is required and set it up.
3952 */
3953 if (tiosp->c_cflag & CLOCAL) {
3954 portp->flags &= ~ASYNC_CHECK_CD;
3955 } else {
3956 iopr |= IOPR_DCDCOS;
3957 imron |= IR_IOPORT;
3958 portp->flags |= ASYNC_CHECK_CD;
3959 }
3960
3961/*
3962 * Setup sc26198 enhanced modes if we can. In particular we want to
3963 * handle as much of the flow control as possible automatically. As
3964 * well as saving a few CPU cycles it will also greatly improve flow
3965 * control reliability.
3966 */
3967 if (tiosp->c_iflag & IXON) {
3968 mr0 |= MR0_SWFTX | MR0_SWFT;
3969 imron |= IR_XONXOFF;
3970 } else {
3971 imroff |= IR_XONXOFF;
3972 }
3973 if (tiosp->c_iflag & IXOFF)
3974 mr0 |= MR0_SWFRX;
3975
3976 if (tiosp->c_cflag & CRTSCTS) {
3977 mr2 |= MR2_AUTOCTS;
3978 mr1 |= MR1_AUTORTS;
3979 }
3980
3981/*
3982 * All sc26198 register values calculated so go through and set
3983 * them all up.
3984 */
3985
Jiri Slabya0564e12006-12-08 02:38:37 -08003986 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003988 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3989 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3990 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3992 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Alan Coxb65b5b52006-06-27 02:54:05 -07003994 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 BRDENABLE(portp->brdnr, portp->pagenr);
3996 stl_sc26198setreg(portp, IMR, 0);
3997 stl_sc26198updatereg(portp, MR0, mr0);
3998 stl_sc26198updatereg(portp, MR1, mr1);
3999 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4000 stl_sc26198updatereg(portp, MR2, mr2);
4001 stl_sc26198updatereg(portp, IOPIOR,
4002 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4003
4004 if (baudrate > 0) {
4005 stl_sc26198setreg(portp, TXCSR, clk);
4006 stl_sc26198setreg(portp, RXCSR, clk);
4007 }
4008
4009 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4010 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4011
4012 ipr = stl_sc26198getreg(portp, IPR);
4013 if (ipr & IPR_DCD)
4014 portp->sigs &= ~TIOCM_CD;
4015 else
4016 portp->sigs |= TIOCM_CD;
4017
4018 portp->imr = (portp->imr & ~imroff) | imron;
4019 stl_sc26198setreg(portp, IMR, portp->imr);
4020 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004021 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022}
4023
4024/*****************************************************************************/
4025
4026/*
4027 * Set the state of the DTR and RTS signals.
4028 */
4029
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004030static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031{
4032 unsigned char iopioron, iopioroff;
4033 unsigned long flags;
4034
Jiri Slabya0564e12006-12-08 02:38:37 -08004035 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4036 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
4038 iopioron = 0;
4039 iopioroff = 0;
4040 if (dtr == 0)
4041 iopioroff |= IPR_DTR;
4042 else if (dtr > 0)
4043 iopioron |= IPR_DTR;
4044 if (rts == 0)
4045 iopioroff |= IPR_RTS;
4046 else if (rts > 0)
4047 iopioron |= IPR_RTS;
4048
Alan Coxb65b5b52006-06-27 02:54:05 -07004049 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050 BRDENABLE(portp->brdnr, portp->pagenr);
4051 stl_sc26198setreg(portp, IOPIOR,
4052 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4053 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004054 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055}
4056
4057/*****************************************************************************/
4058
4059/*
4060 * Return the state of the signals.
4061 */
4062
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004063static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064{
4065 unsigned char ipr;
4066 unsigned long flags;
4067 int sigs;
4068
Jiri Slabya0564e12006-12-08 02:38:37 -08004069 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Alan Coxb65b5b52006-06-27 02:54:05 -07004071 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 BRDENABLE(portp->brdnr, portp->pagenr);
4073 ipr = stl_sc26198getreg(portp, IPR);
4074 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004075 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076
4077 sigs = 0;
4078 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4079 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4080 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4081 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4082 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004083 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084}
4085
4086/*****************************************************************************/
4087
4088/*
4089 * Enable/Disable the Transmitter and/or Receiver.
4090 */
4091
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004092static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093{
4094 unsigned char ccr;
4095 unsigned long flags;
4096
Jiri Slabya0564e12006-12-08 02:38:37 -08004097 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098
4099 ccr = portp->crenable;
4100 if (tx == 0)
4101 ccr &= ~CR_TXENABLE;
4102 else if (tx > 0)
4103 ccr |= CR_TXENABLE;
4104 if (rx == 0)
4105 ccr &= ~CR_RXENABLE;
4106 else if (rx > 0)
4107 ccr |= CR_RXENABLE;
4108
Alan Coxb65b5b52006-06-27 02:54:05 -07004109 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 BRDENABLE(portp->brdnr, portp->pagenr);
4111 stl_sc26198setreg(portp, SCCR, ccr);
4112 BRDDISABLE(portp->brdnr);
4113 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004114 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115}
4116
4117/*****************************************************************************/
4118
4119/*
4120 * Start/stop the Transmitter and/or Receiver.
4121 */
4122
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004123static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124{
4125 unsigned char imr;
4126 unsigned long flags;
4127
Jiri Slabya0564e12006-12-08 02:38:37 -08004128 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
4130 imr = portp->imr;
4131 if (tx == 0)
4132 imr &= ~IR_TXRDY;
4133 else if (tx == 1)
4134 imr |= IR_TXRDY;
4135 if (rx == 0)
4136 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4137 else if (rx > 0)
4138 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4139
Alan Coxb65b5b52006-06-27 02:54:05 -07004140 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141 BRDENABLE(portp->brdnr, portp->pagenr);
4142 stl_sc26198setreg(portp, IMR, imr);
4143 BRDDISABLE(portp->brdnr);
4144 portp->imr = imr;
4145 if (tx > 0)
4146 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004147 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148}
4149
4150/*****************************************************************************/
4151
4152/*
4153 * Disable all interrupts from this port.
4154 */
4155
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004156static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157{
4158 unsigned long flags;
4159
Jiri Slabya0564e12006-12-08 02:38:37 -08004160 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161
Alan Coxb65b5b52006-06-27 02:54:05 -07004162 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163 BRDENABLE(portp->brdnr, portp->pagenr);
4164 portp->imr = 0;
4165 stl_sc26198setreg(portp, IMR, 0);
4166 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004167 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168}
4169
4170/*****************************************************************************/
4171
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004172static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173{
4174 unsigned long flags;
4175
Jiri Slabya0564e12006-12-08 02:38:37 -08004176 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177
Alan Coxb65b5b52006-06-27 02:54:05 -07004178 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 BRDENABLE(portp->brdnr, portp->pagenr);
4180 if (len == 1) {
4181 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4182 portp->stats.txbreaks++;
4183 } else {
4184 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4185 }
4186 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004187 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188}
4189
4190/*****************************************************************************/
4191
4192/*
4193 * Take flow control actions...
4194 */
4195
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004196static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197{
4198 struct tty_struct *tty;
4199 unsigned long flags;
4200 unsigned char mr0;
4201
Jiri Slabya0564e12006-12-08 02:38:37 -08004202 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203
Jiri Slaby615e4a72006-12-08 02:38:38 -08004204 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 return;
4206 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004207 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 return;
4209
Alan Coxb65b5b52006-06-27 02:54:05 -07004210 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 BRDENABLE(portp->brdnr, portp->pagenr);
4212
4213 if (state) {
4214 if (tty->termios->c_iflag & IXOFF) {
4215 mr0 = stl_sc26198getreg(portp, MR0);
4216 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4217 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4218 mr0 |= MR0_SWFRX;
4219 portp->stats.rxxon++;
4220 stl_sc26198wait(portp);
4221 stl_sc26198setreg(portp, MR0, mr0);
4222 }
4223/*
4224 * Question: should we return RTS to what it was before? It may
4225 * have been set by an ioctl... Suppose not, since if you have
4226 * hardware flow control set then it is pretty silly to go and
4227 * set the RTS line by hand.
4228 */
4229 if (tty->termios->c_cflag & CRTSCTS) {
4230 stl_sc26198setreg(portp, MR1,
4231 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4232 stl_sc26198setreg(portp, IOPIOR,
4233 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4234 portp->stats.rxrtson++;
4235 }
4236 } else {
4237 if (tty->termios->c_iflag & IXOFF) {
4238 mr0 = stl_sc26198getreg(portp, MR0);
4239 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4240 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4241 mr0 &= ~MR0_SWFRX;
4242 portp->stats.rxxoff++;
4243 stl_sc26198wait(portp);
4244 stl_sc26198setreg(portp, MR0, mr0);
4245 }
4246 if (tty->termios->c_cflag & CRTSCTS) {
4247 stl_sc26198setreg(portp, MR1,
4248 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4249 stl_sc26198setreg(portp, IOPIOR,
4250 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4251 portp->stats.rxrtsoff++;
4252 }
4253 }
4254
4255 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004256 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257}
4258
4259/*****************************************************************************/
4260
4261/*
4262 * Send a flow control character.
4263 */
4264
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004265static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266{
4267 struct tty_struct *tty;
4268 unsigned long flags;
4269 unsigned char mr0;
4270
Jiri Slabya0564e12006-12-08 02:38:37 -08004271 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272
Jiri Slaby615e4a72006-12-08 02:38:38 -08004273 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 return;
4275 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004276 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277 return;
4278
Alan Coxb65b5b52006-06-27 02:54:05 -07004279 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 BRDENABLE(portp->brdnr, portp->pagenr);
4281 if (state) {
4282 mr0 = stl_sc26198getreg(portp, MR0);
4283 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4284 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4285 mr0 |= MR0_SWFRX;
4286 portp->stats.rxxon++;
4287 stl_sc26198wait(portp);
4288 stl_sc26198setreg(portp, MR0, mr0);
4289 } else {
4290 mr0 = stl_sc26198getreg(portp, MR0);
4291 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4292 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4293 mr0 &= ~MR0_SWFRX;
4294 portp->stats.rxxoff++;
4295 stl_sc26198wait(portp);
4296 stl_sc26198setreg(portp, MR0, mr0);
4297 }
4298 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004299 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300}
4301
4302/*****************************************************************************/
4303
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004304static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305{
4306 unsigned long flags;
4307
Jiri Slabya0564e12006-12-08 02:38:37 -08004308 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309
Jiri Slaby615e4a72006-12-08 02:38:38 -08004310 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 return;
4312
Alan Coxb65b5b52006-06-27 02:54:05 -07004313 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 BRDENABLE(portp->brdnr, portp->pagenr);
4315 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4316 stl_sc26198setreg(portp, SCCR, portp->crenable);
4317 BRDDISABLE(portp->brdnr);
4318 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004319 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320}
4321
4322/*****************************************************************************/
4323
4324/*
4325 * Return the current state of data flow on this port. This is only
4326 * really interresting when determining if data has fully completed
4327 * transmission or not... The sc26198 interrupt scheme cannot
4328 * determine when all data has actually drained, so we need to
4329 * check the port statusy register to be sure.
4330 */
4331
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004332static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333{
4334 unsigned long flags;
4335 unsigned char sr;
4336
Jiri Slabya0564e12006-12-08 02:38:37 -08004337 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338
Jiri Slaby615e4a72006-12-08 02:38:38 -08004339 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004340 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004342 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Alan Coxb65b5b52006-06-27 02:54:05 -07004344 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345 BRDENABLE(portp->brdnr, portp->pagenr);
4346 sr = stl_sc26198getreg(portp, SR);
4347 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004348 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349
Jesper Juhl014c2542006-01-15 02:37:08 +01004350 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351}
4352
4353/*****************************************************************************/
4354
4355/*
4356 * Delay for a small amount of time, to give the sc26198 a chance
4357 * to process a command...
4358 */
4359
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004360static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361{
4362 int i;
4363
Jiri Slabya0564e12006-12-08 02:38:37 -08004364 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365
Jiri Slaby615e4a72006-12-08 02:38:38 -08004366 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 return;
4368
4369 for (i = 0; (i < 20); i++)
4370 stl_sc26198getglobreg(portp, TSTR);
4371}
4372
4373/*****************************************************************************/
4374
4375/*
4376 * If we are TX flow controlled and in IXANY mode then we may
4377 * need to unflow control here. We gotta do this because of the
4378 * automatic flow control modes of the sc26198.
4379 */
4380
Jiri Slaby60be4812006-12-08 02:38:40 -08004381static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382{
4383 unsigned char mr0;
4384
4385 mr0 = stl_sc26198getreg(portp, MR0);
4386 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4387 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4388 stl_sc26198wait(portp);
4389 stl_sc26198setreg(portp, MR0, mr0);
4390 clear_bit(ASYI_TXFLOWED, &portp->istate);
4391}
4392
4393/*****************************************************************************/
4394
4395/*
4396 * Interrupt service routine for sc26198 panels.
4397 */
4398
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004399static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004401 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 unsigned int iack;
4403
Alan Coxb65b5b52006-06-27 02:54:05 -07004404 spin_lock(&brd_lock);
4405
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406/*
4407 * Work around bug in sc26198 chip... Cannot have A6 address
4408 * line of UART high, else iack will be returned as 0.
4409 */
4410 outb(0, (iobase + 1));
4411
4412 iack = inb(iobase + XP_IACK);
4413 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4414
4415 if (iack & IVR_RXDATA)
4416 stl_sc26198rxisr(portp, iack);
4417 else if (iack & IVR_TXDATA)
4418 stl_sc26198txisr(portp);
4419 else
4420 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004421
4422 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423}
4424
4425/*****************************************************************************/
4426
4427/*
4428 * Transmit interrupt handler. This has gotta be fast! Handling TX
4429 * chars is pretty simple, stuff as many as possible from the TX buffer
4430 * into the sc26198 FIFO.
4431 * In practice it is possible that interrupts are enabled but that the
4432 * port has been hung up. Need to handle not having any TX buffer here,
4433 * this is done by using the side effect that head and tail will also
4434 * be NULL if the buffer has been freed.
4435 */
4436
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004437static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438{
4439 unsigned int ioaddr;
4440 unsigned char mr0;
4441 int len, stlen;
4442 char *head, *tail;
4443
Jiri Slabya0564e12006-12-08 02:38:37 -08004444 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445
4446 ioaddr = portp->ioaddr;
4447 head = portp->tx.head;
4448 tail = portp->tx.tail;
4449 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4450 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4451 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4452 set_bit(ASYI_TXLOW, &portp->istate);
4453 schedule_work(&portp->tqueue);
4454 }
4455
4456 if (len == 0) {
4457 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4458 mr0 = inb(ioaddr + XP_DATA);
4459 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4460 portp->imr &= ~IR_TXRDY;
4461 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4462 outb(portp->imr, (ioaddr + XP_DATA));
4463 clear_bit(ASYI_TXBUSY, &portp->istate);
4464 } else {
4465 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4466 outb(mr0, (ioaddr + XP_DATA));
4467 }
4468 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004469 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08004471 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472 outb(GTXFIFO, (ioaddr + XP_ADDR));
4473 outsb((ioaddr + XP_DATA), tail, stlen);
4474 len -= stlen;
4475 tail += stlen;
4476 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4477 tail = portp->tx.buf;
4478 if (len > 0) {
4479 outsb((ioaddr + XP_DATA), tail, len);
4480 tail += len;
4481 }
4482 portp->tx.tail = tail;
4483 }
4484}
4485
4486/*****************************************************************************/
4487
4488/*
4489 * Receive character interrupt handler. Determine if we have good chars
4490 * or bad chars and then process appropriately. Good chars are easy
4491 * just shove the lot into the RX buffer and set all status byte to 0.
4492 * If a bad RX char then process as required. This routine needs to be
4493 * fast! In practice it is possible that we get an interrupt on a port
4494 * that is closed. This can happen on hangups - since they completely
4495 * shutdown a port not in user context. Need to handle this case.
4496 */
4497
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004498static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499{
4500 struct tty_struct *tty;
4501 unsigned int len, buflen, ioaddr;
4502
Jiri Slabya0564e12006-12-08 02:38:37 -08004503 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504
4505 tty = portp->tty;
4506 ioaddr = portp->ioaddr;
4507 outb(GIBCR, (ioaddr + XP_ADDR));
4508 len = inb(ioaddr + XP_DATA) + 1;
4509
4510 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004511 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08004512 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513 outb(GRXFIFO, (ioaddr + XP_ADDR));
4514 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4515 portp->stats.rxlost += len;
4516 portp->stats.rxtotal += len;
4517 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004518 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004520 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004522 tty_prepare_flip_string(tty, &ptr, len);
4523 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524 tty_schedule_flip(tty);
4525 portp->stats.rxtotal += len;
4526 }
4527 }
4528 } else {
4529 stl_sc26198rxbadchars(portp);
4530 }
4531
4532/*
4533 * If we are TX flow controlled and in IXANY mode then we may need
4534 * to unflow control here. We gotta do this because of the automatic
4535 * flow control modes of the sc26198.
4536 */
4537 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004538 if ((tty != NULL) &&
4539 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540 (tty->termios->c_iflag & IXANY)) {
4541 stl_sc26198txunflow(portp, tty);
4542 }
4543 }
4544}
4545
4546/*****************************************************************************/
4547
4548/*
4549 * Process an RX bad character.
4550 */
4551
Jiri Slaby60be4812006-12-08 02:38:40 -08004552static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553{
4554 struct tty_struct *tty;
4555 unsigned int ioaddr;
4556
4557 tty = portp->tty;
4558 ioaddr = portp->ioaddr;
4559
4560 if (status & SR_RXPARITY)
4561 portp->stats.rxparity++;
4562 if (status & SR_RXFRAMING)
4563 portp->stats.rxframing++;
4564 if (status & SR_RXOVERRUN)
4565 portp->stats.rxoverrun++;
4566 if (status & SR_RXBREAK)
4567 portp->stats.rxbreaks++;
4568
Jiri Slaby615e4a72006-12-08 02:38:38 -08004569 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570 ((portp->rxignoremsk & status) == 0)) {
4571 if (portp->rxmarkmsk & status) {
4572 if (status & SR_RXBREAK) {
4573 status = TTY_BREAK;
4574 if (portp->flags & ASYNC_SAK) {
4575 do_SAK(tty);
4576 BRDENABLE(portp->brdnr, portp->pagenr);
4577 }
4578 } else if (status & SR_RXPARITY) {
4579 status = TTY_PARITY;
4580 } else if (status & SR_RXFRAMING) {
4581 status = TTY_FRAME;
4582 } else if(status & SR_RXOVERRUN) {
4583 status = TTY_OVERRUN;
4584 } else {
4585 status = 0;
4586 }
4587 } else {
4588 status = 0;
4589 }
4590
Alan Cox33f0f882006-01-09 20:54:13 -08004591 tty_insert_flip_char(tty, ch, status);
4592 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593
4594 if (status == 0)
4595 portp->stats.rxtotal++;
4596 }
4597}
4598
4599/*****************************************************************************/
4600
4601/*
4602 * Process all characters in the RX FIFO of the UART. Check all char
4603 * status bytes as well, and process as required. We need to check
4604 * all bytes in the FIFO, in case some more enter the FIFO while we
4605 * are here. To get the exact character error type we need to switch
4606 * into CHAR error mode (that is why we need to make sure we empty
4607 * the FIFO).
4608 */
4609
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004610static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611{
4612 unsigned char status, mr1;
4613 char ch;
4614
4615/*
4616 * To get the precise error type for each character we must switch
4617 * back into CHAR error mode.
4618 */
4619 mr1 = stl_sc26198getreg(portp, MR1);
4620 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4621
4622 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4623 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4624 ch = stl_sc26198getreg(portp, RXFIFO);
4625 stl_sc26198rxbadch(portp, status, ch);
4626 }
4627
4628/*
4629 * To get correct interrupt class we must switch back into BLOCK
4630 * error mode.
4631 */
4632 stl_sc26198setreg(portp, MR1, mr1);
4633}
4634
4635/*****************************************************************************/
4636
4637/*
4638 * Other interrupt handler. This includes modem signals, flow
4639 * control actions, etc. Most stuff is left to off-level interrupt
4640 * processing time.
4641 */
4642
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004643static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644{
4645 unsigned char cir, ipr, xisr;
4646
Jiri Slabya0564e12006-12-08 02:38:37 -08004647 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648
4649 cir = stl_sc26198getglobreg(portp, CIR);
4650
4651 switch (cir & CIR_SUBTYPEMASK) {
4652 case CIR_SUBCOS:
4653 ipr = stl_sc26198getreg(portp, IPR);
4654 if (ipr & IPR_DCDCHANGE) {
4655 set_bit(ASYI_DCDCHANGE, &portp->istate);
4656 schedule_work(&portp->tqueue);
4657 portp->stats.modem++;
4658 }
4659 break;
4660 case CIR_SUBXONXOFF:
4661 xisr = stl_sc26198getreg(portp, XISR);
4662 if (xisr & XISR_RXXONGOT) {
4663 set_bit(ASYI_TXFLOWED, &portp->istate);
4664 portp->stats.txxoff++;
4665 }
4666 if (xisr & XISR_RXXOFFGOT) {
4667 clear_bit(ASYI_TXFLOWED, &portp->istate);
4668 portp->stats.txxon++;
4669 }
4670 break;
4671 case CIR_SUBBREAK:
4672 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4673 stl_sc26198rxbadchars(portp);
4674 break;
4675 default:
4676 break;
4677 }
4678}
4679
Jiri Slaby23b85a12006-12-08 02:38:40 -08004680/*
4681 * Loadable module initialization stuff.
4682 */
4683static int __init stallion_module_init(void)
4684{
Jiri Slaby843b5682006-12-08 02:39:12 -08004685 struct stlbrd *brdp;
4686 struct stlconf conf;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004687 unsigned int i, retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004688
4689 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4690
4691 spin_lock_init(&stallion_lock);
4692 spin_lock_init(&brd_lock);
4693
Jiri Slaby843b5682006-12-08 02:39:12 -08004694/*
4695 * Find any dynamically supported boards. That is via module load
4696 * line options.
4697 */
4698 for (i = stl_nrbrds; i < stl_nargs; i++) {
4699 memset(&conf, 0, sizeof(conf));
4700 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4701 continue;
4702 if ((brdp = stl_allocbrd()) == NULL)
4703 continue;
4704 brdp->brdnr = i;
4705 brdp->brdtype = conf.brdtype;
4706 brdp->ioaddr1 = conf.ioaddr1;
4707 brdp->ioaddr2 = conf.ioaddr2;
4708 brdp->irq = conf.irq;
4709 brdp->irqtype = conf.irqtype;
4710 if (stl_brdinit(brdp))
4711 kfree(brdp);
4712 else
4713 stl_nrbrds = i + 1;
4714 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004715
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004716 retval = pci_register_driver(&stl_pcidriver);
4717 if (retval)
4718 goto err;
4719
Jiri Slaby23b85a12006-12-08 02:38:40 -08004720 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4721 if (!stl_serial)
4722 return -1;
4723
4724/*
4725 * Set up a character driver for per board stuff. This is mainly used
4726 * to do stats ioctls on the ports.
4727 */
4728 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4729 printk("STALLION: failed to register serial board device\n");
4730
4731 stallion_class = class_create(THIS_MODULE, "staliomem");
4732 for (i = 0; i < 4; i++)
4733 class_device_create(stallion_class, NULL,
4734 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4735 "staliomem%d", i);
4736
4737 stl_serial->owner = THIS_MODULE;
4738 stl_serial->driver_name = stl_drvname;
4739 stl_serial->name = "ttyE";
4740 stl_serial->major = STL_SERIALMAJOR;
4741 stl_serial->minor_start = 0;
4742 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4743 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4744 stl_serial->init_termios = stl_deftermios;
4745 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4746 tty_set_operations(stl_serial, &stl_ops);
4747
4748 if (tty_register_driver(stl_serial)) {
4749 put_tty_driver(stl_serial);
4750 printk("STALLION: failed to register serial driver\n");
4751 return -1;
4752 }
4753
4754 return 0;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004755err:
4756 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004757}
4758
4759static void __exit stallion_module_exit(void)
4760{
4761 struct stlbrd *brdp;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004762 int i;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004763
4764 pr_debug("cleanup_module()\n");
4765
4766 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4767 stl_drvversion);
4768
4769/*
4770 * Free up all allocated resources used by the ports. This includes
4771 * memory and interrupts. As part of this process we will also do
4772 * a hangup on every open port - to try to flush out any processes
4773 * hanging onto ports.
4774 */
4775 i = tty_unregister_driver(stl_serial);
4776 put_tty_driver(stl_serial);
4777 if (i) {
4778 printk("STALLION: failed to un-register tty driver, "
4779 "errno=%d\n", -i);
4780 return;
4781 }
4782 for (i = 0; i < 4; i++)
4783 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4784 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4785 printk("STALLION: failed to un-register serial memory device, "
4786 "errno=%d\n", -i);
4787 class_destroy(stallion_class);
4788
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004789 pci_unregister_driver(&stl_pcidriver);
4790
Jiri Slaby23b85a12006-12-08 02:38:40 -08004791 for (i = 0; (i < stl_nrbrds); i++) {
4792 if ((brdp = stl_brds[i]) == NULL)
4793 continue;
4794
4795 free_irq(brdp->irq, brdp);
4796
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004797 stl_cleanup_panels(brdp);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004798
4799 release_region(brdp->ioaddr1, brdp->iosize1);
4800 if (brdp->iosize2 > 0)
4801 release_region(brdp->ioaddr2, brdp->iosize2);
4802
4803 kfree(brdp);
4804 stl_brds[i] = NULL;
4805 }
4806}
4807
4808module_init(stallion_module_init);
4809module_exit(stallion_module_exit);
4810
4811MODULE_AUTHOR("Greg Ungerer");
4812MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4813MODULE_LICENSE("GPL");