blob: 87bda40be61aaf4db5c54e6cd646a20ae1ca3eaf [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*****************************************************************************/
2
3/*
4 * stallion.c -- stallion multiport serial driver.
5 *
6 * Copyright (C) 1996-1999 Stallion Technologies
7 * Copyright (C) 1994-1996 Greg Ungerer.
8 *
9 * This code is loosely based on the Linux serial driver, written by
10 * Linus Torvalds, Theodore T'so and others.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27/*****************************************************************************/
28
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/interrupt.h>
32#include <linux/tty.h>
33#include <linux/tty_flip.h>
34#include <linux/serial.h>
35#include <linux/cd1400.h>
36#include <linux/sc26198.h>
37#include <linux/comstats.h>
38#include <linux/stallion.h>
39#include <linux/ioport.h>
40#include <linux/init.h>
41#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/device.h>
43#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080044#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46#include <asm/io.h>
47#include <asm/uaccess.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51/*****************************************************************************/
52
53/*
54 * Define different board types. Use the standard Stallion "assigned"
55 * board numbers. Boards supported in this driver are abbreviated as
56 * EIO = EasyIO and ECH = EasyConnection 8/32.
57 */
58#define BRD_EASYIO 20
59#define BRD_ECH 21
60#define BRD_ECHMC 22
61#define BRD_ECHPCI 26
62#define BRD_ECH64PCI 27
63#define BRD_EASYIOPCI 28
64
Jiri Slaby843b5682006-12-08 02:39:12 -080065struct stlconf {
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 int brdtype;
67 int ioaddr1;
68 int ioaddr2;
69 unsigned long memaddr;
70 int irq;
71 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072};
73
Jiri Slaby843b5682006-12-08 02:39:12 -080074static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76/*****************************************************************************/
77
78/*
79 * Define some important driver characteristics. Device major numbers
80 * allocated as per Linux Device Registry.
81 */
82#ifndef STL_SIOMEMMAJOR
83#define STL_SIOMEMMAJOR 28
84#endif
85#ifndef STL_SERIALMAJOR
86#define STL_SERIALMAJOR 24
87#endif
88#ifndef STL_CALLOUTMAJOR
89#define STL_CALLOUTMAJOR 25
90#endif
91
92/*
93 * Set the TX buffer size. Bigger is better, but we don't want
94 * to chew too much memory with buffers!
95 */
96#define STL_TXBUFLOW 512
97#define STL_TXBUFSIZE 4096
98
99/*****************************************************************************/
100
101/*
102 * Define our local driver identity first. Set up stuff to deal with
103 * all the local structures required by a serial tty driver.
104 */
105static char *stl_drvtitle = "Stallion Multiport Serial Driver";
106static char *stl_drvname = "stallion";
107static char *stl_drvversion = "5.6.0";
108
109static struct tty_driver *stl_serial;
110
111/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * Define a local default termios struct. All ports will be created
113 * with this termios initially. Basically all it defines is a raw port
114 * at 9600, 8 data bits, 1 stop bit.
115 */
Alan Cox606d0992006-12-08 02:38:45 -0800116static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
118 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800119 .c_ispeed = 9600,
120 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121};
122
123/*
124 * Define global stats structures. Not used often, and can be
125 * re-used for each stats call.
126 */
127static comstats_t stl_comstats;
128static combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800129static struct stlbrd stl_dummybrd;
130static struct stlport stl_dummyport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
132/*
133 * Define global place to put buffer overflow characters.
134 */
135static char stl_unwanted[SC26198_RXFIFOSIZE];
136
137/*****************************************************************************/
138
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800139static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800140static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
142/*
143 * Per board state flags. Used with the state field of the board struct.
144 * Not really much here!
145 */
146#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800147#define STL_PROBED 0x2
148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150/*
151 * Define the port structure istate flags. These set of flags are
152 * modified at interrupt time - so setting and reseting them needs
153 * to be atomic. Use the bit clear/setting routines for this.
154 */
155#define ASYI_TXBUSY 1
156#define ASYI_TXLOW 2
157#define ASYI_DCDCHANGE 3
158#define ASYI_TXFLOWED 4
159
160/*
161 * Define an array of board names as printable strings. Handy for
162 * referencing boards when printing trace and stuff.
163 */
164static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
176 NULL,
177 NULL,
178 NULL,
179 NULL,
180 NULL,
181 NULL,
182 NULL,
183 NULL,
184 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 "EasyIO",
186 "EC8/32-AT",
187 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800188 NULL,
189 NULL,
190 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 "EC8/32-PCI",
192 "EC8/64-PCI",
193 "EasyIO-PCI",
194};
195
196/*****************************************************************************/
197
198/*
199 * Define some string labels for arguments passed from the module
200 * load line. These allow for easy board definitions, and easy
201 * modification of the io, memory and irq resoucres.
202 */
203static int stl_nargs = 0;
204static char *board0[4];
205static char *board1[4];
206static char *board2[4];
207static char *board3[4];
208
209static char **stl_brdsp[] = {
210 (char **) &board0,
211 (char **) &board1,
212 (char **) &board2,
213 (char **) &board3
214};
215
216/*
217 * Define a set of common board names, and types. This is used to
218 * parse any module arguments.
219 */
220
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800221static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 char *name;
223 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800224} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 { "easyio", BRD_EASYIO },
226 { "eio", BRD_EASYIO },
227 { "20", BRD_EASYIO },
228 { "ec8/32", BRD_ECH },
229 { "ec8/32-at", BRD_ECH },
230 { "ec8/32-isa", BRD_ECH },
231 { "ech", BRD_ECH },
232 { "echat", BRD_ECH },
233 { "21", BRD_ECH },
234 { "ec8/32-mc", BRD_ECHMC },
235 { "ec8/32-mca", BRD_ECHMC },
236 { "echmc", BRD_ECHMC },
237 { "echmca", BRD_ECHMC },
238 { "22", BRD_ECHMC },
239 { "ec8/32-pc", BRD_ECHPCI },
240 { "ec8/32-pci", BRD_ECHPCI },
241 { "26", BRD_ECHPCI },
242 { "ec8/64-pc", BRD_ECH64PCI },
243 { "ec8/64-pci", BRD_ECH64PCI },
244 { "ech-pci", BRD_ECH64PCI },
245 { "echpci", BRD_ECH64PCI },
246 { "echpc", BRD_ECH64PCI },
247 { "27", BRD_ECH64PCI },
248 { "easyio-pc", BRD_EASYIOPCI },
249 { "easyio-pci", BRD_EASYIOPCI },
250 { "eio-pci", BRD_EASYIOPCI },
251 { "eiopci", BRD_EASYIOPCI },
252 { "28", BRD_EASYIOPCI },
253};
254
255/*
256 * Define the module agruments.
257 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259module_param_array(board0, charp, &stl_nargs, 0);
260MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
261module_param_array(board1, charp, &stl_nargs, 0);
262MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
263module_param_array(board2, charp, &stl_nargs, 0);
264MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
265module_param_array(board3, charp, &stl_nargs, 0);
266MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
267
268/*****************************************************************************/
269
270/*
271 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
272 * to the directly accessible io ports of these boards (not the uarts -
273 * they are in cd1400.h and sc26198.h).
274 */
275#define EIO_8PORTRS 0x04
276#define EIO_4PORTRS 0x05
277#define EIO_8PORTDI 0x00
278#define EIO_8PORTM 0x06
279#define EIO_MK3 0x03
280#define EIO_IDBITMASK 0x07
281
282#define EIO_BRDMASK 0xf0
283#define ID_BRD4 0x10
284#define ID_BRD8 0x20
285#define ID_BRD16 0x30
286
287#define EIO_INTRPEND 0x08
288#define EIO_INTEDGE 0x00
289#define EIO_INTLEVEL 0x08
290#define EIO_0WS 0x10
291
292#define ECH_ID 0xa0
293#define ECH_IDBITMASK 0xe0
294#define ECH_BRDENABLE 0x08
295#define ECH_BRDDISABLE 0x00
296#define ECH_INTENABLE 0x01
297#define ECH_INTDISABLE 0x00
298#define ECH_INTLEVEL 0x02
299#define ECH_INTEDGE 0x00
300#define ECH_INTRPEND 0x01
301#define ECH_BRDRESET 0x01
302
303#define ECHMC_INTENABLE 0x01
304#define ECHMC_BRDRESET 0x02
305
306#define ECH_PNLSTATUS 2
307#define ECH_PNL16PORT 0x20
308#define ECH_PNLIDMASK 0x07
309#define ECH_PNLXPID 0x40
310#define ECH_PNLINTRPEND 0x80
311
312#define ECH_ADDR2MASK 0x1e0
313
314/*
315 * Define the vector mapping bits for the programmable interrupt board
316 * hardware. These bits encode the interrupt for the board to use - it
317 * is software selectable (except the EIO-8M).
318 */
319static unsigned char stl_vecmap[] = {
320 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
321 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
322};
323
324/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700325 * Lock ordering is that you may not take stallion_lock holding
326 * brd_lock.
327 */
328
329static spinlock_t brd_lock; /* Guard the board mapping */
330static spinlock_t stallion_lock; /* Guard the tty driver */
331
332/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 * Set up enable and disable macros for the ECH boards. They require
334 * the secondary io address space to be activated and deactivated.
335 * This way all ECH boards can share their secondary io region.
336 * If this is an ECH-PCI board then also need to set the page pointer
337 * to point to the correct page.
338 */
339#define BRDENABLE(brdnr,pagenr) \
340 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
341 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
342 stl_brds[(brdnr)]->ioctrl); \
343 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
344 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
345
346#define BRDDISABLE(brdnr) \
347 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
348 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
349 stl_brds[(brdnr)]->ioctrl);
350
351#define STL_CD1400MAXBAUD 230400
352#define STL_SC26198MAXBAUD 460800
353
354#define STL_BAUDBASE 115200
355#define STL_CLOSEDELAY (5 * HZ / 10)
356
357/*****************************************************************************/
358
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359/*
360 * Define the Stallion PCI vendor and device IDs.
361 */
362#ifndef PCI_VENDOR_ID_STALLION
363#define PCI_VENDOR_ID_STALLION 0x124d
364#endif
365#ifndef PCI_DEVICE_ID_ECHPCI832
366#define PCI_DEVICE_ID_ECHPCI832 0x0000
367#endif
368#ifndef PCI_DEVICE_ID_ECHPCI864
369#define PCI_DEVICE_ID_ECHPCI864 0x0002
370#endif
371#ifndef PCI_DEVICE_ID_EIOPCI
372#define PCI_DEVICE_ID_EIOPCI 0x0003
373#endif
374
375/*
376 * Define structure to hold all Stallion PCI boards.
377 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800379static struct pci_device_id stl_pcibrds[] = {
380 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
381 .driver_data = BRD_ECH64PCI },
382 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
383 .driver_data = BRD_EASYIOPCI },
384 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
385 .driver_data = BRD_ECHPCI },
386 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
387 .driver_data = BRD_ECHPCI },
388 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800390MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
392/*****************************************************************************/
393
394/*
395 * Define macros to extract a brd/port number from a minor number.
396 */
397#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
398#define MINOR2PORT(min) ((min) & 0x3f)
399
400/*
401 * Define a baud rate table that converts termios baud rate selector
402 * into the actual baud rate value. All baud rate calculations are
403 * based on the actual baud rate required.
404 */
405static unsigned int stl_baudrates[] = {
406 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
407 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
408};
409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410/*****************************************************************************/
411
412/*
413 * Declare all those functions in this driver!
414 */
415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800417static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800418static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
419static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800420static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422/*
423 * CD1400 uart specific handling functions.
424 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800425static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
426static int stl_cd1400getreg(struct stlport *portp, int regnr);
427static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
428static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
429static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800430static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800431static int stl_cd1400getsignals(struct stlport *portp);
432static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
433static void stl_cd1400ccrwait(struct stlport *portp);
434static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
435static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
436static void stl_cd1400disableintrs(struct stlport *portp);
437static void stl_cd1400sendbreak(struct stlport *portp, int len);
438static void stl_cd1400flowctrl(struct stlport *portp, int state);
439static void stl_cd1400sendflow(struct stlport *portp, int state);
440static void stl_cd1400flush(struct stlport *portp);
441static int stl_cd1400datastate(struct stlport *portp);
442static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
443static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
444static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
445static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
446static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800448static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
450/*
451 * SC26198 uart specific handling functions.
452 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800453static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
454static int stl_sc26198getreg(struct stlport *portp, int regnr);
455static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
456static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
457static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
458static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800459static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800460static int stl_sc26198getsignals(struct stlport *portp);
461static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
462static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
463static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
464static void stl_sc26198disableintrs(struct stlport *portp);
465static void stl_sc26198sendbreak(struct stlport *portp, int len);
466static void stl_sc26198flowctrl(struct stlport *portp, int state);
467static void stl_sc26198sendflow(struct stlport *portp, int state);
468static void stl_sc26198flush(struct stlport *portp);
469static int stl_sc26198datastate(struct stlport *portp);
470static void stl_sc26198wait(struct stlport *portp);
471static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
472static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
473static void stl_sc26198txisr(struct stlport *port);
474static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
475static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
476static void stl_sc26198rxbadchars(struct stlport *portp);
477static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479/*****************************************************************************/
480
481/*
482 * Generic UART support structure.
483 */
484typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800485 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
486 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800487 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800488 int (*getsignals)(struct stlport *portp);
489 void (*setsignals)(struct stlport *portp, int dtr, int rts);
490 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
491 void (*startrxtx)(struct stlport *portp, int rx, int tx);
492 void (*disableintrs)(struct stlport *portp);
493 void (*sendbreak)(struct stlport *portp, int len);
494 void (*flowctrl)(struct stlport *portp, int state);
495 void (*sendflow)(struct stlport *portp, int state);
496 void (*flush)(struct stlport *portp);
497 int (*datastate)(struct stlport *portp);
498 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499} uart_t;
500
501/*
502 * Define some macros to make calling these functions nice and clean.
503 */
504#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
505#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
506#define stl_setport (* ((uart_t *) portp->uartp)->setport)
507#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
508#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
509#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
510#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
511#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
512#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
513#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
514#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
515#define stl_flush (* ((uart_t *) portp->uartp)->flush)
516#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
517
518/*****************************************************************************/
519
520/*
521 * CD1400 UART specific data initialization.
522 */
523static uart_t stl_cd1400uart = {
524 stl_cd1400panelinit,
525 stl_cd1400portinit,
526 stl_cd1400setport,
527 stl_cd1400getsignals,
528 stl_cd1400setsignals,
529 stl_cd1400enablerxtx,
530 stl_cd1400startrxtx,
531 stl_cd1400disableintrs,
532 stl_cd1400sendbreak,
533 stl_cd1400flowctrl,
534 stl_cd1400sendflow,
535 stl_cd1400flush,
536 stl_cd1400datastate,
537 stl_cd1400eiointr
538};
539
540/*
541 * Define the offsets within the register bank of a cd1400 based panel.
542 * These io address offsets are common to the EasyIO board as well.
543 */
544#define EREG_ADDR 0
545#define EREG_DATA 4
546#define EREG_RXACK 5
547#define EREG_TXACK 6
548#define EREG_MDACK 7
549
550#define EREG_BANKSIZE 8
551
552#define CD1400_CLK 25000000
553#define CD1400_CLK8M 20000000
554
555/*
556 * Define the cd1400 baud rate clocks. These are used when calculating
557 * what clock and divisor to use for the required baud rate. Also
558 * define the maximum baud rate allowed, and the default base baud.
559 */
560static int stl_cd1400clkdivs[] = {
561 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
562};
563
564/*****************************************************************************/
565
566/*
567 * SC26198 UART specific data initization.
568 */
569static uart_t stl_sc26198uart = {
570 stl_sc26198panelinit,
571 stl_sc26198portinit,
572 stl_sc26198setport,
573 stl_sc26198getsignals,
574 stl_sc26198setsignals,
575 stl_sc26198enablerxtx,
576 stl_sc26198startrxtx,
577 stl_sc26198disableintrs,
578 stl_sc26198sendbreak,
579 stl_sc26198flowctrl,
580 stl_sc26198sendflow,
581 stl_sc26198flush,
582 stl_sc26198datastate,
583 stl_sc26198intr
584};
585
586/*
587 * Define the offsets within the register bank of a sc26198 based panel.
588 */
589#define XP_DATA 0
590#define XP_ADDR 1
591#define XP_MODID 2
592#define XP_STATUS 2
593#define XP_IACK 3
594
595#define XP_BANKSIZE 4
596
597/*
598 * Define the sc26198 baud rate table. Offsets within the table
599 * represent the actual baud rate selector of sc26198 registers.
600 */
601static unsigned int sc26198_baudtable[] = {
602 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
603 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
604 230400, 460800, 921600
605};
606
Tobias Klauserfe971072006-01-09 20:54:02 -0800607#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
609/*****************************************************************************/
610
611/*
612 * Define the driver info for a user level control device. Used mainly
613 * to get at port stats - only not using the port device itself.
614 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700615static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 .owner = THIS_MODULE,
617 .ioctl = stl_memioctl,
618};
619
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800620static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 * Check for any arguments passed in on the module load command line.
624 */
625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626/*****************************************************************************/
627
628/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 * Parse the supplied argument string, into the board conf struct.
630 */
631
Jiri Slaby40e82652006-12-08 02:38:41 -0800632static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
634 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800635 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Jiri Slabya0564e12006-12-08 02:38:37 -0800637 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Jiri Slaby615e4a72006-12-08 02:38:38 -0800639 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100640 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800643 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Tobias Klauserfe971072006-01-09 20:54:02 -0800645 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
647 break;
648 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800649 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800651 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 }
653
654 confp->brdtype = stl_brdstr[i].type;
655
656 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800657 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800658 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 i++;
660 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800661 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800662 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 i++;
664 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800665 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800666 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100667 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668}
669
670/*****************************************************************************/
671
672/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 * Allocate a new board structure. Fill out the basic info in it.
674 */
675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800676static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800678 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800680 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800681 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700682 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800683 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800684 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100688 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689}
690
691/*****************************************************************************/
692
693static int stl_open(struct tty_struct *tty, struct file *filp)
694{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800695 struct stlport *portp;
696 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 unsigned int minordev;
698 int brdnr, panelnr, portnr, rc;
699
Jiri Slabya0564e12006-12-08 02:38:37 -0800700 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
702 minordev = tty->index;
703 brdnr = MINOR2BRD(minordev);
704 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100705 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800707 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100708 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 minordev = MINOR2PORT(minordev);
710 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800711 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 break;
713 if (minordev < brdp->panels[panelnr]->nrports) {
714 portnr = minordev;
715 break;
716 }
717 minordev -= brdp->panels[panelnr]->nrports;
718 }
719 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100720 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
722 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800723 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100724 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726/*
727 * On the first open of the device setup the port hardware, and
728 * initialize the per port data structure.
729 */
730 portp->tty = tty;
731 tty->driver_data = portp;
732 portp->refcount++;
733
734 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800735 if (!portp->tx.buf) {
736 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
737 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100738 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 portp->tx.head = portp->tx.buf;
740 portp->tx.tail = portp->tx.buf;
741 }
742 stl_setport(portp, tty->termios);
743 portp->sigs = stl_getsignals(portp);
744 stl_setsignals(portp, 1, 1);
745 stl_enablerxtx(portp, 1, 1);
746 stl_startrxtx(portp, 1, 0);
747 clear_bit(TTY_IO_ERROR, &tty->flags);
748 portp->flags |= ASYNC_INITIALIZED;
749 }
750
751/*
752 * Check if this port is in the middle of closing. If so then wait
753 * until it is closed then return error status, based on flag settings.
754 * The sleep here does not need interrupt protection since the wakeup
755 * for it is done with the same context.
756 */
757 if (portp->flags & ASYNC_CLOSING) {
758 interruptible_sleep_on(&portp->close_wait);
759 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100760 return -EAGAIN;
761 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 }
763
764/*
765 * Based on type of open being done check if it can overlap with any
766 * previous opens still in effect. If we are a normal serial device
767 * then also we might have to wait for carrier.
768 */
769 if (!(filp->f_flags & O_NONBLOCK)) {
770 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100771 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 }
773 portp->flags |= ASYNC_NORMAL_ACTIVE;
774
Jesper Juhl014c2542006-01-15 02:37:08 +0100775 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776}
777
778/*****************************************************************************/
779
780/*
781 * Possibly need to wait for carrier (DCD signal) to come high. Say
782 * maybe because if we are clocal then we don't need to wait...
783 */
784
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800785static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
787 unsigned long flags;
788 int rc, doclocal;
789
Jiri Slabya0564e12006-12-08 02:38:37 -0800790 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 rc = 0;
793 doclocal = 0;
794
Alan Coxb65b5b52006-06-27 02:54:05 -0700795 spin_lock_irqsave(&stallion_lock, flags);
796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 if (portp->tty->termios->c_cflag & CLOCAL)
798 doclocal++;
799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 portp->openwaitcnt++;
801 if (! tty_hung_up_p(filp))
802 portp->refcount--;
803
804 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700805 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 stl_setsignals(portp, 1, 1);
807 if (tty_hung_up_p(filp) ||
808 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
809 if (portp->flags & ASYNC_HUP_NOTIFY)
810 rc = -EBUSY;
811 else
812 rc = -ERESTARTSYS;
813 break;
814 }
815 if (((portp->flags & ASYNC_CLOSING) == 0) &&
816 (doclocal || (portp->sigs & TIOCM_CD))) {
817 break;
818 }
819 if (signal_pending(current)) {
820 rc = -ERESTARTSYS;
821 break;
822 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700823 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 interruptible_sleep_on(&portp->open_wait);
825 }
826
827 if (! tty_hung_up_p(filp))
828 portp->refcount++;
829 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700830 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
Jesper Juhl014c2542006-01-15 02:37:08 +0100832 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833}
834
835/*****************************************************************************/
836
Jiri Slaby96b066b2006-12-08 02:38:42 -0800837static void stl_flushbuffer(struct tty_struct *tty)
838{
839 struct stlport *portp;
840
841 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
842
843 if (tty == NULL)
844 return;
845 portp = tty->driver_data;
846 if (portp == NULL)
847 return;
848
849 stl_flush(portp);
850 tty_wakeup(tty);
851}
852
853/*****************************************************************************/
854
855static void stl_waituntilsent(struct tty_struct *tty, int timeout)
856{
857 struct stlport *portp;
858 unsigned long tend;
859
860 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
861
862 if (tty == NULL)
863 return;
864 portp = tty->driver_data;
865 if (portp == NULL)
866 return;
867
868 if (timeout == 0)
869 timeout = HZ;
870 tend = jiffies + timeout;
871
872 while (stl_datastate(portp)) {
873 if (signal_pending(current))
874 break;
875 msleep_interruptible(20);
876 if (time_after_eq(jiffies, tend))
877 break;
878 }
879}
880
881/*****************************************************************************/
882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883static void stl_close(struct tty_struct *tty, struct file *filp)
884{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800885 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 unsigned long flags;
887
Jiri Slabya0564e12006-12-08 02:38:37 -0800888 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
890 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800891 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 return;
893
Alan Coxb65b5b52006-06-27 02:54:05 -0700894 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700896 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 return;
898 }
899 if ((tty->count == 1) && (portp->refcount != 1))
900 portp->refcount = 1;
901 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700902 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return;
904 }
905
906 portp->refcount = 0;
907 portp->flags |= ASYNC_CLOSING;
908
909/*
910 * May want to wait for any data to drain before closing. The BUSY
911 * flag keeps track of whether we are still sending or not - it is
912 * very accurate for the cd1400, not quite so for the sc26198.
913 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
914 */
915 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700916
917 spin_unlock_irqrestore(&stallion_lock, flags);
918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
920 tty_wait_until_sent(tty, portp->closing_wait);
921 stl_waituntilsent(tty, (HZ / 2));
922
Alan Coxb65b5b52006-06-27 02:54:05 -0700923
924 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700926 spin_unlock_irqrestore(&stallion_lock, flags);
927
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 stl_disableintrs(portp);
929 if (tty->termios->c_cflag & HUPCL)
930 stl_setsignals(portp, 0, 0);
931 stl_enablerxtx(portp, 0, 0);
932 stl_flushbuffer(tty);
933 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800934 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800936 portp->tx.buf = NULL;
937 portp->tx.head = NULL;
938 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 }
940 set_bit(TTY_IO_ERROR, &tty->flags);
941 tty_ldisc_flush(tty);
942
943 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800944 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
946 if (portp->openwaitcnt) {
947 if (portp->close_delay)
948 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
949 wake_up_interruptible(&portp->open_wait);
950 }
951
952 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
953 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954}
955
956/*****************************************************************************/
957
958/*
959 * Write routine. Take data and stuff it in to the TX ring queue.
960 * If transmit interrupts are not running then start them.
961 */
962
963static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
964{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800965 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 unsigned int len, stlen;
967 unsigned char *chbuf;
968 char *head, *tail;
969
Jiri Slabya0564e12006-12-08 02:38:37 -0800970 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800973 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100974 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800975 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100976 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
978/*
979 * If copying direct from user space we must cater for page faults,
980 * causing us to "sleep" here for a while. To handle this copy in all
981 * the data we need now, into a local buffer. Then when we got it all
982 * copy it into the TX buffer.
983 */
984 chbuf = (unsigned char *) buf;
985
986 head = portp->tx.head;
987 tail = portp->tx.tail;
988 if (head >= tail) {
989 len = STL_TXBUFSIZE - (head - tail) - 1;
990 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
991 } else {
992 len = tail - head - 1;
993 stlen = len;
994 }
995
Jiri Slaby843b5682006-12-08 02:39:12 -0800996 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 count = 0;
998 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800999 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 memcpy(head, chbuf, stlen);
1001 len -= stlen;
1002 chbuf += stlen;
1003 count += stlen;
1004 head += stlen;
1005 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1006 head = portp->tx.buf;
1007 stlen = tail - head;
1008 }
1009 }
1010 portp->tx.head = head;
1011
1012 clear_bit(ASYI_TXLOW, &portp->istate);
1013 stl_startrxtx(portp, -1, 1);
1014
Jesper Juhl014c2542006-01-15 02:37:08 +01001015 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016}
1017
1018/*****************************************************************************/
1019
1020static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1021{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001022 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 unsigned int len;
1024 char *head, *tail;
1025
Jiri Slabya0564e12006-12-08 02:38:37 -08001026 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
Jiri Slaby615e4a72006-12-08 02:38:38 -08001028 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 return;
1030 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001031 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001033 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 return;
1035
1036 head = portp->tx.head;
1037 tail = portp->tx.tail;
1038
1039 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1040 len--;
1041
1042 if (len > 0) {
1043 *head++ = ch;
1044 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1045 head = portp->tx.buf;
1046 }
1047 portp->tx.head = head;
1048}
1049
1050/*****************************************************************************/
1051
1052/*
1053 * If there are any characters in the buffer then make sure that TX
1054 * interrupts are on and get'em out. Normally used after the putchar
1055 * routine has been called.
1056 */
1057
1058static void stl_flushchars(struct tty_struct *tty)
1059{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001060 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Jiri Slabya0564e12006-12-08 02:38:37 -08001062 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Jiri Slaby615e4a72006-12-08 02:38:38 -08001064 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 return;
1066 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001067 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001069 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 return;
1071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 stl_startrxtx(portp, -1, 1);
1073}
1074
1075/*****************************************************************************/
1076
1077static int stl_writeroom(struct tty_struct *tty)
1078{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001079 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 char *head, *tail;
1081
Jiri Slabya0564e12006-12-08 02:38:37 -08001082 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
Jiri Slaby615e4a72006-12-08 02:38:38 -08001084 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001085 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001087 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001088 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001089 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001090 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
1092 head = portp->tx.head;
1093 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001094 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095}
1096
1097/*****************************************************************************/
1098
1099/*
1100 * Return number of chars in the TX buffer. Normally we would just
1101 * calculate the number of chars in the buffer and return that, but if
1102 * the buffer is empty and TX interrupts are still on then we return
1103 * that the buffer still has 1 char in it. This way whoever called us
1104 * will not think that ALL chars have drained - since the UART still
1105 * must have some chars in it (we are busy after all).
1106 */
1107
1108static int stl_charsinbuffer(struct tty_struct *tty)
1109{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001110 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 unsigned int size;
1112 char *head, *tail;
1113
Jiri Slabya0564e12006-12-08 02:38:37 -08001114 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Jiri Slaby615e4a72006-12-08 02:38:38 -08001116 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001117 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001119 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001120 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001121 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001122 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
1124 head = portp->tx.head;
1125 tail = portp->tx.tail;
1126 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1127 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1128 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001129 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130}
1131
1132/*****************************************************************************/
1133
1134/*
1135 * Generate the serial struct info.
1136 */
1137
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001138static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139{
1140 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001141 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Jiri Slabya0564e12006-12-08 02:38:37 -08001143 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
1145 memset(&sio, 0, sizeof(struct serial_struct));
1146 sio.line = portp->portnr;
1147 sio.port = portp->ioaddr;
1148 sio.flags = portp->flags;
1149 sio.baud_base = portp->baud_base;
1150 sio.close_delay = portp->close_delay;
1151 sio.closing_wait = portp->closing_wait;
1152 sio.custom_divisor = portp->custom_divisor;
1153 sio.hub6 = 0;
1154 if (portp->uartp == &stl_cd1400uart) {
1155 sio.type = PORT_CIRRUS;
1156 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1157 } else {
1158 sio.type = PORT_UNKNOWN;
1159 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1160 }
1161
1162 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001163 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 sio.irq = brdp->irq;
1165
1166 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1167}
1168
1169/*****************************************************************************/
1170
1171/*
1172 * Set port according to the serial struct info.
1173 * At this point we do not do any auto-configure stuff, so we will
1174 * just quietly ignore any requests to change irq, etc.
1175 */
1176
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001177static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178{
1179 struct serial_struct sio;
1180
Jiri Slabya0564e12006-12-08 02:38:37 -08001181 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
1183 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1184 return -EFAULT;
1185 if (!capable(CAP_SYS_ADMIN)) {
1186 if ((sio.baud_base != portp->baud_base) ||
1187 (sio.close_delay != portp->close_delay) ||
1188 ((sio.flags & ~ASYNC_USR_MASK) !=
1189 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001190 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 }
1192
1193 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1194 (sio.flags & ASYNC_USR_MASK);
1195 portp->baud_base = sio.baud_base;
1196 portp->close_delay = sio.close_delay;
1197 portp->closing_wait = sio.closing_wait;
1198 portp->custom_divisor = sio.custom_divisor;
1199 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001200 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201}
1202
1203/*****************************************************************************/
1204
1205static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1206{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001207 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
Jiri Slaby615e4a72006-12-08 02:38:38 -08001209 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001210 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001212 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001213 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001215 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
1217 return stl_getsignals(portp);
1218}
1219
1220static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1221 unsigned int set, unsigned int clear)
1222{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001223 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 int rts = -1, dtr = -1;
1225
Jiri Slaby615e4a72006-12-08 02:38:38 -08001226 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001227 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001229 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001230 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001232 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
1234 if (set & TIOCM_RTS)
1235 rts = 1;
1236 if (set & TIOCM_DTR)
1237 dtr = 1;
1238 if (clear & TIOCM_RTS)
1239 rts = 0;
1240 if (clear & TIOCM_DTR)
1241 dtr = 0;
1242
1243 stl_setsignals(portp, dtr, rts);
1244 return 0;
1245}
1246
1247static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1248{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001249 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 unsigned int ival;
1251 int rc;
1252 void __user *argp = (void __user *)arg;
1253
Jiri Slabya0564e12006-12-08 02:38:37 -08001254 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1255 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Jiri Slaby615e4a72006-12-08 02:38:38 -08001257 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001258 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001260 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001261 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
1263 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1264 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1265 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001266 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 }
1268
1269 rc = 0;
1270
1271 switch (cmd) {
1272 case TIOCGSOFTCAR:
1273 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1274 (unsigned __user *) argp);
1275 break;
1276 case TIOCSSOFTCAR:
1277 if (get_user(ival, (unsigned int __user *) arg))
1278 return -EFAULT;
1279 tty->termios->c_cflag =
1280 (tty->termios->c_cflag & ~CLOCAL) |
1281 (ival ? CLOCAL : 0);
1282 break;
1283 case TIOCGSERIAL:
1284 rc = stl_getserial(portp, argp);
1285 break;
1286 case TIOCSSERIAL:
1287 rc = stl_setserial(portp, argp);
1288 break;
1289 case COM_GETPORTSTATS:
1290 rc = stl_getportstats(portp, argp);
1291 break;
1292 case COM_CLRPORTSTATS:
1293 rc = stl_clrportstats(portp, argp);
1294 break;
1295 case TIOCSERCONFIG:
1296 case TIOCSERGWILD:
1297 case TIOCSERSWILD:
1298 case TIOCSERGETLSR:
1299 case TIOCSERGSTRUCT:
1300 case TIOCSERGETMULTI:
1301 case TIOCSERSETMULTI:
1302 default:
1303 rc = -ENOIOCTLCMD;
1304 break;
1305 }
1306
Jesper Juhl014c2542006-01-15 02:37:08 +01001307 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308}
1309
1310/*****************************************************************************/
1311
Jiri Slaby96b066b2006-12-08 02:38:42 -08001312/*
1313 * Start the transmitter again. Just turn TX interrupts back on.
1314 */
1315
1316static void stl_start(struct tty_struct *tty)
1317{
1318 struct stlport *portp;
1319
1320 pr_debug("stl_start(tty=%p)\n", tty);
1321
1322 if (tty == NULL)
1323 return;
1324 portp = tty->driver_data;
1325 if (portp == NULL)
1326 return;
1327 stl_startrxtx(portp, -1, 1);
1328}
1329
1330/*****************************************************************************/
1331
Alan Cox606d0992006-12-08 02:38:45 -08001332static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001334 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001335 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Jiri Slabya0564e12006-12-08 02:38:37 -08001337 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
Jiri Slaby615e4a72006-12-08 02:38:38 -08001339 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 return;
1341 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001342 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 return;
1344
1345 tiosp = tty->termios;
1346 if ((tiosp->c_cflag == old->c_cflag) &&
1347 (tiosp->c_iflag == old->c_iflag))
1348 return;
1349
1350 stl_setport(portp, tiosp);
1351 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1352 -1);
1353 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1354 tty->hw_stopped = 0;
1355 stl_start(tty);
1356 }
1357 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1358 wake_up_interruptible(&portp->open_wait);
1359}
1360
1361/*****************************************************************************/
1362
1363/*
1364 * Attempt to flow control who ever is sending us data. Based on termios
1365 * settings use software or/and hardware flow control.
1366 */
1367
1368static void stl_throttle(struct tty_struct *tty)
1369{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001370 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Jiri Slabya0564e12006-12-08 02:38:37 -08001372 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Jiri Slaby615e4a72006-12-08 02:38:38 -08001374 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 return;
1376 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001377 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 return;
1379 stl_flowctrl(portp, 0);
1380}
1381
1382/*****************************************************************************/
1383
1384/*
1385 * Unflow control the device sending us data...
1386 */
1387
1388static void stl_unthrottle(struct tty_struct *tty)
1389{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001390 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Jiri Slabya0564e12006-12-08 02:38:37 -08001392 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Jiri Slaby615e4a72006-12-08 02:38:38 -08001394 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 return;
1396 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001397 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 return;
1399 stl_flowctrl(portp, 1);
1400}
1401
1402/*****************************************************************************/
1403
1404/*
1405 * Stop the transmitter. Basically to do this we will just turn TX
1406 * interrupts off.
1407 */
1408
1409static void stl_stop(struct tty_struct *tty)
1410{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001411 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
Jiri Slabya0564e12006-12-08 02:38:37 -08001413 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Jiri Slaby615e4a72006-12-08 02:38:38 -08001415 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 return;
1417 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001418 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 return;
1420 stl_startrxtx(portp, -1, 0);
1421}
1422
1423/*****************************************************************************/
1424
1425/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 * Hangup this port. This is pretty much like closing the port, only
1427 * a little more brutal. No waiting for data to drain. Shutdown the
1428 * port and maybe drop signals.
1429 */
1430
1431static void stl_hangup(struct tty_struct *tty)
1432{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001433 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Jiri Slabya0564e12006-12-08 02:38:37 -08001435 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Jiri Slaby615e4a72006-12-08 02:38:38 -08001437 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 return;
1439 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001440 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 return;
1442
1443 portp->flags &= ~ASYNC_INITIALIZED;
1444 stl_disableintrs(portp);
1445 if (tty->termios->c_cflag & HUPCL)
1446 stl_setsignals(portp, 0, 0);
1447 stl_enablerxtx(portp, 0, 0);
1448 stl_flushbuffer(tty);
1449 portp->istate = 0;
1450 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001451 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001453 portp->tx.buf = NULL;
1454 portp->tx.head = NULL;
1455 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001457 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1459 portp->refcount = 0;
1460 wake_up_interruptible(&portp->open_wait);
1461}
1462
1463/*****************************************************************************/
1464
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465static void stl_breakctl(struct tty_struct *tty, int state)
1466{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001467 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Jiri Slabya0564e12006-12-08 02:38:37 -08001469 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
Jiri Slaby615e4a72006-12-08 02:38:38 -08001471 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 return;
1473 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001474 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 return;
1476
1477 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1478}
1479
1480/*****************************************************************************/
1481
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482static void stl_sendxchar(struct tty_struct *tty, char ch)
1483{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001484 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
Jiri Slabya0564e12006-12-08 02:38:37 -08001486 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Jiri Slaby615e4a72006-12-08 02:38:38 -08001488 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 return;
1490 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001491 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 return;
1493
1494 if (ch == STOP_CHAR(tty))
1495 stl_sendflow(portp, 0);
1496 else if (ch == START_CHAR(tty))
1497 stl_sendflow(portp, 1);
1498 else
1499 stl_putchar(tty, ch);
1500}
1501
1502/*****************************************************************************/
1503
1504#define MAXLINE 80
1505
1506/*
1507 * Format info for a specified port. The line is deliberately limited
1508 * to 80 characters. (If it is too long it will be truncated, if too
1509 * short then padded with spaces).
1510 */
1511
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001512static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
1514 char *sp;
1515 int sigs, cnt;
1516
1517 sp = pos;
1518 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1519 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1520 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1521
1522 if (portp->stats.rxframing)
1523 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1524 if (portp->stats.rxparity)
1525 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1526 if (portp->stats.rxbreaks)
1527 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1528 if (portp->stats.rxoverrun)
1529 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1530
1531 sigs = stl_getsignals(portp);
1532 cnt = sprintf(sp, "%s%s%s%s%s ",
1533 (sigs & TIOCM_RTS) ? "|RTS" : "",
1534 (sigs & TIOCM_CTS) ? "|CTS" : "",
1535 (sigs & TIOCM_DTR) ? "|DTR" : "",
1536 (sigs & TIOCM_CD) ? "|DCD" : "",
1537 (sigs & TIOCM_DSR) ? "|DSR" : "");
1538 *sp = ' ';
1539 sp += cnt;
1540
1541 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1542 *sp++ = ' ';
1543 if (cnt >= MAXLINE)
1544 pos[(MAXLINE - 2)] = '+';
1545 pos[(MAXLINE - 1)] = '\n';
1546
Jesper Juhl014c2542006-01-15 02:37:08 +01001547 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548}
1549
1550/*****************************************************************************/
1551
1552/*
1553 * Port info, read from the /proc file system.
1554 */
1555
1556static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1557{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001558 struct stlbrd *brdp;
1559 struct stlpanel *panelp;
1560 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 int brdnr, panelnr, portnr, totalport;
1562 int curoff, maxoff;
1563 char *pos;
1564
Jiri Slabya0564e12006-12-08 02:38:37 -08001565 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1566 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
1568 pos = page;
1569 totalport = 0;
1570 curoff = 0;
1571
1572 if (off == 0) {
1573 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1574 stl_drvversion);
1575 while (pos < (page + MAXLINE - 1))
1576 *pos++ = ' ';
1577 *pos++ = '\n';
1578 }
1579 curoff = MAXLINE;
1580
1581/*
1582 * We scan through for each board, panel and port. The offset is
1583 * calculated on the fly, and irrelevant ports are skipped.
1584 */
1585 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1586 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001587 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 continue;
1589 if (brdp->state == 0)
1590 continue;
1591
1592 maxoff = curoff + (brdp->nrports * MAXLINE);
1593 if (off >= maxoff) {
1594 curoff = maxoff;
1595 continue;
1596 }
1597
1598 totalport = brdnr * STL_MAXPORTS;
1599 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1600 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001601 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 continue;
1603
1604 maxoff = curoff + (panelp->nrports * MAXLINE);
1605 if (off >= maxoff) {
1606 curoff = maxoff;
1607 totalport += panelp->nrports;
1608 continue;
1609 }
1610
1611 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1612 totalport++) {
1613 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001614 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 continue;
1616 if (off >= (curoff += MAXLINE))
1617 continue;
1618 if ((pos - page + MAXLINE) > count)
1619 goto stl_readdone;
1620 pos += stl_portinfo(portp, totalport, pos);
1621 }
1622 }
1623 }
1624
1625 *eof = 1;
1626
1627stl_readdone:
1628 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001629 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630}
1631
1632/*****************************************************************************/
1633
1634/*
1635 * All board interrupts are vectored through here first. This code then
1636 * calls off to the approrpriate board interrupt handlers.
1637 */
1638
David Howells7d12e782006-10-05 14:55:46 +01001639static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001641 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
Jiri Slabya0564e12006-12-08 02:38:37 -08001643 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645 return IRQ_RETVAL((* brdp->isr)(brdp));
1646}
1647
1648/*****************************************************************************/
1649
1650/*
1651 * Interrupt service routine for EasyIO board types.
1652 */
1653
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001654static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001656 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 unsigned int iobase;
1658 int handled = 0;
1659
Alan Coxb65b5b52006-06-27 02:54:05 -07001660 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 panelp = brdp->panels[0];
1662 iobase = panelp->iobase;
1663 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1664 handled = 1;
1665 (* panelp->isr)(panelp, iobase);
1666 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001667 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 return handled;
1669}
1670
1671/*****************************************************************************/
1672
1673/*
1674 * Interrupt service routine for ECH-AT board types.
1675 */
1676
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001677static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001679 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 unsigned int ioaddr;
1681 int bnknr;
1682 int handled = 0;
1683
1684 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1685
1686 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1687 handled = 1;
1688 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1689 ioaddr = brdp->bnkstataddr[bnknr];
1690 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1691 panelp = brdp->bnk2panel[bnknr];
1692 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1693 }
1694 }
1695 }
1696
1697 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1698
1699 return handled;
1700}
1701
1702/*****************************************************************************/
1703
1704/*
1705 * Interrupt service routine for ECH-MCA board types.
1706 */
1707
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001708static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001710 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 unsigned int ioaddr;
1712 int bnknr;
1713 int handled = 0;
1714
1715 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1716 handled = 1;
1717 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1718 ioaddr = brdp->bnkstataddr[bnknr];
1719 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1720 panelp = brdp->bnk2panel[bnknr];
1721 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1722 }
1723 }
1724 }
1725 return handled;
1726}
1727
1728/*****************************************************************************/
1729
1730/*
1731 * Interrupt service routine for ECH-PCI board types.
1732 */
1733
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001734static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001736 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 unsigned int ioaddr;
1738 int bnknr, recheck;
1739 int handled = 0;
1740
1741 while (1) {
1742 recheck = 0;
1743 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1744 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1745 ioaddr = brdp->bnkstataddr[bnknr];
1746 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1747 panelp = brdp->bnk2panel[bnknr];
1748 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1749 recheck++;
1750 handled = 1;
1751 }
1752 }
1753 if (! recheck)
1754 break;
1755 }
1756 return handled;
1757}
1758
1759/*****************************************************************************/
1760
1761/*
1762 * Interrupt service routine for ECH-8/64-PCI board types.
1763 */
1764
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001765static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001767 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 unsigned int ioaddr;
1769 int bnknr;
1770 int handled = 0;
1771
1772 while (inb(brdp->ioctrl) & 0x1) {
1773 handled = 1;
1774 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1775 ioaddr = brdp->bnkstataddr[bnknr];
1776 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1777 panelp = brdp->bnk2panel[bnknr];
1778 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1779 }
1780 }
1781 }
1782
1783 return handled;
1784}
1785
1786/*****************************************************************************/
1787
1788/*
1789 * Service an off-level request for some channel.
1790 */
Al Viro3e577a82006-12-06 18:41:45 +00001791static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001793 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 struct tty_struct *tty;
1795 unsigned int oldsigs;
1796
Jiri Slabya0564e12006-12-08 02:38:37 -08001797 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
Jiri Slaby615e4a72006-12-08 02:38:38 -08001799 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 return;
1801
1802 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001803 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 return;
1805
1806 lock_kernel();
1807 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1808 tty_wakeup(tty);
1809 }
1810 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1811 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1812 oldsigs = portp->sigs;
1813 portp->sigs = stl_getsignals(portp);
1814 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1815 wake_up_interruptible(&portp->open_wait);
1816 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1817 if (portp->flags & ASYNC_CHECK_CD)
1818 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1819 }
1820 }
1821 unlock_kernel();
1822}
1823
1824/*****************************************************************************/
1825
1826/*
1827 * Initialize all the ports on a panel.
1828 */
1829
Jiri Slaby705c1862006-12-08 02:39:11 -08001830static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001832 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 int chipmask, i;
1834
Jiri Slabya0564e12006-12-08 02:38:37 -08001835 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
1837 chipmask = stl_panelinit(brdp, panelp);
1838
1839/*
1840 * All UART's are initialized (if found!). Now go through and setup
1841 * each ports data structures.
1842 */
1843 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001844 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001845 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001847 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 break;
1849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850
1851 portp->magic = STL_PORTMAGIC;
1852 portp->portnr = i;
1853 portp->brdnr = panelp->brdnr;
1854 portp->panelnr = panelp->panelnr;
1855 portp->uartp = panelp->uartp;
1856 portp->clk = brdp->clk;
1857 portp->baud_base = STL_BAUDBASE;
1858 portp->close_delay = STL_CLOSEDELAY;
1859 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001860 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 init_waitqueue_head(&portp->open_wait);
1862 init_waitqueue_head(&portp->close_wait);
1863 portp->stats.brd = portp->brdnr;
1864 portp->stats.panel = portp->panelnr;
1865 portp->stats.port = portp->portnr;
1866 panelp->ports[i] = portp;
1867 stl_portinit(brdp, panelp, portp);
1868 }
1869
1870 return(0);
1871}
1872
Jiri Slaby3b85b342006-12-08 02:39:10 -08001873static void stl_cleanup_panels(struct stlbrd *brdp)
1874{
1875 struct stlpanel *panelp;
1876 struct stlport *portp;
1877 unsigned int j, k;
1878
1879 for (j = 0; j < STL_MAXPANELS; j++) {
1880 panelp = brdp->panels[j];
1881 if (panelp == NULL)
1882 continue;
1883 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1884 portp = panelp->ports[k];
1885 if (portp == NULL)
1886 continue;
1887 if (portp->tty != NULL)
1888 stl_hangup(portp->tty);
1889 kfree(portp->tx.buf);
1890 kfree(portp);
1891 }
1892 kfree(panelp);
1893 }
1894}
1895
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896/*****************************************************************************/
1897
1898/*
1899 * Try to find and initialize an EasyIO board.
1900 */
1901
Jiri Slaby705c1862006-12-08 02:39:11 -08001902static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001904 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 unsigned int status;
1906 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001907 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Jiri Slabya0564e12006-12-08 02:38:37 -08001909 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
1911 brdp->ioctrl = brdp->ioaddr1 + 1;
1912 brdp->iostatus = brdp->ioaddr1 + 2;
1913
1914 status = inb(brdp->iostatus);
1915 if ((status & EIO_IDBITMASK) == EIO_MK3)
1916 brdp->ioctrl++;
1917
1918/*
1919 * Handle board specific stuff now. The real difference is PCI
1920 * or not PCI.
1921 */
1922 if (brdp->brdtype == BRD_EASYIOPCI) {
1923 brdp->iosize1 = 0x80;
1924 brdp->iosize2 = 0x80;
1925 name = "serial(EIO-PCI)";
1926 outb(0x41, (brdp->ioaddr2 + 0x4c));
1927 } else {
1928 brdp->iosize1 = 8;
1929 name = "serial(EIO)";
1930 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1931 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1932 printk("STALLION: invalid irq=%d for brd=%d\n",
1933 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001934 retval = -EINVAL;
1935 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 }
1937 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1938 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1939 brdp->ioctrl);
1940 }
1941
Jiri Slaby3b85b342006-12-08 02:39:10 -08001942 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1944 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1945 "%x conflicts with another device\n", brdp->brdnr,
1946 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001947 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 }
1949
1950 if (brdp->iosize2 > 0)
1951 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1952 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1953 "address %x conflicts with another device\n",
1954 brdp->brdnr, brdp->ioaddr2);
1955 printk(KERN_WARNING "STALLION: Warning, also "
1956 "releasing board %d I/O address %x \n",
1957 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001958 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 }
1960
1961/*
1962 * Everything looks OK, so let's go ahead and probe for the hardware.
1963 */
1964 brdp->clk = CD1400_CLK;
1965 brdp->isr = stl_eiointr;
1966
Jiri Slaby3b85b342006-12-08 02:39:10 -08001967 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 switch (status & EIO_IDBITMASK) {
1969 case EIO_8PORTM:
1970 brdp->clk = CD1400_CLK8M;
1971 /* fall thru */
1972 case EIO_8PORTRS:
1973 case EIO_8PORTDI:
1974 brdp->nrports = 8;
1975 break;
1976 case EIO_4PORTRS:
1977 brdp->nrports = 4;
1978 break;
1979 case EIO_MK3:
1980 switch (status & EIO_BRDMASK) {
1981 case ID_BRD4:
1982 brdp->nrports = 4;
1983 break;
1984 case ID_BRD8:
1985 brdp->nrports = 8;
1986 break;
1987 case ID_BRD16:
1988 brdp->nrports = 16;
1989 break;
1990 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001991 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 }
1993 break;
1994 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001995 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 }
1997
1998/*
1999 * We have verified that the board is actually present, so now we
2000 * can complete the setup.
2001 */
2002
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002003 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002004 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002006 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002007 retval = -ENOMEM;
2008 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
2011 panelp->magic = STL_PANELMAGIC;
2012 panelp->brdnr = brdp->brdnr;
2013 panelp->panelnr = 0;
2014 panelp->nrports = brdp->nrports;
2015 panelp->iobase = brdp->ioaddr1;
2016 panelp->hwid = status;
2017 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002018 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 panelp->isr = stl_sc26198intr;
2020 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002021 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 panelp->isr = stl_cd1400eiointr;
2023 }
2024
2025 brdp->panels[0] = panelp;
2026 brdp->nrpanels = 1;
2027 brdp->state |= BRD_FOUND;
2028 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002029 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 printk("STALLION: failed to register interrupt "
2031 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002032 retval = -ENODEV;
2033 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08002035
2036 return 0;
2037err_fr:
2038 stl_cleanup_panels(brdp);
2039err_rel2:
2040 if (brdp->iosize2 > 0)
2041 release_region(brdp->ioaddr2, brdp->iosize2);
2042err_rel1:
2043 release_region(brdp->ioaddr1, brdp->iosize1);
2044err:
2045 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046}
2047
2048/*****************************************************************************/
2049
2050/*
2051 * Try to find an ECH board and initialize it. This code is capable of
2052 * dealing with all types of ECH board.
2053 */
2054
Jiri Slaby705c1862006-12-08 02:39:11 -08002055static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002057 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 unsigned int status, nxtid, ioaddr, conflict;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002059 int panelnr, banknr, i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 char *name;
2061
Jiri Slabya0564e12006-12-08 02:38:37 -08002062 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
2064 status = 0;
2065 conflict = 0;
2066
2067/*
2068 * Set up the initial board register contents for boards. This varies a
2069 * bit between the different board types. So we need to handle each
2070 * separately. Also do a check that the supplied IRQ is good.
2071 */
2072 switch (brdp->brdtype) {
2073
2074 case BRD_ECH:
2075 brdp->isr = stl_echatintr;
2076 brdp->ioctrl = brdp->ioaddr1 + 1;
2077 brdp->iostatus = brdp->ioaddr1 + 1;
2078 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002079 if ((status & ECH_IDBITMASK) != ECH_ID) {
2080 retval = -ENODEV;
2081 goto err;
2082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2084 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2085 printk("STALLION: invalid irq=%d for brd=%d\n",
2086 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002087 retval = -EINVAL;
2088 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 }
2090 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2091 status |= (stl_vecmap[brdp->irq] << 1);
2092 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2093 brdp->ioctrlval = ECH_INTENABLE |
2094 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2095 for (i = 0; (i < 10); i++)
2096 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2097 brdp->iosize1 = 2;
2098 brdp->iosize2 = 32;
2099 name = "serial(EC8/32)";
2100 outb(status, brdp->ioaddr1);
2101 break;
2102
2103 case BRD_ECHMC:
2104 brdp->isr = stl_echmcaintr;
2105 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2106 brdp->iostatus = brdp->ioctrl;
2107 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002108 if ((status & ECH_IDBITMASK) != ECH_ID) {
2109 retval = -ENODEV;
2110 goto err;
2111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2113 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2114 printk("STALLION: invalid irq=%d for brd=%d\n",
2115 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002116 retval = -EINVAL;
2117 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 }
2119 outb(ECHMC_BRDRESET, brdp->ioctrl);
2120 outb(ECHMC_INTENABLE, brdp->ioctrl);
2121 brdp->iosize1 = 64;
2122 name = "serial(EC8/32-MC)";
2123 break;
2124
2125 case BRD_ECHPCI:
2126 brdp->isr = stl_echpciintr;
2127 brdp->ioctrl = brdp->ioaddr1 + 2;
2128 brdp->iosize1 = 4;
2129 brdp->iosize2 = 8;
2130 name = "serial(EC8/32-PCI)";
2131 break;
2132
2133 case BRD_ECH64PCI:
2134 brdp->isr = stl_echpci64intr;
2135 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2136 outb(0x43, (brdp->ioaddr1 + 0x4c));
2137 brdp->iosize1 = 0x80;
2138 brdp->iosize2 = 0x80;
2139 name = "serial(EC8/64-PCI)";
2140 break;
2141
2142 default:
2143 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002144 retval = -EINVAL;
2145 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 }
2147
2148/*
2149 * Check boards for possible IO address conflicts and return fail status
2150 * if an IO conflict found.
2151 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002152 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2154 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2155 "%x conflicts with another device\n", brdp->brdnr,
2156 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002157 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 }
2159
2160 if (brdp->iosize2 > 0)
2161 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2162 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2163 "address %x conflicts with another device\n",
2164 brdp->brdnr, brdp->ioaddr2);
2165 printk(KERN_WARNING "STALLION: Warning, also "
2166 "releasing board %d I/O address %x \n",
2167 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002168 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 }
2170
2171/*
2172 * Scan through the secondary io address space looking for panels.
2173 * As we find'em allocate and initialize panel structures for each.
2174 */
2175 brdp->clk = CD1400_CLK;
2176 brdp->hwid = status;
2177
2178 ioaddr = brdp->ioaddr2;
2179 banknr = 0;
2180 panelnr = 0;
2181 nxtid = 0;
2182
2183 for (i = 0; (i < STL_MAXPANELS); i++) {
2184 if (brdp->brdtype == BRD_ECHPCI) {
2185 outb(nxtid, brdp->ioctrl);
2186 ioaddr = brdp->ioaddr2;
2187 }
2188 status = inb(ioaddr + ECH_PNLSTATUS);
2189 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002190 goto err_fr;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002191 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002192 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002194 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08002195 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 panelp->magic = STL_PANELMAGIC;
2198 panelp->brdnr = brdp->brdnr;
2199 panelp->panelnr = panelnr;
2200 panelp->iobase = ioaddr;
2201 panelp->pagenr = nxtid;
2202 panelp->hwid = status;
2203 brdp->bnk2panel[banknr] = panelp;
2204 brdp->bnkpageaddr[banknr] = nxtid;
2205 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2206
2207 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002208 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 panelp->isr = stl_sc26198intr;
2210 if (status & ECH_PNL16PORT) {
2211 panelp->nrports = 16;
2212 brdp->bnk2panel[banknr] = panelp;
2213 brdp->bnkpageaddr[banknr] = nxtid;
2214 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2215 ECH_PNLSTATUS;
2216 } else {
2217 panelp->nrports = 8;
2218 }
2219 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002220 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 panelp->isr = stl_cd1400echintr;
2222 if (status & ECH_PNL16PORT) {
2223 panelp->nrports = 16;
2224 panelp->ackmask = 0x80;
2225 if (brdp->brdtype != BRD_ECHPCI)
2226 ioaddr += EREG_BANKSIZE;
2227 brdp->bnk2panel[banknr] = panelp;
2228 brdp->bnkpageaddr[banknr] = ++nxtid;
2229 brdp->bnkstataddr[banknr++] = ioaddr +
2230 ECH_PNLSTATUS;
2231 } else {
2232 panelp->nrports = 8;
2233 panelp->ackmask = 0xc0;
2234 }
2235 }
2236
2237 nxtid++;
2238 ioaddr += EREG_BANKSIZE;
2239 brdp->nrports += panelp->nrports;
2240 brdp->panels[panelnr++] = panelp;
2241 if ((brdp->brdtype != BRD_ECHPCI) &&
2242 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
Jiri Slaby3b85b342006-12-08 02:39:10 -08002243 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 }
2245
2246 brdp->nrpanels = panelnr;
2247 brdp->nrbnks = banknr;
2248 if (brdp->brdtype == BRD_ECH)
2249 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2250
2251 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002252 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 printk("STALLION: failed to register interrupt "
2254 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002255 retval = -ENODEV;
2256 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 }
2258
Jiri Slaby3b85b342006-12-08 02:39:10 -08002259 return 0;
2260err_fr:
2261 stl_cleanup_panels(brdp);
2262 if (brdp->iosize2 > 0)
2263 release_region(brdp->ioaddr2, brdp->iosize2);
2264err_rel1:
2265 release_region(brdp->ioaddr1, brdp->iosize1);
2266err:
2267 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268}
2269
2270/*****************************************************************************/
2271
2272/*
2273 * Initialize and configure the specified board.
2274 * Scan through all the boards in the configuration and see what we
2275 * can find. Handle EIO and the ECH boards a little differently here
2276 * since the initial search and setup is very different.
2277 */
2278
Jiri Slaby705c1862006-12-08 02:39:11 -08002279static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002281 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282
Jiri Slabya0564e12006-12-08 02:38:37 -08002283 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
2285 switch (brdp->brdtype) {
2286 case BRD_EASYIO:
2287 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002288 retval = stl_initeio(brdp);
2289 if (retval)
2290 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 break;
2292 case BRD_ECH:
2293 case BRD_ECHMC:
2294 case BRD_ECHPCI:
2295 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002296 retval = stl_initech(brdp);
2297 if (retval)
2298 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 break;
2300 default:
2301 printk("STALLION: board=%d is unknown board type=%d\n",
2302 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002303 retval = -ENODEV;
2304 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 }
2306
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 if ((brdp->state & BRD_FOUND) == 0) {
2308 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2309 stl_brdnames[brdp->brdtype], brdp->brdnr,
2310 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002311 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 }
2313
2314 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002315 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 stl_initports(brdp, brdp->panels[i]);
2317
2318 printk("STALLION: %s found, board=%d io=%x irq=%d "
2319 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2320 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2321 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002322
2323 return 0;
2324err_free:
2325 free_irq(brdp->irq, brdp);
2326
2327 stl_cleanup_panels(brdp);
2328
2329 release_region(brdp->ioaddr1, brdp->iosize1);
2330 if (brdp->iosize2 > 0)
2331 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002332err:
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 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002384 mutex_lock(&stl_brdslock);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002385 brdp->brdnr = stl_getbrdnr();
2386 if (brdp->brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002387 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002389 mutex_unlock(&stl_brdslock);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002390 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002392 stl_brds[brdp->brdnr] = brdp;
2393 mutex_unlock(&stl_brdslock);
2394
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002396 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397
2398/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 * We have all resources from the board, so let's setup the actual
2400 * board structure now.
2401 */
2402 switch (brdtype) {
2403 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002404 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2405 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 break;
2407 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002408 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2409 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 break;
2411 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002412 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2413 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 break;
2415 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002416 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 break;
2418 }
2419
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002420 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002421 retval = stl_brdinit(brdp);
2422 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002423 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002425 pci_set_drvdata(pdev, brdp);
2426
Jiri Slaby3b85b342006-12-08 02:39:10 -08002427 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002428err_null:
2429 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002430err_fr:
2431 kfree(brdp);
2432err:
2433 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434}
2435
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002436static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002438 struct stlbrd *brdp = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002440 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002442 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002444 release_region(brdp->ioaddr1, brdp->iosize1);
2445 if (brdp->iosize2 > 0)
2446 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002448 stl_brds[brdp->brdnr] = NULL;
2449 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450}
2451
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002452static struct pci_driver stl_pcidriver = {
2453 .name = "stallion",
2454 .id_table = stl_pcibrds,
2455 .probe = stl_pciprobe,
2456 .remove = __devexit_p(stl_pciremove)
2457};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458
2459/*****************************************************************************/
2460
2461/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 * Return the board stats structure to user app.
2463 */
2464
2465static int stl_getbrdstats(combrd_t __user *bp)
2466{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002467 struct stlbrd *brdp;
2468 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 int i;
2470
2471 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2472 return -EFAULT;
2473 if (stl_brdstats.brd >= STL_MAXBRDS)
2474 return(-ENODEV);
2475 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002476 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 return(-ENODEV);
2478
2479 memset(&stl_brdstats, 0, sizeof(combrd_t));
2480 stl_brdstats.brd = brdp->brdnr;
2481 stl_brdstats.type = brdp->brdtype;
2482 stl_brdstats.hwid = brdp->hwid;
2483 stl_brdstats.state = brdp->state;
2484 stl_brdstats.ioaddr = brdp->ioaddr1;
2485 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2486 stl_brdstats.irq = brdp->irq;
2487 stl_brdstats.nrpanels = brdp->nrpanels;
2488 stl_brdstats.nrports = brdp->nrports;
2489 for (i = 0; (i < brdp->nrpanels); i++) {
2490 panelp = brdp->panels[i];
2491 stl_brdstats.panels[i].panel = i;
2492 stl_brdstats.panels[i].hwid = panelp->hwid;
2493 stl_brdstats.panels[i].nrports = panelp->nrports;
2494 }
2495
2496 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2497}
2498
2499/*****************************************************************************/
2500
2501/*
2502 * Resolve the referenced port number into a port struct pointer.
2503 */
2504
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002505static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002507 struct stlbrd *brdp;
2508 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
2510 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002511 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002513 if (brdp == NULL)
2514 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002516 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002518 if (panelp == NULL)
2519 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002521 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 return(panelp->ports[portnr]);
2523}
2524
2525/*****************************************************************************/
2526
2527/*
2528 * Return the port stats structure to user app. A NULL port struct
2529 * pointer passed in means that we need to find out from the app
2530 * what port to get stats for (used through board control device).
2531 */
2532
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002533static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534{
2535 unsigned char *head, *tail;
2536 unsigned long flags;
2537
2538 if (!portp) {
2539 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2540 return -EFAULT;
2541 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2542 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002543 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 return(-ENODEV);
2545 }
2546
2547 portp->stats.state = portp->istate;
2548 portp->stats.flags = portp->flags;
2549 portp->stats.hwid = portp->hwid;
2550
2551 portp->stats.ttystate = 0;
2552 portp->stats.cflags = 0;
2553 portp->stats.iflags = 0;
2554 portp->stats.oflags = 0;
2555 portp->stats.lflags = 0;
2556 portp->stats.rxbuffered = 0;
2557
Alan Coxb65b5b52006-06-27 02:54:05 -07002558 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002559 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 if (portp->tty->driver_data == portp) {
2561 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002562 /* No longer available as a statistic */
2563 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002564 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 portp->stats.cflags = portp->tty->termios->c_cflag;
2566 portp->stats.iflags = portp->tty->termios->c_iflag;
2567 portp->stats.oflags = portp->tty->termios->c_oflag;
2568 portp->stats.lflags = portp->tty->termios->c_lflag;
2569 }
2570 }
2571 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002572 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
2574 head = portp->tx.head;
2575 tail = portp->tx.tail;
2576 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2577 (STL_TXBUFSIZE - (tail - head)));
2578
2579 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2580
2581 return copy_to_user(cp, &portp->stats,
2582 sizeof(comstats_t)) ? -EFAULT : 0;
2583}
2584
2585/*****************************************************************************/
2586
2587/*
2588 * Clear the port stats structure. We also return it zeroed out...
2589 */
2590
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002591static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592{
2593 if (!portp) {
2594 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2595 return -EFAULT;
2596 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2597 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002598 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 return(-ENODEV);
2600 }
2601
2602 memset(&portp->stats, 0, sizeof(comstats_t));
2603 portp->stats.brd = portp->brdnr;
2604 portp->stats.panel = portp->panelnr;
2605 portp->stats.port = portp->portnr;
2606 return copy_to_user(cp, &portp->stats,
2607 sizeof(comstats_t)) ? -EFAULT : 0;
2608}
2609
2610/*****************************************************************************/
2611
2612/*
2613 * Return the entire driver ports structure to a user app.
2614 */
2615
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002616static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002618 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002620 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 return -EFAULT;
2622 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2623 stl_dummyport.portnr);
2624 if (!portp)
2625 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002626 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627}
2628
2629/*****************************************************************************/
2630
2631/*
2632 * Return the entire driver board structure to a user app.
2633 */
2634
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002635static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002637 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002639 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 return -EFAULT;
2641 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2642 return -ENODEV;
2643 brdp = stl_brds[stl_dummybrd.brdnr];
2644 if (!brdp)
2645 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002646 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647}
2648
2649/*****************************************************************************/
2650
2651/*
2652 * The "staliomem" device is also required to do some special operations
2653 * on the board and/or ports. In this driver it is mostly used for stats
2654 * collection.
2655 */
2656
2657static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2658{
2659 int brdnr, rc;
2660 void __user *argp = (void __user *)arg;
2661
Jiri Slabya0564e12006-12-08 02:38:37 -08002662 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663
2664 brdnr = iminor(ip);
2665 if (brdnr >= STL_MAXBRDS)
2666 return(-ENODEV);
2667 rc = 0;
2668
2669 switch (cmd) {
2670 case COM_GETPORTSTATS:
2671 rc = stl_getportstats(NULL, argp);
2672 break;
2673 case COM_CLRPORTSTATS:
2674 rc = stl_clrportstats(NULL, argp);
2675 break;
2676 case COM_GETBRDSTATS:
2677 rc = stl_getbrdstats(argp);
2678 break;
2679 case COM_READPORT:
2680 rc = stl_getportstruct(argp);
2681 break;
2682 case COM_READBOARD:
2683 rc = stl_getbrdstruct(argp);
2684 break;
2685 default:
2686 rc = -ENOIOCTLCMD;
2687 break;
2688 }
2689
2690 return(rc);
2691}
2692
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002693static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 .open = stl_open,
2695 .close = stl_close,
2696 .write = stl_write,
2697 .put_char = stl_putchar,
2698 .flush_chars = stl_flushchars,
2699 .write_room = stl_writeroom,
2700 .chars_in_buffer = stl_charsinbuffer,
2701 .ioctl = stl_ioctl,
2702 .set_termios = stl_settermios,
2703 .throttle = stl_throttle,
2704 .unthrottle = stl_unthrottle,
2705 .stop = stl_stop,
2706 .start = stl_start,
2707 .hangup = stl_hangup,
2708 .flush_buffer = stl_flushbuffer,
2709 .break_ctl = stl_breakctl,
2710 .wait_until_sent = stl_waituntilsent,
2711 .send_xchar = stl_sendxchar,
2712 .read_proc = stl_readproc,
2713 .tiocmget = stl_tiocmget,
2714 .tiocmset = stl_tiocmset,
2715};
2716
2717/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718/* CD1400 HARDWARE FUNCTIONS */
2719/*****************************************************************************/
2720
2721/*
2722 * These functions get/set/update the registers of the cd1400 UARTs.
2723 * Access to the cd1400 registers is via an address/data io port pair.
2724 * (Maybe should make this inline...)
2725 */
2726
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002727static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728{
2729 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002730 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731}
2732
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002733static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734{
2735 outb((regnr + portp->uartaddr), portp->ioaddr);
2736 outb(value, portp->ioaddr + EREG_DATA);
2737}
2738
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002739static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740{
2741 outb((regnr + portp->uartaddr), portp->ioaddr);
2742 if (inb(portp->ioaddr + EREG_DATA) != value) {
2743 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002744 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002746 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747}
2748
2749/*****************************************************************************/
2750
2751/*
2752 * Inbitialize the UARTs in a panel. We don't care what sort of board
2753 * these ports are on - since the port io registers are almost
2754 * identical when dealing with ports.
2755 */
2756
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002757static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758{
2759 unsigned int gfrcr;
2760 int chipmask, i, j;
2761 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002762 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763
Jiri Slabya0564e12006-12-08 02:38:37 -08002764 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765
Alan Coxb65b5b52006-06-27 02:54:05 -07002766 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 BRDENABLE(panelp->brdnr, panelp->pagenr);
2768
2769/*
2770 * Check that each chip is present and started up OK.
2771 */
2772 chipmask = 0;
2773 nrchips = panelp->nrports / CD1400_PORTS;
2774 for (i = 0; (i < nrchips); i++) {
2775 if (brdp->brdtype == BRD_ECHPCI) {
2776 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2777 ioaddr = panelp->iobase;
2778 } else {
2779 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2780 }
2781 uartaddr = (i & 0x01) ? 0x080 : 0;
2782 outb((GFRCR + uartaddr), ioaddr);
2783 outb(0, (ioaddr + EREG_DATA));
2784 outb((CCR + uartaddr), ioaddr);
2785 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2786 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2787 outb((GFRCR + uartaddr), ioaddr);
2788 for (j = 0; (j < CCR_MAXWAIT); j++) {
2789 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2790 break;
2791 }
2792 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2793 printk("STALLION: cd1400 not responding, "
2794 "brd=%d panel=%d chip=%d\n",
2795 panelp->brdnr, panelp->panelnr, i);
2796 continue;
2797 }
2798 chipmask |= (0x1 << i);
2799 outb((PPR + uartaddr), ioaddr);
2800 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2801 }
2802
2803 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002804 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002805 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806}
2807
2808/*****************************************************************************/
2809
2810/*
2811 * Initialize hardware specific port registers.
2812 */
2813
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002814static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815{
Alan Coxb65b5b52006-06-27 02:54:05 -07002816 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002817 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2818 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
Jiri Slaby615e4a72006-12-08 02:38:38 -08002820 if ((brdp == NULL) || (panelp == NULL) ||
2821 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 return;
2823
Alan Coxb65b5b52006-06-27 02:54:05 -07002824 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2826 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2827 portp->uartaddr = (portp->portnr & 0x04) << 5;
2828 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2829
2830 BRDENABLE(portp->brdnr, portp->pagenr);
2831 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2832 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2833 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2834 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002835 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836}
2837
2838/*****************************************************************************/
2839
2840/*
2841 * Wait for the command register to be ready. We will poll this,
2842 * since it won't usually take too long to be ready.
2843 */
2844
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002845static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846{
2847 int i;
2848
2849 for (i = 0; (i < CCR_MAXWAIT); i++) {
2850 if (stl_cd1400getreg(portp, CCR) == 0) {
2851 return;
2852 }
2853 }
2854
2855 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2856 portp->portnr, portp->panelnr, portp->brdnr);
2857}
2858
2859/*****************************************************************************/
2860
2861/*
2862 * Set up the cd1400 registers for a port based on the termios port
2863 * settings.
2864 */
2865
Alan Cox606d0992006-12-08 02:38:45 -08002866static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002868 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 unsigned long flags;
2870 unsigned int clkdiv, baudrate;
2871 unsigned char cor1, cor2, cor3;
2872 unsigned char cor4, cor5, ccr;
2873 unsigned char srer, sreron, sreroff;
2874 unsigned char mcor1, mcor2, rtpr;
2875 unsigned char clk, div;
2876
2877 cor1 = 0;
2878 cor2 = 0;
2879 cor3 = 0;
2880 cor4 = 0;
2881 cor5 = 0;
2882 ccr = 0;
2883 rtpr = 0;
2884 clk = 0;
2885 div = 0;
2886 mcor1 = 0;
2887 mcor2 = 0;
2888 sreron = 0;
2889 sreroff = 0;
2890
2891 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002892 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 return;
2894
2895/*
2896 * Set up the RX char ignore mask with those RX error types we
2897 * can ignore. We can get the cd1400 to help us out a little here,
2898 * it will ignore parity errors and breaks for us.
2899 */
2900 portp->rxignoremsk = 0;
2901 if (tiosp->c_iflag & IGNPAR) {
2902 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2903 cor1 |= COR1_PARIGNORE;
2904 }
2905 if (tiosp->c_iflag & IGNBRK) {
2906 portp->rxignoremsk |= ST_BREAK;
2907 cor4 |= COR4_IGNBRK;
2908 }
2909
2910 portp->rxmarkmsk = ST_OVERRUN;
2911 if (tiosp->c_iflag & (INPCK | PARMRK))
2912 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2913 if (tiosp->c_iflag & BRKINT)
2914 portp->rxmarkmsk |= ST_BREAK;
2915
2916/*
2917 * Go through the char size, parity and stop bits and set all the
2918 * option register appropriately.
2919 */
2920 switch (tiosp->c_cflag & CSIZE) {
2921 case CS5:
2922 cor1 |= COR1_CHL5;
2923 break;
2924 case CS6:
2925 cor1 |= COR1_CHL6;
2926 break;
2927 case CS7:
2928 cor1 |= COR1_CHL7;
2929 break;
2930 default:
2931 cor1 |= COR1_CHL8;
2932 break;
2933 }
2934
2935 if (tiosp->c_cflag & CSTOPB)
2936 cor1 |= COR1_STOP2;
2937 else
2938 cor1 |= COR1_STOP1;
2939
2940 if (tiosp->c_cflag & PARENB) {
2941 if (tiosp->c_cflag & PARODD)
2942 cor1 |= (COR1_PARENB | COR1_PARODD);
2943 else
2944 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2945 } else {
2946 cor1 |= COR1_PARNONE;
2947 }
2948
2949/*
2950 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2951 * space for hardware flow control and the like. This should be set to
2952 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2953 * really be based on VTIME.
2954 */
2955 cor3 |= FIFO_RXTHRESHOLD;
2956 rtpr = 2;
2957
2958/*
2959 * Calculate the baud rate timers. For now we will just assume that
2960 * the input and output baud are the same. Could have used a baud
2961 * table here, but this way we can generate virtually any baud rate
2962 * we like!
2963 */
2964 baudrate = tiosp->c_cflag & CBAUD;
2965 if (baudrate & CBAUDEX) {
2966 baudrate &= ~CBAUDEX;
2967 if ((baudrate < 1) || (baudrate > 4))
2968 tiosp->c_cflag &= ~CBAUDEX;
2969 else
2970 baudrate += 15;
2971 }
2972 baudrate = stl_baudrates[baudrate];
2973 if ((tiosp->c_cflag & CBAUD) == B38400) {
2974 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2975 baudrate = 57600;
2976 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2977 baudrate = 115200;
2978 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2979 baudrate = 230400;
2980 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2981 baudrate = 460800;
2982 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
2983 baudrate = (portp->baud_base / portp->custom_divisor);
2984 }
2985 if (baudrate > STL_CD1400MAXBAUD)
2986 baudrate = STL_CD1400MAXBAUD;
2987
2988 if (baudrate > 0) {
2989 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
2990 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
2991 if (clkdiv < 0x100)
2992 break;
2993 }
2994 div = (unsigned char) clkdiv;
2995 }
2996
2997/*
2998 * Check what form of modem signaling is required and set it up.
2999 */
3000 if ((tiosp->c_cflag & CLOCAL) == 0) {
3001 mcor1 |= MCOR1_DCD;
3002 mcor2 |= MCOR2_DCD;
3003 sreron |= SRER_MODEM;
3004 portp->flags |= ASYNC_CHECK_CD;
3005 } else {
3006 portp->flags &= ~ASYNC_CHECK_CD;
3007 }
3008
3009/*
3010 * Setup cd1400 enhanced modes if we can. In particular we want to
3011 * handle as much of the flow control as possible automatically. As
3012 * well as saving a few CPU cycles it will also greatly improve flow
3013 * control reliability.
3014 */
3015 if (tiosp->c_iflag & IXON) {
3016 cor2 |= COR2_TXIBE;
3017 cor3 |= COR3_SCD12;
3018 if (tiosp->c_iflag & IXANY)
3019 cor2 |= COR2_IXM;
3020 }
3021
3022 if (tiosp->c_cflag & CRTSCTS) {
3023 cor2 |= COR2_CTSAE;
3024 mcor1 |= FIFO_RTSTHRESHOLD;
3025 }
3026
3027/*
3028 * All cd1400 register values calculated so go through and set
3029 * them all up.
3030 */
3031
Jiri Slabya0564e12006-12-08 02:38:37 -08003032 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003034 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003036 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003038 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3039 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3041 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042
Alan Coxb65b5b52006-06-27 02:54:05 -07003043 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 BRDENABLE(portp->brdnr, portp->pagenr);
3045 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3046 srer = stl_cd1400getreg(portp, SRER);
3047 stl_cd1400setreg(portp, SRER, 0);
3048 if (stl_cd1400updatereg(portp, COR1, cor1))
3049 ccr = 1;
3050 if (stl_cd1400updatereg(portp, COR2, cor2))
3051 ccr = 1;
3052 if (stl_cd1400updatereg(portp, COR3, cor3))
3053 ccr = 1;
3054 if (ccr) {
3055 stl_cd1400ccrwait(portp);
3056 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3057 }
3058 stl_cd1400setreg(portp, COR4, cor4);
3059 stl_cd1400setreg(portp, COR5, cor5);
3060 stl_cd1400setreg(portp, MCOR1, mcor1);
3061 stl_cd1400setreg(portp, MCOR2, mcor2);
3062 if (baudrate > 0) {
3063 stl_cd1400setreg(portp, TCOR, clk);
3064 stl_cd1400setreg(portp, TBPR, div);
3065 stl_cd1400setreg(portp, RCOR, clk);
3066 stl_cd1400setreg(portp, RBPR, div);
3067 }
3068 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3069 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3070 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3071 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3072 stl_cd1400setreg(portp, RTPR, rtpr);
3073 mcor1 = stl_cd1400getreg(portp, MSVR1);
3074 if (mcor1 & MSVR1_DCD)
3075 portp->sigs |= TIOCM_CD;
3076 else
3077 portp->sigs &= ~TIOCM_CD;
3078 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3079 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003080 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081}
3082
3083/*****************************************************************************/
3084
3085/*
3086 * Set the state of the DTR and RTS signals.
3087 */
3088
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003089static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090{
3091 unsigned char msvr1, msvr2;
3092 unsigned long flags;
3093
Jiri Slabya0564e12006-12-08 02:38:37 -08003094 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3095 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096
3097 msvr1 = 0;
3098 msvr2 = 0;
3099 if (dtr > 0)
3100 msvr1 = MSVR1_DTR;
3101 if (rts > 0)
3102 msvr2 = MSVR2_RTS;
3103
Alan Coxb65b5b52006-06-27 02:54:05 -07003104 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 BRDENABLE(portp->brdnr, portp->pagenr);
3106 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3107 if (rts >= 0)
3108 stl_cd1400setreg(portp, MSVR2, msvr2);
3109 if (dtr >= 0)
3110 stl_cd1400setreg(portp, MSVR1, msvr1);
3111 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003112 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113}
3114
3115/*****************************************************************************/
3116
3117/*
3118 * Return the state of the signals.
3119 */
3120
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003121static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122{
3123 unsigned char msvr1, msvr2;
3124 unsigned long flags;
3125 int sigs;
3126
Jiri Slabya0564e12006-12-08 02:38:37 -08003127 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Alan Coxb65b5b52006-06-27 02:54:05 -07003129 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 BRDENABLE(portp->brdnr, portp->pagenr);
3131 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3132 msvr1 = stl_cd1400getreg(portp, MSVR1);
3133 msvr2 = stl_cd1400getreg(portp, MSVR2);
3134 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003135 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136
3137 sigs = 0;
3138 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3139 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3140 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3141 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3142#if 0
3143 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3144 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3145#else
3146 sigs |= TIOCM_DSR;
3147#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003148 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149}
3150
3151/*****************************************************************************/
3152
3153/*
3154 * Enable/Disable the Transmitter and/or Receiver.
3155 */
3156
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003157static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158{
3159 unsigned char ccr;
3160 unsigned long flags;
3161
Jiri Slabya0564e12006-12-08 02:38:37 -08003162 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3163
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 ccr = 0;
3165
3166 if (tx == 0)
3167 ccr |= CCR_TXDISABLE;
3168 else if (tx > 0)
3169 ccr |= CCR_TXENABLE;
3170 if (rx == 0)
3171 ccr |= CCR_RXDISABLE;
3172 else if (rx > 0)
3173 ccr |= CCR_RXENABLE;
3174
Alan Coxb65b5b52006-06-27 02:54:05 -07003175 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 BRDENABLE(portp->brdnr, portp->pagenr);
3177 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3178 stl_cd1400ccrwait(portp);
3179 stl_cd1400setreg(portp, CCR, ccr);
3180 stl_cd1400ccrwait(portp);
3181 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003182 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183}
3184
3185/*****************************************************************************/
3186
3187/*
3188 * Start/stop the Transmitter and/or Receiver.
3189 */
3190
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003191static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192{
3193 unsigned char sreron, sreroff;
3194 unsigned long flags;
3195
Jiri Slabya0564e12006-12-08 02:38:37 -08003196 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
3198 sreron = 0;
3199 sreroff = 0;
3200 if (tx == 0)
3201 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3202 else if (tx == 1)
3203 sreron |= SRER_TXDATA;
3204 else if (tx >= 2)
3205 sreron |= SRER_TXEMPTY;
3206 if (rx == 0)
3207 sreroff |= SRER_RXDATA;
3208 else if (rx > 0)
3209 sreron |= SRER_RXDATA;
3210
Alan Coxb65b5b52006-06-27 02:54:05 -07003211 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212 BRDENABLE(portp->brdnr, portp->pagenr);
3213 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3214 stl_cd1400setreg(portp, SRER,
3215 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3216 BRDDISABLE(portp->brdnr);
3217 if (tx > 0)
3218 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003219 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220}
3221
3222/*****************************************************************************/
3223
3224/*
3225 * Disable all interrupts from this port.
3226 */
3227
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003228static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229{
3230 unsigned long flags;
3231
Jiri Slabya0564e12006-12-08 02:38:37 -08003232 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3233
Alan Coxb65b5b52006-06-27 02:54:05 -07003234 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 BRDENABLE(portp->brdnr, portp->pagenr);
3236 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3237 stl_cd1400setreg(portp, SRER, 0);
3238 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003239 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240}
3241
3242/*****************************************************************************/
3243
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003244static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245{
3246 unsigned long flags;
3247
Jiri Slabya0564e12006-12-08 02:38:37 -08003248 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
Alan Coxb65b5b52006-06-27 02:54:05 -07003250 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251 BRDENABLE(portp->brdnr, portp->pagenr);
3252 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3253 stl_cd1400setreg(portp, SRER,
3254 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3255 SRER_TXEMPTY));
3256 BRDDISABLE(portp->brdnr);
3257 portp->brklen = len;
3258 if (len == 1)
3259 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003260 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261}
3262
3263/*****************************************************************************/
3264
3265/*
3266 * Take flow control actions...
3267 */
3268
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003269static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270{
3271 struct tty_struct *tty;
3272 unsigned long flags;
3273
Jiri Slabya0564e12006-12-08 02:38:37 -08003274 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275
Jiri Slaby615e4a72006-12-08 02:38:38 -08003276 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 return;
3278 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003279 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280 return;
3281
Alan Coxb65b5b52006-06-27 02:54:05 -07003282 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283 BRDENABLE(portp->brdnr, portp->pagenr);
3284 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3285
3286 if (state) {
3287 if (tty->termios->c_iflag & IXOFF) {
3288 stl_cd1400ccrwait(portp);
3289 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3290 portp->stats.rxxon++;
3291 stl_cd1400ccrwait(portp);
3292 }
3293/*
3294 * Question: should we return RTS to what it was before? It may
3295 * have been set by an ioctl... Suppose not, since if you have
3296 * hardware flow control set then it is pretty silly to go and
3297 * set the RTS line by hand.
3298 */
3299 if (tty->termios->c_cflag & CRTSCTS) {
3300 stl_cd1400setreg(portp, MCOR1,
3301 (stl_cd1400getreg(portp, MCOR1) |
3302 FIFO_RTSTHRESHOLD));
3303 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3304 portp->stats.rxrtson++;
3305 }
3306 } else {
3307 if (tty->termios->c_iflag & IXOFF) {
3308 stl_cd1400ccrwait(portp);
3309 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3310 portp->stats.rxxoff++;
3311 stl_cd1400ccrwait(portp);
3312 }
3313 if (tty->termios->c_cflag & CRTSCTS) {
3314 stl_cd1400setreg(portp, MCOR1,
3315 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3316 stl_cd1400setreg(portp, MSVR2, 0);
3317 portp->stats.rxrtsoff++;
3318 }
3319 }
3320
3321 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003322 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323}
3324
3325/*****************************************************************************/
3326
3327/*
3328 * Send a flow control character...
3329 */
3330
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003331static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332{
3333 struct tty_struct *tty;
3334 unsigned long flags;
3335
Jiri Slabya0564e12006-12-08 02:38:37 -08003336 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337
Jiri Slaby615e4a72006-12-08 02:38:38 -08003338 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 return;
3340 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003341 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 return;
3343
Alan Coxb65b5b52006-06-27 02:54:05 -07003344 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345 BRDENABLE(portp->brdnr, portp->pagenr);
3346 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3347 if (state) {
3348 stl_cd1400ccrwait(portp);
3349 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3350 portp->stats.rxxon++;
3351 stl_cd1400ccrwait(portp);
3352 } else {
3353 stl_cd1400ccrwait(portp);
3354 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3355 portp->stats.rxxoff++;
3356 stl_cd1400ccrwait(portp);
3357 }
3358 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003359 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360}
3361
3362/*****************************************************************************/
3363
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003364static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365{
3366 unsigned long flags;
3367
Jiri Slabya0564e12006-12-08 02:38:37 -08003368 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369
Jiri Slaby615e4a72006-12-08 02:38:38 -08003370 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 return;
3372
Alan Coxb65b5b52006-06-27 02:54:05 -07003373 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 BRDENABLE(portp->brdnr, portp->pagenr);
3375 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3376 stl_cd1400ccrwait(portp);
3377 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3378 stl_cd1400ccrwait(portp);
3379 portp->tx.tail = portp->tx.head;
3380 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003381 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382}
3383
3384/*****************************************************************************/
3385
3386/*
3387 * Return the current state of data flow on this port. This is only
3388 * really interresting when determining if data has fully completed
3389 * transmission or not... This is easy for the cd1400, it accurately
3390 * maintains the busy port flag.
3391 */
3392
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003393static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394{
Jiri Slabya0564e12006-12-08 02:38:37 -08003395 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396
Jiri Slaby615e4a72006-12-08 02:38:38 -08003397 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003398 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399
Jesper Juhl014c2542006-01-15 02:37:08 +01003400 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401}
3402
3403/*****************************************************************************/
3404
3405/*
3406 * Interrupt service routine for cd1400 EasyIO boards.
3407 */
3408
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003409static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410{
3411 unsigned char svrtype;
3412
Jiri Slabya0564e12006-12-08 02:38:37 -08003413 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414
Alan Coxb65b5b52006-06-27 02:54:05 -07003415 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 outb(SVRR, iobase);
3417 svrtype = inb(iobase + EREG_DATA);
3418 if (panelp->nrports > 4) {
3419 outb((SVRR + 0x80), iobase);
3420 svrtype |= inb(iobase + EREG_DATA);
3421 }
3422
3423 if (svrtype & SVRR_RX)
3424 stl_cd1400rxisr(panelp, iobase);
3425 else if (svrtype & SVRR_TX)
3426 stl_cd1400txisr(panelp, iobase);
3427 else if (svrtype & SVRR_MDM)
3428 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003429
3430 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431}
3432
3433/*****************************************************************************/
3434
3435/*
3436 * Interrupt service routine for cd1400 panels.
3437 */
3438
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003439static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440{
3441 unsigned char svrtype;
3442
Jiri Slabya0564e12006-12-08 02:38:37 -08003443 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444
3445 outb(SVRR, iobase);
3446 svrtype = inb(iobase + EREG_DATA);
3447 outb((SVRR + 0x80), iobase);
3448 svrtype |= inb(iobase + EREG_DATA);
3449 if (svrtype & SVRR_RX)
3450 stl_cd1400rxisr(panelp, iobase);
3451 else if (svrtype & SVRR_TX)
3452 stl_cd1400txisr(panelp, iobase);
3453 else if (svrtype & SVRR_MDM)
3454 stl_cd1400mdmisr(panelp, iobase);
3455}
3456
3457
3458/*****************************************************************************/
3459
3460/*
3461 * Unfortunately we need to handle breaks in the TX data stream, since
3462 * this is the only way to generate them on the cd1400.
3463 */
3464
Jiri Slaby60be4812006-12-08 02:38:40 -08003465static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466{
3467 if (portp->brklen == 1) {
3468 outb((COR2 + portp->uartaddr), ioaddr);
3469 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3470 (ioaddr + EREG_DATA));
3471 outb((TDR + portp->uartaddr), ioaddr);
3472 outb(ETC_CMD, (ioaddr + EREG_DATA));
3473 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3474 outb((SRER + portp->uartaddr), ioaddr);
3475 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3476 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003477 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 } else if (portp->brklen > 1) {
3479 outb((TDR + portp->uartaddr), ioaddr);
3480 outb(ETC_CMD, (ioaddr + EREG_DATA));
3481 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3482 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003483 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 } else {
3485 outb((COR2 + portp->uartaddr), ioaddr);
3486 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3487 (ioaddr + EREG_DATA));
3488 portp->brklen = 0;
3489 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003490 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491}
3492
3493/*****************************************************************************/
3494
3495/*
3496 * Transmit interrupt handler. This has gotta be fast! Handling TX
3497 * chars is pretty simple, stuff as many as possible from the TX buffer
3498 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3499 * are embedded as commands in the data stream. Oh no, had to use a goto!
3500 * This could be optimized more, will do when I get time...
3501 * In practice it is possible that interrupts are enabled but that the
3502 * port has been hung up. Need to handle not having any TX buffer here,
3503 * this is done by using the side effect that head and tail will also
3504 * be NULL if the buffer has been freed.
3505 */
3506
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003507static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003509 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 int len, stlen;
3511 char *head, *tail;
3512 unsigned char ioack, srer;
3513
Jiri Slabya0564e12006-12-08 02:38:37 -08003514 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515
3516 ioack = inb(ioaddr + EREG_TXACK);
3517 if (((ioack & panelp->ackmask) != 0) ||
3518 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3519 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3520 return;
3521 }
3522 portp = panelp->ports[(ioack >> 3)];
3523
3524/*
3525 * Unfortunately we need to handle breaks in the data stream, since
3526 * this is the only way to generate them on the cd1400. Do it now if
3527 * a break is to be sent.
3528 */
3529 if (portp->brklen != 0)
3530 if (stl_cd1400breakisr(portp, ioaddr))
3531 goto stl_txalldone;
3532
3533 head = portp->tx.head;
3534 tail = portp->tx.tail;
3535 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3536 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3537 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3538 set_bit(ASYI_TXLOW, &portp->istate);
3539 schedule_work(&portp->tqueue);
3540 }
3541
3542 if (len == 0) {
3543 outb((SRER + portp->uartaddr), ioaddr);
3544 srer = inb(ioaddr + EREG_DATA);
3545 if (srer & SRER_TXDATA) {
3546 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3547 } else {
3548 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3549 clear_bit(ASYI_TXBUSY, &portp->istate);
3550 }
3551 outb(srer, (ioaddr + EREG_DATA));
3552 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003553 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08003555 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 outb((TDR + portp->uartaddr), ioaddr);
3557 outsb((ioaddr + EREG_DATA), tail, stlen);
3558 len -= stlen;
3559 tail += stlen;
3560 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3561 tail = portp->tx.buf;
3562 if (len > 0) {
3563 outsb((ioaddr + EREG_DATA), tail, len);
3564 tail += len;
3565 }
3566 portp->tx.tail = tail;
3567 }
3568
3569stl_txalldone:
3570 outb((EOSRR + portp->uartaddr), ioaddr);
3571 outb(0, (ioaddr + EREG_DATA));
3572}
3573
3574/*****************************************************************************/
3575
3576/*
3577 * Receive character interrupt handler. Determine if we have good chars
3578 * or bad chars and then process appropriately. Good chars are easy
3579 * just shove the lot into the RX buffer and set all status byte to 0.
3580 * If a bad RX char then process as required. This routine needs to be
3581 * fast! In practice it is possible that we get an interrupt on a port
3582 * that is closed. This can happen on hangups - since they completely
3583 * shutdown a port not in user context. Need to handle this case.
3584 */
3585
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003586static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003588 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589 struct tty_struct *tty;
3590 unsigned int ioack, len, buflen;
3591 unsigned char status;
3592 char ch;
3593
Jiri Slabya0564e12006-12-08 02:38:37 -08003594 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595
3596 ioack = inb(ioaddr + EREG_RXACK);
3597 if ((ioack & panelp->ackmask) != 0) {
3598 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3599 return;
3600 }
3601 portp = panelp->ports[(ioack >> 3)];
3602 tty = portp->tty;
3603
3604 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3605 outb((RDCR + portp->uartaddr), ioaddr);
3606 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003607 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08003608 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 outb((RDSR + portp->uartaddr), ioaddr);
3610 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3611 portp->stats.rxlost += len;
3612 portp->stats.rxtotal += len;
3613 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003614 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003616 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003618 tty_prepare_flip_string(tty, &ptr, len);
3619 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620 tty_schedule_flip(tty);
3621 portp->stats.rxtotal += len;
3622 }
3623 }
3624 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3625 outb((RDSR + portp->uartaddr), ioaddr);
3626 status = inb(ioaddr + EREG_DATA);
3627 ch = inb(ioaddr + EREG_DATA);
3628 if (status & ST_PARITY)
3629 portp->stats.rxparity++;
3630 if (status & ST_FRAMING)
3631 portp->stats.rxframing++;
3632 if (status & ST_OVERRUN)
3633 portp->stats.rxoverrun++;
3634 if (status & ST_BREAK)
3635 portp->stats.rxbreaks++;
3636 if (status & ST_SCHARMASK) {
3637 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3638 portp->stats.txxon++;
3639 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3640 portp->stats.txxoff++;
3641 goto stl_rxalldone;
3642 }
Alan Cox33f0f882006-01-09 20:54:13 -08003643 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 if (portp->rxmarkmsk & status) {
3645 if (status & ST_BREAK) {
3646 status = TTY_BREAK;
3647 if (portp->flags & ASYNC_SAK) {
3648 do_SAK(tty);
3649 BRDENABLE(portp->brdnr, portp->pagenr);
3650 }
3651 } else if (status & ST_PARITY) {
3652 status = TTY_PARITY;
3653 } else if (status & ST_FRAMING) {
3654 status = TTY_FRAME;
3655 } else if(status & ST_OVERRUN) {
3656 status = TTY_OVERRUN;
3657 } else {
3658 status = 0;
3659 }
3660 } else {
3661 status = 0;
3662 }
Alan Cox33f0f882006-01-09 20:54:13 -08003663 tty_insert_flip_char(tty, ch, status);
3664 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 }
3666 } else {
3667 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3668 return;
3669 }
3670
3671stl_rxalldone:
3672 outb((EOSRR + portp->uartaddr), ioaddr);
3673 outb(0, (ioaddr + EREG_DATA));
3674}
3675
3676/*****************************************************************************/
3677
3678/*
3679 * Modem interrupt handler. The is called when the modem signal line
3680 * (DCD) has changed state. Leave most of the work to the off-level
3681 * processing routine.
3682 */
3683
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003684static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003686 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 unsigned int ioack;
3688 unsigned char misr;
3689
Jiri Slabya0564e12006-12-08 02:38:37 -08003690 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691
3692 ioack = inb(ioaddr + EREG_MDACK);
3693 if (((ioack & panelp->ackmask) != 0) ||
3694 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3695 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3696 return;
3697 }
3698 portp = panelp->ports[(ioack >> 3)];
3699
3700 outb((MISR + portp->uartaddr), ioaddr);
3701 misr = inb(ioaddr + EREG_DATA);
3702 if (misr & MISR_DCD) {
3703 set_bit(ASYI_DCDCHANGE, &portp->istate);
3704 schedule_work(&portp->tqueue);
3705 portp->stats.modem++;
3706 }
3707
3708 outb((EOSRR + portp->uartaddr), ioaddr);
3709 outb(0, (ioaddr + EREG_DATA));
3710}
3711
3712/*****************************************************************************/
3713/* SC26198 HARDWARE FUNCTIONS */
3714/*****************************************************************************/
3715
3716/*
3717 * These functions get/set/update the registers of the sc26198 UARTs.
3718 * Access to the sc26198 registers is via an address/data io port pair.
3719 * (Maybe should make this inline...)
3720 */
3721
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003722static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723{
3724 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003725 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726}
3727
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003728static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729{
3730 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3731 outb(value, (portp->ioaddr + XP_DATA));
3732}
3733
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003734static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735{
3736 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3737 if (inb(portp->ioaddr + XP_DATA) != value) {
3738 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003739 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003741 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742}
3743
3744/*****************************************************************************/
3745
3746/*
3747 * Functions to get and set the sc26198 global registers.
3748 */
3749
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003750static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751{
3752 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003753 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754}
3755
3756#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003757static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758{
3759 outb(regnr, (portp->ioaddr + XP_ADDR));
3760 outb(value, (portp->ioaddr + XP_DATA));
3761}
3762#endif
3763
3764/*****************************************************************************/
3765
3766/*
3767 * Inbitialize the UARTs in a panel. We don't care what sort of board
3768 * these ports are on - since the port io registers are almost
3769 * identical when dealing with ports.
3770 */
3771
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003772static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773{
3774 int chipmask, i;
3775 int nrchips, ioaddr;
3776
Jiri Slabya0564e12006-12-08 02:38:37 -08003777 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
3779 BRDENABLE(panelp->brdnr, panelp->pagenr);
3780
3781/*
3782 * Check that each chip is present and started up OK.
3783 */
3784 chipmask = 0;
3785 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3786 if (brdp->brdtype == BRD_ECHPCI)
3787 outb(panelp->pagenr, brdp->ioctrl);
3788
3789 for (i = 0; (i < nrchips); i++) {
3790 ioaddr = panelp->iobase + (i * 4);
3791 outb(SCCR, (ioaddr + XP_ADDR));
3792 outb(CR_RESETALL, (ioaddr + XP_DATA));
3793 outb(TSTR, (ioaddr + XP_ADDR));
3794 if (inb(ioaddr + XP_DATA) != 0) {
3795 printk("STALLION: sc26198 not responding, "
3796 "brd=%d panel=%d chip=%d\n",
3797 panelp->brdnr, panelp->panelnr, i);
3798 continue;
3799 }
3800 chipmask |= (0x1 << i);
3801 outb(GCCR, (ioaddr + XP_ADDR));
3802 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3803 outb(WDTRCR, (ioaddr + XP_ADDR));
3804 outb(0xff, (ioaddr + XP_DATA));
3805 }
3806
3807 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003808 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809}
3810
3811/*****************************************************************************/
3812
3813/*
3814 * Initialize hardware specific port registers.
3815 */
3816
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003817static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818{
Jiri Slabya0564e12006-12-08 02:38:37 -08003819 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3820 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
Jiri Slaby615e4a72006-12-08 02:38:38 -08003822 if ((brdp == NULL) || (panelp == NULL) ||
3823 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 return;
3825
3826 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3827 portp->uartaddr = (portp->portnr & 0x07) << 4;
3828 portp->pagenr = panelp->pagenr;
3829 portp->hwid = 0x1;
3830
3831 BRDENABLE(portp->brdnr, portp->pagenr);
3832 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3833 BRDDISABLE(portp->brdnr);
3834}
3835
3836/*****************************************************************************/
3837
3838/*
3839 * Set up the sc26198 registers for a port based on the termios port
3840 * settings.
3841 */
3842
Alan Cox606d0992006-12-08 02:38:45 -08003843static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003845 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 unsigned long flags;
3847 unsigned int baudrate;
3848 unsigned char mr0, mr1, mr2, clk;
3849 unsigned char imron, imroff, iopr, ipr;
3850
3851 mr0 = 0;
3852 mr1 = 0;
3853 mr2 = 0;
3854 clk = 0;
3855 iopr = 0;
3856 imron = 0;
3857 imroff = 0;
3858
3859 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003860 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 return;
3862
3863/*
3864 * Set up the RX char ignore mask with those RX error types we
3865 * can ignore.
3866 */
3867 portp->rxignoremsk = 0;
3868 if (tiosp->c_iflag & IGNPAR)
3869 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3870 SR_RXOVERRUN);
3871 if (tiosp->c_iflag & IGNBRK)
3872 portp->rxignoremsk |= SR_RXBREAK;
3873
3874 portp->rxmarkmsk = SR_RXOVERRUN;
3875 if (tiosp->c_iflag & (INPCK | PARMRK))
3876 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3877 if (tiosp->c_iflag & BRKINT)
3878 portp->rxmarkmsk |= SR_RXBREAK;
3879
3880/*
3881 * Go through the char size, parity and stop bits and set all the
3882 * option register appropriately.
3883 */
3884 switch (tiosp->c_cflag & CSIZE) {
3885 case CS5:
3886 mr1 |= MR1_CS5;
3887 break;
3888 case CS6:
3889 mr1 |= MR1_CS6;
3890 break;
3891 case CS7:
3892 mr1 |= MR1_CS7;
3893 break;
3894 default:
3895 mr1 |= MR1_CS8;
3896 break;
3897 }
3898
3899 if (tiosp->c_cflag & CSTOPB)
3900 mr2 |= MR2_STOP2;
3901 else
3902 mr2 |= MR2_STOP1;
3903
3904 if (tiosp->c_cflag & PARENB) {
3905 if (tiosp->c_cflag & PARODD)
3906 mr1 |= (MR1_PARENB | MR1_PARODD);
3907 else
3908 mr1 |= (MR1_PARENB | MR1_PAREVEN);
3909 } else {
3910 mr1 |= MR1_PARNONE;
3911 }
3912
3913 mr1 |= MR1_ERRBLOCK;
3914
3915/*
3916 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3917 * space for hardware flow control and the like. This should be set to
3918 * VMIN.
3919 */
3920 mr2 |= MR2_RXFIFOHALF;
3921
3922/*
3923 * Calculate the baud rate timers. For now we will just assume that
3924 * the input and output baud are the same. The sc26198 has a fixed
3925 * baud rate table, so only discrete baud rates possible.
3926 */
3927 baudrate = tiosp->c_cflag & CBAUD;
3928 if (baudrate & CBAUDEX) {
3929 baudrate &= ~CBAUDEX;
3930 if ((baudrate < 1) || (baudrate > 4))
3931 tiosp->c_cflag &= ~CBAUDEX;
3932 else
3933 baudrate += 15;
3934 }
3935 baudrate = stl_baudrates[baudrate];
3936 if ((tiosp->c_cflag & CBAUD) == B38400) {
3937 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3938 baudrate = 57600;
3939 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3940 baudrate = 115200;
3941 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3942 baudrate = 230400;
3943 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3944 baudrate = 460800;
3945 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3946 baudrate = (portp->baud_base / portp->custom_divisor);
3947 }
3948 if (baudrate > STL_SC26198MAXBAUD)
3949 baudrate = STL_SC26198MAXBAUD;
3950
3951 if (baudrate > 0) {
3952 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
3953 if (baudrate <= sc26198_baudtable[clk])
3954 break;
3955 }
3956 }
3957
3958/*
3959 * Check what form of modem signaling is required and set it up.
3960 */
3961 if (tiosp->c_cflag & CLOCAL) {
3962 portp->flags &= ~ASYNC_CHECK_CD;
3963 } else {
3964 iopr |= IOPR_DCDCOS;
3965 imron |= IR_IOPORT;
3966 portp->flags |= ASYNC_CHECK_CD;
3967 }
3968
3969/*
3970 * Setup sc26198 enhanced modes if we can. In particular we want to
3971 * handle as much of the flow control as possible automatically. As
3972 * well as saving a few CPU cycles it will also greatly improve flow
3973 * control reliability.
3974 */
3975 if (tiosp->c_iflag & IXON) {
3976 mr0 |= MR0_SWFTX | MR0_SWFT;
3977 imron |= IR_XONXOFF;
3978 } else {
3979 imroff |= IR_XONXOFF;
3980 }
3981 if (tiosp->c_iflag & IXOFF)
3982 mr0 |= MR0_SWFRX;
3983
3984 if (tiosp->c_cflag & CRTSCTS) {
3985 mr2 |= MR2_AUTOCTS;
3986 mr1 |= MR1_AUTORTS;
3987 }
3988
3989/*
3990 * All sc26198 register values calculated so go through and set
3991 * them all up.
3992 */
3993
Jiri Slabya0564e12006-12-08 02:38:37 -08003994 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003996 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3997 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3998 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4000 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001
Alan Coxb65b5b52006-06-27 02:54:05 -07004002 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 BRDENABLE(portp->brdnr, portp->pagenr);
4004 stl_sc26198setreg(portp, IMR, 0);
4005 stl_sc26198updatereg(portp, MR0, mr0);
4006 stl_sc26198updatereg(portp, MR1, mr1);
4007 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4008 stl_sc26198updatereg(portp, MR2, mr2);
4009 stl_sc26198updatereg(portp, IOPIOR,
4010 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4011
4012 if (baudrate > 0) {
4013 stl_sc26198setreg(portp, TXCSR, clk);
4014 stl_sc26198setreg(portp, RXCSR, clk);
4015 }
4016
4017 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4018 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4019
4020 ipr = stl_sc26198getreg(portp, IPR);
4021 if (ipr & IPR_DCD)
4022 portp->sigs &= ~TIOCM_CD;
4023 else
4024 portp->sigs |= TIOCM_CD;
4025
4026 portp->imr = (portp->imr & ~imroff) | imron;
4027 stl_sc26198setreg(portp, IMR, portp->imr);
4028 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004029 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030}
4031
4032/*****************************************************************************/
4033
4034/*
4035 * Set the state of the DTR and RTS signals.
4036 */
4037
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004038static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039{
4040 unsigned char iopioron, iopioroff;
4041 unsigned long flags;
4042
Jiri Slabya0564e12006-12-08 02:38:37 -08004043 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4044 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
4046 iopioron = 0;
4047 iopioroff = 0;
4048 if (dtr == 0)
4049 iopioroff |= IPR_DTR;
4050 else if (dtr > 0)
4051 iopioron |= IPR_DTR;
4052 if (rts == 0)
4053 iopioroff |= IPR_RTS;
4054 else if (rts > 0)
4055 iopioron |= IPR_RTS;
4056
Alan Coxb65b5b52006-06-27 02:54:05 -07004057 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058 BRDENABLE(portp->brdnr, portp->pagenr);
4059 stl_sc26198setreg(portp, IOPIOR,
4060 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4061 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004062 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063}
4064
4065/*****************************************************************************/
4066
4067/*
4068 * Return the state of the signals.
4069 */
4070
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004071static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072{
4073 unsigned char ipr;
4074 unsigned long flags;
4075 int sigs;
4076
Jiri Slabya0564e12006-12-08 02:38:37 -08004077 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Alan Coxb65b5b52006-06-27 02:54:05 -07004079 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 BRDENABLE(portp->brdnr, portp->pagenr);
4081 ipr = stl_sc26198getreg(portp, IPR);
4082 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004083 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084
4085 sigs = 0;
4086 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4087 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4088 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4089 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4090 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004091 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092}
4093
4094/*****************************************************************************/
4095
4096/*
4097 * Enable/Disable the Transmitter and/or Receiver.
4098 */
4099
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004100static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101{
4102 unsigned char ccr;
4103 unsigned long flags;
4104
Jiri Slabya0564e12006-12-08 02:38:37 -08004105 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
4107 ccr = portp->crenable;
4108 if (tx == 0)
4109 ccr &= ~CR_TXENABLE;
4110 else if (tx > 0)
4111 ccr |= CR_TXENABLE;
4112 if (rx == 0)
4113 ccr &= ~CR_RXENABLE;
4114 else if (rx > 0)
4115 ccr |= CR_RXENABLE;
4116
Alan Coxb65b5b52006-06-27 02:54:05 -07004117 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 BRDENABLE(portp->brdnr, portp->pagenr);
4119 stl_sc26198setreg(portp, SCCR, ccr);
4120 BRDDISABLE(portp->brdnr);
4121 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004122 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123}
4124
4125/*****************************************************************************/
4126
4127/*
4128 * Start/stop the Transmitter and/or Receiver.
4129 */
4130
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004131static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132{
4133 unsigned char imr;
4134 unsigned long flags;
4135
Jiri Slabya0564e12006-12-08 02:38:37 -08004136 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137
4138 imr = portp->imr;
4139 if (tx == 0)
4140 imr &= ~IR_TXRDY;
4141 else if (tx == 1)
4142 imr |= IR_TXRDY;
4143 if (rx == 0)
4144 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4145 else if (rx > 0)
4146 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4147
Alan Coxb65b5b52006-06-27 02:54:05 -07004148 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 BRDENABLE(portp->brdnr, portp->pagenr);
4150 stl_sc26198setreg(portp, IMR, imr);
4151 BRDDISABLE(portp->brdnr);
4152 portp->imr = imr;
4153 if (tx > 0)
4154 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004155 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156}
4157
4158/*****************************************************************************/
4159
4160/*
4161 * Disable all interrupts from this port.
4162 */
4163
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004164static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165{
4166 unsigned long flags;
4167
Jiri Slabya0564e12006-12-08 02:38:37 -08004168 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169
Alan Coxb65b5b52006-06-27 02:54:05 -07004170 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 BRDENABLE(portp->brdnr, portp->pagenr);
4172 portp->imr = 0;
4173 stl_sc26198setreg(portp, IMR, 0);
4174 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004175 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176}
4177
4178/*****************************************************************************/
4179
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004180static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181{
4182 unsigned long flags;
4183
Jiri Slabya0564e12006-12-08 02:38:37 -08004184 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185
Alan Coxb65b5b52006-06-27 02:54:05 -07004186 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187 BRDENABLE(portp->brdnr, portp->pagenr);
4188 if (len == 1) {
4189 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4190 portp->stats.txbreaks++;
4191 } else {
4192 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4193 }
4194 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004195 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196}
4197
4198/*****************************************************************************/
4199
4200/*
4201 * Take flow control actions...
4202 */
4203
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004204static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205{
4206 struct tty_struct *tty;
4207 unsigned long flags;
4208 unsigned char mr0;
4209
Jiri Slabya0564e12006-12-08 02:38:37 -08004210 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211
Jiri Slaby615e4a72006-12-08 02:38:38 -08004212 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 return;
4214 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004215 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216 return;
4217
Alan Coxb65b5b52006-06-27 02:54:05 -07004218 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219 BRDENABLE(portp->brdnr, portp->pagenr);
4220
4221 if (state) {
4222 if (tty->termios->c_iflag & IXOFF) {
4223 mr0 = stl_sc26198getreg(portp, MR0);
4224 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4225 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4226 mr0 |= MR0_SWFRX;
4227 portp->stats.rxxon++;
4228 stl_sc26198wait(portp);
4229 stl_sc26198setreg(portp, MR0, mr0);
4230 }
4231/*
4232 * Question: should we return RTS to what it was before? It may
4233 * have been set by an ioctl... Suppose not, since if you have
4234 * hardware flow control set then it is pretty silly to go and
4235 * set the RTS line by hand.
4236 */
4237 if (tty->termios->c_cflag & CRTSCTS) {
4238 stl_sc26198setreg(portp, MR1,
4239 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4240 stl_sc26198setreg(portp, IOPIOR,
4241 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4242 portp->stats.rxrtson++;
4243 }
4244 } else {
4245 if (tty->termios->c_iflag & IXOFF) {
4246 mr0 = stl_sc26198getreg(portp, MR0);
4247 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4248 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4249 mr0 &= ~MR0_SWFRX;
4250 portp->stats.rxxoff++;
4251 stl_sc26198wait(portp);
4252 stl_sc26198setreg(portp, MR0, mr0);
4253 }
4254 if (tty->termios->c_cflag & CRTSCTS) {
4255 stl_sc26198setreg(portp, MR1,
4256 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4257 stl_sc26198setreg(portp, IOPIOR,
4258 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4259 portp->stats.rxrtsoff++;
4260 }
4261 }
4262
4263 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004264 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265}
4266
4267/*****************************************************************************/
4268
4269/*
4270 * Send a flow control character.
4271 */
4272
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004273static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274{
4275 struct tty_struct *tty;
4276 unsigned long flags;
4277 unsigned char mr0;
4278
Jiri Slabya0564e12006-12-08 02:38:37 -08004279 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280
Jiri Slaby615e4a72006-12-08 02:38:38 -08004281 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 return;
4283 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004284 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285 return;
4286
Alan Coxb65b5b52006-06-27 02:54:05 -07004287 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 BRDENABLE(portp->brdnr, portp->pagenr);
4289 if (state) {
4290 mr0 = stl_sc26198getreg(portp, MR0);
4291 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4292 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4293 mr0 |= MR0_SWFRX;
4294 portp->stats.rxxon++;
4295 stl_sc26198wait(portp);
4296 stl_sc26198setreg(portp, MR0, mr0);
4297 } else {
4298 mr0 = stl_sc26198getreg(portp, MR0);
4299 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4300 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4301 mr0 &= ~MR0_SWFRX;
4302 portp->stats.rxxoff++;
4303 stl_sc26198wait(portp);
4304 stl_sc26198setreg(portp, MR0, mr0);
4305 }
4306 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004307 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308}
4309
4310/*****************************************************************************/
4311
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004312static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313{
4314 unsigned long flags;
4315
Jiri Slabya0564e12006-12-08 02:38:37 -08004316 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
Jiri Slaby615e4a72006-12-08 02:38:38 -08004318 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 return;
4320
Alan Coxb65b5b52006-06-27 02:54:05 -07004321 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322 BRDENABLE(portp->brdnr, portp->pagenr);
4323 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4324 stl_sc26198setreg(portp, SCCR, portp->crenable);
4325 BRDDISABLE(portp->brdnr);
4326 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004327 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328}
4329
4330/*****************************************************************************/
4331
4332/*
4333 * Return the current state of data flow on this port. This is only
4334 * really interresting when determining if data has fully completed
4335 * transmission or not... The sc26198 interrupt scheme cannot
4336 * determine when all data has actually drained, so we need to
4337 * check the port statusy register to be sure.
4338 */
4339
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004340static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341{
4342 unsigned long flags;
4343 unsigned char sr;
4344
Jiri Slabya0564e12006-12-08 02:38:37 -08004345 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Jiri Slaby615e4a72006-12-08 02:38:38 -08004347 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004348 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004350 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351
Alan Coxb65b5b52006-06-27 02:54:05 -07004352 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353 BRDENABLE(portp->brdnr, portp->pagenr);
4354 sr = stl_sc26198getreg(portp, SR);
4355 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004356 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357
Jesper Juhl014c2542006-01-15 02:37:08 +01004358 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359}
4360
4361/*****************************************************************************/
4362
4363/*
4364 * Delay for a small amount of time, to give the sc26198 a chance
4365 * to process a command...
4366 */
4367
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004368static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369{
4370 int i;
4371
Jiri Slabya0564e12006-12-08 02:38:37 -08004372 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373
Jiri Slaby615e4a72006-12-08 02:38:38 -08004374 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 return;
4376
4377 for (i = 0; (i < 20); i++)
4378 stl_sc26198getglobreg(portp, TSTR);
4379}
4380
4381/*****************************************************************************/
4382
4383/*
4384 * If we are TX flow controlled and in IXANY mode then we may
4385 * need to unflow control here. We gotta do this because of the
4386 * automatic flow control modes of the sc26198.
4387 */
4388
Jiri Slaby60be4812006-12-08 02:38:40 -08004389static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390{
4391 unsigned char mr0;
4392
4393 mr0 = stl_sc26198getreg(portp, MR0);
4394 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4395 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4396 stl_sc26198wait(portp);
4397 stl_sc26198setreg(portp, MR0, mr0);
4398 clear_bit(ASYI_TXFLOWED, &portp->istate);
4399}
4400
4401/*****************************************************************************/
4402
4403/*
4404 * Interrupt service routine for sc26198 panels.
4405 */
4406
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004407static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004409 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410 unsigned int iack;
4411
Alan Coxb65b5b52006-06-27 02:54:05 -07004412 spin_lock(&brd_lock);
4413
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414/*
4415 * Work around bug in sc26198 chip... Cannot have A6 address
4416 * line of UART high, else iack will be returned as 0.
4417 */
4418 outb(0, (iobase + 1));
4419
4420 iack = inb(iobase + XP_IACK);
4421 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4422
4423 if (iack & IVR_RXDATA)
4424 stl_sc26198rxisr(portp, iack);
4425 else if (iack & IVR_TXDATA)
4426 stl_sc26198txisr(portp);
4427 else
4428 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004429
4430 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431}
4432
4433/*****************************************************************************/
4434
4435/*
4436 * Transmit interrupt handler. This has gotta be fast! Handling TX
4437 * chars is pretty simple, stuff as many as possible from the TX buffer
4438 * into the sc26198 FIFO.
4439 * In practice it is possible that interrupts are enabled but that the
4440 * port has been hung up. Need to handle not having any TX buffer here,
4441 * this is done by using the side effect that head and tail will also
4442 * be NULL if the buffer has been freed.
4443 */
4444
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004445static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446{
4447 unsigned int ioaddr;
4448 unsigned char mr0;
4449 int len, stlen;
4450 char *head, *tail;
4451
Jiri Slabya0564e12006-12-08 02:38:37 -08004452 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453
4454 ioaddr = portp->ioaddr;
4455 head = portp->tx.head;
4456 tail = portp->tx.tail;
4457 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4458 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4459 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4460 set_bit(ASYI_TXLOW, &portp->istate);
4461 schedule_work(&portp->tqueue);
4462 }
4463
4464 if (len == 0) {
4465 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4466 mr0 = inb(ioaddr + XP_DATA);
4467 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4468 portp->imr &= ~IR_TXRDY;
4469 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4470 outb(portp->imr, (ioaddr + XP_DATA));
4471 clear_bit(ASYI_TXBUSY, &portp->istate);
4472 } else {
4473 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4474 outb(mr0, (ioaddr + XP_DATA));
4475 }
4476 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004477 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08004479 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480 outb(GTXFIFO, (ioaddr + XP_ADDR));
4481 outsb((ioaddr + XP_DATA), tail, stlen);
4482 len -= stlen;
4483 tail += stlen;
4484 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4485 tail = portp->tx.buf;
4486 if (len > 0) {
4487 outsb((ioaddr + XP_DATA), tail, len);
4488 tail += len;
4489 }
4490 portp->tx.tail = tail;
4491 }
4492}
4493
4494/*****************************************************************************/
4495
4496/*
4497 * Receive character interrupt handler. Determine if we have good chars
4498 * or bad chars and then process appropriately. Good chars are easy
4499 * just shove the lot into the RX buffer and set all status byte to 0.
4500 * If a bad RX char then process as required. This routine needs to be
4501 * fast! In practice it is possible that we get an interrupt on a port
4502 * that is closed. This can happen on hangups - since they completely
4503 * shutdown a port not in user context. Need to handle this case.
4504 */
4505
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004506static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507{
4508 struct tty_struct *tty;
4509 unsigned int len, buflen, ioaddr;
4510
Jiri Slabya0564e12006-12-08 02:38:37 -08004511 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512
4513 tty = portp->tty;
4514 ioaddr = portp->ioaddr;
4515 outb(GIBCR, (ioaddr + XP_ADDR));
4516 len = inb(ioaddr + XP_DATA) + 1;
4517
4518 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004519 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08004520 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 outb(GRXFIFO, (ioaddr + XP_ADDR));
4522 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4523 portp->stats.rxlost += len;
4524 portp->stats.rxtotal += len;
4525 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004526 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004528 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004530 tty_prepare_flip_string(tty, &ptr, len);
4531 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 tty_schedule_flip(tty);
4533 portp->stats.rxtotal += len;
4534 }
4535 }
4536 } else {
4537 stl_sc26198rxbadchars(portp);
4538 }
4539
4540/*
4541 * If we are TX flow controlled and in IXANY mode then we may need
4542 * to unflow control here. We gotta do this because of the automatic
4543 * flow control modes of the sc26198.
4544 */
4545 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004546 if ((tty != NULL) &&
4547 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548 (tty->termios->c_iflag & IXANY)) {
4549 stl_sc26198txunflow(portp, tty);
4550 }
4551 }
4552}
4553
4554/*****************************************************************************/
4555
4556/*
4557 * Process an RX bad character.
4558 */
4559
Jiri Slaby60be4812006-12-08 02:38:40 -08004560static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561{
4562 struct tty_struct *tty;
4563 unsigned int ioaddr;
4564
4565 tty = portp->tty;
4566 ioaddr = portp->ioaddr;
4567
4568 if (status & SR_RXPARITY)
4569 portp->stats.rxparity++;
4570 if (status & SR_RXFRAMING)
4571 portp->stats.rxframing++;
4572 if (status & SR_RXOVERRUN)
4573 portp->stats.rxoverrun++;
4574 if (status & SR_RXBREAK)
4575 portp->stats.rxbreaks++;
4576
Jiri Slaby615e4a72006-12-08 02:38:38 -08004577 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578 ((portp->rxignoremsk & status) == 0)) {
4579 if (portp->rxmarkmsk & status) {
4580 if (status & SR_RXBREAK) {
4581 status = TTY_BREAK;
4582 if (portp->flags & ASYNC_SAK) {
4583 do_SAK(tty);
4584 BRDENABLE(portp->brdnr, portp->pagenr);
4585 }
4586 } else if (status & SR_RXPARITY) {
4587 status = TTY_PARITY;
4588 } else if (status & SR_RXFRAMING) {
4589 status = TTY_FRAME;
4590 } else if(status & SR_RXOVERRUN) {
4591 status = TTY_OVERRUN;
4592 } else {
4593 status = 0;
4594 }
4595 } else {
4596 status = 0;
4597 }
4598
Alan Cox33f0f882006-01-09 20:54:13 -08004599 tty_insert_flip_char(tty, ch, status);
4600 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601
4602 if (status == 0)
4603 portp->stats.rxtotal++;
4604 }
4605}
4606
4607/*****************************************************************************/
4608
4609/*
4610 * Process all characters in the RX FIFO of the UART. Check all char
4611 * status bytes as well, and process as required. We need to check
4612 * all bytes in the FIFO, in case some more enter the FIFO while we
4613 * are here. To get the exact character error type we need to switch
4614 * into CHAR error mode (that is why we need to make sure we empty
4615 * the FIFO).
4616 */
4617
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004618static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004619{
4620 unsigned char status, mr1;
4621 char ch;
4622
4623/*
4624 * To get the precise error type for each character we must switch
4625 * back into CHAR error mode.
4626 */
4627 mr1 = stl_sc26198getreg(portp, MR1);
4628 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4629
4630 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4631 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4632 ch = stl_sc26198getreg(portp, RXFIFO);
4633 stl_sc26198rxbadch(portp, status, ch);
4634 }
4635
4636/*
4637 * To get correct interrupt class we must switch back into BLOCK
4638 * error mode.
4639 */
4640 stl_sc26198setreg(portp, MR1, mr1);
4641}
4642
4643/*****************************************************************************/
4644
4645/*
4646 * Other interrupt handler. This includes modem signals, flow
4647 * control actions, etc. Most stuff is left to off-level interrupt
4648 * processing time.
4649 */
4650
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004651static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652{
4653 unsigned char cir, ipr, xisr;
4654
Jiri Slabya0564e12006-12-08 02:38:37 -08004655 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656
4657 cir = stl_sc26198getglobreg(portp, CIR);
4658
4659 switch (cir & CIR_SUBTYPEMASK) {
4660 case CIR_SUBCOS:
4661 ipr = stl_sc26198getreg(portp, IPR);
4662 if (ipr & IPR_DCDCHANGE) {
4663 set_bit(ASYI_DCDCHANGE, &portp->istate);
4664 schedule_work(&portp->tqueue);
4665 portp->stats.modem++;
4666 }
4667 break;
4668 case CIR_SUBXONXOFF:
4669 xisr = stl_sc26198getreg(portp, XISR);
4670 if (xisr & XISR_RXXONGOT) {
4671 set_bit(ASYI_TXFLOWED, &portp->istate);
4672 portp->stats.txxoff++;
4673 }
4674 if (xisr & XISR_RXXOFFGOT) {
4675 clear_bit(ASYI_TXFLOWED, &portp->istate);
4676 portp->stats.txxon++;
4677 }
4678 break;
4679 case CIR_SUBBREAK:
4680 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4681 stl_sc26198rxbadchars(portp);
4682 break;
4683 default:
4684 break;
4685 }
4686}
4687
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004688static void stl_free_isabrds(void)
4689{
4690 struct stlbrd *brdp;
4691 unsigned int i;
4692
4693 for (i = 0; i < stl_nrbrds; i++) {
4694 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4695 continue;
4696
4697 free_irq(brdp->irq, brdp);
4698
4699 stl_cleanup_panels(brdp);
4700
4701 release_region(brdp->ioaddr1, brdp->iosize1);
4702 if (brdp->iosize2 > 0)
4703 release_region(brdp->ioaddr2, brdp->iosize2);
4704
4705 kfree(brdp);
4706 stl_brds[i] = NULL;
4707 }
4708}
4709
Jiri Slaby23b85a12006-12-08 02:38:40 -08004710/*
4711 * Loadable module initialization stuff.
4712 */
4713static int __init stallion_module_init(void)
4714{
Jiri Slaby843b5682006-12-08 02:39:12 -08004715 struct stlbrd *brdp;
4716 struct stlconf conf;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004717 unsigned int i;
4718 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004719
4720 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4721
4722 spin_lock_init(&stallion_lock);
4723 spin_lock_init(&brd_lock);
4724
Jiri Slaby843b5682006-12-08 02:39:12 -08004725/*
4726 * Find any dynamically supported boards. That is via module load
4727 * line options.
4728 */
4729 for (i = stl_nrbrds; i < stl_nargs; i++) {
4730 memset(&conf, 0, sizeof(conf));
4731 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4732 continue;
4733 if ((brdp = stl_allocbrd()) == NULL)
4734 continue;
4735 brdp->brdnr = i;
4736 brdp->brdtype = conf.brdtype;
4737 brdp->ioaddr1 = conf.ioaddr1;
4738 brdp->ioaddr2 = conf.ioaddr2;
4739 brdp->irq = conf.irq;
4740 brdp->irqtype = conf.irqtype;
4741 if (stl_brdinit(brdp))
4742 kfree(brdp);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004743 else {
4744 stl_brds[brdp->brdnr] = brdp;
Jiri Slaby843b5682006-12-08 02:39:12 -08004745 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004746 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004747 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004748
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004749 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004750 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004751 if (retval && stl_nrbrds == 0)
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004752 goto err;
4753
Jiri Slaby23b85a12006-12-08 02:38:40 -08004754 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004755 if (!stl_serial) {
4756 retval = -ENOMEM;
4757 goto err_pcidr;
4758 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004759
4760/*
4761 * Set up a character driver for per board stuff. This is mainly used
4762 * to do stats ioctls on the ports.
4763 */
4764 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4765 printk("STALLION: failed to register serial board device\n");
4766
4767 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004768 if (IS_ERR(stallion_class)) {
4769 retval = PTR_ERR(stallion_class);
4770 goto err_reg;
4771 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004772 for (i = 0; i < 4; i++)
4773 class_device_create(stallion_class, NULL,
4774 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4775 "staliomem%d", i);
4776
4777 stl_serial->owner = THIS_MODULE;
4778 stl_serial->driver_name = stl_drvname;
4779 stl_serial->name = "ttyE";
4780 stl_serial->major = STL_SERIALMAJOR;
4781 stl_serial->minor_start = 0;
4782 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4783 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4784 stl_serial->init_termios = stl_deftermios;
4785 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4786 tty_set_operations(stl_serial, &stl_ops);
4787
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004788 retval = tty_register_driver(stl_serial);
4789 if (retval) {
Jiri Slaby23b85a12006-12-08 02:38:40 -08004790 printk("STALLION: failed to register serial driver\n");
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004791 goto err_clsdev;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004792 }
4793
4794 return 0;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004795err_clsdev:
4796 for (i = 0; i < 4; i++)
4797 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4798 class_destroy(stallion_class);
4799err_reg:
4800 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
4801 put_tty_driver(stl_serial);
4802err_pcidr:
4803 pci_unregister_driver(&stl_pcidriver);
4804 stl_free_isabrds();
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004805err:
4806 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004807}
4808
4809static void __exit stallion_module_exit(void)
4810{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004811 int i;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004812
4813 pr_debug("cleanup_module()\n");
4814
4815 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4816 stl_drvversion);
4817
4818/*
4819 * Free up all allocated resources used by the ports. This includes
4820 * memory and interrupts. As part of this process we will also do
4821 * a hangup on every open port - to try to flush out any processes
4822 * hanging onto ports.
4823 */
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004824 tty_unregister_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004825 put_tty_driver(stl_serial);
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004826
Jiri Slaby23b85a12006-12-08 02:38:40 -08004827 for (i = 0; i < 4; i++)
4828 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4829 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4830 printk("STALLION: failed to un-register serial memory device, "
4831 "errno=%d\n", -i);
4832 class_destroy(stallion_class);
4833
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004834 pci_unregister_driver(&stl_pcidriver);
4835
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004836 stl_free_isabrds();
Jiri Slaby23b85a12006-12-08 02:38:40 -08004837}
4838
4839module_init(stallion_module_init);
4840module_exit(stallion_module_exit);
4841
4842MODULE_AUTHOR("Greg Ungerer");
4843MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4844MODULE_LICENSE("GPL");