blob: 8c73ccb8830ff685e8e21bb2dc6a6413e6a813b5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*****************************************************************************/
2
3/*
4 * stallion.c -- stallion multiport serial driver.
5 *
6 * Copyright (C) 1996-1999 Stallion Technologies
7 * Copyright (C) 1994-1996 Greg Ungerer.
8 *
9 * This code is loosely based on the Linux serial driver, written by
10 * Linus Torvalds, Theodore T'so and others.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27/*****************************************************************************/
28
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/interrupt.h>
32#include <linux/tty.h>
33#include <linux/tty_flip.h>
34#include <linux/serial.h>
35#include <linux/cd1400.h>
36#include <linux/sc26198.h>
37#include <linux/comstats.h>
38#include <linux/stallion.h>
39#include <linux/ioport.h>
40#include <linux/init.h>
41#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/device.h>
43#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080044#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46#include <asm/io.h>
47#include <asm/uaccess.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51/*****************************************************************************/
52
53/*
54 * Define different board types. Use the standard Stallion "assigned"
55 * board numbers. Boards supported in this driver are abbreviated as
56 * EIO = EasyIO and ECH = EasyConnection 8/32.
57 */
58#define BRD_EASYIO 20
59#define BRD_ECH 21
60#define BRD_ECHMC 22
61#define BRD_ECHPCI 26
62#define BRD_ECH64PCI 27
63#define BRD_EASYIOPCI 28
64
Jiri Slaby843b5682006-12-08 02:39:12 -080065struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080066 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 int ioaddr1;
68 int ioaddr2;
69 unsigned long memaddr;
70 int irq;
71 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072};
73
Jiri Slaby843b5682006-12-08 02:39:12 -080074static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76/*****************************************************************************/
77
78/*
79 * Define some important driver characteristics. Device major numbers
80 * allocated as per Linux Device Registry.
81 */
82#ifndef STL_SIOMEMMAJOR
83#define STL_SIOMEMMAJOR 28
84#endif
85#ifndef STL_SERIALMAJOR
86#define STL_SERIALMAJOR 24
87#endif
88#ifndef STL_CALLOUTMAJOR
89#define STL_CALLOUTMAJOR 25
90#endif
91
92/*
93 * Set the TX buffer size. Bigger is better, but we don't want
94 * to chew too much memory with buffers!
95 */
96#define STL_TXBUFLOW 512
97#define STL_TXBUFSIZE 4096
98
99/*****************************************************************************/
100
101/*
102 * Define our local driver identity first. Set up stuff to deal with
103 * all the local structures required by a serial tty driver.
104 */
105static char *stl_drvtitle = "Stallion Multiport Serial Driver";
106static char *stl_drvname = "stallion";
107static char *stl_drvversion = "5.6.0";
108
109static struct tty_driver *stl_serial;
110
111/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * Define a local default termios struct. All ports will be created
113 * with this termios initially. Basically all it defines is a raw port
114 * at 9600, 8 data bits, 1 stop bit.
115 */
Alan Cox606d0992006-12-08 02:38:45 -0800116static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
118 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800119 .c_ispeed = 9600,
120 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121};
122
123/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 * Define global place to put buffer overflow characters.
125 */
126static char stl_unwanted[SC26198_RXFIFOSIZE];
127
128/*****************************************************************************/
129
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800130static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800131static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133/*
134 * Per board state flags. Used with the state field of the board struct.
135 * Not really much here!
136 */
137#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800138#define STL_PROBED 0x2
139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141/*
142 * Define the port structure istate flags. These set of flags are
143 * modified at interrupt time - so setting and reseting them needs
144 * to be atomic. Use the bit clear/setting routines for this.
145 */
146#define ASYI_TXBUSY 1
147#define ASYI_TXLOW 2
148#define ASYI_DCDCHANGE 3
149#define ASYI_TXFLOWED 4
150
151/*
152 * Define an array of board names as printable strings. Handy for
153 * referencing boards when printing trace and stuff.
154 */
155static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800156 NULL,
157 NULL,
158 NULL,
159 NULL,
160 NULL,
161 NULL,
162 NULL,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 "EasyIO",
177 "EC8/32-AT",
178 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800179 NULL,
180 NULL,
181 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 "EC8/32-PCI",
183 "EC8/64-PCI",
184 "EasyIO-PCI",
185};
186
187/*****************************************************************************/
188
189/*
190 * Define some string labels for arguments passed from the module
191 * load line. These allow for easy board definitions, and easy
192 * modification of the io, memory and irq resoucres.
193 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800194static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195static char *board0[4];
196static char *board1[4];
197static char *board2[4];
198static char *board3[4];
199
200static char **stl_brdsp[] = {
201 (char **) &board0,
202 (char **) &board1,
203 (char **) &board2,
204 (char **) &board3
205};
206
207/*
208 * Define a set of common board names, and types. This is used to
209 * parse any module arguments.
210 */
211
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800212static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 char *name;
214 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800215} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 { "easyio", BRD_EASYIO },
217 { "eio", BRD_EASYIO },
218 { "20", BRD_EASYIO },
219 { "ec8/32", BRD_ECH },
220 { "ec8/32-at", BRD_ECH },
221 { "ec8/32-isa", BRD_ECH },
222 { "ech", BRD_ECH },
223 { "echat", BRD_ECH },
224 { "21", BRD_ECH },
225 { "ec8/32-mc", BRD_ECHMC },
226 { "ec8/32-mca", BRD_ECHMC },
227 { "echmc", BRD_ECHMC },
228 { "echmca", BRD_ECHMC },
229 { "22", BRD_ECHMC },
230 { "ec8/32-pc", BRD_ECHPCI },
231 { "ec8/32-pci", BRD_ECHPCI },
232 { "26", BRD_ECHPCI },
233 { "ec8/64-pc", BRD_ECH64PCI },
234 { "ec8/64-pci", BRD_ECH64PCI },
235 { "ech-pci", BRD_ECH64PCI },
236 { "echpci", BRD_ECH64PCI },
237 { "echpc", BRD_ECH64PCI },
238 { "27", BRD_ECH64PCI },
239 { "easyio-pc", BRD_EASYIOPCI },
240 { "easyio-pci", BRD_EASYIOPCI },
241 { "eio-pci", BRD_EASYIOPCI },
242 { "eiopci", BRD_EASYIOPCI },
243 { "28", BRD_EASYIOPCI },
244};
245
246/*
247 * Define the module agruments.
248 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
250module_param_array(board0, charp, &stl_nargs, 0);
251MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
252module_param_array(board1, charp, &stl_nargs, 0);
253MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
254module_param_array(board2, charp, &stl_nargs, 0);
255MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
256module_param_array(board3, charp, &stl_nargs, 0);
257MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
258
259/*****************************************************************************/
260
261/*
262 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
263 * to the directly accessible io ports of these boards (not the uarts -
264 * they are in cd1400.h and sc26198.h).
265 */
266#define EIO_8PORTRS 0x04
267#define EIO_4PORTRS 0x05
268#define EIO_8PORTDI 0x00
269#define EIO_8PORTM 0x06
270#define EIO_MK3 0x03
271#define EIO_IDBITMASK 0x07
272
273#define EIO_BRDMASK 0xf0
274#define ID_BRD4 0x10
275#define ID_BRD8 0x20
276#define ID_BRD16 0x30
277
278#define EIO_INTRPEND 0x08
279#define EIO_INTEDGE 0x00
280#define EIO_INTLEVEL 0x08
281#define EIO_0WS 0x10
282
283#define ECH_ID 0xa0
284#define ECH_IDBITMASK 0xe0
285#define ECH_BRDENABLE 0x08
286#define ECH_BRDDISABLE 0x00
287#define ECH_INTENABLE 0x01
288#define ECH_INTDISABLE 0x00
289#define ECH_INTLEVEL 0x02
290#define ECH_INTEDGE 0x00
291#define ECH_INTRPEND 0x01
292#define ECH_BRDRESET 0x01
293
294#define ECHMC_INTENABLE 0x01
295#define ECHMC_BRDRESET 0x02
296
297#define ECH_PNLSTATUS 2
298#define ECH_PNL16PORT 0x20
299#define ECH_PNLIDMASK 0x07
300#define ECH_PNLXPID 0x40
301#define ECH_PNLINTRPEND 0x80
302
303#define ECH_ADDR2MASK 0x1e0
304
305/*
306 * Define the vector mapping bits for the programmable interrupt board
307 * hardware. These bits encode the interrupt for the board to use - it
308 * is software selectable (except the EIO-8M).
309 */
310static unsigned char stl_vecmap[] = {
311 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
312 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
313};
314
315/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700316 * Lock ordering is that you may not take stallion_lock holding
317 * brd_lock.
318 */
319
320static spinlock_t brd_lock; /* Guard the board mapping */
321static spinlock_t stallion_lock; /* Guard the tty driver */
322
323/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 * Set up enable and disable macros for the ECH boards. They require
325 * the secondary io address space to be activated and deactivated.
326 * This way all ECH boards can share their secondary io region.
327 * If this is an ECH-PCI board then also need to set the page pointer
328 * to point to the correct page.
329 */
330#define BRDENABLE(brdnr,pagenr) \
331 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
332 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
333 stl_brds[(brdnr)]->ioctrl); \
334 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
335 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
336
337#define BRDDISABLE(brdnr) \
338 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
339 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
340 stl_brds[(brdnr)]->ioctrl);
341
342#define STL_CD1400MAXBAUD 230400
343#define STL_SC26198MAXBAUD 460800
344
345#define STL_BAUDBASE 115200
346#define STL_CLOSEDELAY (5 * HZ / 10)
347
348/*****************************************************************************/
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350/*
351 * Define the Stallion PCI vendor and device IDs.
352 */
353#ifndef PCI_VENDOR_ID_STALLION
354#define PCI_VENDOR_ID_STALLION 0x124d
355#endif
356#ifndef PCI_DEVICE_ID_ECHPCI832
357#define PCI_DEVICE_ID_ECHPCI832 0x0000
358#endif
359#ifndef PCI_DEVICE_ID_ECHPCI864
360#define PCI_DEVICE_ID_ECHPCI864 0x0002
361#endif
362#ifndef PCI_DEVICE_ID_EIOPCI
363#define PCI_DEVICE_ID_EIOPCI 0x0003
364#endif
365
366/*
367 * Define structure to hold all Stallion PCI boards.
368 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800370static struct pci_device_id stl_pcibrds[] = {
371 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
372 .driver_data = BRD_ECH64PCI },
373 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
374 .driver_data = BRD_EASYIOPCI },
375 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
376 .driver_data = BRD_ECHPCI },
377 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
378 .driver_data = BRD_ECHPCI },
379 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800381MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383/*****************************************************************************/
384
385/*
386 * Define macros to extract a brd/port number from a minor number.
387 */
388#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
389#define MINOR2PORT(min) ((min) & 0x3f)
390
391/*
392 * Define a baud rate table that converts termios baud rate selector
393 * into the actual baud rate value. All baud rate calculations are
394 * based on the actual baud rate required.
395 */
396static unsigned int stl_baudrates[] = {
397 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
398 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
399};
400
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401/*****************************************************************************/
402
403/*
404 * Declare all those functions in this driver!
405 */
406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800408static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800409static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
410static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800411static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413/*
414 * CD1400 uart specific handling functions.
415 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800416static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
417static int stl_cd1400getreg(struct stlport *portp, int regnr);
418static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
419static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
420static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800421static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800422static int stl_cd1400getsignals(struct stlport *portp);
423static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
424static void stl_cd1400ccrwait(struct stlport *portp);
425static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
426static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
427static void stl_cd1400disableintrs(struct stlport *portp);
428static void stl_cd1400sendbreak(struct stlport *portp, int len);
429static void stl_cd1400flowctrl(struct stlport *portp, int state);
430static void stl_cd1400sendflow(struct stlport *portp, int state);
431static void stl_cd1400flush(struct stlport *portp);
432static int stl_cd1400datastate(struct stlport *portp);
433static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
434static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
435static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
436static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
437static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800439static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
441/*
442 * SC26198 uart specific handling functions.
443 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800444static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
445static int stl_sc26198getreg(struct stlport *portp, int regnr);
446static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
447static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
448static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
449static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800450static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800451static int stl_sc26198getsignals(struct stlport *portp);
452static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
453static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
454static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
455static void stl_sc26198disableintrs(struct stlport *portp);
456static void stl_sc26198sendbreak(struct stlport *portp, int len);
457static void stl_sc26198flowctrl(struct stlport *portp, int state);
458static void stl_sc26198sendflow(struct stlport *portp, int state);
459static void stl_sc26198flush(struct stlport *portp);
460static int stl_sc26198datastate(struct stlport *portp);
461static void stl_sc26198wait(struct stlport *portp);
462static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
463static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
464static void stl_sc26198txisr(struct stlport *port);
465static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
466static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
467static void stl_sc26198rxbadchars(struct stlport *portp);
468static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470/*****************************************************************************/
471
472/*
473 * Generic UART support structure.
474 */
475typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800476 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
477 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800478 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800479 int (*getsignals)(struct stlport *portp);
480 void (*setsignals)(struct stlport *portp, int dtr, int rts);
481 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
482 void (*startrxtx)(struct stlport *portp, int rx, int tx);
483 void (*disableintrs)(struct stlport *portp);
484 void (*sendbreak)(struct stlport *portp, int len);
485 void (*flowctrl)(struct stlport *portp, int state);
486 void (*sendflow)(struct stlport *portp, int state);
487 void (*flush)(struct stlport *portp);
488 int (*datastate)(struct stlport *portp);
489 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490} uart_t;
491
492/*
493 * Define some macros to make calling these functions nice and clean.
494 */
495#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
496#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
497#define stl_setport (* ((uart_t *) portp->uartp)->setport)
498#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
499#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
500#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
501#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
502#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
503#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
504#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
505#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
506#define stl_flush (* ((uart_t *) portp->uartp)->flush)
507#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
508
509/*****************************************************************************/
510
511/*
512 * CD1400 UART specific data initialization.
513 */
514static uart_t stl_cd1400uart = {
515 stl_cd1400panelinit,
516 stl_cd1400portinit,
517 stl_cd1400setport,
518 stl_cd1400getsignals,
519 stl_cd1400setsignals,
520 stl_cd1400enablerxtx,
521 stl_cd1400startrxtx,
522 stl_cd1400disableintrs,
523 stl_cd1400sendbreak,
524 stl_cd1400flowctrl,
525 stl_cd1400sendflow,
526 stl_cd1400flush,
527 stl_cd1400datastate,
528 stl_cd1400eiointr
529};
530
531/*
532 * Define the offsets within the register bank of a cd1400 based panel.
533 * These io address offsets are common to the EasyIO board as well.
534 */
535#define EREG_ADDR 0
536#define EREG_DATA 4
537#define EREG_RXACK 5
538#define EREG_TXACK 6
539#define EREG_MDACK 7
540
541#define EREG_BANKSIZE 8
542
543#define CD1400_CLK 25000000
544#define CD1400_CLK8M 20000000
545
546/*
547 * Define the cd1400 baud rate clocks. These are used when calculating
548 * what clock and divisor to use for the required baud rate. Also
549 * define the maximum baud rate allowed, and the default base baud.
550 */
551static int stl_cd1400clkdivs[] = {
552 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
553};
554
555/*****************************************************************************/
556
557/*
558 * SC26198 UART specific data initization.
559 */
560static uart_t stl_sc26198uart = {
561 stl_sc26198panelinit,
562 stl_sc26198portinit,
563 stl_sc26198setport,
564 stl_sc26198getsignals,
565 stl_sc26198setsignals,
566 stl_sc26198enablerxtx,
567 stl_sc26198startrxtx,
568 stl_sc26198disableintrs,
569 stl_sc26198sendbreak,
570 stl_sc26198flowctrl,
571 stl_sc26198sendflow,
572 stl_sc26198flush,
573 stl_sc26198datastate,
574 stl_sc26198intr
575};
576
577/*
578 * Define the offsets within the register bank of a sc26198 based panel.
579 */
580#define XP_DATA 0
581#define XP_ADDR 1
582#define XP_MODID 2
583#define XP_STATUS 2
584#define XP_IACK 3
585
586#define XP_BANKSIZE 4
587
588/*
589 * Define the sc26198 baud rate table. Offsets within the table
590 * represent the actual baud rate selector of sc26198 registers.
591 */
592static unsigned int sc26198_baudtable[] = {
593 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
594 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
595 230400, 460800, 921600
596};
597
Tobias Klauserfe971072006-01-09 20:54:02 -0800598#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600/*****************************************************************************/
601
602/*
603 * Define the driver info for a user level control device. Used mainly
604 * to get at port stats - only not using the port device itself.
605 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700606static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 .owner = THIS_MODULE,
608 .ioctl = stl_memioctl,
609};
610
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800611static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
613/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 * Check for any arguments passed in on the module load command line.
615 */
616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617/*****************************************************************************/
618
619/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 * Parse the supplied argument string, into the board conf struct.
621 */
622
Jiri Slaby40e82652006-12-08 02:38:41 -0800623static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624{
625 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800626 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Jiri Slabya0564e12006-12-08 02:38:37 -0800628 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
Jiri Slaby615e4a72006-12-08 02:38:38 -0800630 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100631 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Jiri Slabyc62429d2006-12-08 02:39:14 -0800633 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800634 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Jiri Slabyc62429d2006-12-08 02:39:14 -0800636 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
638 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800639
Tobias Klauserfe971072006-01-09 20:54:02 -0800640 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800642 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 }
644
645 confp->brdtype = stl_brdstr[i].type;
646
647 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800648 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800649 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 i++;
651 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800652 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800653 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 i++;
655 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800656 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800657 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100658 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659}
660
661/*****************************************************************************/
662
663/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 * Allocate a new board structure. Fill out the basic info in it.
665 */
666
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800667static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800669 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800671 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800672 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700673 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800674 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800675 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 }
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100679 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680}
681
682/*****************************************************************************/
683
684static int stl_open(struct tty_struct *tty, struct file *filp)
685{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800686 struct stlport *portp;
687 struct stlbrd *brdp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800688 unsigned int minordev, brdnr, panelnr;
689 int portnr, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Jiri Slabya0564e12006-12-08 02:38:37 -0800691 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 minordev = tty->index;
694 brdnr = MINOR2BRD(minordev);
695 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100696 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800698 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100699 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800701 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800702 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 break;
704 if (minordev < brdp->panels[panelnr]->nrports) {
705 portnr = minordev;
706 break;
707 }
708 minordev -= brdp->panels[panelnr]->nrports;
709 }
710 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100711 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
713 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800714 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100715 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717/*
718 * On the first open of the device setup the port hardware, and
719 * initialize the per port data structure.
720 */
721 portp->tty = tty;
722 tty->driver_data = portp;
723 portp->refcount++;
724
725 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800726 if (!portp->tx.buf) {
727 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
728 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100729 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 portp->tx.head = portp->tx.buf;
731 portp->tx.tail = portp->tx.buf;
732 }
733 stl_setport(portp, tty->termios);
734 portp->sigs = stl_getsignals(portp);
735 stl_setsignals(portp, 1, 1);
736 stl_enablerxtx(portp, 1, 1);
737 stl_startrxtx(portp, 1, 0);
738 clear_bit(TTY_IO_ERROR, &tty->flags);
739 portp->flags |= ASYNC_INITIALIZED;
740 }
741
742/*
743 * Check if this port is in the middle of closing. If so then wait
744 * until it is closed then return error status, based on flag settings.
745 * The sleep here does not need interrupt protection since the wakeup
746 * for it is done with the same context.
747 */
748 if (portp->flags & ASYNC_CLOSING) {
749 interruptible_sleep_on(&portp->close_wait);
750 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100751 return -EAGAIN;
752 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 }
754
755/*
756 * Based on type of open being done check if it can overlap with any
757 * previous opens still in effect. If we are a normal serial device
758 * then also we might have to wait for carrier.
759 */
Jiri Slabyc62429d2006-12-08 02:39:14 -0800760 if (!(filp->f_flags & O_NONBLOCK))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100762 return rc;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 portp->flags |= ASYNC_NORMAL_ACTIVE;
765
Jesper Juhl014c2542006-01-15 02:37:08 +0100766 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767}
768
769/*****************************************************************************/
770
771/*
772 * Possibly need to wait for carrier (DCD signal) to come high. Say
773 * maybe because if we are clocal then we don't need to wait...
774 */
775
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800776static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777{
778 unsigned long flags;
779 int rc, doclocal;
780
Jiri Slabya0564e12006-12-08 02:38:37 -0800781 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
783 rc = 0;
784 doclocal = 0;
785
Alan Coxb65b5b52006-06-27 02:54:05 -0700786 spin_lock_irqsave(&stallion_lock, flags);
787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 if (portp->tty->termios->c_cflag & CLOCAL)
789 doclocal++;
790
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 portp->openwaitcnt++;
792 if (! tty_hung_up_p(filp))
793 portp->refcount--;
794
795 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700796 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 stl_setsignals(portp, 1, 1);
798 if (tty_hung_up_p(filp) ||
799 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
800 if (portp->flags & ASYNC_HUP_NOTIFY)
801 rc = -EBUSY;
802 else
803 rc = -ERESTARTSYS;
804 break;
805 }
806 if (((portp->flags & ASYNC_CLOSING) == 0) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -0800807 (doclocal || (portp->sigs & TIOCM_CD)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 if (signal_pending(current)) {
810 rc = -ERESTARTSYS;
811 break;
812 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700813 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 interruptible_sleep_on(&portp->open_wait);
815 }
816
817 if (! tty_hung_up_p(filp))
818 portp->refcount++;
819 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700820 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
Jesper Juhl014c2542006-01-15 02:37:08 +0100822 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823}
824
825/*****************************************************************************/
826
Jiri Slaby96b066b2006-12-08 02:38:42 -0800827static void stl_flushbuffer(struct tty_struct *tty)
828{
829 struct stlport *portp;
830
831 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
832
833 if (tty == NULL)
834 return;
835 portp = tty->driver_data;
836 if (portp == NULL)
837 return;
838
839 stl_flush(portp);
840 tty_wakeup(tty);
841}
842
843/*****************************************************************************/
844
845static void stl_waituntilsent(struct tty_struct *tty, int timeout)
846{
847 struct stlport *portp;
848 unsigned long tend;
849
850 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
851
852 if (tty == NULL)
853 return;
854 portp = tty->driver_data;
855 if (portp == NULL)
856 return;
857
858 if (timeout == 0)
859 timeout = HZ;
860 tend = jiffies + timeout;
861
862 while (stl_datastate(portp)) {
863 if (signal_pending(current))
864 break;
865 msleep_interruptible(20);
866 if (time_after_eq(jiffies, tend))
867 break;
868 }
869}
870
871/*****************************************************************************/
872
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873static void stl_close(struct tty_struct *tty, struct file *filp)
874{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800875 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 unsigned long flags;
877
Jiri Slabya0564e12006-12-08 02:38:37 -0800878 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
880 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800881 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 return;
883
Alan Coxb65b5b52006-06-27 02:54:05 -0700884 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700886 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 return;
888 }
889 if ((tty->count == 1) && (portp->refcount != 1))
890 portp->refcount = 1;
891 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700892 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 return;
894 }
895
896 portp->refcount = 0;
897 portp->flags |= ASYNC_CLOSING;
898
899/*
900 * May want to wait for any data to drain before closing. The BUSY
901 * flag keeps track of whether we are still sending or not - it is
902 * very accurate for the cd1400, not quite so for the sc26198.
903 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
904 */
905 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700906
907 spin_unlock_irqrestore(&stallion_lock, flags);
908
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
910 tty_wait_until_sent(tty, portp->closing_wait);
911 stl_waituntilsent(tty, (HZ / 2));
912
Alan Coxb65b5b52006-06-27 02:54:05 -0700913
914 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700916 spin_unlock_irqrestore(&stallion_lock, flags);
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 stl_disableintrs(portp);
919 if (tty->termios->c_cflag & HUPCL)
920 stl_setsignals(portp, 0, 0);
921 stl_enablerxtx(portp, 0, 0);
922 stl_flushbuffer(tty);
923 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800924 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800926 portp->tx.buf = NULL;
927 portp->tx.head = NULL;
928 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 }
930 set_bit(TTY_IO_ERROR, &tty->flags);
931 tty_ldisc_flush(tty);
932
933 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800934 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
936 if (portp->openwaitcnt) {
937 if (portp->close_delay)
938 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
939 wake_up_interruptible(&portp->open_wait);
940 }
941
942 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
943 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944}
945
946/*****************************************************************************/
947
948/*
949 * Write routine. Take data and stuff it in to the TX ring queue.
950 * If transmit interrupts are not running then start them.
951 */
952
953static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
954{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800955 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 unsigned int len, stlen;
957 unsigned char *chbuf;
958 char *head, *tail;
959
Jiri Slabya0564e12006-12-08 02:38:37 -0800960 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800963 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100964 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800965 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100966 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
968/*
969 * If copying direct from user space we must cater for page faults,
970 * causing us to "sleep" here for a while. To handle this copy in all
971 * the data we need now, into a local buffer. Then when we got it all
972 * copy it into the TX buffer.
973 */
974 chbuf = (unsigned char *) buf;
975
976 head = portp->tx.head;
977 tail = portp->tx.tail;
978 if (head >= tail) {
979 len = STL_TXBUFSIZE - (head - tail) - 1;
980 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
981 } else {
982 len = tail - head - 1;
983 stlen = len;
984 }
985
Jiri Slaby843b5682006-12-08 02:39:12 -0800986 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 count = 0;
988 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800989 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 memcpy(head, chbuf, stlen);
991 len -= stlen;
992 chbuf += stlen;
993 count += stlen;
994 head += stlen;
995 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
996 head = portp->tx.buf;
997 stlen = tail - head;
998 }
999 }
1000 portp->tx.head = head;
1001
1002 clear_bit(ASYI_TXLOW, &portp->istate);
1003 stl_startrxtx(portp, -1, 1);
1004
Jesper Juhl014c2542006-01-15 02:37:08 +01001005 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006}
1007
1008/*****************************************************************************/
1009
1010static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1011{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001012 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 unsigned int len;
1014 char *head, *tail;
1015
Jiri Slabya0564e12006-12-08 02:38:37 -08001016 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
Jiri Slaby615e4a72006-12-08 02:38:38 -08001018 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return;
1020 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001021 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001023 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 return;
1025
1026 head = portp->tx.head;
1027 tail = portp->tx.tail;
1028
1029 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1030 len--;
1031
1032 if (len > 0) {
1033 *head++ = ch;
1034 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1035 head = portp->tx.buf;
1036 }
1037 portp->tx.head = head;
1038}
1039
1040/*****************************************************************************/
1041
1042/*
1043 * If there are any characters in the buffer then make sure that TX
1044 * interrupts are on and get'em out. Normally used after the putchar
1045 * routine has been called.
1046 */
1047
1048static void stl_flushchars(struct tty_struct *tty)
1049{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001050 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Jiri Slabya0564e12006-12-08 02:38:37 -08001052 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
Jiri Slaby615e4a72006-12-08 02:38:38 -08001054 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 return;
1056 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001057 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001059 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 return;
1061
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 stl_startrxtx(portp, -1, 1);
1063}
1064
1065/*****************************************************************************/
1066
1067static int stl_writeroom(struct tty_struct *tty)
1068{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001069 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 char *head, *tail;
1071
Jiri Slabya0564e12006-12-08 02:38:37 -08001072 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Jiri Slaby615e4a72006-12-08 02:38:38 -08001074 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001075 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001077 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001078 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001079 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001080 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
1082 head = portp->tx.head;
1083 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001084 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085}
1086
1087/*****************************************************************************/
1088
1089/*
1090 * Return number of chars in the TX buffer. Normally we would just
1091 * calculate the number of chars in the buffer and return that, but if
1092 * the buffer is empty and TX interrupts are still on then we return
1093 * that the buffer still has 1 char in it. This way whoever called us
1094 * will not think that ALL chars have drained - since the UART still
1095 * must have some chars in it (we are busy after all).
1096 */
1097
1098static int stl_charsinbuffer(struct tty_struct *tty)
1099{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001100 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 unsigned int size;
1102 char *head, *tail;
1103
Jiri Slabya0564e12006-12-08 02:38:37 -08001104 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Jiri Slaby615e4a72006-12-08 02:38:38 -08001106 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001107 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001109 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001110 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001111 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001112 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
1114 head = portp->tx.head;
1115 tail = portp->tx.tail;
1116 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1117 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1118 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001119 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120}
1121
1122/*****************************************************************************/
1123
1124/*
1125 * Generate the serial struct info.
1126 */
1127
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001128static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129{
1130 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001131 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Jiri Slabya0564e12006-12-08 02:38:37 -08001133 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
1135 memset(&sio, 0, sizeof(struct serial_struct));
1136 sio.line = portp->portnr;
1137 sio.port = portp->ioaddr;
1138 sio.flags = portp->flags;
1139 sio.baud_base = portp->baud_base;
1140 sio.close_delay = portp->close_delay;
1141 sio.closing_wait = portp->closing_wait;
1142 sio.custom_divisor = portp->custom_divisor;
1143 sio.hub6 = 0;
1144 if (portp->uartp == &stl_cd1400uart) {
1145 sio.type = PORT_CIRRUS;
1146 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1147 } else {
1148 sio.type = PORT_UNKNOWN;
1149 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1150 }
1151
1152 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001153 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 sio.irq = brdp->irq;
1155
1156 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1157}
1158
1159/*****************************************************************************/
1160
1161/*
1162 * Set port according to the serial struct info.
1163 * At this point we do not do any auto-configure stuff, so we will
1164 * just quietly ignore any requests to change irq, etc.
1165 */
1166
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001167static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168{
1169 struct serial_struct sio;
1170
Jiri Slabya0564e12006-12-08 02:38:37 -08001171 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
1173 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1174 return -EFAULT;
1175 if (!capable(CAP_SYS_ADMIN)) {
1176 if ((sio.baud_base != portp->baud_base) ||
1177 (sio.close_delay != portp->close_delay) ||
1178 ((sio.flags & ~ASYNC_USR_MASK) !=
1179 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001180 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 }
1182
1183 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1184 (sio.flags & ASYNC_USR_MASK);
1185 portp->baud_base = sio.baud_base;
1186 portp->close_delay = sio.close_delay;
1187 portp->closing_wait = sio.closing_wait;
1188 portp->custom_divisor = sio.custom_divisor;
1189 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001190 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191}
1192
1193/*****************************************************************************/
1194
1195static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1196{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001197 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
Jiri Slaby615e4a72006-12-08 02:38:38 -08001199 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001200 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001202 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001203 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001205 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
1207 return stl_getsignals(portp);
1208}
1209
1210static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1211 unsigned int set, unsigned int clear)
1212{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001213 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 int rts = -1, dtr = -1;
1215
Jiri Slaby615e4a72006-12-08 02:38:38 -08001216 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001217 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001219 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001220 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001222 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
1224 if (set & TIOCM_RTS)
1225 rts = 1;
1226 if (set & TIOCM_DTR)
1227 dtr = 1;
1228 if (clear & TIOCM_RTS)
1229 rts = 0;
1230 if (clear & TIOCM_DTR)
1231 dtr = 0;
1232
1233 stl_setsignals(portp, dtr, rts);
1234 return 0;
1235}
1236
1237static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1238{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001239 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 unsigned int ival;
1241 int rc;
1242 void __user *argp = (void __user *)arg;
1243
Jiri Slabya0564e12006-12-08 02:38:37 -08001244 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1245 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
Jiri Slaby615e4a72006-12-08 02:38:38 -08001247 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001248 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001250 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001251 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
1253 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001254 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001256 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
1258 rc = 0;
1259
1260 switch (cmd) {
1261 case TIOCGSOFTCAR:
1262 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1263 (unsigned __user *) argp);
1264 break;
1265 case TIOCSSOFTCAR:
1266 if (get_user(ival, (unsigned int __user *) arg))
1267 return -EFAULT;
1268 tty->termios->c_cflag =
1269 (tty->termios->c_cflag & ~CLOCAL) |
1270 (ival ? CLOCAL : 0);
1271 break;
1272 case TIOCGSERIAL:
1273 rc = stl_getserial(portp, argp);
1274 break;
1275 case TIOCSSERIAL:
1276 rc = stl_setserial(portp, argp);
1277 break;
1278 case COM_GETPORTSTATS:
1279 rc = stl_getportstats(portp, argp);
1280 break;
1281 case COM_CLRPORTSTATS:
1282 rc = stl_clrportstats(portp, argp);
1283 break;
1284 case TIOCSERCONFIG:
1285 case TIOCSERGWILD:
1286 case TIOCSERSWILD:
1287 case TIOCSERGETLSR:
1288 case TIOCSERGSTRUCT:
1289 case TIOCSERGETMULTI:
1290 case TIOCSERSETMULTI:
1291 default:
1292 rc = -ENOIOCTLCMD;
1293 break;
1294 }
1295
Jesper Juhl014c2542006-01-15 02:37:08 +01001296 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297}
1298
1299/*****************************************************************************/
1300
Jiri Slaby96b066b2006-12-08 02:38:42 -08001301/*
1302 * Start the transmitter again. Just turn TX interrupts back on.
1303 */
1304
1305static void stl_start(struct tty_struct *tty)
1306{
1307 struct stlport *portp;
1308
1309 pr_debug("stl_start(tty=%p)\n", tty);
1310
1311 if (tty == NULL)
1312 return;
1313 portp = tty->driver_data;
1314 if (portp == NULL)
1315 return;
1316 stl_startrxtx(portp, -1, 1);
1317}
1318
1319/*****************************************************************************/
1320
Alan Cox606d0992006-12-08 02:38:45 -08001321static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001323 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001324 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
Jiri Slabya0564e12006-12-08 02:38:37 -08001326 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
Jiri Slaby615e4a72006-12-08 02:38:38 -08001328 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 return;
1330 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001331 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 return;
1333
1334 tiosp = tty->termios;
1335 if ((tiosp->c_cflag == old->c_cflag) &&
1336 (tiosp->c_iflag == old->c_iflag))
1337 return;
1338
1339 stl_setport(portp, tiosp);
1340 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1341 -1);
1342 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1343 tty->hw_stopped = 0;
1344 stl_start(tty);
1345 }
1346 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1347 wake_up_interruptible(&portp->open_wait);
1348}
1349
1350/*****************************************************************************/
1351
1352/*
1353 * Attempt to flow control who ever is sending us data. Based on termios
1354 * settings use software or/and hardware flow control.
1355 */
1356
1357static void stl_throttle(struct tty_struct *tty)
1358{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001359 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Jiri Slabya0564e12006-12-08 02:38:37 -08001361 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Jiri Slaby615e4a72006-12-08 02:38:38 -08001363 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 return;
1365 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001366 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 return;
1368 stl_flowctrl(portp, 0);
1369}
1370
1371/*****************************************************************************/
1372
1373/*
1374 * Unflow control the device sending us data...
1375 */
1376
1377static void stl_unthrottle(struct tty_struct *tty)
1378{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001379 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
Jiri Slabya0564e12006-12-08 02:38:37 -08001381 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Jiri Slaby615e4a72006-12-08 02:38:38 -08001383 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 return;
1385 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001386 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 return;
1388 stl_flowctrl(portp, 1);
1389}
1390
1391/*****************************************************************************/
1392
1393/*
1394 * Stop the transmitter. Basically to do this we will just turn TX
1395 * interrupts off.
1396 */
1397
1398static void stl_stop(struct tty_struct *tty)
1399{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001400 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Jiri Slabya0564e12006-12-08 02:38:37 -08001402 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Jiri Slaby615e4a72006-12-08 02:38:38 -08001404 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 return;
1406 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001407 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 return;
1409 stl_startrxtx(portp, -1, 0);
1410}
1411
1412/*****************************************************************************/
1413
1414/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 * Hangup this port. This is pretty much like closing the port, only
1416 * a little more brutal. No waiting for data to drain. Shutdown the
1417 * port and maybe drop signals.
1418 */
1419
1420static void stl_hangup(struct tty_struct *tty)
1421{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001422 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Jiri Slabya0564e12006-12-08 02:38:37 -08001424 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
Jiri Slaby615e4a72006-12-08 02:38:38 -08001426 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 return;
1428 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001429 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 return;
1431
1432 portp->flags &= ~ASYNC_INITIALIZED;
1433 stl_disableintrs(portp);
1434 if (tty->termios->c_cflag & HUPCL)
1435 stl_setsignals(portp, 0, 0);
1436 stl_enablerxtx(portp, 0, 0);
1437 stl_flushbuffer(tty);
1438 portp->istate = 0;
1439 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001440 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001442 portp->tx.buf = NULL;
1443 portp->tx.head = NULL;
1444 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001446 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1448 portp->refcount = 0;
1449 wake_up_interruptible(&portp->open_wait);
1450}
1451
1452/*****************************************************************************/
1453
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454static void stl_breakctl(struct tty_struct *tty, int state)
1455{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001456 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
Jiri Slabya0564e12006-12-08 02:38:37 -08001458 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
Jiri Slaby615e4a72006-12-08 02:38:38 -08001460 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 return;
1462 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001463 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 return;
1465
1466 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1467}
1468
1469/*****************************************************************************/
1470
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471static void stl_sendxchar(struct tty_struct *tty, char ch)
1472{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001473 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
Jiri Slabya0564e12006-12-08 02:38:37 -08001475 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
Jiri Slaby615e4a72006-12-08 02:38:38 -08001477 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 return;
1479 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001480 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 return;
1482
1483 if (ch == STOP_CHAR(tty))
1484 stl_sendflow(portp, 0);
1485 else if (ch == START_CHAR(tty))
1486 stl_sendflow(portp, 1);
1487 else
1488 stl_putchar(tty, ch);
1489}
1490
1491/*****************************************************************************/
1492
1493#define MAXLINE 80
1494
1495/*
1496 * Format info for a specified port. The line is deliberately limited
1497 * to 80 characters. (If it is too long it will be truncated, if too
1498 * short then padded with spaces).
1499 */
1500
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001501static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
1503 char *sp;
1504 int sigs, cnt;
1505
1506 sp = pos;
1507 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1508 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1509 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1510
1511 if (portp->stats.rxframing)
1512 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1513 if (portp->stats.rxparity)
1514 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1515 if (portp->stats.rxbreaks)
1516 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1517 if (portp->stats.rxoverrun)
1518 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1519
1520 sigs = stl_getsignals(portp);
1521 cnt = sprintf(sp, "%s%s%s%s%s ",
1522 (sigs & TIOCM_RTS) ? "|RTS" : "",
1523 (sigs & TIOCM_CTS) ? "|CTS" : "",
1524 (sigs & TIOCM_DTR) ? "|DTR" : "",
1525 (sigs & TIOCM_CD) ? "|DCD" : "",
1526 (sigs & TIOCM_DSR) ? "|DSR" : "");
1527 *sp = ' ';
1528 sp += cnt;
1529
Jiri Slabyc62429d2006-12-08 02:39:14 -08001530 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 *sp++ = ' ';
1532 if (cnt >= MAXLINE)
1533 pos[(MAXLINE - 2)] = '+';
1534 pos[(MAXLINE - 1)] = '\n';
1535
Jesper Juhl014c2542006-01-15 02:37:08 +01001536 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537}
1538
1539/*****************************************************************************/
1540
1541/*
1542 * Port info, read from the /proc file system.
1543 */
1544
1545static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1546{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001547 struct stlbrd *brdp;
1548 struct stlpanel *panelp;
1549 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001550 unsigned int brdnr, panelnr, portnr;
1551 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 char *pos;
1553
Jiri Slabya0564e12006-12-08 02:38:37 -08001554 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1555 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
1557 pos = page;
1558 totalport = 0;
1559 curoff = 0;
1560
1561 if (off == 0) {
1562 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1563 stl_drvversion);
1564 while (pos < (page + MAXLINE - 1))
1565 *pos++ = ' ';
1566 *pos++ = '\n';
1567 }
1568 curoff = MAXLINE;
1569
1570/*
1571 * We scan through for each board, panel and port. The offset is
1572 * calculated on the fly, and irrelevant ports are skipped.
1573 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001574 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001576 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 continue;
1578 if (brdp->state == 0)
1579 continue;
1580
1581 maxoff = curoff + (brdp->nrports * MAXLINE);
1582 if (off >= maxoff) {
1583 curoff = maxoff;
1584 continue;
1585 }
1586
1587 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001588 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001590 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 continue;
1592
1593 maxoff = curoff + (panelp->nrports * MAXLINE);
1594 if (off >= maxoff) {
1595 curoff = maxoff;
1596 totalport += panelp->nrports;
1597 continue;
1598 }
1599
Jiri Slabyc62429d2006-12-08 02:39:14 -08001600 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 totalport++) {
1602 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001603 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 continue;
1605 if (off >= (curoff += MAXLINE))
1606 continue;
1607 if ((pos - page + MAXLINE) > count)
1608 goto stl_readdone;
1609 pos += stl_portinfo(portp, totalport, pos);
1610 }
1611 }
1612 }
1613
1614 *eof = 1;
1615
1616stl_readdone:
1617 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001618 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619}
1620
1621/*****************************************************************************/
1622
1623/*
1624 * All board interrupts are vectored through here first. This code then
1625 * calls off to the approrpriate board interrupt handlers.
1626 */
1627
David Howells7d12e782006-10-05 14:55:46 +01001628static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001630 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
Jiri Slabya0564e12006-12-08 02:38:37 -08001632 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
1634 return IRQ_RETVAL((* brdp->isr)(brdp));
1635}
1636
1637/*****************************************************************************/
1638
1639/*
1640 * Interrupt service routine for EasyIO board types.
1641 */
1642
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001643static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001645 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 unsigned int iobase;
1647 int handled = 0;
1648
Alan Coxb65b5b52006-06-27 02:54:05 -07001649 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 panelp = brdp->panels[0];
1651 iobase = panelp->iobase;
1652 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1653 handled = 1;
1654 (* panelp->isr)(panelp, iobase);
1655 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001656 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 return handled;
1658}
1659
1660/*****************************************************************************/
1661
1662/*
1663 * Interrupt service routine for ECH-AT board types.
1664 */
1665
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001666static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001668 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001669 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 int handled = 0;
1671
1672 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1673
1674 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1675 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001676 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 ioaddr = brdp->bnkstataddr[bnknr];
1678 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1679 panelp = brdp->bnk2panel[bnknr];
1680 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1681 }
1682 }
1683 }
1684
1685 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1686
1687 return handled;
1688}
1689
1690/*****************************************************************************/
1691
1692/*
1693 * Interrupt service routine for ECH-MCA board types.
1694 */
1695
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001696static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001698 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001699 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 int handled = 0;
1701
1702 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1703 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001704 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 ioaddr = brdp->bnkstataddr[bnknr];
1706 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1707 panelp = brdp->bnk2panel[bnknr];
1708 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1709 }
1710 }
1711 }
1712 return handled;
1713}
1714
1715/*****************************************************************************/
1716
1717/*
1718 * Interrupt service routine for ECH-PCI board types.
1719 */
1720
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001721static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001723 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001724 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 int handled = 0;
1726
1727 while (1) {
1728 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001729 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1731 ioaddr = brdp->bnkstataddr[bnknr];
1732 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1733 panelp = brdp->bnk2panel[bnknr];
1734 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1735 recheck++;
1736 handled = 1;
1737 }
1738 }
1739 if (! recheck)
1740 break;
1741 }
1742 return handled;
1743}
1744
1745/*****************************************************************************/
1746
1747/*
1748 * Interrupt service routine for ECH-8/64-PCI board types.
1749 */
1750
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001751static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001753 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001754 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 int handled = 0;
1756
1757 while (inb(brdp->ioctrl) & 0x1) {
1758 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001759 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 ioaddr = brdp->bnkstataddr[bnknr];
1761 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1762 panelp = brdp->bnk2panel[bnknr];
1763 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1764 }
1765 }
1766 }
1767
1768 return handled;
1769}
1770
1771/*****************************************************************************/
1772
1773/*
1774 * Service an off-level request for some channel.
1775 */
Al Viro3e577a82006-12-06 18:41:45 +00001776static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001778 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 struct tty_struct *tty;
1780 unsigned int oldsigs;
1781
Jiri Slabya0564e12006-12-08 02:38:37 -08001782 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
Jiri Slaby615e4a72006-12-08 02:38:38 -08001784 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 return;
1786
1787 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001788 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 return;
1790
1791 lock_kernel();
Jiri Slabyc62429d2006-12-08 02:39:14 -08001792 if (test_bit(ASYI_TXLOW, &portp->istate))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 tty_wakeup(tty);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001794
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1796 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1797 oldsigs = portp->sigs;
1798 portp->sigs = stl_getsignals(portp);
1799 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1800 wake_up_interruptible(&portp->open_wait);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001801 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 if (portp->flags & ASYNC_CHECK_CD)
1803 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 }
1805 unlock_kernel();
1806}
1807
1808/*****************************************************************************/
1809
1810/*
1811 * Initialize all the ports on a panel.
1812 */
1813
Jiri Slaby705c1862006-12-08 02:39:11 -08001814static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001816 struct stlport *portp;
1817 unsigned int i;
1818 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
Jiri Slabya0564e12006-12-08 02:38:37 -08001820 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821
1822 chipmask = stl_panelinit(brdp, panelp);
1823
1824/*
1825 * All UART's are initialized (if found!). Now go through and setup
1826 * each ports data structures.
1827 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001828 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001829 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001830 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001832 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 break;
1834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835
1836 portp->magic = STL_PORTMAGIC;
1837 portp->portnr = i;
1838 portp->brdnr = panelp->brdnr;
1839 portp->panelnr = panelp->panelnr;
1840 portp->uartp = panelp->uartp;
1841 portp->clk = brdp->clk;
1842 portp->baud_base = STL_BAUDBASE;
1843 portp->close_delay = STL_CLOSEDELAY;
1844 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001845 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 init_waitqueue_head(&portp->open_wait);
1847 init_waitqueue_head(&portp->close_wait);
1848 portp->stats.brd = portp->brdnr;
1849 portp->stats.panel = portp->panelnr;
1850 portp->stats.port = portp->portnr;
1851 panelp->ports[i] = portp;
1852 stl_portinit(brdp, panelp, portp);
1853 }
1854
Jiri Slabyc62429d2006-12-08 02:39:14 -08001855 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856}
1857
Jiri Slaby3b85b342006-12-08 02:39:10 -08001858static void stl_cleanup_panels(struct stlbrd *brdp)
1859{
1860 struct stlpanel *panelp;
1861 struct stlport *portp;
1862 unsigned int j, k;
1863
1864 for (j = 0; j < STL_MAXPANELS; j++) {
1865 panelp = brdp->panels[j];
1866 if (panelp == NULL)
1867 continue;
1868 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1869 portp = panelp->ports[k];
1870 if (portp == NULL)
1871 continue;
1872 if (portp->tty != NULL)
1873 stl_hangup(portp->tty);
1874 kfree(portp->tx.buf);
1875 kfree(portp);
1876 }
1877 kfree(panelp);
1878 }
1879}
1880
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881/*****************************************************************************/
1882
1883/*
1884 * Try to find and initialize an EasyIO board.
1885 */
1886
Jiri Slaby705c1862006-12-08 02:39:11 -08001887static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001889 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 unsigned int status;
1891 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001892 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
Jiri Slabya0564e12006-12-08 02:38:37 -08001894 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895
1896 brdp->ioctrl = brdp->ioaddr1 + 1;
1897 brdp->iostatus = brdp->ioaddr1 + 2;
1898
1899 status = inb(brdp->iostatus);
1900 if ((status & EIO_IDBITMASK) == EIO_MK3)
1901 brdp->ioctrl++;
1902
1903/*
1904 * Handle board specific stuff now. The real difference is PCI
1905 * or not PCI.
1906 */
1907 if (brdp->brdtype == BRD_EASYIOPCI) {
1908 brdp->iosize1 = 0x80;
1909 brdp->iosize2 = 0x80;
1910 name = "serial(EIO-PCI)";
1911 outb(0x41, (brdp->ioaddr2 + 0x4c));
1912 } else {
1913 brdp->iosize1 = 8;
1914 name = "serial(EIO)";
1915 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1916 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1917 printk("STALLION: invalid irq=%d for brd=%d\n",
1918 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001919 retval = -EINVAL;
1920 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 }
1922 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1923 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1924 brdp->ioctrl);
1925 }
1926
Jiri Slaby3b85b342006-12-08 02:39:10 -08001927 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1929 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1930 "%x conflicts with another device\n", brdp->brdnr,
1931 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001932 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 }
1934
1935 if (brdp->iosize2 > 0)
1936 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1937 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1938 "address %x conflicts with another device\n",
1939 brdp->brdnr, brdp->ioaddr2);
1940 printk(KERN_WARNING "STALLION: Warning, also "
1941 "releasing board %d I/O address %x \n",
1942 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001943 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 }
1945
1946/*
1947 * Everything looks OK, so let's go ahead and probe for the hardware.
1948 */
1949 brdp->clk = CD1400_CLK;
1950 brdp->isr = stl_eiointr;
1951
Jiri Slaby3b85b342006-12-08 02:39:10 -08001952 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 switch (status & EIO_IDBITMASK) {
1954 case EIO_8PORTM:
1955 brdp->clk = CD1400_CLK8M;
1956 /* fall thru */
1957 case EIO_8PORTRS:
1958 case EIO_8PORTDI:
1959 brdp->nrports = 8;
1960 break;
1961 case EIO_4PORTRS:
1962 brdp->nrports = 4;
1963 break;
1964 case EIO_MK3:
1965 switch (status & EIO_BRDMASK) {
1966 case ID_BRD4:
1967 brdp->nrports = 4;
1968 break;
1969 case ID_BRD8:
1970 brdp->nrports = 8;
1971 break;
1972 case ID_BRD16:
1973 brdp->nrports = 16;
1974 break;
1975 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001976 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 }
1978 break;
1979 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001980 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 }
1982
1983/*
1984 * We have verified that the board is actually present, so now we
1985 * can complete the setup.
1986 */
1987
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001988 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001989 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001991 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001992 retval = -ENOMEM;
1993 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995
1996 panelp->magic = STL_PANELMAGIC;
1997 panelp->brdnr = brdp->brdnr;
1998 panelp->panelnr = 0;
1999 panelp->nrports = brdp->nrports;
2000 panelp->iobase = brdp->ioaddr1;
2001 panelp->hwid = status;
2002 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002003 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 panelp->isr = stl_sc26198intr;
2005 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002006 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 panelp->isr = stl_cd1400eiointr;
2008 }
2009
2010 brdp->panels[0] = panelp;
2011 brdp->nrpanels = 1;
2012 brdp->state |= BRD_FOUND;
2013 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002014 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 printk("STALLION: failed to register interrupt "
2016 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002017 retval = -ENODEV;
2018 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08002020
2021 return 0;
2022err_fr:
2023 stl_cleanup_panels(brdp);
2024err_rel2:
2025 if (brdp->iosize2 > 0)
2026 release_region(brdp->ioaddr2, brdp->iosize2);
2027err_rel1:
2028 release_region(brdp->ioaddr1, brdp->iosize1);
2029err:
2030 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031}
2032
2033/*****************************************************************************/
2034
2035/*
2036 * Try to find an ECH board and initialize it. This code is capable of
2037 * dealing with all types of ECH board.
2038 */
2039
Jiri Slaby705c1862006-12-08 02:39:11 -08002040static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002042 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002043 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
2044 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 char *name;
2046
Jiri Slabya0564e12006-12-08 02:38:37 -08002047 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
2049 status = 0;
2050 conflict = 0;
2051
2052/*
2053 * Set up the initial board register contents for boards. This varies a
2054 * bit between the different board types. So we need to handle each
2055 * separately. Also do a check that the supplied IRQ is good.
2056 */
2057 switch (brdp->brdtype) {
2058
2059 case BRD_ECH:
2060 brdp->isr = stl_echatintr;
2061 brdp->ioctrl = brdp->ioaddr1 + 1;
2062 brdp->iostatus = brdp->ioaddr1 + 1;
2063 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002064 if ((status & ECH_IDBITMASK) != ECH_ID) {
2065 retval = -ENODEV;
2066 goto err;
2067 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2069 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2070 printk("STALLION: invalid irq=%d for brd=%d\n",
2071 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002072 retval = -EINVAL;
2073 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 }
2075 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2076 status |= (stl_vecmap[brdp->irq] << 1);
2077 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2078 brdp->ioctrlval = ECH_INTENABLE |
2079 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002080 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2082 brdp->iosize1 = 2;
2083 brdp->iosize2 = 32;
2084 name = "serial(EC8/32)";
2085 outb(status, brdp->ioaddr1);
2086 break;
2087
2088 case BRD_ECHMC:
2089 brdp->isr = stl_echmcaintr;
2090 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2091 brdp->iostatus = brdp->ioctrl;
2092 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002093 if ((status & ECH_IDBITMASK) != ECH_ID) {
2094 retval = -ENODEV;
2095 goto err;
2096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2098 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2099 printk("STALLION: invalid irq=%d for brd=%d\n",
2100 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002101 retval = -EINVAL;
2102 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 }
2104 outb(ECHMC_BRDRESET, brdp->ioctrl);
2105 outb(ECHMC_INTENABLE, brdp->ioctrl);
2106 brdp->iosize1 = 64;
2107 name = "serial(EC8/32-MC)";
2108 break;
2109
2110 case BRD_ECHPCI:
2111 brdp->isr = stl_echpciintr;
2112 brdp->ioctrl = brdp->ioaddr1 + 2;
2113 brdp->iosize1 = 4;
2114 brdp->iosize2 = 8;
2115 name = "serial(EC8/32-PCI)";
2116 break;
2117
2118 case BRD_ECH64PCI:
2119 brdp->isr = stl_echpci64intr;
2120 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2121 outb(0x43, (brdp->ioaddr1 + 0x4c));
2122 brdp->iosize1 = 0x80;
2123 brdp->iosize2 = 0x80;
2124 name = "serial(EC8/64-PCI)";
2125 break;
2126
2127 default:
2128 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002129 retval = -EINVAL;
2130 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 }
2132
2133/*
2134 * Check boards for possible IO address conflicts and return fail status
2135 * if an IO conflict found.
2136 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002137 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2139 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2140 "%x conflicts with another device\n", brdp->brdnr,
2141 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002142 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 }
2144
2145 if (brdp->iosize2 > 0)
2146 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2147 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2148 "address %x conflicts with another device\n",
2149 brdp->brdnr, brdp->ioaddr2);
2150 printk(KERN_WARNING "STALLION: Warning, also "
2151 "releasing board %d I/O address %x \n",
2152 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002153 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 }
2155
2156/*
2157 * Scan through the secondary io address space looking for panels.
2158 * As we find'em allocate and initialize panel structures for each.
2159 */
2160 brdp->clk = CD1400_CLK;
2161 brdp->hwid = status;
2162
2163 ioaddr = brdp->ioaddr2;
2164 banknr = 0;
2165 panelnr = 0;
2166 nxtid = 0;
2167
Jiri Slabyc62429d2006-12-08 02:39:14 -08002168 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 if (brdp->brdtype == BRD_ECHPCI) {
2170 outb(nxtid, brdp->ioctrl);
2171 ioaddr = brdp->ioaddr2;
2172 }
2173 status = inb(ioaddr + ECH_PNLSTATUS);
2174 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002175 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002176 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002177 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002179 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002180 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002181 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 panelp->magic = STL_PANELMAGIC;
2184 panelp->brdnr = brdp->brdnr;
2185 panelp->panelnr = panelnr;
2186 panelp->iobase = ioaddr;
2187 panelp->pagenr = nxtid;
2188 panelp->hwid = status;
2189 brdp->bnk2panel[banknr] = panelp;
2190 brdp->bnkpageaddr[banknr] = nxtid;
2191 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2192
2193 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002194 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 panelp->isr = stl_sc26198intr;
2196 if (status & ECH_PNL16PORT) {
2197 panelp->nrports = 16;
2198 brdp->bnk2panel[banknr] = panelp;
2199 brdp->bnkpageaddr[banknr] = nxtid;
2200 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2201 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002202 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002205 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 panelp->isr = stl_cd1400echintr;
2207 if (status & ECH_PNL16PORT) {
2208 panelp->nrports = 16;
2209 panelp->ackmask = 0x80;
2210 if (brdp->brdtype != BRD_ECHPCI)
2211 ioaddr += EREG_BANKSIZE;
2212 brdp->bnk2panel[banknr] = panelp;
2213 brdp->bnkpageaddr[banknr] = ++nxtid;
2214 brdp->bnkstataddr[banknr++] = ioaddr +
2215 ECH_PNLSTATUS;
2216 } else {
2217 panelp->nrports = 8;
2218 panelp->ackmask = 0xc0;
2219 }
2220 }
2221
2222 nxtid++;
2223 ioaddr += EREG_BANKSIZE;
2224 brdp->nrports += panelp->nrports;
2225 brdp->panels[panelnr++] = panelp;
2226 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002227 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2228 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002229 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 }
2232
2233 brdp->nrpanels = panelnr;
2234 brdp->nrbnks = banknr;
2235 if (brdp->brdtype == BRD_ECH)
2236 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2237
2238 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002239 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 printk("STALLION: failed to register interrupt "
2241 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002242 retval = -ENODEV;
2243 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 }
2245
Jiri Slaby3b85b342006-12-08 02:39:10 -08002246 return 0;
2247err_fr:
2248 stl_cleanup_panels(brdp);
2249 if (brdp->iosize2 > 0)
2250 release_region(brdp->ioaddr2, brdp->iosize2);
2251err_rel1:
2252 release_region(brdp->ioaddr1, brdp->iosize1);
2253err:
2254 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255}
2256
2257/*****************************************************************************/
2258
2259/*
2260 * Initialize and configure the specified board.
2261 * Scan through all the boards in the configuration and see what we
2262 * can find. Handle EIO and the ECH boards a little differently here
2263 * since the initial search and setup is very different.
2264 */
2265
Jiri Slaby705c1862006-12-08 02:39:11 -08002266static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002268 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269
Jiri Slabya0564e12006-12-08 02:38:37 -08002270 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271
2272 switch (brdp->brdtype) {
2273 case BRD_EASYIO:
2274 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002275 retval = stl_initeio(brdp);
2276 if (retval)
2277 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 break;
2279 case BRD_ECH:
2280 case BRD_ECHMC:
2281 case BRD_ECHPCI:
2282 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002283 retval = stl_initech(brdp);
2284 if (retval)
2285 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 break;
2287 default:
2288 printk("STALLION: board=%d is unknown board type=%d\n",
2289 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002290 retval = -ENODEV;
2291 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 }
2293
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 if ((brdp->state & BRD_FOUND) == 0) {
2295 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2296 stl_brdnames[brdp->brdtype], brdp->brdnr,
2297 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002298 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 }
2300
Jiri Slabyc62429d2006-12-08 02:39:14 -08002301 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002302 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 stl_initports(brdp, brdp->panels[i]);
2304
2305 printk("STALLION: %s found, board=%d io=%x irq=%d "
2306 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2307 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2308 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002309
2310 return 0;
2311err_free:
2312 free_irq(brdp->irq, brdp);
2313
2314 stl_cleanup_panels(brdp);
2315
2316 release_region(brdp->ioaddr1, brdp->iosize1);
2317 if (brdp->iosize2 > 0)
2318 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002319err:
2320 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321}
2322
2323/*****************************************************************************/
2324
2325/*
2326 * Find the next available board number that is free.
2327 */
2328
Jiri Slaby705c1862006-12-08 02:39:11 -08002329static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002331 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332
Jiri Slabyc62429d2006-12-08 02:39:14 -08002333 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002334 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 if (i >= stl_nrbrds)
2336 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002337 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002339
2340 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341}
2342
2343/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344/*
2345 * We have a Stallion board. Allocate a board structure and
2346 * initialize it. Read its IO and IRQ resources from PCI
2347 * configuration space.
2348 */
2349
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002350static int __devinit stl_pciprobe(struct pci_dev *pdev,
2351 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002353 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002354 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002355 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002357 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002358 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002359
2360 dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
2361 pdev->vendor, pdev->device, pdev->class);
2362
Jiri Slaby3b85b342006-12-08 02:39:10 -08002363 retval = pci_enable_device(pdev);
2364 if (retval)
2365 goto err;
2366 brdp = stl_allocbrd();
2367 if (brdp == NULL) {
2368 retval = -ENOMEM;
2369 goto err;
2370 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002371 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002372 brdnr = stl_getbrdnr();
2373 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002374 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002376 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002377 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002378 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002380 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002381 stl_brds[brdp->brdnr] = brdp;
2382 mutex_unlock(&stl_brdslock);
2383
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002385 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386
2387/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 * We have all resources from the board, so let's setup the actual
2389 * board structure now.
2390 */
2391 switch (brdtype) {
2392 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002393 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2394 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 break;
2396 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002397 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2398 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 break;
2400 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002401 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2402 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 break;
2404 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002405 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 break;
2407 }
2408
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002409 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002410 retval = stl_brdinit(brdp);
2411 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002412 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002414 pci_set_drvdata(pdev, brdp);
2415
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002416 for (i = 0; i < brdp->nrports; i++)
2417 tty_register_device(stl_serial,
2418 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2419
Jiri Slaby3b85b342006-12-08 02:39:10 -08002420 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002421err_null:
2422 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002423err_fr:
2424 kfree(brdp);
2425err:
2426 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427}
2428
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002429static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002431 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002432 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002434 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002436 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002438 release_region(brdp->ioaddr1, brdp->iosize1);
2439 if (brdp->iosize2 > 0)
2440 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002442 for (i = 0; i < brdp->nrports; i++)
2443 tty_unregister_device(stl_serial,
2444 brdp->brdnr * STL_MAXPORTS + i);
2445
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002446 stl_brds[brdp->brdnr] = NULL;
2447 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448}
2449
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002450static struct pci_driver stl_pcidriver = {
2451 .name = "stallion",
2452 .id_table = stl_pcibrds,
2453 .probe = stl_pciprobe,
2454 .remove = __devexit_p(stl_pciremove)
2455};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
2457/*****************************************************************************/
2458
2459/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 * Return the board stats structure to user app.
2461 */
2462
2463static int stl_getbrdstats(combrd_t __user *bp)
2464{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002465 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002466 struct stlbrd *brdp;
2467 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002468 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
2470 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2471 return -EFAULT;
2472 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002473 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002475 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002476 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
2478 memset(&stl_brdstats, 0, sizeof(combrd_t));
2479 stl_brdstats.brd = brdp->brdnr;
2480 stl_brdstats.type = brdp->brdtype;
2481 stl_brdstats.hwid = brdp->hwid;
2482 stl_brdstats.state = brdp->state;
2483 stl_brdstats.ioaddr = brdp->ioaddr1;
2484 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2485 stl_brdstats.irq = brdp->irq;
2486 stl_brdstats.nrpanels = brdp->nrpanels;
2487 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002488 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 panelp = brdp->panels[i];
2490 stl_brdstats.panels[i].panel = i;
2491 stl_brdstats.panels[i].hwid = panelp->hwid;
2492 stl_brdstats.panels[i].nrports = panelp->nrports;
2493 }
2494
2495 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2496}
2497
2498/*****************************************************************************/
2499
2500/*
2501 * Resolve the referenced port number into a port struct pointer.
2502 */
2503
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002504static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002506 struct stlbrd *brdp;
2507 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
Jiri Slabyc62429d2006-12-08 02:39:14 -08002509 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2510 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002512 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002513 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002514 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002515 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002517 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002518 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002519 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002520 return NULL;
2521 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522}
2523
2524/*****************************************************************************/
2525
2526/*
2527 * Return the port stats structure to user app. A NULL port struct
2528 * pointer passed in means that we need to find out from the app
2529 * what port to get stats for (used through board control device).
2530 */
2531
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002532static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002534 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 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)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002544 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 }
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 Slabyc62429d2006-12-08 02:39:14 -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 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002571 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572
2573 head = portp->tx.head;
2574 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002575 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2576 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577
2578 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2579
2580 return copy_to_user(cp, &portp->stats,
2581 sizeof(comstats_t)) ? -EFAULT : 0;
2582}
2583
2584/*****************************************************************************/
2585
2586/*
2587 * Clear the port stats structure. We also return it zeroed out...
2588 */
2589
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002590static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002592 comstats_t stl_comstats;
2593
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 if (!portp) {
2595 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2596 return -EFAULT;
2597 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2598 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002599 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002600 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 }
2602
2603 memset(&portp->stats, 0, sizeof(comstats_t));
2604 portp->stats.brd = portp->brdnr;
2605 portp->stats.panel = portp->panelnr;
2606 portp->stats.port = portp->portnr;
2607 return copy_to_user(cp, &portp->stats,
2608 sizeof(comstats_t)) ? -EFAULT : 0;
2609}
2610
2611/*****************************************************************************/
2612
2613/*
2614 * Return the entire driver ports structure to a user app.
2615 */
2616
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002617static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002619 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002620 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002622 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 return -EFAULT;
2624 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2625 stl_dummyport.portnr);
2626 if (!portp)
2627 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002628 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629}
2630
2631/*****************************************************************************/
2632
2633/*
2634 * Return the entire driver board structure to a user app.
2635 */
2636
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002637static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002639 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002640 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002642 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002644 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 return -ENODEV;
2646 brdp = stl_brds[stl_dummybrd.brdnr];
2647 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002648 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002649 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650}
2651
2652/*****************************************************************************/
2653
2654/*
2655 * The "staliomem" device is also required to do some special operations
2656 * on the board and/or ports. In this driver it is mostly used for stats
2657 * collection.
2658 */
2659
2660static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2661{
2662 int brdnr, rc;
2663 void __user *argp = (void __user *)arg;
2664
Jiri Slabya0564e12006-12-08 02:38:37 -08002665 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666
2667 brdnr = iminor(ip);
2668 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002669 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 rc = 0;
2671
2672 switch (cmd) {
2673 case COM_GETPORTSTATS:
2674 rc = stl_getportstats(NULL, argp);
2675 break;
2676 case COM_CLRPORTSTATS:
2677 rc = stl_clrportstats(NULL, argp);
2678 break;
2679 case COM_GETBRDSTATS:
2680 rc = stl_getbrdstats(argp);
2681 break;
2682 case COM_READPORT:
2683 rc = stl_getportstruct(argp);
2684 break;
2685 case COM_READBOARD:
2686 rc = stl_getbrdstruct(argp);
2687 break;
2688 default:
2689 rc = -ENOIOCTLCMD;
2690 break;
2691 }
2692
Jiri Slabyc62429d2006-12-08 02:39:14 -08002693 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694}
2695
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002696static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 .open = stl_open,
2698 .close = stl_close,
2699 .write = stl_write,
2700 .put_char = stl_putchar,
2701 .flush_chars = stl_flushchars,
2702 .write_room = stl_writeroom,
2703 .chars_in_buffer = stl_charsinbuffer,
2704 .ioctl = stl_ioctl,
2705 .set_termios = stl_settermios,
2706 .throttle = stl_throttle,
2707 .unthrottle = stl_unthrottle,
2708 .stop = stl_stop,
2709 .start = stl_start,
2710 .hangup = stl_hangup,
2711 .flush_buffer = stl_flushbuffer,
2712 .break_ctl = stl_breakctl,
2713 .wait_until_sent = stl_waituntilsent,
2714 .send_xchar = stl_sendxchar,
2715 .read_proc = stl_readproc,
2716 .tiocmget = stl_tiocmget,
2717 .tiocmset = stl_tiocmset,
2718};
2719
2720/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721/* CD1400 HARDWARE FUNCTIONS */
2722/*****************************************************************************/
2723
2724/*
2725 * These functions get/set/update the registers of the cd1400 UARTs.
2726 * Access to the cd1400 registers is via an address/data io port pair.
2727 * (Maybe should make this inline...)
2728 */
2729
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002730static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731{
2732 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002733 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734}
2735
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002736static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002738 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 outb(value, portp->ioaddr + EREG_DATA);
2740}
2741
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002742static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002744 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 if (inb(portp->ioaddr + EREG_DATA) != value) {
2746 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002747 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002749 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750}
2751
2752/*****************************************************************************/
2753
2754/*
2755 * Inbitialize the UARTs in a panel. We don't care what sort of board
2756 * these ports are on - since the port io registers are almost
2757 * identical when dealing with ports.
2758 */
2759
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002760static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761{
2762 unsigned int gfrcr;
2763 int chipmask, i, j;
2764 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002765 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766
Jiri Slabya0564e12006-12-08 02:38:37 -08002767 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
Alan Coxb65b5b52006-06-27 02:54:05 -07002769 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 BRDENABLE(panelp->brdnr, panelp->pagenr);
2771
2772/*
2773 * Check that each chip is present and started up OK.
2774 */
2775 chipmask = 0;
2776 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002777 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 if (brdp->brdtype == BRD_ECHPCI) {
2779 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2780 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002781 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 uartaddr = (i & 0x01) ? 0x080 : 0;
2784 outb((GFRCR + uartaddr), ioaddr);
2785 outb(0, (ioaddr + EREG_DATA));
2786 outb((CCR + uartaddr), ioaddr);
2787 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2788 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2789 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002790 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2792 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002793
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2795 printk("STALLION: cd1400 not responding, "
2796 "brd=%d panel=%d chip=%d\n",
2797 panelp->brdnr, panelp->panelnr, i);
2798 continue;
2799 }
2800 chipmask |= (0x1 << i);
2801 outb((PPR + uartaddr), ioaddr);
2802 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2803 }
2804
2805 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002806 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002807 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808}
2809
2810/*****************************************************************************/
2811
2812/*
2813 * Initialize hardware specific port registers.
2814 */
2815
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002816static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817{
Alan Coxb65b5b52006-06-27 02:54:05 -07002818 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002819 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2820 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821
Jiri Slaby615e4a72006-12-08 02:38:38 -08002822 if ((brdp == NULL) || (panelp == NULL) ||
2823 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 return;
2825
Alan Coxb65b5b52006-06-27 02:54:05 -07002826 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2828 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2829 portp->uartaddr = (portp->portnr & 0x04) << 5;
2830 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2831
2832 BRDENABLE(portp->brdnr, portp->pagenr);
2833 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2834 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2835 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2836 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002837 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838}
2839
2840/*****************************************************************************/
2841
2842/*
2843 * Wait for the command register to be ready. We will poll this,
2844 * since it won't usually take too long to be ready.
2845 */
2846
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002847static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848{
2849 int i;
2850
Jiri Slabyc62429d2006-12-08 02:39:14 -08002851 for (i = 0; i < CCR_MAXWAIT; i++)
2852 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854
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) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002989 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2990 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 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;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003005 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 portp->flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
3008/*
3009 * Setup cd1400 enhanced modes if we can. In particular we want to
3010 * handle as much of the flow control as possible automatically. As
3011 * well as saving a few CPU cycles it will also greatly improve flow
3012 * control reliability.
3013 */
3014 if (tiosp->c_iflag & IXON) {
3015 cor2 |= COR2_TXIBE;
3016 cor3 |= COR3_SCD12;
3017 if (tiosp->c_iflag & IXANY)
3018 cor2 |= COR2_IXM;
3019 }
3020
3021 if (tiosp->c_cflag & CRTSCTS) {
3022 cor2 |= COR2_CTSAE;
3023 mcor1 |= FIFO_RTSTHRESHOLD;
3024 }
3025
3026/*
3027 * All cd1400 register values calculated so go through and set
3028 * them all up.
3029 */
3030
Jiri Slabya0564e12006-12-08 02:38:37 -08003031 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003033 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003035 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003037 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3038 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3040 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041
Alan Coxb65b5b52006-06-27 02:54:05 -07003042 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 BRDENABLE(portp->brdnr, portp->pagenr);
3044 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3045 srer = stl_cd1400getreg(portp, SRER);
3046 stl_cd1400setreg(portp, SRER, 0);
3047 if (stl_cd1400updatereg(portp, COR1, cor1))
3048 ccr = 1;
3049 if (stl_cd1400updatereg(portp, COR2, cor2))
3050 ccr = 1;
3051 if (stl_cd1400updatereg(portp, COR3, cor3))
3052 ccr = 1;
3053 if (ccr) {
3054 stl_cd1400ccrwait(portp);
3055 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3056 }
3057 stl_cd1400setreg(portp, COR4, cor4);
3058 stl_cd1400setreg(portp, COR5, cor5);
3059 stl_cd1400setreg(portp, MCOR1, mcor1);
3060 stl_cd1400setreg(portp, MCOR2, mcor2);
3061 if (baudrate > 0) {
3062 stl_cd1400setreg(portp, TCOR, clk);
3063 stl_cd1400setreg(portp, TBPR, div);
3064 stl_cd1400setreg(portp, RCOR, clk);
3065 stl_cd1400setreg(portp, RBPR, div);
3066 }
3067 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3068 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3069 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3070 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3071 stl_cd1400setreg(portp, RTPR, rtpr);
3072 mcor1 = stl_cd1400getreg(portp, MSVR1);
3073 if (mcor1 & MSVR1_DCD)
3074 portp->sigs |= TIOCM_CD;
3075 else
3076 portp->sigs &= ~TIOCM_CD;
3077 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3078 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003079 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080}
3081
3082/*****************************************************************************/
3083
3084/*
3085 * Set the state of the DTR and RTS signals.
3086 */
3087
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003088static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089{
3090 unsigned char msvr1, msvr2;
3091 unsigned long flags;
3092
Jiri Slabya0564e12006-12-08 02:38:37 -08003093 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3094 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
3096 msvr1 = 0;
3097 msvr2 = 0;
3098 if (dtr > 0)
3099 msvr1 = MSVR1_DTR;
3100 if (rts > 0)
3101 msvr2 = MSVR2_RTS;
3102
Alan Coxb65b5b52006-06-27 02:54:05 -07003103 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 BRDENABLE(portp->brdnr, portp->pagenr);
3105 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3106 if (rts >= 0)
3107 stl_cd1400setreg(portp, MSVR2, msvr2);
3108 if (dtr >= 0)
3109 stl_cd1400setreg(portp, MSVR1, msvr1);
3110 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003111 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112}
3113
3114/*****************************************************************************/
3115
3116/*
3117 * Return the state of the signals.
3118 */
3119
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003120static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121{
3122 unsigned char msvr1, msvr2;
3123 unsigned long flags;
3124 int sigs;
3125
Jiri Slabya0564e12006-12-08 02:38:37 -08003126 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
Alan Coxb65b5b52006-06-27 02:54:05 -07003128 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 BRDENABLE(portp->brdnr, portp->pagenr);
3130 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3131 msvr1 = stl_cd1400getreg(portp, MSVR1);
3132 msvr2 = stl_cd1400getreg(portp, MSVR2);
3133 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003134 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135
3136 sigs = 0;
3137 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3138 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3139 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3140 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3141#if 0
3142 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3143 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3144#else
3145 sigs |= TIOCM_DSR;
3146#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003147 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148}
3149
3150/*****************************************************************************/
3151
3152/*
3153 * Enable/Disable the Transmitter and/or Receiver.
3154 */
3155
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003156static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157{
3158 unsigned char ccr;
3159 unsigned long flags;
3160
Jiri Slabya0564e12006-12-08 02:38:37 -08003161 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3162
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 ccr = 0;
3164
3165 if (tx == 0)
3166 ccr |= CCR_TXDISABLE;
3167 else if (tx > 0)
3168 ccr |= CCR_TXENABLE;
3169 if (rx == 0)
3170 ccr |= CCR_RXDISABLE;
3171 else if (rx > 0)
3172 ccr |= CCR_RXENABLE;
3173
Alan Coxb65b5b52006-06-27 02:54:05 -07003174 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 BRDENABLE(portp->brdnr, portp->pagenr);
3176 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3177 stl_cd1400ccrwait(portp);
3178 stl_cd1400setreg(portp, CCR, ccr);
3179 stl_cd1400ccrwait(portp);
3180 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003181 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182}
3183
3184/*****************************************************************************/
3185
3186/*
3187 * Start/stop the Transmitter and/or Receiver.
3188 */
3189
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003190static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191{
3192 unsigned char sreron, sreroff;
3193 unsigned long flags;
3194
Jiri Slabya0564e12006-12-08 02:38:37 -08003195 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
3197 sreron = 0;
3198 sreroff = 0;
3199 if (tx == 0)
3200 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3201 else if (tx == 1)
3202 sreron |= SRER_TXDATA;
3203 else if (tx >= 2)
3204 sreron |= SRER_TXEMPTY;
3205 if (rx == 0)
3206 sreroff |= SRER_RXDATA;
3207 else if (rx > 0)
3208 sreron |= SRER_RXDATA;
3209
Alan Coxb65b5b52006-06-27 02:54:05 -07003210 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 BRDENABLE(portp->brdnr, portp->pagenr);
3212 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3213 stl_cd1400setreg(portp, SRER,
3214 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3215 BRDDISABLE(portp->brdnr);
3216 if (tx > 0)
3217 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003218 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219}
3220
3221/*****************************************************************************/
3222
3223/*
3224 * Disable all interrupts from this port.
3225 */
3226
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003227static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228{
3229 unsigned long flags;
3230
Jiri Slabya0564e12006-12-08 02:38:37 -08003231 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3232
Alan Coxb65b5b52006-06-27 02:54:05 -07003233 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 BRDENABLE(portp->brdnr, portp->pagenr);
3235 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3236 stl_cd1400setreg(portp, SRER, 0);
3237 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003238 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239}
3240
3241/*****************************************************************************/
3242
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003243static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244{
3245 unsigned long flags;
3246
Jiri Slabya0564e12006-12-08 02:38:37 -08003247 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
Alan Coxb65b5b52006-06-27 02:54:05 -07003249 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250 BRDENABLE(portp->brdnr, portp->pagenr);
3251 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3252 stl_cd1400setreg(portp, SRER,
3253 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3254 SRER_TXEMPTY));
3255 BRDDISABLE(portp->brdnr);
3256 portp->brklen = len;
3257 if (len == 1)
3258 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003259 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260}
3261
3262/*****************************************************************************/
3263
3264/*
3265 * Take flow control actions...
3266 */
3267
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003268static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269{
3270 struct tty_struct *tty;
3271 unsigned long flags;
3272
Jiri Slabya0564e12006-12-08 02:38:37 -08003273 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274
Jiri Slaby615e4a72006-12-08 02:38:38 -08003275 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276 return;
3277 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003278 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279 return;
3280
Alan Coxb65b5b52006-06-27 02:54:05 -07003281 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282 BRDENABLE(portp->brdnr, portp->pagenr);
3283 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3284
3285 if (state) {
3286 if (tty->termios->c_iflag & IXOFF) {
3287 stl_cd1400ccrwait(portp);
3288 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3289 portp->stats.rxxon++;
3290 stl_cd1400ccrwait(portp);
3291 }
3292/*
3293 * Question: should we return RTS to what it was before? It may
3294 * have been set by an ioctl... Suppose not, since if you have
3295 * hardware flow control set then it is pretty silly to go and
3296 * set the RTS line by hand.
3297 */
3298 if (tty->termios->c_cflag & CRTSCTS) {
3299 stl_cd1400setreg(portp, MCOR1,
3300 (stl_cd1400getreg(portp, MCOR1) |
3301 FIFO_RTSTHRESHOLD));
3302 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3303 portp->stats.rxrtson++;
3304 }
3305 } else {
3306 if (tty->termios->c_iflag & IXOFF) {
3307 stl_cd1400ccrwait(portp);
3308 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3309 portp->stats.rxxoff++;
3310 stl_cd1400ccrwait(portp);
3311 }
3312 if (tty->termios->c_cflag & CRTSCTS) {
3313 stl_cd1400setreg(portp, MCOR1,
3314 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3315 stl_cd1400setreg(portp, MSVR2, 0);
3316 portp->stats.rxrtsoff++;
3317 }
3318 }
3319
3320 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003321 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322}
3323
3324/*****************************************************************************/
3325
3326/*
3327 * Send a flow control character...
3328 */
3329
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003330static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331{
3332 struct tty_struct *tty;
3333 unsigned long flags;
3334
Jiri Slabya0564e12006-12-08 02:38:37 -08003335 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336
Jiri Slaby615e4a72006-12-08 02:38:38 -08003337 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 return;
3339 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003340 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 return;
3342
Alan Coxb65b5b52006-06-27 02:54:05 -07003343 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 BRDENABLE(portp->brdnr, portp->pagenr);
3345 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3346 if (state) {
3347 stl_cd1400ccrwait(portp);
3348 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3349 portp->stats.rxxon++;
3350 stl_cd1400ccrwait(portp);
3351 } else {
3352 stl_cd1400ccrwait(portp);
3353 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3354 portp->stats.rxxoff++;
3355 stl_cd1400ccrwait(portp);
3356 }
3357 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003358 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359}
3360
3361/*****************************************************************************/
3362
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003363static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364{
3365 unsigned long flags;
3366
Jiri Slabya0564e12006-12-08 02:38:37 -08003367 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368
Jiri Slaby615e4a72006-12-08 02:38:38 -08003369 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 return;
3371
Alan Coxb65b5b52006-06-27 02:54:05 -07003372 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 BRDENABLE(portp->brdnr, portp->pagenr);
3374 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3375 stl_cd1400ccrwait(portp);
3376 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3377 stl_cd1400ccrwait(portp);
3378 portp->tx.tail = portp->tx.head;
3379 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003380 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381}
3382
3383/*****************************************************************************/
3384
3385/*
3386 * Return the current state of data flow on this port. This is only
3387 * really interresting when determining if data has fully completed
3388 * transmission or not... This is easy for the cd1400, it accurately
3389 * maintains the busy port flag.
3390 */
3391
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003392static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393{
Jiri Slabya0564e12006-12-08 02:38:37 -08003394 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395
Jiri Slaby615e4a72006-12-08 02:38:38 -08003396 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003397 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398
Jesper Juhl014c2542006-01-15 02:37:08 +01003399 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400}
3401
3402/*****************************************************************************/
3403
3404/*
3405 * Interrupt service routine for cd1400 EasyIO boards.
3406 */
3407
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003408static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409{
3410 unsigned char svrtype;
3411
Jiri Slabya0564e12006-12-08 02:38:37 -08003412 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413
Alan Coxb65b5b52006-06-27 02:54:05 -07003414 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 outb(SVRR, iobase);
3416 svrtype = inb(iobase + EREG_DATA);
3417 if (panelp->nrports > 4) {
3418 outb((SVRR + 0x80), iobase);
3419 svrtype |= inb(iobase + EREG_DATA);
3420 }
3421
3422 if (svrtype & SVRR_RX)
3423 stl_cd1400rxisr(panelp, iobase);
3424 else if (svrtype & SVRR_TX)
3425 stl_cd1400txisr(panelp, iobase);
3426 else if (svrtype & SVRR_MDM)
3427 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003428
3429 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430}
3431
3432/*****************************************************************************/
3433
3434/*
3435 * Interrupt service routine for cd1400 panels.
3436 */
3437
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003438static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439{
3440 unsigned char svrtype;
3441
Jiri Slabya0564e12006-12-08 02:38:37 -08003442 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443
3444 outb(SVRR, iobase);
3445 svrtype = inb(iobase + EREG_DATA);
3446 outb((SVRR + 0x80), iobase);
3447 svrtype |= inb(iobase + EREG_DATA);
3448 if (svrtype & SVRR_RX)
3449 stl_cd1400rxisr(panelp, iobase);
3450 else if (svrtype & SVRR_TX)
3451 stl_cd1400txisr(panelp, iobase);
3452 else if (svrtype & SVRR_MDM)
3453 stl_cd1400mdmisr(panelp, iobase);
3454}
3455
3456
3457/*****************************************************************************/
3458
3459/*
3460 * Unfortunately we need to handle breaks in the TX data stream, since
3461 * this is the only way to generate them on the cd1400.
3462 */
3463
Jiri Slaby60be4812006-12-08 02:38:40 -08003464static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465{
3466 if (portp->brklen == 1) {
3467 outb((COR2 + portp->uartaddr), ioaddr);
3468 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3469 (ioaddr + EREG_DATA));
3470 outb((TDR + portp->uartaddr), ioaddr);
3471 outb(ETC_CMD, (ioaddr + EREG_DATA));
3472 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3473 outb((SRER + portp->uartaddr), ioaddr);
3474 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3475 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003476 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477 } else if (portp->brklen > 1) {
3478 outb((TDR + portp->uartaddr), ioaddr);
3479 outb(ETC_CMD, (ioaddr + EREG_DATA));
3480 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3481 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003482 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 } else {
3484 outb((COR2 + portp->uartaddr), ioaddr);
3485 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3486 (ioaddr + EREG_DATA));
3487 portp->brklen = 0;
3488 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003489 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490}
3491
3492/*****************************************************************************/
3493
3494/*
3495 * Transmit interrupt handler. This has gotta be fast! Handling TX
3496 * chars is pretty simple, stuff as many as possible from the TX buffer
3497 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3498 * are embedded as commands in the data stream. Oh no, had to use a goto!
3499 * This could be optimized more, will do when I get time...
3500 * In practice it is possible that interrupts are enabled but that the
3501 * port has been hung up. Need to handle not having any TX buffer here,
3502 * this is done by using the side effect that head and tail will also
3503 * be NULL if the buffer has been freed.
3504 */
3505
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003506static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003508 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 int len, stlen;
3510 char *head, *tail;
3511 unsigned char ioack, srer;
3512
Jiri Slabya0564e12006-12-08 02:38:37 -08003513 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514
3515 ioack = inb(ioaddr + EREG_TXACK);
3516 if (((ioack & panelp->ackmask) != 0) ||
3517 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3518 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3519 return;
3520 }
3521 portp = panelp->ports[(ioack >> 3)];
3522
3523/*
3524 * Unfortunately we need to handle breaks in the data stream, since
3525 * this is the only way to generate them on the cd1400. Do it now if
3526 * a break is to be sent.
3527 */
3528 if (portp->brklen != 0)
3529 if (stl_cd1400breakisr(portp, ioaddr))
3530 goto stl_txalldone;
3531
3532 head = portp->tx.head;
3533 tail = portp->tx.tail;
3534 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3535 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3536 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3537 set_bit(ASYI_TXLOW, &portp->istate);
3538 schedule_work(&portp->tqueue);
3539 }
3540
3541 if (len == 0) {
3542 outb((SRER + portp->uartaddr), ioaddr);
3543 srer = inb(ioaddr + EREG_DATA);
3544 if (srer & SRER_TXDATA) {
3545 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3546 } else {
3547 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3548 clear_bit(ASYI_TXBUSY, &portp->istate);
3549 }
3550 outb(srer, (ioaddr + EREG_DATA));
3551 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003552 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08003554 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 outb((TDR + portp->uartaddr), ioaddr);
3556 outsb((ioaddr + EREG_DATA), tail, stlen);
3557 len -= stlen;
3558 tail += stlen;
3559 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3560 tail = portp->tx.buf;
3561 if (len > 0) {
3562 outsb((ioaddr + EREG_DATA), tail, len);
3563 tail += len;
3564 }
3565 portp->tx.tail = tail;
3566 }
3567
3568stl_txalldone:
3569 outb((EOSRR + portp->uartaddr), ioaddr);
3570 outb(0, (ioaddr + EREG_DATA));
3571}
3572
3573/*****************************************************************************/
3574
3575/*
3576 * Receive character interrupt handler. Determine if we have good chars
3577 * or bad chars and then process appropriately. Good chars are easy
3578 * just shove the lot into the RX buffer and set all status byte to 0.
3579 * If a bad RX char then process as required. This routine needs to be
3580 * fast! In practice it is possible that we get an interrupt on a port
3581 * that is closed. This can happen on hangups - since they completely
3582 * shutdown a port not in user context. Need to handle this case.
3583 */
3584
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003585static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003587 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588 struct tty_struct *tty;
3589 unsigned int ioack, len, buflen;
3590 unsigned char status;
3591 char ch;
3592
Jiri Slabya0564e12006-12-08 02:38:37 -08003593 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594
3595 ioack = inb(ioaddr + EREG_RXACK);
3596 if ((ioack & panelp->ackmask) != 0) {
3597 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3598 return;
3599 }
3600 portp = panelp->ports[(ioack >> 3)];
3601 tty = portp->tty;
3602
3603 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3604 outb((RDCR + portp->uartaddr), ioaddr);
3605 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003606 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08003607 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 outb((RDSR + portp->uartaddr), ioaddr);
3609 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3610 portp->stats.rxlost += len;
3611 portp->stats.rxtotal += len;
3612 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003613 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003615 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003617 tty_prepare_flip_string(tty, &ptr, len);
3618 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 tty_schedule_flip(tty);
3620 portp->stats.rxtotal += len;
3621 }
3622 }
3623 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3624 outb((RDSR + portp->uartaddr), ioaddr);
3625 status = inb(ioaddr + EREG_DATA);
3626 ch = inb(ioaddr + EREG_DATA);
3627 if (status & ST_PARITY)
3628 portp->stats.rxparity++;
3629 if (status & ST_FRAMING)
3630 portp->stats.rxframing++;
3631 if (status & ST_OVERRUN)
3632 portp->stats.rxoverrun++;
3633 if (status & ST_BREAK)
3634 portp->stats.rxbreaks++;
3635 if (status & ST_SCHARMASK) {
3636 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3637 portp->stats.txxon++;
3638 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3639 portp->stats.txxoff++;
3640 goto stl_rxalldone;
3641 }
Alan Cox33f0f882006-01-09 20:54:13 -08003642 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 if (portp->rxmarkmsk & status) {
3644 if (status & ST_BREAK) {
3645 status = TTY_BREAK;
3646 if (portp->flags & ASYNC_SAK) {
3647 do_SAK(tty);
3648 BRDENABLE(portp->brdnr, portp->pagenr);
3649 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003650 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003652 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003654 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003656 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003658 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003660 tty_insert_flip_char(tty, ch, status);
3661 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 }
3663 } else {
3664 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3665 return;
3666 }
3667
3668stl_rxalldone:
3669 outb((EOSRR + portp->uartaddr), ioaddr);
3670 outb(0, (ioaddr + EREG_DATA));
3671}
3672
3673/*****************************************************************************/
3674
3675/*
3676 * Modem interrupt handler. The is called when the modem signal line
3677 * (DCD) has changed state. Leave most of the work to the off-level
3678 * processing routine.
3679 */
3680
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003681static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003683 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684 unsigned int ioack;
3685 unsigned char misr;
3686
Jiri Slabya0564e12006-12-08 02:38:37 -08003687 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688
3689 ioack = inb(ioaddr + EREG_MDACK);
3690 if (((ioack & panelp->ackmask) != 0) ||
3691 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3692 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3693 return;
3694 }
3695 portp = panelp->ports[(ioack >> 3)];
3696
3697 outb((MISR + portp->uartaddr), ioaddr);
3698 misr = inb(ioaddr + EREG_DATA);
3699 if (misr & MISR_DCD) {
3700 set_bit(ASYI_DCDCHANGE, &portp->istate);
3701 schedule_work(&portp->tqueue);
3702 portp->stats.modem++;
3703 }
3704
3705 outb((EOSRR + portp->uartaddr), ioaddr);
3706 outb(0, (ioaddr + EREG_DATA));
3707}
3708
3709/*****************************************************************************/
3710/* SC26198 HARDWARE FUNCTIONS */
3711/*****************************************************************************/
3712
3713/*
3714 * These functions get/set/update the registers of the sc26198 UARTs.
3715 * Access to the sc26198 registers is via an address/data io port pair.
3716 * (Maybe should make this inline...)
3717 */
3718
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003719static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720{
3721 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003722 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723}
3724
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003725static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726{
3727 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3728 outb(value, (portp->ioaddr + XP_DATA));
3729}
3730
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003731static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732{
3733 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3734 if (inb(portp->ioaddr + XP_DATA) != value) {
3735 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003736 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003738 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739}
3740
3741/*****************************************************************************/
3742
3743/*
3744 * Functions to get and set the sc26198 global registers.
3745 */
3746
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003747static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748{
3749 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003750 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751}
3752
3753#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003754static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755{
3756 outb(regnr, (portp->ioaddr + XP_ADDR));
3757 outb(value, (portp->ioaddr + XP_DATA));
3758}
3759#endif
3760
3761/*****************************************************************************/
3762
3763/*
3764 * Inbitialize the UARTs in a panel. We don't care what sort of board
3765 * these ports are on - since the port io registers are almost
3766 * identical when dealing with ports.
3767 */
3768
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003769static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770{
3771 int chipmask, i;
3772 int nrchips, ioaddr;
3773
Jiri Slabya0564e12006-12-08 02:38:37 -08003774 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775
3776 BRDENABLE(panelp->brdnr, panelp->pagenr);
3777
3778/*
3779 * Check that each chip is present and started up OK.
3780 */
3781 chipmask = 0;
3782 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3783 if (brdp->brdtype == BRD_ECHPCI)
3784 outb(panelp->pagenr, brdp->ioctrl);
3785
Jiri Slabyc62429d2006-12-08 02:39:14 -08003786 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787 ioaddr = panelp->iobase + (i * 4);
3788 outb(SCCR, (ioaddr + XP_ADDR));
3789 outb(CR_RESETALL, (ioaddr + XP_DATA));
3790 outb(TSTR, (ioaddr + XP_ADDR));
3791 if (inb(ioaddr + XP_DATA) != 0) {
3792 printk("STALLION: sc26198 not responding, "
3793 "brd=%d panel=%d chip=%d\n",
3794 panelp->brdnr, panelp->panelnr, i);
3795 continue;
3796 }
3797 chipmask |= (0x1 << i);
3798 outb(GCCR, (ioaddr + XP_ADDR));
3799 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3800 outb(WDTRCR, (ioaddr + XP_ADDR));
3801 outb(0xff, (ioaddr + XP_DATA));
3802 }
3803
3804 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003805 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806}
3807
3808/*****************************************************************************/
3809
3810/*
3811 * Initialize hardware specific port registers.
3812 */
3813
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003814static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815{
Jiri Slabya0564e12006-12-08 02:38:37 -08003816 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3817 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818
Jiri Slaby615e4a72006-12-08 02:38:38 -08003819 if ((brdp == NULL) || (panelp == NULL) ||
3820 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 return;
3822
3823 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3824 portp->uartaddr = (portp->portnr & 0x07) << 4;
3825 portp->pagenr = panelp->pagenr;
3826 portp->hwid = 0x1;
3827
3828 BRDENABLE(portp->brdnr, portp->pagenr);
3829 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3830 BRDDISABLE(portp->brdnr);
3831}
3832
3833/*****************************************************************************/
3834
3835/*
3836 * Set up the sc26198 registers for a port based on the termios port
3837 * settings.
3838 */
3839
Alan Cox606d0992006-12-08 02:38:45 -08003840static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003842 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 unsigned long flags;
3844 unsigned int baudrate;
3845 unsigned char mr0, mr1, mr2, clk;
3846 unsigned char imron, imroff, iopr, ipr;
3847
3848 mr0 = 0;
3849 mr1 = 0;
3850 mr2 = 0;
3851 clk = 0;
3852 iopr = 0;
3853 imron = 0;
3854 imroff = 0;
3855
3856 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003857 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 return;
3859
3860/*
3861 * Set up the RX char ignore mask with those RX error types we
3862 * can ignore.
3863 */
3864 portp->rxignoremsk = 0;
3865 if (tiosp->c_iflag & IGNPAR)
3866 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3867 SR_RXOVERRUN);
3868 if (tiosp->c_iflag & IGNBRK)
3869 portp->rxignoremsk |= SR_RXBREAK;
3870
3871 portp->rxmarkmsk = SR_RXOVERRUN;
3872 if (tiosp->c_iflag & (INPCK | PARMRK))
3873 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3874 if (tiosp->c_iflag & BRKINT)
3875 portp->rxmarkmsk |= SR_RXBREAK;
3876
3877/*
3878 * Go through the char size, parity and stop bits and set all the
3879 * option register appropriately.
3880 */
3881 switch (tiosp->c_cflag & CSIZE) {
3882 case CS5:
3883 mr1 |= MR1_CS5;
3884 break;
3885 case CS6:
3886 mr1 |= MR1_CS6;
3887 break;
3888 case CS7:
3889 mr1 |= MR1_CS7;
3890 break;
3891 default:
3892 mr1 |= MR1_CS8;
3893 break;
3894 }
3895
3896 if (tiosp->c_cflag & CSTOPB)
3897 mr2 |= MR2_STOP2;
3898 else
3899 mr2 |= MR2_STOP1;
3900
3901 if (tiosp->c_cflag & PARENB) {
3902 if (tiosp->c_cflag & PARODD)
3903 mr1 |= (MR1_PARENB | MR1_PARODD);
3904 else
3905 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003906 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908
3909 mr1 |= MR1_ERRBLOCK;
3910
3911/*
3912 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3913 * space for hardware flow control and the like. This should be set to
3914 * VMIN.
3915 */
3916 mr2 |= MR2_RXFIFOHALF;
3917
3918/*
3919 * Calculate the baud rate timers. For now we will just assume that
3920 * the input and output baud are the same. The sc26198 has a fixed
3921 * baud rate table, so only discrete baud rates possible.
3922 */
3923 baudrate = tiosp->c_cflag & CBAUD;
3924 if (baudrate & CBAUDEX) {
3925 baudrate &= ~CBAUDEX;
3926 if ((baudrate < 1) || (baudrate > 4))
3927 tiosp->c_cflag &= ~CBAUDEX;
3928 else
3929 baudrate += 15;
3930 }
3931 baudrate = stl_baudrates[baudrate];
3932 if ((tiosp->c_cflag & CBAUD) == B38400) {
3933 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3934 baudrate = 57600;
3935 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3936 baudrate = 115200;
3937 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3938 baudrate = 230400;
3939 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3940 baudrate = 460800;
3941 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3942 baudrate = (portp->baud_base / portp->custom_divisor);
3943 }
3944 if (baudrate > STL_SC26198MAXBAUD)
3945 baudrate = STL_SC26198MAXBAUD;
3946
Jiri Slabyc62429d2006-12-08 02:39:14 -08003947 if (baudrate > 0)
3948 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 if (baudrate <= sc26198_baudtable[clk])
3950 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951
3952/*
3953 * Check what form of modem signaling is required and set it up.
3954 */
3955 if (tiosp->c_cflag & CLOCAL) {
3956 portp->flags &= ~ASYNC_CHECK_CD;
3957 } else {
3958 iopr |= IOPR_DCDCOS;
3959 imron |= IR_IOPORT;
3960 portp->flags |= ASYNC_CHECK_CD;
3961 }
3962
3963/*
3964 * Setup sc26198 enhanced modes if we can. In particular we want to
3965 * handle as much of the flow control as possible automatically. As
3966 * well as saving a few CPU cycles it will also greatly improve flow
3967 * control reliability.
3968 */
3969 if (tiosp->c_iflag & IXON) {
3970 mr0 |= MR0_SWFTX | MR0_SWFT;
3971 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003972 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003974
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 if (tiosp->c_iflag & IXOFF)
3976 mr0 |= MR0_SWFRX;
3977
3978 if (tiosp->c_cflag & CRTSCTS) {
3979 mr2 |= MR2_AUTOCTS;
3980 mr1 |= MR1_AUTORTS;
3981 }
3982
3983/*
3984 * All sc26198 register values calculated so go through and set
3985 * them all up.
3986 */
3987
Jiri Slabya0564e12006-12-08 02:38:37 -08003988 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003990 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3991 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3992 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3994 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995
Alan Coxb65b5b52006-06-27 02:54:05 -07003996 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997 BRDENABLE(portp->brdnr, portp->pagenr);
3998 stl_sc26198setreg(portp, IMR, 0);
3999 stl_sc26198updatereg(portp, MR0, mr0);
4000 stl_sc26198updatereg(portp, MR1, mr1);
4001 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4002 stl_sc26198updatereg(portp, MR2, mr2);
4003 stl_sc26198updatereg(portp, IOPIOR,
4004 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4005
4006 if (baudrate > 0) {
4007 stl_sc26198setreg(portp, TXCSR, clk);
4008 stl_sc26198setreg(portp, RXCSR, clk);
4009 }
4010
4011 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4012 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4013
4014 ipr = stl_sc26198getreg(portp, IPR);
4015 if (ipr & IPR_DCD)
4016 portp->sigs &= ~TIOCM_CD;
4017 else
4018 portp->sigs |= TIOCM_CD;
4019
4020 portp->imr = (portp->imr & ~imroff) | imron;
4021 stl_sc26198setreg(portp, IMR, portp->imr);
4022 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004023 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024}
4025
4026/*****************************************************************************/
4027
4028/*
4029 * Set the state of the DTR and RTS signals.
4030 */
4031
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004032static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033{
4034 unsigned char iopioron, iopioroff;
4035 unsigned long flags;
4036
Jiri Slabya0564e12006-12-08 02:38:37 -08004037 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4038 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039
4040 iopioron = 0;
4041 iopioroff = 0;
4042 if (dtr == 0)
4043 iopioroff |= IPR_DTR;
4044 else if (dtr > 0)
4045 iopioron |= IPR_DTR;
4046 if (rts == 0)
4047 iopioroff |= IPR_RTS;
4048 else if (rts > 0)
4049 iopioron |= IPR_RTS;
4050
Alan Coxb65b5b52006-06-27 02:54:05 -07004051 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 BRDENABLE(portp->brdnr, portp->pagenr);
4053 stl_sc26198setreg(portp, IOPIOR,
4054 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4055 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004056 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057}
4058
4059/*****************************************************************************/
4060
4061/*
4062 * Return the state of the signals.
4063 */
4064
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004065static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066{
4067 unsigned char ipr;
4068 unsigned long flags;
4069 int sigs;
4070
Jiri Slabya0564e12006-12-08 02:38:37 -08004071 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072
Alan Coxb65b5b52006-06-27 02:54:05 -07004073 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074 BRDENABLE(portp->brdnr, portp->pagenr);
4075 ipr = stl_sc26198getreg(portp, IPR);
4076 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004077 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
4079 sigs = 0;
4080 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4081 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4082 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4083 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4084 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004085 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086}
4087
4088/*****************************************************************************/
4089
4090/*
4091 * Enable/Disable the Transmitter and/or Receiver.
4092 */
4093
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004094static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095{
4096 unsigned char ccr;
4097 unsigned long flags;
4098
Jiri Slabya0564e12006-12-08 02:38:37 -08004099 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100
4101 ccr = portp->crenable;
4102 if (tx == 0)
4103 ccr &= ~CR_TXENABLE;
4104 else if (tx > 0)
4105 ccr |= CR_TXENABLE;
4106 if (rx == 0)
4107 ccr &= ~CR_RXENABLE;
4108 else if (rx > 0)
4109 ccr |= CR_RXENABLE;
4110
Alan Coxb65b5b52006-06-27 02:54:05 -07004111 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 BRDENABLE(portp->brdnr, portp->pagenr);
4113 stl_sc26198setreg(portp, SCCR, ccr);
4114 BRDDISABLE(portp->brdnr);
4115 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004116 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117}
4118
4119/*****************************************************************************/
4120
4121/*
4122 * Start/stop the Transmitter and/or Receiver.
4123 */
4124
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004125static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126{
4127 unsigned char imr;
4128 unsigned long flags;
4129
Jiri Slabya0564e12006-12-08 02:38:37 -08004130 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131
4132 imr = portp->imr;
4133 if (tx == 0)
4134 imr &= ~IR_TXRDY;
4135 else if (tx == 1)
4136 imr |= IR_TXRDY;
4137 if (rx == 0)
4138 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4139 else if (rx > 0)
4140 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4141
Alan Coxb65b5b52006-06-27 02:54:05 -07004142 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 BRDENABLE(portp->brdnr, portp->pagenr);
4144 stl_sc26198setreg(portp, IMR, imr);
4145 BRDDISABLE(portp->brdnr);
4146 portp->imr = imr;
4147 if (tx > 0)
4148 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004149 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150}
4151
4152/*****************************************************************************/
4153
4154/*
4155 * Disable all interrupts from this port.
4156 */
4157
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004158static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159{
4160 unsigned long flags;
4161
Jiri Slabya0564e12006-12-08 02:38:37 -08004162 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163
Alan Coxb65b5b52006-06-27 02:54:05 -07004164 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165 BRDENABLE(portp->brdnr, portp->pagenr);
4166 portp->imr = 0;
4167 stl_sc26198setreg(portp, IMR, 0);
4168 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004169 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170}
4171
4172/*****************************************************************************/
4173
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004174static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175{
4176 unsigned long flags;
4177
Jiri Slabya0564e12006-12-08 02:38:37 -08004178 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
Alan Coxb65b5b52006-06-27 02:54:05 -07004180 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 BRDENABLE(portp->brdnr, portp->pagenr);
4182 if (len == 1) {
4183 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4184 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004185 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004187
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004189 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190}
4191
4192/*****************************************************************************/
4193
4194/*
4195 * Take flow control actions...
4196 */
4197
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004198static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199{
4200 struct tty_struct *tty;
4201 unsigned long flags;
4202 unsigned char mr0;
4203
Jiri Slabya0564e12006-12-08 02:38:37 -08004204 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205
Jiri Slaby615e4a72006-12-08 02:38:38 -08004206 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207 return;
4208 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004209 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 return;
4211
Alan Coxb65b5b52006-06-27 02:54:05 -07004212 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 BRDENABLE(portp->brdnr, portp->pagenr);
4214
4215 if (state) {
4216 if (tty->termios->c_iflag & IXOFF) {
4217 mr0 = stl_sc26198getreg(portp, MR0);
4218 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4219 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4220 mr0 |= MR0_SWFRX;
4221 portp->stats.rxxon++;
4222 stl_sc26198wait(portp);
4223 stl_sc26198setreg(portp, MR0, mr0);
4224 }
4225/*
4226 * Question: should we return RTS to what it was before? It may
4227 * have been set by an ioctl... Suppose not, since if you have
4228 * hardware flow control set then it is pretty silly to go and
4229 * set the RTS line by hand.
4230 */
4231 if (tty->termios->c_cflag & CRTSCTS) {
4232 stl_sc26198setreg(portp, MR1,
4233 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4234 stl_sc26198setreg(portp, IOPIOR,
4235 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4236 portp->stats.rxrtson++;
4237 }
4238 } else {
4239 if (tty->termios->c_iflag & IXOFF) {
4240 mr0 = stl_sc26198getreg(portp, MR0);
4241 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4242 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4243 mr0 &= ~MR0_SWFRX;
4244 portp->stats.rxxoff++;
4245 stl_sc26198wait(portp);
4246 stl_sc26198setreg(portp, MR0, mr0);
4247 }
4248 if (tty->termios->c_cflag & CRTSCTS) {
4249 stl_sc26198setreg(portp, MR1,
4250 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4251 stl_sc26198setreg(portp, IOPIOR,
4252 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4253 portp->stats.rxrtsoff++;
4254 }
4255 }
4256
4257 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004258 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259}
4260
4261/*****************************************************************************/
4262
4263/*
4264 * Send a flow control character.
4265 */
4266
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004267static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268{
4269 struct tty_struct *tty;
4270 unsigned long flags;
4271 unsigned char mr0;
4272
Jiri Slabya0564e12006-12-08 02:38:37 -08004273 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274
Jiri Slaby615e4a72006-12-08 02:38:38 -08004275 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276 return;
4277 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004278 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 return;
4280
Alan Coxb65b5b52006-06-27 02:54:05 -07004281 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 BRDENABLE(portp->brdnr, portp->pagenr);
4283 if (state) {
4284 mr0 = stl_sc26198getreg(portp, MR0);
4285 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4286 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4287 mr0 |= MR0_SWFRX;
4288 portp->stats.rxxon++;
4289 stl_sc26198wait(portp);
4290 stl_sc26198setreg(portp, MR0, mr0);
4291 } else {
4292 mr0 = stl_sc26198getreg(portp, MR0);
4293 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4294 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4295 mr0 &= ~MR0_SWFRX;
4296 portp->stats.rxxoff++;
4297 stl_sc26198wait(portp);
4298 stl_sc26198setreg(portp, MR0, mr0);
4299 }
4300 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004301 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302}
4303
4304/*****************************************************************************/
4305
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004306static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307{
4308 unsigned long flags;
4309
Jiri Slabya0564e12006-12-08 02:38:37 -08004310 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311
Jiri Slaby615e4a72006-12-08 02:38:38 -08004312 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 return;
4314
Alan Coxb65b5b52006-06-27 02:54:05 -07004315 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316 BRDENABLE(portp->brdnr, portp->pagenr);
4317 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4318 stl_sc26198setreg(portp, SCCR, portp->crenable);
4319 BRDDISABLE(portp->brdnr);
4320 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004321 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322}
4323
4324/*****************************************************************************/
4325
4326/*
4327 * Return the current state of data flow on this port. This is only
4328 * really interresting when determining if data has fully completed
4329 * transmission or not... The sc26198 interrupt scheme cannot
4330 * determine when all data has actually drained, so we need to
4331 * check the port statusy register to be sure.
4332 */
4333
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004334static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335{
4336 unsigned long flags;
4337 unsigned char sr;
4338
Jiri Slabya0564e12006-12-08 02:38:37 -08004339 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340
Jiri Slaby615e4a72006-12-08 02:38:38 -08004341 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004342 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004344 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
Alan Coxb65b5b52006-06-27 02:54:05 -07004346 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 BRDENABLE(portp->brdnr, portp->pagenr);
4348 sr = stl_sc26198getreg(portp, SR);
4349 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004350 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351
Jesper Juhl014c2542006-01-15 02:37:08 +01004352 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353}
4354
4355/*****************************************************************************/
4356
4357/*
4358 * Delay for a small amount of time, to give the sc26198 a chance
4359 * to process a command...
4360 */
4361
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004362static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363{
4364 int i;
4365
Jiri Slabya0564e12006-12-08 02:38:37 -08004366 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367
Jiri Slaby615e4a72006-12-08 02:38:38 -08004368 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 return;
4370
Jiri Slabyc62429d2006-12-08 02:39:14 -08004371 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372 stl_sc26198getglobreg(portp, TSTR);
4373}
4374
4375/*****************************************************************************/
4376
4377/*
4378 * If we are TX flow controlled and in IXANY mode then we may
4379 * need to unflow control here. We gotta do this because of the
4380 * automatic flow control modes of the sc26198.
4381 */
4382
Jiri Slaby60be4812006-12-08 02:38:40 -08004383static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384{
4385 unsigned char mr0;
4386
4387 mr0 = stl_sc26198getreg(portp, MR0);
4388 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4389 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4390 stl_sc26198wait(portp);
4391 stl_sc26198setreg(portp, MR0, mr0);
4392 clear_bit(ASYI_TXFLOWED, &portp->istate);
4393}
4394
4395/*****************************************************************************/
4396
4397/*
4398 * Interrupt service routine for sc26198 panels.
4399 */
4400
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004401static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004403 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404 unsigned int iack;
4405
Alan Coxb65b5b52006-06-27 02:54:05 -07004406 spin_lock(&brd_lock);
4407
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408/*
4409 * Work around bug in sc26198 chip... Cannot have A6 address
4410 * line of UART high, else iack will be returned as 0.
4411 */
4412 outb(0, (iobase + 1));
4413
4414 iack = inb(iobase + XP_IACK);
4415 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4416
4417 if (iack & IVR_RXDATA)
4418 stl_sc26198rxisr(portp, iack);
4419 else if (iack & IVR_TXDATA)
4420 stl_sc26198txisr(portp);
4421 else
4422 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004423
4424 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425}
4426
4427/*****************************************************************************/
4428
4429/*
4430 * Transmit interrupt handler. This has gotta be fast! Handling TX
4431 * chars is pretty simple, stuff as many as possible from the TX buffer
4432 * into the sc26198 FIFO.
4433 * In practice it is possible that interrupts are enabled but that the
4434 * port has been hung up. Need to handle not having any TX buffer here,
4435 * this is done by using the side effect that head and tail will also
4436 * be NULL if the buffer has been freed.
4437 */
4438
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004439static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440{
4441 unsigned int ioaddr;
4442 unsigned char mr0;
4443 int len, stlen;
4444 char *head, *tail;
4445
Jiri Slabya0564e12006-12-08 02:38:37 -08004446 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447
4448 ioaddr = portp->ioaddr;
4449 head = portp->tx.head;
4450 tail = portp->tx.tail;
4451 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4452 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4453 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4454 set_bit(ASYI_TXLOW, &portp->istate);
4455 schedule_work(&portp->tqueue);
4456 }
4457
4458 if (len == 0) {
4459 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4460 mr0 = inb(ioaddr + XP_DATA);
4461 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4462 portp->imr &= ~IR_TXRDY;
4463 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4464 outb(portp->imr, (ioaddr + XP_DATA));
4465 clear_bit(ASYI_TXBUSY, &portp->istate);
4466 } else {
4467 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4468 outb(mr0, (ioaddr + XP_DATA));
4469 }
4470 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004471 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08004473 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474 outb(GTXFIFO, (ioaddr + XP_ADDR));
4475 outsb((ioaddr + XP_DATA), tail, stlen);
4476 len -= stlen;
4477 tail += stlen;
4478 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4479 tail = portp->tx.buf;
4480 if (len > 0) {
4481 outsb((ioaddr + XP_DATA), tail, len);
4482 tail += len;
4483 }
4484 portp->tx.tail = tail;
4485 }
4486}
4487
4488/*****************************************************************************/
4489
4490/*
4491 * Receive character interrupt handler. Determine if we have good chars
4492 * or bad chars and then process appropriately. Good chars are easy
4493 * just shove the lot into the RX buffer and set all status byte to 0.
4494 * If a bad RX char then process as required. This routine needs to be
4495 * fast! In practice it is possible that we get an interrupt on a port
4496 * that is closed. This can happen on hangups - since they completely
4497 * shutdown a port not in user context. Need to handle this case.
4498 */
4499
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004500static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501{
4502 struct tty_struct *tty;
4503 unsigned int len, buflen, ioaddr;
4504
Jiri Slabya0564e12006-12-08 02:38:37 -08004505 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
4507 tty = portp->tty;
4508 ioaddr = portp->ioaddr;
4509 outb(GIBCR, (ioaddr + XP_ADDR));
4510 len = inb(ioaddr + XP_DATA) + 1;
4511
4512 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004513 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08004514 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 outb(GRXFIFO, (ioaddr + XP_ADDR));
4516 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4517 portp->stats.rxlost += len;
4518 portp->stats.rxtotal += len;
4519 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004520 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004522 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004523 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004524 tty_prepare_flip_string(tty, &ptr, len);
4525 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526 tty_schedule_flip(tty);
4527 portp->stats.rxtotal += len;
4528 }
4529 }
4530 } else {
4531 stl_sc26198rxbadchars(portp);
4532 }
4533
4534/*
4535 * If we are TX flow controlled and in IXANY mode then we may need
4536 * to unflow control here. We gotta do this because of the automatic
4537 * flow control modes of the sc26198.
4538 */
4539 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004540 if ((tty != NULL) &&
4541 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542 (tty->termios->c_iflag & IXANY)) {
4543 stl_sc26198txunflow(portp, tty);
4544 }
4545 }
4546}
4547
4548/*****************************************************************************/
4549
4550/*
4551 * Process an RX bad character.
4552 */
4553
Jiri Slaby60be4812006-12-08 02:38:40 -08004554static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555{
4556 struct tty_struct *tty;
4557 unsigned int ioaddr;
4558
4559 tty = portp->tty;
4560 ioaddr = portp->ioaddr;
4561
4562 if (status & SR_RXPARITY)
4563 portp->stats.rxparity++;
4564 if (status & SR_RXFRAMING)
4565 portp->stats.rxframing++;
4566 if (status & SR_RXOVERRUN)
4567 portp->stats.rxoverrun++;
4568 if (status & SR_RXBREAK)
4569 portp->stats.rxbreaks++;
4570
Jiri Slaby615e4a72006-12-08 02:38:38 -08004571 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572 ((portp->rxignoremsk & status) == 0)) {
4573 if (portp->rxmarkmsk & status) {
4574 if (status & SR_RXBREAK) {
4575 status = TTY_BREAK;
4576 if (portp->flags & ASYNC_SAK) {
4577 do_SAK(tty);
4578 BRDENABLE(portp->brdnr, portp->pagenr);
4579 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004580 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004582 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004584 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004586 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004588 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590
Alan Cox33f0f882006-01-09 20:54:13 -08004591 tty_insert_flip_char(tty, ch, status);
4592 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593
4594 if (status == 0)
4595 portp->stats.rxtotal++;
4596 }
4597}
4598
4599/*****************************************************************************/
4600
4601/*
4602 * Process all characters in the RX FIFO of the UART. Check all char
4603 * status bytes as well, and process as required. We need to check
4604 * all bytes in the FIFO, in case some more enter the FIFO while we
4605 * are here. To get the exact character error type we need to switch
4606 * into CHAR error mode (that is why we need to make sure we empty
4607 * the FIFO).
4608 */
4609
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004610static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611{
4612 unsigned char status, mr1;
4613 char ch;
4614
4615/*
4616 * To get the precise error type for each character we must switch
4617 * back into CHAR error mode.
4618 */
4619 mr1 = stl_sc26198getreg(portp, MR1);
4620 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4621
4622 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4623 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4624 ch = stl_sc26198getreg(portp, RXFIFO);
4625 stl_sc26198rxbadch(portp, status, ch);
4626 }
4627
4628/*
4629 * To get correct interrupt class we must switch back into BLOCK
4630 * error mode.
4631 */
4632 stl_sc26198setreg(portp, MR1, mr1);
4633}
4634
4635/*****************************************************************************/
4636
4637/*
4638 * Other interrupt handler. This includes modem signals, flow
4639 * control actions, etc. Most stuff is left to off-level interrupt
4640 * processing time.
4641 */
4642
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004643static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644{
4645 unsigned char cir, ipr, xisr;
4646
Jiri Slabya0564e12006-12-08 02:38:37 -08004647 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648
4649 cir = stl_sc26198getglobreg(portp, CIR);
4650
4651 switch (cir & CIR_SUBTYPEMASK) {
4652 case CIR_SUBCOS:
4653 ipr = stl_sc26198getreg(portp, IPR);
4654 if (ipr & IPR_DCDCHANGE) {
4655 set_bit(ASYI_DCDCHANGE, &portp->istate);
4656 schedule_work(&portp->tqueue);
4657 portp->stats.modem++;
4658 }
4659 break;
4660 case CIR_SUBXONXOFF:
4661 xisr = stl_sc26198getreg(portp, XISR);
4662 if (xisr & XISR_RXXONGOT) {
4663 set_bit(ASYI_TXFLOWED, &portp->istate);
4664 portp->stats.txxoff++;
4665 }
4666 if (xisr & XISR_RXXOFFGOT) {
4667 clear_bit(ASYI_TXFLOWED, &portp->istate);
4668 portp->stats.txxon++;
4669 }
4670 break;
4671 case CIR_SUBBREAK:
4672 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4673 stl_sc26198rxbadchars(portp);
4674 break;
4675 default:
4676 break;
4677 }
4678}
4679
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004680static void stl_free_isabrds(void)
4681{
4682 struct stlbrd *brdp;
4683 unsigned int i;
4684
4685 for (i = 0; i < stl_nrbrds; i++) {
4686 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4687 continue;
4688
4689 free_irq(brdp->irq, brdp);
4690
4691 stl_cleanup_panels(brdp);
4692
4693 release_region(brdp->ioaddr1, brdp->iosize1);
4694 if (brdp->iosize2 > 0)
4695 release_region(brdp->ioaddr2, brdp->iosize2);
4696
4697 kfree(brdp);
4698 stl_brds[i] = NULL;
4699 }
4700}
4701
Jiri Slaby23b85a12006-12-08 02:38:40 -08004702/*
4703 * Loadable module initialization stuff.
4704 */
4705static int __init stallion_module_init(void)
4706{
Jiri Slaby843b5682006-12-08 02:39:12 -08004707 struct stlbrd *brdp;
4708 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004709 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004710 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004711
4712 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4713
4714 spin_lock_init(&stallion_lock);
4715 spin_lock_init(&brd_lock);
4716
Jiri Slabye4151092007-06-08 13:46:52 -07004717 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4718 if (!stl_serial) {
4719 retval = -ENOMEM;
4720 goto err;
4721 }
4722
4723 stl_serial->owner = THIS_MODULE;
4724 stl_serial->driver_name = stl_drvname;
4725 stl_serial->name = "ttyE";
4726 stl_serial->major = STL_SERIALMAJOR;
4727 stl_serial->minor_start = 0;
4728 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4729 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4730 stl_serial->init_termios = stl_deftermios;
4731 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4732 tty_set_operations(stl_serial, &stl_ops);
4733
4734 retval = tty_register_driver(stl_serial);
4735 if (retval) {
4736 printk("STALLION: failed to register serial driver\n");
4737 goto err_frtty;
4738 }
4739
Jiri Slaby843b5682006-12-08 02:39:12 -08004740/*
4741 * Find any dynamically supported boards. That is via module load
4742 * line options.
4743 */
4744 for (i = stl_nrbrds; i < stl_nargs; i++) {
4745 memset(&conf, 0, sizeof(conf));
4746 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4747 continue;
4748 if ((brdp = stl_allocbrd()) == NULL)
4749 continue;
4750 brdp->brdnr = i;
4751 brdp->brdtype = conf.brdtype;
4752 brdp->ioaddr1 = conf.ioaddr1;
4753 brdp->ioaddr2 = conf.ioaddr2;
4754 brdp->irq = conf.irq;
4755 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004756 stl_brds[brdp->brdnr] = brdp;
4757 if (stl_brdinit(brdp)) {
4758 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004759 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004760 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004761 for (j = 0; j < brdp->nrports; j++)
4762 tty_register_device(stl_serial,
4763 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004764 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004765 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004766 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004767
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004768 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004769 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004770 if (retval && stl_nrbrds == 0) {
4771 printk(KERN_ERR "STALLION: can't register pci driver\n");
4772 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004773 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004774
4775/*
4776 * Set up a character driver for per board stuff. This is mainly used
4777 * to do stats ioctls on the ports.
4778 */
4779 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4780 printk("STALLION: failed to register serial board device\n");
4781
4782 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004783 if (IS_ERR(stallion_class))
4784 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004785 for (i = 0; i < 4; i++)
4786 class_device_create(stallion_class, NULL,
4787 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4788 "staliomem%d", i);
4789
Jiri Slaby23b85a12006-12-08 02:38:40 -08004790 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004791err_unrtty:
4792 tty_unregister_driver(stl_serial);
4793err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004794 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004795err:
4796 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004797}
4798
4799static void __exit stallion_module_exit(void)
4800{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004801 struct stlbrd *brdp;
4802 unsigned int i, j;
4803 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004804
4805 pr_debug("cleanup_module()\n");
4806
4807 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4808 stl_drvversion);
4809
4810/*
4811 * Free up all allocated resources used by the ports. This includes
4812 * memory and interrupts. As part of this process we will also do
4813 * a hangup on every open port - to try to flush out any processes
4814 * hanging onto ports.
4815 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004816 for (i = 0; i < stl_nrbrds; i++) {
4817 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4818 continue;
4819 for (j = 0; j < brdp->nrports; j++)
4820 tty_unregister_device(stl_serial,
4821 brdp->brdnr * STL_MAXPORTS + j);
4822 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004823
Jiri Slaby23b85a12006-12-08 02:38:40 -08004824 for (i = 0; i < 4; i++)
4825 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004826 if ((retval = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
Jiri Slaby23b85a12006-12-08 02:38:40 -08004827 printk("STALLION: failed to un-register serial memory device, "
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004828 "errno=%d\n", -retval);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004829 class_destroy(stallion_class);
4830
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004831 pci_unregister_driver(&stl_pcidriver);
4832
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004833 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004834
4835 tty_unregister_driver(stl_serial);
4836 put_tty_driver(stl_serial);
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");