blob: 45758d5b56ef88f3c2700fb218b55d6b71994b90 [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
Jiri Slabyc62429d2006-12-08 02:39:14 -08001791 if (test_bit(ASYI_TXLOW, &portp->istate))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 tty_wakeup(tty);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001793
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1795 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1796 oldsigs = portp->sigs;
1797 portp->sigs = stl_getsignals(portp);
1798 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1799 wake_up_interruptible(&portp->open_wait);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001800 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 if (portp->flags & ASYNC_CHECK_CD)
1802 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804}
1805
1806/*****************************************************************************/
1807
1808/*
1809 * Initialize all the ports on a panel.
1810 */
1811
Jiri Slaby705c1862006-12-08 02:39:11 -08001812static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001814 struct stlport *portp;
1815 unsigned int i;
1816 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
Jiri Slabya0564e12006-12-08 02:38:37 -08001818 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
1820 chipmask = stl_panelinit(brdp, panelp);
1821
1822/*
1823 * All UART's are initialized (if found!). Now go through and setup
1824 * each ports data structures.
1825 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001826 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001827 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001828 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001830 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 break;
1832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
1834 portp->magic = STL_PORTMAGIC;
1835 portp->portnr = i;
1836 portp->brdnr = panelp->brdnr;
1837 portp->panelnr = panelp->panelnr;
1838 portp->uartp = panelp->uartp;
1839 portp->clk = brdp->clk;
1840 portp->baud_base = STL_BAUDBASE;
1841 portp->close_delay = STL_CLOSEDELAY;
1842 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001843 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 init_waitqueue_head(&portp->open_wait);
1845 init_waitqueue_head(&portp->close_wait);
1846 portp->stats.brd = portp->brdnr;
1847 portp->stats.panel = portp->panelnr;
1848 portp->stats.port = portp->portnr;
1849 panelp->ports[i] = portp;
1850 stl_portinit(brdp, panelp, portp);
1851 }
1852
Jiri Slabyc62429d2006-12-08 02:39:14 -08001853 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854}
1855
Jiri Slaby3b85b342006-12-08 02:39:10 -08001856static void stl_cleanup_panels(struct stlbrd *brdp)
1857{
1858 struct stlpanel *panelp;
1859 struct stlport *portp;
1860 unsigned int j, k;
1861
1862 for (j = 0; j < STL_MAXPANELS; j++) {
1863 panelp = brdp->panels[j];
1864 if (panelp == NULL)
1865 continue;
1866 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1867 portp = panelp->ports[k];
1868 if (portp == NULL)
1869 continue;
1870 if (portp->tty != NULL)
1871 stl_hangup(portp->tty);
1872 kfree(portp->tx.buf);
1873 kfree(portp);
1874 }
1875 kfree(panelp);
1876 }
1877}
1878
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879/*****************************************************************************/
1880
1881/*
1882 * Try to find and initialize an EasyIO board.
1883 */
1884
Jiri Slaby705c1862006-12-08 02:39:11 -08001885static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001887 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 unsigned int status;
1889 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001890 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891
Jiri Slabya0564e12006-12-08 02:38:37 -08001892 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
1894 brdp->ioctrl = brdp->ioaddr1 + 1;
1895 brdp->iostatus = brdp->ioaddr1 + 2;
1896
1897 status = inb(brdp->iostatus);
1898 if ((status & EIO_IDBITMASK) == EIO_MK3)
1899 brdp->ioctrl++;
1900
1901/*
1902 * Handle board specific stuff now. The real difference is PCI
1903 * or not PCI.
1904 */
1905 if (brdp->brdtype == BRD_EASYIOPCI) {
1906 brdp->iosize1 = 0x80;
1907 brdp->iosize2 = 0x80;
1908 name = "serial(EIO-PCI)";
1909 outb(0x41, (brdp->ioaddr2 + 0x4c));
1910 } else {
1911 brdp->iosize1 = 8;
1912 name = "serial(EIO)";
1913 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1914 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1915 printk("STALLION: invalid irq=%d for brd=%d\n",
1916 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001917 retval = -EINVAL;
1918 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 }
1920 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1921 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1922 brdp->ioctrl);
1923 }
1924
Jiri Slaby3b85b342006-12-08 02:39:10 -08001925 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1927 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1928 "%x conflicts with another device\n", brdp->brdnr,
1929 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001930 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 }
1932
1933 if (brdp->iosize2 > 0)
1934 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1935 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1936 "address %x conflicts with another device\n",
1937 brdp->brdnr, brdp->ioaddr2);
1938 printk(KERN_WARNING "STALLION: Warning, also "
1939 "releasing board %d I/O address %x \n",
1940 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001941 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 }
1943
1944/*
1945 * Everything looks OK, so let's go ahead and probe for the hardware.
1946 */
1947 brdp->clk = CD1400_CLK;
1948 brdp->isr = stl_eiointr;
1949
Jiri Slaby3b85b342006-12-08 02:39:10 -08001950 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 switch (status & EIO_IDBITMASK) {
1952 case EIO_8PORTM:
1953 brdp->clk = CD1400_CLK8M;
1954 /* fall thru */
1955 case EIO_8PORTRS:
1956 case EIO_8PORTDI:
1957 brdp->nrports = 8;
1958 break;
1959 case EIO_4PORTRS:
1960 brdp->nrports = 4;
1961 break;
1962 case EIO_MK3:
1963 switch (status & EIO_BRDMASK) {
1964 case ID_BRD4:
1965 brdp->nrports = 4;
1966 break;
1967 case ID_BRD8:
1968 brdp->nrports = 8;
1969 break;
1970 case ID_BRD16:
1971 brdp->nrports = 16;
1972 break;
1973 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001974 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 }
1976 break;
1977 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001978 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 }
1980
1981/*
1982 * We have verified that the board is actually present, so now we
1983 * can complete the setup.
1984 */
1985
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001986 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001987 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001989 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001990 retval = -ENOMEM;
1991 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993
1994 panelp->magic = STL_PANELMAGIC;
1995 panelp->brdnr = brdp->brdnr;
1996 panelp->panelnr = 0;
1997 panelp->nrports = brdp->nrports;
1998 panelp->iobase = brdp->ioaddr1;
1999 panelp->hwid = status;
2000 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002001 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 panelp->isr = stl_sc26198intr;
2003 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002004 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 panelp->isr = stl_cd1400eiointr;
2006 }
2007
2008 brdp->panels[0] = panelp;
2009 brdp->nrpanels = 1;
2010 brdp->state |= BRD_FOUND;
2011 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002012 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 printk("STALLION: failed to register interrupt "
2014 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002015 retval = -ENODEV;
2016 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08002018
2019 return 0;
2020err_fr:
2021 stl_cleanup_panels(brdp);
2022err_rel2:
2023 if (brdp->iosize2 > 0)
2024 release_region(brdp->ioaddr2, brdp->iosize2);
2025err_rel1:
2026 release_region(brdp->ioaddr1, brdp->iosize1);
2027err:
2028 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029}
2030
2031/*****************************************************************************/
2032
2033/*
2034 * Try to find an ECH board and initialize it. This code is capable of
2035 * dealing with all types of ECH board.
2036 */
2037
Jiri Slaby705c1862006-12-08 02:39:11 -08002038static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002040 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002041 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
2042 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 char *name;
2044
Jiri Slabya0564e12006-12-08 02:38:37 -08002045 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
2047 status = 0;
2048 conflict = 0;
2049
2050/*
2051 * Set up the initial board register contents for boards. This varies a
2052 * bit between the different board types. So we need to handle each
2053 * separately. Also do a check that the supplied IRQ is good.
2054 */
2055 switch (brdp->brdtype) {
2056
2057 case BRD_ECH:
2058 brdp->isr = stl_echatintr;
2059 brdp->ioctrl = brdp->ioaddr1 + 1;
2060 brdp->iostatus = brdp->ioaddr1 + 1;
2061 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002062 if ((status & ECH_IDBITMASK) != ECH_ID) {
2063 retval = -ENODEV;
2064 goto err;
2065 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2067 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2068 printk("STALLION: invalid irq=%d for brd=%d\n",
2069 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002070 retval = -EINVAL;
2071 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 }
2073 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2074 status |= (stl_vecmap[brdp->irq] << 1);
2075 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2076 brdp->ioctrlval = ECH_INTENABLE |
2077 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002078 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2080 brdp->iosize1 = 2;
2081 brdp->iosize2 = 32;
2082 name = "serial(EC8/32)";
2083 outb(status, brdp->ioaddr1);
2084 break;
2085
2086 case BRD_ECHMC:
2087 brdp->isr = stl_echmcaintr;
2088 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2089 brdp->iostatus = brdp->ioctrl;
2090 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002091 if ((status & ECH_IDBITMASK) != ECH_ID) {
2092 retval = -ENODEV;
2093 goto err;
2094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2096 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2097 printk("STALLION: invalid irq=%d for brd=%d\n",
2098 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002099 retval = -EINVAL;
2100 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 }
2102 outb(ECHMC_BRDRESET, brdp->ioctrl);
2103 outb(ECHMC_INTENABLE, brdp->ioctrl);
2104 brdp->iosize1 = 64;
2105 name = "serial(EC8/32-MC)";
2106 break;
2107
2108 case BRD_ECHPCI:
2109 brdp->isr = stl_echpciintr;
2110 brdp->ioctrl = brdp->ioaddr1 + 2;
2111 brdp->iosize1 = 4;
2112 brdp->iosize2 = 8;
2113 name = "serial(EC8/32-PCI)";
2114 break;
2115
2116 case BRD_ECH64PCI:
2117 brdp->isr = stl_echpci64intr;
2118 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2119 outb(0x43, (brdp->ioaddr1 + 0x4c));
2120 brdp->iosize1 = 0x80;
2121 brdp->iosize2 = 0x80;
2122 name = "serial(EC8/64-PCI)";
2123 break;
2124
2125 default:
2126 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002127 retval = -EINVAL;
2128 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 }
2130
2131/*
2132 * Check boards for possible IO address conflicts and return fail status
2133 * if an IO conflict found.
2134 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002135 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2137 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2138 "%x conflicts with another device\n", brdp->brdnr,
2139 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002140 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 }
2142
2143 if (brdp->iosize2 > 0)
2144 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2145 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2146 "address %x conflicts with another device\n",
2147 brdp->brdnr, brdp->ioaddr2);
2148 printk(KERN_WARNING "STALLION: Warning, also "
2149 "releasing board %d I/O address %x \n",
2150 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002151 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 }
2153
2154/*
2155 * Scan through the secondary io address space looking for panels.
2156 * As we find'em allocate and initialize panel structures for each.
2157 */
2158 brdp->clk = CD1400_CLK;
2159 brdp->hwid = status;
2160
2161 ioaddr = brdp->ioaddr2;
2162 banknr = 0;
2163 panelnr = 0;
2164 nxtid = 0;
2165
Jiri Slabyc62429d2006-12-08 02:39:14 -08002166 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 if (brdp->brdtype == BRD_ECHPCI) {
2168 outb(nxtid, brdp->ioctrl);
2169 ioaddr = brdp->ioaddr2;
2170 }
2171 status = inb(ioaddr + ECH_PNLSTATUS);
2172 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002173 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002174 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002175 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002177 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002178 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002179 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 panelp->magic = STL_PANELMAGIC;
2182 panelp->brdnr = brdp->brdnr;
2183 panelp->panelnr = panelnr;
2184 panelp->iobase = ioaddr;
2185 panelp->pagenr = nxtid;
2186 panelp->hwid = status;
2187 brdp->bnk2panel[banknr] = panelp;
2188 brdp->bnkpageaddr[banknr] = nxtid;
2189 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2190
2191 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002192 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 panelp->isr = stl_sc26198intr;
2194 if (status & ECH_PNL16PORT) {
2195 panelp->nrports = 16;
2196 brdp->bnk2panel[banknr] = panelp;
2197 brdp->bnkpageaddr[banknr] = nxtid;
2198 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2199 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002200 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002203 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 panelp->isr = stl_cd1400echintr;
2205 if (status & ECH_PNL16PORT) {
2206 panelp->nrports = 16;
2207 panelp->ackmask = 0x80;
2208 if (brdp->brdtype != BRD_ECHPCI)
2209 ioaddr += EREG_BANKSIZE;
2210 brdp->bnk2panel[banknr] = panelp;
2211 brdp->bnkpageaddr[banknr] = ++nxtid;
2212 brdp->bnkstataddr[banknr++] = ioaddr +
2213 ECH_PNLSTATUS;
2214 } else {
2215 panelp->nrports = 8;
2216 panelp->ackmask = 0xc0;
2217 }
2218 }
2219
2220 nxtid++;
2221 ioaddr += EREG_BANKSIZE;
2222 brdp->nrports += panelp->nrports;
2223 brdp->panels[panelnr++] = panelp;
2224 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002225 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2226 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002227 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 }
2230
2231 brdp->nrpanels = panelnr;
2232 brdp->nrbnks = banknr;
2233 if (brdp->brdtype == BRD_ECH)
2234 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2235
2236 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002237 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 printk("STALLION: failed to register interrupt "
2239 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002240 retval = -ENODEV;
2241 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 }
2243
Jiri Slaby3b85b342006-12-08 02:39:10 -08002244 return 0;
2245err_fr:
2246 stl_cleanup_panels(brdp);
2247 if (brdp->iosize2 > 0)
2248 release_region(brdp->ioaddr2, brdp->iosize2);
2249err_rel1:
2250 release_region(brdp->ioaddr1, brdp->iosize1);
2251err:
2252 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253}
2254
2255/*****************************************************************************/
2256
2257/*
2258 * Initialize and configure the specified board.
2259 * Scan through all the boards in the configuration and see what we
2260 * can find. Handle EIO and the ECH boards a little differently here
2261 * since the initial search and setup is very different.
2262 */
2263
Jiri Slaby705c1862006-12-08 02:39:11 -08002264static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002266 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267
Jiri Slabya0564e12006-12-08 02:38:37 -08002268 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269
2270 switch (brdp->brdtype) {
2271 case BRD_EASYIO:
2272 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002273 retval = stl_initeio(brdp);
2274 if (retval)
2275 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 break;
2277 case BRD_ECH:
2278 case BRD_ECHMC:
2279 case BRD_ECHPCI:
2280 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002281 retval = stl_initech(brdp);
2282 if (retval)
2283 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 break;
2285 default:
2286 printk("STALLION: board=%d is unknown board type=%d\n",
2287 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002288 retval = -ENODEV;
2289 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 }
2291
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 if ((brdp->state & BRD_FOUND) == 0) {
2293 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2294 stl_brdnames[brdp->brdtype], brdp->brdnr,
2295 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002296 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 }
2298
Jiri Slabyc62429d2006-12-08 02:39:14 -08002299 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002300 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 stl_initports(brdp, brdp->panels[i]);
2302
2303 printk("STALLION: %s found, board=%d io=%x irq=%d "
2304 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2305 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2306 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002307
2308 return 0;
2309err_free:
2310 free_irq(brdp->irq, brdp);
2311
2312 stl_cleanup_panels(brdp);
2313
2314 release_region(brdp->ioaddr1, brdp->iosize1);
2315 if (brdp->iosize2 > 0)
2316 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002317err:
2318 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319}
2320
2321/*****************************************************************************/
2322
2323/*
2324 * Find the next available board number that is free.
2325 */
2326
Jiri Slaby705c1862006-12-08 02:39:11 -08002327static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002329 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330
Jiri Slabyc62429d2006-12-08 02:39:14 -08002331 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002332 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 if (i >= stl_nrbrds)
2334 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002335 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002337
2338 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339}
2340
2341/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342/*
2343 * We have a Stallion board. Allocate a board structure and
2344 * initialize it. Read its IO and IRQ resources from PCI
2345 * configuration space.
2346 */
2347
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002348static int __devinit stl_pciprobe(struct pci_dev *pdev,
2349 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002351 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002352 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002353 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002355 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002356 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002357
Jiri Slaby3b85b342006-12-08 02:39:10 -08002358 retval = pci_enable_device(pdev);
2359 if (retval)
2360 goto err;
2361 brdp = stl_allocbrd();
2362 if (brdp == NULL) {
2363 retval = -ENOMEM;
2364 goto err;
2365 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002366 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002367 brdnr = stl_getbrdnr();
2368 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002369 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002371 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002372 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002373 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002375 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002376 stl_brds[brdp->brdnr] = brdp;
2377 mutex_unlock(&stl_brdslock);
2378
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002380 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
2382/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 * We have all resources from the board, so let's setup the actual
2384 * board structure now.
2385 */
2386 switch (brdtype) {
2387 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002388 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2389 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 break;
2391 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002392 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2393 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 break;
2395 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002396 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2397 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 break;
2399 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002400 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 break;
2402 }
2403
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002404 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002405 retval = stl_brdinit(brdp);
2406 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002407 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002409 pci_set_drvdata(pdev, brdp);
2410
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002411 for (i = 0; i < brdp->nrports; i++)
2412 tty_register_device(stl_serial,
2413 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2414
Jiri Slaby3b85b342006-12-08 02:39:10 -08002415 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002416err_null:
2417 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002418err_fr:
2419 kfree(brdp);
2420err:
2421 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422}
2423
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002424static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002426 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002427 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002429 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002431 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002433 release_region(brdp->ioaddr1, brdp->iosize1);
2434 if (brdp->iosize2 > 0)
2435 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002437 for (i = 0; i < brdp->nrports; i++)
2438 tty_unregister_device(stl_serial,
2439 brdp->brdnr * STL_MAXPORTS + i);
2440
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002441 stl_brds[brdp->brdnr] = NULL;
2442 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443}
2444
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002445static struct pci_driver stl_pcidriver = {
2446 .name = "stallion",
2447 .id_table = stl_pcibrds,
2448 .probe = stl_pciprobe,
2449 .remove = __devexit_p(stl_pciremove)
2450};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
2452/*****************************************************************************/
2453
2454/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 * Return the board stats structure to user app.
2456 */
2457
2458static int stl_getbrdstats(combrd_t __user *bp)
2459{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002460 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002461 struct stlbrd *brdp;
2462 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002463 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
2465 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2466 return -EFAULT;
2467 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002468 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002470 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002471 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
2473 memset(&stl_brdstats, 0, sizeof(combrd_t));
2474 stl_brdstats.brd = brdp->brdnr;
2475 stl_brdstats.type = brdp->brdtype;
2476 stl_brdstats.hwid = brdp->hwid;
2477 stl_brdstats.state = brdp->state;
2478 stl_brdstats.ioaddr = brdp->ioaddr1;
2479 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2480 stl_brdstats.irq = brdp->irq;
2481 stl_brdstats.nrpanels = brdp->nrpanels;
2482 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002483 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 panelp = brdp->panels[i];
2485 stl_brdstats.panels[i].panel = i;
2486 stl_brdstats.panels[i].hwid = panelp->hwid;
2487 stl_brdstats.panels[i].nrports = panelp->nrports;
2488 }
2489
2490 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2491}
2492
2493/*****************************************************************************/
2494
2495/*
2496 * Resolve the referenced port number into a port struct pointer.
2497 */
2498
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002499static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002501 struct stlbrd *brdp;
2502 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503
Jiri Slabyc62429d2006-12-08 02:39:14 -08002504 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2505 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002507 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002508 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002509 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002510 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002512 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002513 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002514 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002515 return NULL;
2516 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517}
2518
2519/*****************************************************************************/
2520
2521/*
2522 * Return the port stats structure to user app. A NULL port struct
2523 * pointer passed in means that we need to find out from the app
2524 * what port to get stats for (used through board control device).
2525 */
2526
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002527static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002529 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 unsigned char *head, *tail;
2531 unsigned long flags;
2532
2533 if (!portp) {
2534 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2535 return -EFAULT;
2536 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2537 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002538 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002539 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 }
2541
2542 portp->stats.state = portp->istate;
2543 portp->stats.flags = portp->flags;
2544 portp->stats.hwid = portp->hwid;
2545
2546 portp->stats.ttystate = 0;
2547 portp->stats.cflags = 0;
2548 portp->stats.iflags = 0;
2549 portp->stats.oflags = 0;
2550 portp->stats.lflags = 0;
2551 portp->stats.rxbuffered = 0;
2552
Alan Coxb65b5b52006-06-27 02:54:05 -07002553 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002554 if (portp->tty != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 if (portp->tty->driver_data == portp) {
2556 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002557 /* No longer available as a statistic */
2558 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002559 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 portp->stats.cflags = portp->tty->termios->c_cflag;
2561 portp->stats.iflags = portp->tty->termios->c_iflag;
2562 portp->stats.oflags = portp->tty->termios->c_oflag;
2563 portp->stats.lflags = portp->tty->termios->c_lflag;
2564 }
2565 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002566 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
2568 head = portp->tx.head;
2569 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002570 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2571 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572
2573 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2574
2575 return copy_to_user(cp, &portp->stats,
2576 sizeof(comstats_t)) ? -EFAULT : 0;
2577}
2578
2579/*****************************************************************************/
2580
2581/*
2582 * Clear the port stats structure. We also return it zeroed out...
2583 */
2584
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002585static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002587 comstats_t stl_comstats;
2588
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 if (!portp) {
2590 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2591 return -EFAULT;
2592 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2593 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002594 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002595 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 }
2597
2598 memset(&portp->stats, 0, sizeof(comstats_t));
2599 portp->stats.brd = portp->brdnr;
2600 portp->stats.panel = portp->panelnr;
2601 portp->stats.port = portp->portnr;
2602 return copy_to_user(cp, &portp->stats,
2603 sizeof(comstats_t)) ? -EFAULT : 0;
2604}
2605
2606/*****************************************************************************/
2607
2608/*
2609 * Return the entire driver ports structure to a user app.
2610 */
2611
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002612static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002614 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002615 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002617 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 return -EFAULT;
2619 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2620 stl_dummyport.portnr);
2621 if (!portp)
2622 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002623 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624}
2625
2626/*****************************************************************************/
2627
2628/*
2629 * Return the entire driver board structure to a user app.
2630 */
2631
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002632static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002634 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002635 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002637 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002639 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 return -ENODEV;
2641 brdp = stl_brds[stl_dummybrd.brdnr];
2642 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002643 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002644 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645}
2646
2647/*****************************************************************************/
2648
2649/*
2650 * The "staliomem" device is also required to do some special operations
2651 * on the board and/or ports. In this driver it is mostly used for stats
2652 * collection.
2653 */
2654
2655static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2656{
2657 int brdnr, rc;
2658 void __user *argp = (void __user *)arg;
2659
Jiri Slabya0564e12006-12-08 02:38:37 -08002660 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
2662 brdnr = iminor(ip);
2663 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002664 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 rc = 0;
2666
2667 switch (cmd) {
2668 case COM_GETPORTSTATS:
2669 rc = stl_getportstats(NULL, argp);
2670 break;
2671 case COM_CLRPORTSTATS:
2672 rc = stl_clrportstats(NULL, argp);
2673 break;
2674 case COM_GETBRDSTATS:
2675 rc = stl_getbrdstats(argp);
2676 break;
2677 case COM_READPORT:
2678 rc = stl_getportstruct(argp);
2679 break;
2680 case COM_READBOARD:
2681 rc = stl_getbrdstruct(argp);
2682 break;
2683 default:
2684 rc = -ENOIOCTLCMD;
2685 break;
2686 }
2687
Jiri Slabyc62429d2006-12-08 02:39:14 -08002688 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689}
2690
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002691static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 .open = stl_open,
2693 .close = stl_close,
2694 .write = stl_write,
2695 .put_char = stl_putchar,
2696 .flush_chars = stl_flushchars,
2697 .write_room = stl_writeroom,
2698 .chars_in_buffer = stl_charsinbuffer,
2699 .ioctl = stl_ioctl,
2700 .set_termios = stl_settermios,
2701 .throttle = stl_throttle,
2702 .unthrottle = stl_unthrottle,
2703 .stop = stl_stop,
2704 .start = stl_start,
2705 .hangup = stl_hangup,
2706 .flush_buffer = stl_flushbuffer,
2707 .break_ctl = stl_breakctl,
2708 .wait_until_sent = stl_waituntilsent,
2709 .send_xchar = stl_sendxchar,
2710 .read_proc = stl_readproc,
2711 .tiocmget = stl_tiocmget,
2712 .tiocmset = stl_tiocmset,
2713};
2714
2715/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716/* CD1400 HARDWARE FUNCTIONS */
2717/*****************************************************************************/
2718
2719/*
2720 * These functions get/set/update the registers of the cd1400 UARTs.
2721 * Access to the cd1400 registers is via an address/data io port pair.
2722 * (Maybe should make this inline...)
2723 */
2724
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002725static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726{
2727 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002728 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729}
2730
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002731static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002733 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 outb(value, portp->ioaddr + EREG_DATA);
2735}
2736
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002737static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002739 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 if (inb(portp->ioaddr + EREG_DATA) != value) {
2741 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002742 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002744 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745}
2746
2747/*****************************************************************************/
2748
2749/*
2750 * Inbitialize the UARTs in a panel. We don't care what sort of board
2751 * these ports are on - since the port io registers are almost
2752 * identical when dealing with ports.
2753 */
2754
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002755static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756{
2757 unsigned int gfrcr;
2758 int chipmask, i, j;
2759 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002760 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
Jiri Slabya0564e12006-12-08 02:38:37 -08002762 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763
Alan Coxb65b5b52006-06-27 02:54:05 -07002764 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 BRDENABLE(panelp->brdnr, panelp->pagenr);
2766
2767/*
2768 * Check that each chip is present and started up OK.
2769 */
2770 chipmask = 0;
2771 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002772 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 if (brdp->brdtype == BRD_ECHPCI) {
2774 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2775 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002776 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 uartaddr = (i & 0x01) ? 0x080 : 0;
2779 outb((GFRCR + uartaddr), ioaddr);
2780 outb(0, (ioaddr + EREG_DATA));
2781 outb((CCR + uartaddr), ioaddr);
2782 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2783 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2784 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002785 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2787 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002788
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2790 printk("STALLION: cd1400 not responding, "
2791 "brd=%d panel=%d chip=%d\n",
2792 panelp->brdnr, panelp->panelnr, i);
2793 continue;
2794 }
2795 chipmask |= (0x1 << i);
2796 outb((PPR + uartaddr), ioaddr);
2797 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2798 }
2799
2800 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002801 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002802 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803}
2804
2805/*****************************************************************************/
2806
2807/*
2808 * Initialize hardware specific port registers.
2809 */
2810
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002811static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812{
Alan Coxb65b5b52006-06-27 02:54:05 -07002813 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002814 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2815 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816
Jiri Slaby615e4a72006-12-08 02:38:38 -08002817 if ((brdp == NULL) || (panelp == NULL) ||
2818 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 return;
2820
Alan Coxb65b5b52006-06-27 02:54:05 -07002821 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2823 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2824 portp->uartaddr = (portp->portnr & 0x04) << 5;
2825 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2826
2827 BRDENABLE(portp->brdnr, portp->pagenr);
2828 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2829 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2830 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2831 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002832 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833}
2834
2835/*****************************************************************************/
2836
2837/*
2838 * Wait for the command register to be ready. We will poll this,
2839 * since it won't usually take too long to be ready.
2840 */
2841
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002842static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843{
2844 int i;
2845
Jiri Slabyc62429d2006-12-08 02:39:14 -08002846 for (i = 0; i < CCR_MAXWAIT; i++)
2847 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849
2850 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2851 portp->portnr, portp->panelnr, portp->brdnr);
2852}
2853
2854/*****************************************************************************/
2855
2856/*
2857 * Set up the cd1400 registers for a port based on the termios port
2858 * settings.
2859 */
2860
Alan Cox606d0992006-12-08 02:38:45 -08002861static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002863 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 unsigned long flags;
2865 unsigned int clkdiv, baudrate;
2866 unsigned char cor1, cor2, cor3;
2867 unsigned char cor4, cor5, ccr;
2868 unsigned char srer, sreron, sreroff;
2869 unsigned char mcor1, mcor2, rtpr;
2870 unsigned char clk, div;
2871
2872 cor1 = 0;
2873 cor2 = 0;
2874 cor3 = 0;
2875 cor4 = 0;
2876 cor5 = 0;
2877 ccr = 0;
2878 rtpr = 0;
2879 clk = 0;
2880 div = 0;
2881 mcor1 = 0;
2882 mcor2 = 0;
2883 sreron = 0;
2884 sreroff = 0;
2885
2886 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002887 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 return;
2889
2890/*
2891 * Set up the RX char ignore mask with those RX error types we
2892 * can ignore. We can get the cd1400 to help us out a little here,
2893 * it will ignore parity errors and breaks for us.
2894 */
2895 portp->rxignoremsk = 0;
2896 if (tiosp->c_iflag & IGNPAR) {
2897 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2898 cor1 |= COR1_PARIGNORE;
2899 }
2900 if (tiosp->c_iflag & IGNBRK) {
2901 portp->rxignoremsk |= ST_BREAK;
2902 cor4 |= COR4_IGNBRK;
2903 }
2904
2905 portp->rxmarkmsk = ST_OVERRUN;
2906 if (tiosp->c_iflag & (INPCK | PARMRK))
2907 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2908 if (tiosp->c_iflag & BRKINT)
2909 portp->rxmarkmsk |= ST_BREAK;
2910
2911/*
2912 * Go through the char size, parity and stop bits and set all the
2913 * option register appropriately.
2914 */
2915 switch (tiosp->c_cflag & CSIZE) {
2916 case CS5:
2917 cor1 |= COR1_CHL5;
2918 break;
2919 case CS6:
2920 cor1 |= COR1_CHL6;
2921 break;
2922 case CS7:
2923 cor1 |= COR1_CHL7;
2924 break;
2925 default:
2926 cor1 |= COR1_CHL8;
2927 break;
2928 }
2929
2930 if (tiosp->c_cflag & CSTOPB)
2931 cor1 |= COR1_STOP2;
2932 else
2933 cor1 |= COR1_STOP1;
2934
2935 if (tiosp->c_cflag & PARENB) {
2936 if (tiosp->c_cflag & PARODD)
2937 cor1 |= (COR1_PARENB | COR1_PARODD);
2938 else
2939 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2940 } else {
2941 cor1 |= COR1_PARNONE;
2942 }
2943
2944/*
2945 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2946 * space for hardware flow control and the like. This should be set to
2947 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2948 * really be based on VTIME.
2949 */
2950 cor3 |= FIFO_RXTHRESHOLD;
2951 rtpr = 2;
2952
2953/*
2954 * Calculate the baud rate timers. For now we will just assume that
2955 * the input and output baud are the same. Could have used a baud
2956 * table here, but this way we can generate virtually any baud rate
2957 * we like!
2958 */
2959 baudrate = tiosp->c_cflag & CBAUD;
2960 if (baudrate & CBAUDEX) {
2961 baudrate &= ~CBAUDEX;
2962 if ((baudrate < 1) || (baudrate > 4))
2963 tiosp->c_cflag &= ~CBAUDEX;
2964 else
2965 baudrate += 15;
2966 }
2967 baudrate = stl_baudrates[baudrate];
2968 if ((tiosp->c_cflag & CBAUD) == B38400) {
2969 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2970 baudrate = 57600;
2971 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2972 baudrate = 115200;
2973 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2974 baudrate = 230400;
2975 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2976 baudrate = 460800;
2977 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
2978 baudrate = (portp->baud_base / portp->custom_divisor);
2979 }
2980 if (baudrate > STL_CD1400MAXBAUD)
2981 baudrate = STL_CD1400MAXBAUD;
2982
2983 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002984 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2985 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 if (clkdiv < 0x100)
2987 break;
2988 }
2989 div = (unsigned char) clkdiv;
2990 }
2991
2992/*
2993 * Check what form of modem signaling is required and set it up.
2994 */
2995 if ((tiosp->c_cflag & CLOCAL) == 0) {
2996 mcor1 |= MCOR1_DCD;
2997 mcor2 |= MCOR2_DCD;
2998 sreron |= SRER_MODEM;
2999 portp->flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003000 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 portp->flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
3003/*
3004 * Setup cd1400 enhanced modes if we can. In particular we want to
3005 * handle as much of the flow control as possible automatically. As
3006 * well as saving a few CPU cycles it will also greatly improve flow
3007 * control reliability.
3008 */
3009 if (tiosp->c_iflag & IXON) {
3010 cor2 |= COR2_TXIBE;
3011 cor3 |= COR3_SCD12;
3012 if (tiosp->c_iflag & IXANY)
3013 cor2 |= COR2_IXM;
3014 }
3015
3016 if (tiosp->c_cflag & CRTSCTS) {
3017 cor2 |= COR2_CTSAE;
3018 mcor1 |= FIFO_RTSTHRESHOLD;
3019 }
3020
3021/*
3022 * All cd1400 register values calculated so go through and set
3023 * them all up.
3024 */
3025
Jiri Slabya0564e12006-12-08 02:38:37 -08003026 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003028 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003030 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003032 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3033 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3035 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036
Alan Coxb65b5b52006-06-27 02:54:05 -07003037 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 BRDENABLE(portp->brdnr, portp->pagenr);
3039 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3040 srer = stl_cd1400getreg(portp, SRER);
3041 stl_cd1400setreg(portp, SRER, 0);
3042 if (stl_cd1400updatereg(portp, COR1, cor1))
3043 ccr = 1;
3044 if (stl_cd1400updatereg(portp, COR2, cor2))
3045 ccr = 1;
3046 if (stl_cd1400updatereg(portp, COR3, cor3))
3047 ccr = 1;
3048 if (ccr) {
3049 stl_cd1400ccrwait(portp);
3050 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3051 }
3052 stl_cd1400setreg(portp, COR4, cor4);
3053 stl_cd1400setreg(portp, COR5, cor5);
3054 stl_cd1400setreg(portp, MCOR1, mcor1);
3055 stl_cd1400setreg(portp, MCOR2, mcor2);
3056 if (baudrate > 0) {
3057 stl_cd1400setreg(portp, TCOR, clk);
3058 stl_cd1400setreg(portp, TBPR, div);
3059 stl_cd1400setreg(portp, RCOR, clk);
3060 stl_cd1400setreg(portp, RBPR, div);
3061 }
3062 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3063 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3064 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3065 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3066 stl_cd1400setreg(portp, RTPR, rtpr);
3067 mcor1 = stl_cd1400getreg(portp, MSVR1);
3068 if (mcor1 & MSVR1_DCD)
3069 portp->sigs |= TIOCM_CD;
3070 else
3071 portp->sigs &= ~TIOCM_CD;
3072 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3073 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003074 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075}
3076
3077/*****************************************************************************/
3078
3079/*
3080 * Set the state of the DTR and RTS signals.
3081 */
3082
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003083static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084{
3085 unsigned char msvr1, msvr2;
3086 unsigned long flags;
3087
Jiri Slabya0564e12006-12-08 02:38:37 -08003088 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3089 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090
3091 msvr1 = 0;
3092 msvr2 = 0;
3093 if (dtr > 0)
3094 msvr1 = MSVR1_DTR;
3095 if (rts > 0)
3096 msvr2 = MSVR2_RTS;
3097
Alan Coxb65b5b52006-06-27 02:54:05 -07003098 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 BRDENABLE(portp->brdnr, portp->pagenr);
3100 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3101 if (rts >= 0)
3102 stl_cd1400setreg(portp, MSVR2, msvr2);
3103 if (dtr >= 0)
3104 stl_cd1400setreg(portp, MSVR1, msvr1);
3105 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003106 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107}
3108
3109/*****************************************************************************/
3110
3111/*
3112 * Return the state of the signals.
3113 */
3114
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003115static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116{
3117 unsigned char msvr1, msvr2;
3118 unsigned long flags;
3119 int sigs;
3120
Jiri Slabya0564e12006-12-08 02:38:37 -08003121 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122
Alan Coxb65b5b52006-06-27 02:54:05 -07003123 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 BRDENABLE(portp->brdnr, portp->pagenr);
3125 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3126 msvr1 = stl_cd1400getreg(portp, MSVR1);
3127 msvr2 = stl_cd1400getreg(portp, MSVR2);
3128 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003129 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
3131 sigs = 0;
3132 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3133 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3134 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3135 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3136#if 0
3137 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3138 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3139#else
3140 sigs |= TIOCM_DSR;
3141#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003142 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143}
3144
3145/*****************************************************************************/
3146
3147/*
3148 * Enable/Disable the Transmitter and/or Receiver.
3149 */
3150
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003151static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152{
3153 unsigned char ccr;
3154 unsigned long flags;
3155
Jiri Slabya0564e12006-12-08 02:38:37 -08003156 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3157
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 ccr = 0;
3159
3160 if (tx == 0)
3161 ccr |= CCR_TXDISABLE;
3162 else if (tx > 0)
3163 ccr |= CCR_TXENABLE;
3164 if (rx == 0)
3165 ccr |= CCR_RXDISABLE;
3166 else if (rx > 0)
3167 ccr |= CCR_RXENABLE;
3168
Alan Coxb65b5b52006-06-27 02:54:05 -07003169 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 BRDENABLE(portp->brdnr, portp->pagenr);
3171 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3172 stl_cd1400ccrwait(portp);
3173 stl_cd1400setreg(portp, CCR, ccr);
3174 stl_cd1400ccrwait(portp);
3175 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003176 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177}
3178
3179/*****************************************************************************/
3180
3181/*
3182 * Start/stop the Transmitter and/or Receiver.
3183 */
3184
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003185static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186{
3187 unsigned char sreron, sreroff;
3188 unsigned long flags;
3189
Jiri Slabya0564e12006-12-08 02:38:37 -08003190 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
3192 sreron = 0;
3193 sreroff = 0;
3194 if (tx == 0)
3195 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3196 else if (tx == 1)
3197 sreron |= SRER_TXDATA;
3198 else if (tx >= 2)
3199 sreron |= SRER_TXEMPTY;
3200 if (rx == 0)
3201 sreroff |= SRER_RXDATA;
3202 else if (rx > 0)
3203 sreron |= SRER_RXDATA;
3204
Alan Coxb65b5b52006-06-27 02:54:05 -07003205 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 BRDENABLE(portp->brdnr, portp->pagenr);
3207 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3208 stl_cd1400setreg(portp, SRER,
3209 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3210 BRDDISABLE(portp->brdnr);
3211 if (tx > 0)
3212 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003213 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214}
3215
3216/*****************************************************************************/
3217
3218/*
3219 * Disable all interrupts from this port.
3220 */
3221
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003222static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223{
3224 unsigned long flags;
3225
Jiri Slabya0564e12006-12-08 02:38:37 -08003226 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3227
Alan Coxb65b5b52006-06-27 02:54:05 -07003228 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 BRDENABLE(portp->brdnr, portp->pagenr);
3230 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3231 stl_cd1400setreg(portp, SRER, 0);
3232 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003233 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234}
3235
3236/*****************************************************************************/
3237
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003238static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239{
3240 unsigned long flags;
3241
Jiri Slabya0564e12006-12-08 02:38:37 -08003242 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243
Alan Coxb65b5b52006-06-27 02:54:05 -07003244 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 BRDENABLE(portp->brdnr, portp->pagenr);
3246 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3247 stl_cd1400setreg(portp, SRER,
3248 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3249 SRER_TXEMPTY));
3250 BRDDISABLE(portp->brdnr);
3251 portp->brklen = len;
3252 if (len == 1)
3253 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003254 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255}
3256
3257/*****************************************************************************/
3258
3259/*
3260 * Take flow control actions...
3261 */
3262
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003263static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264{
3265 struct tty_struct *tty;
3266 unsigned long flags;
3267
Jiri Slabya0564e12006-12-08 02:38:37 -08003268 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
Jiri Slaby615e4a72006-12-08 02:38:38 -08003270 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271 return;
3272 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003273 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 return;
3275
Alan Coxb65b5b52006-06-27 02:54:05 -07003276 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 BRDENABLE(portp->brdnr, portp->pagenr);
3278 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3279
3280 if (state) {
3281 if (tty->termios->c_iflag & IXOFF) {
3282 stl_cd1400ccrwait(portp);
3283 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3284 portp->stats.rxxon++;
3285 stl_cd1400ccrwait(portp);
3286 }
3287/*
3288 * Question: should we return RTS to what it was before? It may
3289 * have been set by an ioctl... Suppose not, since if you have
3290 * hardware flow control set then it is pretty silly to go and
3291 * set the RTS line by hand.
3292 */
3293 if (tty->termios->c_cflag & CRTSCTS) {
3294 stl_cd1400setreg(portp, MCOR1,
3295 (stl_cd1400getreg(portp, MCOR1) |
3296 FIFO_RTSTHRESHOLD));
3297 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3298 portp->stats.rxrtson++;
3299 }
3300 } else {
3301 if (tty->termios->c_iflag & IXOFF) {
3302 stl_cd1400ccrwait(portp);
3303 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3304 portp->stats.rxxoff++;
3305 stl_cd1400ccrwait(portp);
3306 }
3307 if (tty->termios->c_cflag & CRTSCTS) {
3308 stl_cd1400setreg(portp, MCOR1,
3309 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3310 stl_cd1400setreg(portp, MSVR2, 0);
3311 portp->stats.rxrtsoff++;
3312 }
3313 }
3314
3315 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003316 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317}
3318
3319/*****************************************************************************/
3320
3321/*
3322 * Send a flow control character...
3323 */
3324
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003325static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326{
3327 struct tty_struct *tty;
3328 unsigned long flags;
3329
Jiri Slabya0564e12006-12-08 02:38:37 -08003330 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331
Jiri Slaby615e4a72006-12-08 02:38:38 -08003332 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333 return;
3334 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003335 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 return;
3337
Alan Coxb65b5b52006-06-27 02:54:05 -07003338 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 BRDENABLE(portp->brdnr, portp->pagenr);
3340 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3341 if (state) {
3342 stl_cd1400ccrwait(portp);
3343 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3344 portp->stats.rxxon++;
3345 stl_cd1400ccrwait(portp);
3346 } else {
3347 stl_cd1400ccrwait(portp);
3348 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3349 portp->stats.rxxoff++;
3350 stl_cd1400ccrwait(portp);
3351 }
3352 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003353 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354}
3355
3356/*****************************************************************************/
3357
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003358static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359{
3360 unsigned long flags;
3361
Jiri Slabya0564e12006-12-08 02:38:37 -08003362 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363
Jiri Slaby615e4a72006-12-08 02:38:38 -08003364 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 return;
3366
Alan Coxb65b5b52006-06-27 02:54:05 -07003367 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 BRDENABLE(portp->brdnr, portp->pagenr);
3369 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3370 stl_cd1400ccrwait(portp);
3371 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3372 stl_cd1400ccrwait(portp);
3373 portp->tx.tail = portp->tx.head;
3374 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003375 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376}
3377
3378/*****************************************************************************/
3379
3380/*
3381 * Return the current state of data flow on this port. This is only
3382 * really interresting when determining if data has fully completed
3383 * transmission or not... This is easy for the cd1400, it accurately
3384 * maintains the busy port flag.
3385 */
3386
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003387static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388{
Jiri Slabya0564e12006-12-08 02:38:37 -08003389 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
Jiri Slaby615e4a72006-12-08 02:38:38 -08003391 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003392 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393
Jesper Juhl014c2542006-01-15 02:37:08 +01003394 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395}
3396
3397/*****************************************************************************/
3398
3399/*
3400 * Interrupt service routine for cd1400 EasyIO boards.
3401 */
3402
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003403static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404{
3405 unsigned char svrtype;
3406
Jiri Slabya0564e12006-12-08 02:38:37 -08003407 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
Alan Coxb65b5b52006-06-27 02:54:05 -07003409 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 outb(SVRR, iobase);
3411 svrtype = inb(iobase + EREG_DATA);
3412 if (panelp->nrports > 4) {
3413 outb((SVRR + 0x80), iobase);
3414 svrtype |= inb(iobase + EREG_DATA);
3415 }
3416
3417 if (svrtype & SVRR_RX)
3418 stl_cd1400rxisr(panelp, iobase);
3419 else if (svrtype & SVRR_TX)
3420 stl_cd1400txisr(panelp, iobase);
3421 else if (svrtype & SVRR_MDM)
3422 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003423
3424 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425}
3426
3427/*****************************************************************************/
3428
3429/*
3430 * Interrupt service routine for cd1400 panels.
3431 */
3432
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003433static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434{
3435 unsigned char svrtype;
3436
Jiri Slabya0564e12006-12-08 02:38:37 -08003437 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438
3439 outb(SVRR, iobase);
3440 svrtype = inb(iobase + EREG_DATA);
3441 outb((SVRR + 0x80), iobase);
3442 svrtype |= inb(iobase + EREG_DATA);
3443 if (svrtype & SVRR_RX)
3444 stl_cd1400rxisr(panelp, iobase);
3445 else if (svrtype & SVRR_TX)
3446 stl_cd1400txisr(panelp, iobase);
3447 else if (svrtype & SVRR_MDM)
3448 stl_cd1400mdmisr(panelp, iobase);
3449}
3450
3451
3452/*****************************************************************************/
3453
3454/*
3455 * Unfortunately we need to handle breaks in the TX data stream, since
3456 * this is the only way to generate them on the cd1400.
3457 */
3458
Jiri Slaby60be4812006-12-08 02:38:40 -08003459static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460{
3461 if (portp->brklen == 1) {
3462 outb((COR2 + portp->uartaddr), ioaddr);
3463 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3464 (ioaddr + EREG_DATA));
3465 outb((TDR + portp->uartaddr), ioaddr);
3466 outb(ETC_CMD, (ioaddr + EREG_DATA));
3467 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3468 outb((SRER + portp->uartaddr), ioaddr);
3469 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3470 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003471 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 } else if (portp->brklen > 1) {
3473 outb((TDR + portp->uartaddr), ioaddr);
3474 outb(ETC_CMD, (ioaddr + EREG_DATA));
3475 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3476 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003477 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 } else {
3479 outb((COR2 + portp->uartaddr), ioaddr);
3480 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3481 (ioaddr + EREG_DATA));
3482 portp->brklen = 0;
3483 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003484 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485}
3486
3487/*****************************************************************************/
3488
3489/*
3490 * Transmit interrupt handler. This has gotta be fast! Handling TX
3491 * chars is pretty simple, stuff as many as possible from the TX buffer
3492 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3493 * are embedded as commands in the data stream. Oh no, had to use a goto!
3494 * This could be optimized more, will do when I get time...
3495 * In practice it is possible that interrupts are enabled but that the
3496 * port has been hung up. Need to handle not having any TX buffer here,
3497 * this is done by using the side effect that head and tail will also
3498 * be NULL if the buffer has been freed.
3499 */
3500
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003501static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003503 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 int len, stlen;
3505 char *head, *tail;
3506 unsigned char ioack, srer;
3507
Jiri Slabya0564e12006-12-08 02:38:37 -08003508 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509
3510 ioack = inb(ioaddr + EREG_TXACK);
3511 if (((ioack & panelp->ackmask) != 0) ||
3512 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3513 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3514 return;
3515 }
3516 portp = panelp->ports[(ioack >> 3)];
3517
3518/*
3519 * Unfortunately we need to handle breaks in the data stream, since
3520 * this is the only way to generate them on the cd1400. Do it now if
3521 * a break is to be sent.
3522 */
3523 if (portp->brklen != 0)
3524 if (stl_cd1400breakisr(portp, ioaddr))
3525 goto stl_txalldone;
3526
3527 head = portp->tx.head;
3528 tail = portp->tx.tail;
3529 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3530 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3531 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3532 set_bit(ASYI_TXLOW, &portp->istate);
3533 schedule_work(&portp->tqueue);
3534 }
3535
3536 if (len == 0) {
3537 outb((SRER + portp->uartaddr), ioaddr);
3538 srer = inb(ioaddr + EREG_DATA);
3539 if (srer & SRER_TXDATA) {
3540 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3541 } else {
3542 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3543 clear_bit(ASYI_TXBUSY, &portp->istate);
3544 }
3545 outb(srer, (ioaddr + EREG_DATA));
3546 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003547 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08003549 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 outb((TDR + portp->uartaddr), ioaddr);
3551 outsb((ioaddr + EREG_DATA), tail, stlen);
3552 len -= stlen;
3553 tail += stlen;
3554 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3555 tail = portp->tx.buf;
3556 if (len > 0) {
3557 outsb((ioaddr + EREG_DATA), tail, len);
3558 tail += len;
3559 }
3560 portp->tx.tail = tail;
3561 }
3562
3563stl_txalldone:
3564 outb((EOSRR + portp->uartaddr), ioaddr);
3565 outb(0, (ioaddr + EREG_DATA));
3566}
3567
3568/*****************************************************************************/
3569
3570/*
3571 * Receive character interrupt handler. Determine if we have good chars
3572 * or bad chars and then process appropriately. Good chars are easy
3573 * just shove the lot into the RX buffer and set all status byte to 0.
3574 * If a bad RX char then process as required. This routine needs to be
3575 * fast! In practice it is possible that we get an interrupt on a port
3576 * that is closed. This can happen on hangups - since they completely
3577 * shutdown a port not in user context. Need to handle this case.
3578 */
3579
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003580static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003582 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583 struct tty_struct *tty;
3584 unsigned int ioack, len, buflen;
3585 unsigned char status;
3586 char ch;
3587
Jiri Slabya0564e12006-12-08 02:38:37 -08003588 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589
3590 ioack = inb(ioaddr + EREG_RXACK);
3591 if ((ioack & panelp->ackmask) != 0) {
3592 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3593 return;
3594 }
3595 portp = panelp->ports[(ioack >> 3)];
3596 tty = portp->tty;
3597
3598 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3599 outb((RDCR + portp->uartaddr), ioaddr);
3600 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003601 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08003602 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 outb((RDSR + portp->uartaddr), ioaddr);
3604 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3605 portp->stats.rxlost += len;
3606 portp->stats.rxtotal += len;
3607 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003608 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003610 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003612 tty_prepare_flip_string(tty, &ptr, len);
3613 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 tty_schedule_flip(tty);
3615 portp->stats.rxtotal += len;
3616 }
3617 }
3618 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3619 outb((RDSR + portp->uartaddr), ioaddr);
3620 status = inb(ioaddr + EREG_DATA);
3621 ch = inb(ioaddr + EREG_DATA);
3622 if (status & ST_PARITY)
3623 portp->stats.rxparity++;
3624 if (status & ST_FRAMING)
3625 portp->stats.rxframing++;
3626 if (status & ST_OVERRUN)
3627 portp->stats.rxoverrun++;
3628 if (status & ST_BREAK)
3629 portp->stats.rxbreaks++;
3630 if (status & ST_SCHARMASK) {
3631 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3632 portp->stats.txxon++;
3633 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3634 portp->stats.txxoff++;
3635 goto stl_rxalldone;
3636 }
Alan Cox33f0f882006-01-09 20:54:13 -08003637 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638 if (portp->rxmarkmsk & status) {
3639 if (status & ST_BREAK) {
3640 status = TTY_BREAK;
3641 if (portp->flags & ASYNC_SAK) {
3642 do_SAK(tty);
3643 BRDENABLE(portp->brdnr, portp->pagenr);
3644 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003645 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003647 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003649 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003651 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003653 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003655 tty_insert_flip_char(tty, ch, status);
3656 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 }
3658 } else {
3659 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3660 return;
3661 }
3662
3663stl_rxalldone:
3664 outb((EOSRR + portp->uartaddr), ioaddr);
3665 outb(0, (ioaddr + EREG_DATA));
3666}
3667
3668/*****************************************************************************/
3669
3670/*
3671 * Modem interrupt handler. The is called when the modem signal line
3672 * (DCD) has changed state. Leave most of the work to the off-level
3673 * processing routine.
3674 */
3675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003676static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003678 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 unsigned int ioack;
3680 unsigned char misr;
3681
Jiri Slabya0564e12006-12-08 02:38:37 -08003682 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683
3684 ioack = inb(ioaddr + EREG_MDACK);
3685 if (((ioack & panelp->ackmask) != 0) ||
3686 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3687 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3688 return;
3689 }
3690 portp = panelp->ports[(ioack >> 3)];
3691
3692 outb((MISR + portp->uartaddr), ioaddr);
3693 misr = inb(ioaddr + EREG_DATA);
3694 if (misr & MISR_DCD) {
3695 set_bit(ASYI_DCDCHANGE, &portp->istate);
3696 schedule_work(&portp->tqueue);
3697 portp->stats.modem++;
3698 }
3699
3700 outb((EOSRR + portp->uartaddr), ioaddr);
3701 outb(0, (ioaddr + EREG_DATA));
3702}
3703
3704/*****************************************************************************/
3705/* SC26198 HARDWARE FUNCTIONS */
3706/*****************************************************************************/
3707
3708/*
3709 * These functions get/set/update the registers of the sc26198 UARTs.
3710 * Access to the sc26198 registers is via an address/data io port pair.
3711 * (Maybe should make this inline...)
3712 */
3713
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003714static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715{
3716 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003717 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718}
3719
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003720static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721{
3722 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3723 outb(value, (portp->ioaddr + XP_DATA));
3724}
3725
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003726static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727{
3728 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3729 if (inb(portp->ioaddr + XP_DATA) != value) {
3730 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003731 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003733 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734}
3735
3736/*****************************************************************************/
3737
3738/*
3739 * Functions to get and set the sc26198 global registers.
3740 */
3741
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003742static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743{
3744 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003745 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746}
3747
3748#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003749static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750{
3751 outb(regnr, (portp->ioaddr + XP_ADDR));
3752 outb(value, (portp->ioaddr + XP_DATA));
3753}
3754#endif
3755
3756/*****************************************************************************/
3757
3758/*
3759 * Inbitialize the UARTs in a panel. We don't care what sort of board
3760 * these ports are on - since the port io registers are almost
3761 * identical when dealing with ports.
3762 */
3763
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003764static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765{
3766 int chipmask, i;
3767 int nrchips, ioaddr;
3768
Jiri Slabya0564e12006-12-08 02:38:37 -08003769 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770
3771 BRDENABLE(panelp->brdnr, panelp->pagenr);
3772
3773/*
3774 * Check that each chip is present and started up OK.
3775 */
3776 chipmask = 0;
3777 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3778 if (brdp->brdtype == BRD_ECHPCI)
3779 outb(panelp->pagenr, brdp->ioctrl);
3780
Jiri Slabyc62429d2006-12-08 02:39:14 -08003781 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 ioaddr = panelp->iobase + (i * 4);
3783 outb(SCCR, (ioaddr + XP_ADDR));
3784 outb(CR_RESETALL, (ioaddr + XP_DATA));
3785 outb(TSTR, (ioaddr + XP_ADDR));
3786 if (inb(ioaddr + XP_DATA) != 0) {
3787 printk("STALLION: sc26198 not responding, "
3788 "brd=%d panel=%d chip=%d\n",
3789 panelp->brdnr, panelp->panelnr, i);
3790 continue;
3791 }
3792 chipmask |= (0x1 << i);
3793 outb(GCCR, (ioaddr + XP_ADDR));
3794 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3795 outb(WDTRCR, (ioaddr + XP_ADDR));
3796 outb(0xff, (ioaddr + XP_DATA));
3797 }
3798
3799 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003800 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801}
3802
3803/*****************************************************************************/
3804
3805/*
3806 * Initialize hardware specific port registers.
3807 */
3808
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003809static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810{
Jiri Slabya0564e12006-12-08 02:38:37 -08003811 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3812 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813
Jiri Slaby615e4a72006-12-08 02:38:38 -08003814 if ((brdp == NULL) || (panelp == NULL) ||
3815 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 return;
3817
3818 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3819 portp->uartaddr = (portp->portnr & 0x07) << 4;
3820 portp->pagenr = panelp->pagenr;
3821 portp->hwid = 0x1;
3822
3823 BRDENABLE(portp->brdnr, portp->pagenr);
3824 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3825 BRDDISABLE(portp->brdnr);
3826}
3827
3828/*****************************************************************************/
3829
3830/*
3831 * Set up the sc26198 registers for a port based on the termios port
3832 * settings.
3833 */
3834
Alan Cox606d0992006-12-08 02:38:45 -08003835static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003837 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 unsigned long flags;
3839 unsigned int baudrate;
3840 unsigned char mr0, mr1, mr2, clk;
3841 unsigned char imron, imroff, iopr, ipr;
3842
3843 mr0 = 0;
3844 mr1 = 0;
3845 mr2 = 0;
3846 clk = 0;
3847 iopr = 0;
3848 imron = 0;
3849 imroff = 0;
3850
3851 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003852 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 return;
3854
3855/*
3856 * Set up the RX char ignore mask with those RX error types we
3857 * can ignore.
3858 */
3859 portp->rxignoremsk = 0;
3860 if (tiosp->c_iflag & IGNPAR)
3861 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3862 SR_RXOVERRUN);
3863 if (tiosp->c_iflag & IGNBRK)
3864 portp->rxignoremsk |= SR_RXBREAK;
3865
3866 portp->rxmarkmsk = SR_RXOVERRUN;
3867 if (tiosp->c_iflag & (INPCK | PARMRK))
3868 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3869 if (tiosp->c_iflag & BRKINT)
3870 portp->rxmarkmsk |= SR_RXBREAK;
3871
3872/*
3873 * Go through the char size, parity and stop bits and set all the
3874 * option register appropriately.
3875 */
3876 switch (tiosp->c_cflag & CSIZE) {
3877 case CS5:
3878 mr1 |= MR1_CS5;
3879 break;
3880 case CS6:
3881 mr1 |= MR1_CS6;
3882 break;
3883 case CS7:
3884 mr1 |= MR1_CS7;
3885 break;
3886 default:
3887 mr1 |= MR1_CS8;
3888 break;
3889 }
3890
3891 if (tiosp->c_cflag & CSTOPB)
3892 mr2 |= MR2_STOP2;
3893 else
3894 mr2 |= MR2_STOP1;
3895
3896 if (tiosp->c_cflag & PARENB) {
3897 if (tiosp->c_cflag & PARODD)
3898 mr1 |= (MR1_PARENB | MR1_PARODD);
3899 else
3900 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003901 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
3904 mr1 |= MR1_ERRBLOCK;
3905
3906/*
3907 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3908 * space for hardware flow control and the like. This should be set to
3909 * VMIN.
3910 */
3911 mr2 |= MR2_RXFIFOHALF;
3912
3913/*
3914 * Calculate the baud rate timers. For now we will just assume that
3915 * the input and output baud are the same. The sc26198 has a fixed
3916 * baud rate table, so only discrete baud rates possible.
3917 */
3918 baudrate = tiosp->c_cflag & CBAUD;
3919 if (baudrate & CBAUDEX) {
3920 baudrate &= ~CBAUDEX;
3921 if ((baudrate < 1) || (baudrate > 4))
3922 tiosp->c_cflag &= ~CBAUDEX;
3923 else
3924 baudrate += 15;
3925 }
3926 baudrate = stl_baudrates[baudrate];
3927 if ((tiosp->c_cflag & CBAUD) == B38400) {
3928 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3929 baudrate = 57600;
3930 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3931 baudrate = 115200;
3932 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3933 baudrate = 230400;
3934 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3935 baudrate = 460800;
3936 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3937 baudrate = (portp->baud_base / portp->custom_divisor);
3938 }
3939 if (baudrate > STL_SC26198MAXBAUD)
3940 baudrate = STL_SC26198MAXBAUD;
3941
Jiri Slabyc62429d2006-12-08 02:39:14 -08003942 if (baudrate > 0)
3943 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 if (baudrate <= sc26198_baudtable[clk])
3945 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
3947/*
3948 * Check what form of modem signaling is required and set it up.
3949 */
3950 if (tiosp->c_cflag & CLOCAL) {
3951 portp->flags &= ~ASYNC_CHECK_CD;
3952 } else {
3953 iopr |= IOPR_DCDCOS;
3954 imron |= IR_IOPORT;
3955 portp->flags |= ASYNC_CHECK_CD;
3956 }
3957
3958/*
3959 * Setup sc26198 enhanced modes if we can. In particular we want to
3960 * handle as much of the flow control as possible automatically. As
3961 * well as saving a few CPU cycles it will also greatly improve flow
3962 * control reliability.
3963 */
3964 if (tiosp->c_iflag & IXON) {
3965 mr0 |= MR0_SWFTX | MR0_SWFT;
3966 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003967 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003969
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 if (tiosp->c_iflag & IXOFF)
3971 mr0 |= MR0_SWFRX;
3972
3973 if (tiosp->c_cflag & CRTSCTS) {
3974 mr2 |= MR2_AUTOCTS;
3975 mr1 |= MR1_AUTORTS;
3976 }
3977
3978/*
3979 * All sc26198 register values calculated so go through and set
3980 * them all up.
3981 */
3982
Jiri Slabya0564e12006-12-08 02:38:37 -08003983 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003985 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3986 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3987 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3989 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
Alan Coxb65b5b52006-06-27 02:54:05 -07003991 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 BRDENABLE(portp->brdnr, portp->pagenr);
3993 stl_sc26198setreg(portp, IMR, 0);
3994 stl_sc26198updatereg(portp, MR0, mr0);
3995 stl_sc26198updatereg(portp, MR1, mr1);
3996 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3997 stl_sc26198updatereg(portp, MR2, mr2);
3998 stl_sc26198updatereg(portp, IOPIOR,
3999 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4000
4001 if (baudrate > 0) {
4002 stl_sc26198setreg(portp, TXCSR, clk);
4003 stl_sc26198setreg(portp, RXCSR, clk);
4004 }
4005
4006 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4007 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4008
4009 ipr = stl_sc26198getreg(portp, IPR);
4010 if (ipr & IPR_DCD)
4011 portp->sigs &= ~TIOCM_CD;
4012 else
4013 portp->sigs |= TIOCM_CD;
4014
4015 portp->imr = (portp->imr & ~imroff) | imron;
4016 stl_sc26198setreg(portp, IMR, portp->imr);
4017 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004018 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019}
4020
4021/*****************************************************************************/
4022
4023/*
4024 * Set the state of the DTR and RTS signals.
4025 */
4026
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004027static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028{
4029 unsigned char iopioron, iopioroff;
4030 unsigned long flags;
4031
Jiri Slabya0564e12006-12-08 02:38:37 -08004032 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4033 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
4035 iopioron = 0;
4036 iopioroff = 0;
4037 if (dtr == 0)
4038 iopioroff |= IPR_DTR;
4039 else if (dtr > 0)
4040 iopioron |= IPR_DTR;
4041 if (rts == 0)
4042 iopioroff |= IPR_RTS;
4043 else if (rts > 0)
4044 iopioron |= IPR_RTS;
4045
Alan Coxb65b5b52006-06-27 02:54:05 -07004046 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047 BRDENABLE(portp->brdnr, portp->pagenr);
4048 stl_sc26198setreg(portp, IOPIOR,
4049 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4050 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004051 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052}
4053
4054/*****************************************************************************/
4055
4056/*
4057 * Return the state of the signals.
4058 */
4059
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004060static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061{
4062 unsigned char ipr;
4063 unsigned long flags;
4064 int sigs;
4065
Jiri Slabya0564e12006-12-08 02:38:37 -08004066 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067
Alan Coxb65b5b52006-06-27 02:54:05 -07004068 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 BRDENABLE(portp->brdnr, portp->pagenr);
4070 ipr = stl_sc26198getreg(portp, IPR);
4071 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004072 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
4074 sigs = 0;
4075 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4076 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4077 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4078 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4079 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004080 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081}
4082
4083/*****************************************************************************/
4084
4085/*
4086 * Enable/Disable the Transmitter and/or Receiver.
4087 */
4088
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004089static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090{
4091 unsigned char ccr;
4092 unsigned long flags;
4093
Jiri Slabya0564e12006-12-08 02:38:37 -08004094 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
4096 ccr = portp->crenable;
4097 if (tx == 0)
4098 ccr &= ~CR_TXENABLE;
4099 else if (tx > 0)
4100 ccr |= CR_TXENABLE;
4101 if (rx == 0)
4102 ccr &= ~CR_RXENABLE;
4103 else if (rx > 0)
4104 ccr |= CR_RXENABLE;
4105
Alan Coxb65b5b52006-06-27 02:54:05 -07004106 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 BRDENABLE(portp->brdnr, portp->pagenr);
4108 stl_sc26198setreg(portp, SCCR, ccr);
4109 BRDDISABLE(portp->brdnr);
4110 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004111 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112}
4113
4114/*****************************************************************************/
4115
4116/*
4117 * Start/stop the Transmitter and/or Receiver.
4118 */
4119
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004120static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121{
4122 unsigned char imr;
4123 unsigned long flags;
4124
Jiri Slabya0564e12006-12-08 02:38:37 -08004125 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126
4127 imr = portp->imr;
4128 if (tx == 0)
4129 imr &= ~IR_TXRDY;
4130 else if (tx == 1)
4131 imr |= IR_TXRDY;
4132 if (rx == 0)
4133 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4134 else if (rx > 0)
4135 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4136
Alan Coxb65b5b52006-06-27 02:54:05 -07004137 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 BRDENABLE(portp->brdnr, portp->pagenr);
4139 stl_sc26198setreg(portp, IMR, imr);
4140 BRDDISABLE(portp->brdnr);
4141 portp->imr = imr;
4142 if (tx > 0)
4143 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004144 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145}
4146
4147/*****************************************************************************/
4148
4149/*
4150 * Disable all interrupts from this port.
4151 */
4152
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004153static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154{
4155 unsigned long flags;
4156
Jiri Slabya0564e12006-12-08 02:38:37 -08004157 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158
Alan Coxb65b5b52006-06-27 02:54:05 -07004159 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 BRDENABLE(portp->brdnr, portp->pagenr);
4161 portp->imr = 0;
4162 stl_sc26198setreg(portp, IMR, 0);
4163 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004164 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165}
4166
4167/*****************************************************************************/
4168
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004169static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170{
4171 unsigned long flags;
4172
Jiri Slabya0564e12006-12-08 02:38:37 -08004173 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174
Alan Coxb65b5b52006-06-27 02:54:05 -07004175 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 BRDENABLE(portp->brdnr, portp->pagenr);
4177 if (len == 1) {
4178 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4179 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004180 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004182
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004184 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185}
4186
4187/*****************************************************************************/
4188
4189/*
4190 * Take flow control actions...
4191 */
4192
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004193static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194{
4195 struct tty_struct *tty;
4196 unsigned long flags;
4197 unsigned char mr0;
4198
Jiri Slabya0564e12006-12-08 02:38:37 -08004199 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200
Jiri Slaby615e4a72006-12-08 02:38:38 -08004201 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 return;
4203 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004204 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 return;
4206
Alan Coxb65b5b52006-06-27 02:54:05 -07004207 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 BRDENABLE(portp->brdnr, portp->pagenr);
4209
4210 if (state) {
4211 if (tty->termios->c_iflag & IXOFF) {
4212 mr0 = stl_sc26198getreg(portp, MR0);
4213 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4214 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4215 mr0 |= MR0_SWFRX;
4216 portp->stats.rxxon++;
4217 stl_sc26198wait(portp);
4218 stl_sc26198setreg(portp, MR0, mr0);
4219 }
4220/*
4221 * Question: should we return RTS to what it was before? It may
4222 * have been set by an ioctl... Suppose not, since if you have
4223 * hardware flow control set then it is pretty silly to go and
4224 * set the RTS line by hand.
4225 */
4226 if (tty->termios->c_cflag & CRTSCTS) {
4227 stl_sc26198setreg(portp, MR1,
4228 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4229 stl_sc26198setreg(portp, IOPIOR,
4230 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4231 portp->stats.rxrtson++;
4232 }
4233 } else {
4234 if (tty->termios->c_iflag & IXOFF) {
4235 mr0 = stl_sc26198getreg(portp, MR0);
4236 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4237 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4238 mr0 &= ~MR0_SWFRX;
4239 portp->stats.rxxoff++;
4240 stl_sc26198wait(portp);
4241 stl_sc26198setreg(portp, MR0, mr0);
4242 }
4243 if (tty->termios->c_cflag & CRTSCTS) {
4244 stl_sc26198setreg(portp, MR1,
4245 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4246 stl_sc26198setreg(portp, IOPIOR,
4247 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4248 portp->stats.rxrtsoff++;
4249 }
4250 }
4251
4252 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004253 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254}
4255
4256/*****************************************************************************/
4257
4258/*
4259 * Send a flow control character.
4260 */
4261
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004262static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263{
4264 struct tty_struct *tty;
4265 unsigned long flags;
4266 unsigned char mr0;
4267
Jiri Slabya0564e12006-12-08 02:38:37 -08004268 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269
Jiri Slaby615e4a72006-12-08 02:38:38 -08004270 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 return;
4272 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004273 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 return;
4275
Alan Coxb65b5b52006-06-27 02:54:05 -07004276 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277 BRDENABLE(portp->brdnr, portp->pagenr);
4278 if (state) {
4279 mr0 = stl_sc26198getreg(portp, MR0);
4280 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4281 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4282 mr0 |= MR0_SWFRX;
4283 portp->stats.rxxon++;
4284 stl_sc26198wait(portp);
4285 stl_sc26198setreg(portp, MR0, mr0);
4286 } else {
4287 mr0 = stl_sc26198getreg(portp, MR0);
4288 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4289 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4290 mr0 &= ~MR0_SWFRX;
4291 portp->stats.rxxoff++;
4292 stl_sc26198wait(portp);
4293 stl_sc26198setreg(portp, MR0, mr0);
4294 }
4295 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004296 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297}
4298
4299/*****************************************************************************/
4300
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004301static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302{
4303 unsigned long flags;
4304
Jiri Slabya0564e12006-12-08 02:38:37 -08004305 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306
Jiri Slaby615e4a72006-12-08 02:38:38 -08004307 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 return;
4309
Alan Coxb65b5b52006-06-27 02:54:05 -07004310 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 BRDENABLE(portp->brdnr, portp->pagenr);
4312 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4313 stl_sc26198setreg(portp, SCCR, portp->crenable);
4314 BRDDISABLE(portp->brdnr);
4315 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004316 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317}
4318
4319/*****************************************************************************/
4320
4321/*
4322 * Return the current state of data flow on this port. This is only
4323 * really interresting when determining if data has fully completed
4324 * transmission or not... The sc26198 interrupt scheme cannot
4325 * determine when all data has actually drained, so we need to
4326 * check the port statusy register to be sure.
4327 */
4328
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004329static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330{
4331 unsigned long flags;
4332 unsigned char sr;
4333
Jiri Slabya0564e12006-12-08 02:38:37 -08004334 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335
Jiri Slaby615e4a72006-12-08 02:38:38 -08004336 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004337 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004339 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340
Alan Coxb65b5b52006-06-27 02:54:05 -07004341 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342 BRDENABLE(portp->brdnr, portp->pagenr);
4343 sr = stl_sc26198getreg(portp, SR);
4344 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004345 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Jesper Juhl014c2542006-01-15 02:37:08 +01004347 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348}
4349
4350/*****************************************************************************/
4351
4352/*
4353 * Delay for a small amount of time, to give the sc26198 a chance
4354 * to process a command...
4355 */
4356
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004357static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358{
4359 int i;
4360
Jiri Slabya0564e12006-12-08 02:38:37 -08004361 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362
Jiri Slaby615e4a72006-12-08 02:38:38 -08004363 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364 return;
4365
Jiri Slabyc62429d2006-12-08 02:39:14 -08004366 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 stl_sc26198getglobreg(portp, TSTR);
4368}
4369
4370/*****************************************************************************/
4371
4372/*
4373 * If we are TX flow controlled and in IXANY mode then we may
4374 * need to unflow control here. We gotta do this because of the
4375 * automatic flow control modes of the sc26198.
4376 */
4377
Jiri Slaby60be4812006-12-08 02:38:40 -08004378static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379{
4380 unsigned char mr0;
4381
4382 mr0 = stl_sc26198getreg(portp, MR0);
4383 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4384 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4385 stl_sc26198wait(portp);
4386 stl_sc26198setreg(portp, MR0, mr0);
4387 clear_bit(ASYI_TXFLOWED, &portp->istate);
4388}
4389
4390/*****************************************************************************/
4391
4392/*
4393 * Interrupt service routine for sc26198 panels.
4394 */
4395
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004396static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004398 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 unsigned int iack;
4400
Alan Coxb65b5b52006-06-27 02:54:05 -07004401 spin_lock(&brd_lock);
4402
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403/*
4404 * Work around bug in sc26198 chip... Cannot have A6 address
4405 * line of UART high, else iack will be returned as 0.
4406 */
4407 outb(0, (iobase + 1));
4408
4409 iack = inb(iobase + XP_IACK);
4410 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4411
4412 if (iack & IVR_RXDATA)
4413 stl_sc26198rxisr(portp, iack);
4414 else if (iack & IVR_TXDATA)
4415 stl_sc26198txisr(portp);
4416 else
4417 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004418
4419 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420}
4421
4422/*****************************************************************************/
4423
4424/*
4425 * Transmit interrupt handler. This has gotta be fast! Handling TX
4426 * chars is pretty simple, stuff as many as possible from the TX buffer
4427 * into the sc26198 FIFO.
4428 * In practice it is possible that interrupts are enabled but that the
4429 * port has been hung up. Need to handle not having any TX buffer here,
4430 * this is done by using the side effect that head and tail will also
4431 * be NULL if the buffer has been freed.
4432 */
4433
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004434static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435{
4436 unsigned int ioaddr;
4437 unsigned char mr0;
4438 int len, stlen;
4439 char *head, *tail;
4440
Jiri Slabya0564e12006-12-08 02:38:37 -08004441 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442
4443 ioaddr = portp->ioaddr;
4444 head = portp->tx.head;
4445 tail = portp->tx.tail;
4446 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4447 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4448 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4449 set_bit(ASYI_TXLOW, &portp->istate);
4450 schedule_work(&portp->tqueue);
4451 }
4452
4453 if (len == 0) {
4454 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4455 mr0 = inb(ioaddr + XP_DATA);
4456 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4457 portp->imr &= ~IR_TXRDY;
4458 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4459 outb(portp->imr, (ioaddr + XP_DATA));
4460 clear_bit(ASYI_TXBUSY, &portp->istate);
4461 } else {
4462 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4463 outb(mr0, (ioaddr + XP_DATA));
4464 }
4465 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004466 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 portp->stats.txtotal += len;
Jiri Slaby843b5682006-12-08 02:39:12 -08004468 stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469 outb(GTXFIFO, (ioaddr + XP_ADDR));
4470 outsb((ioaddr + XP_DATA), tail, stlen);
4471 len -= stlen;
4472 tail += stlen;
4473 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4474 tail = portp->tx.buf;
4475 if (len > 0) {
4476 outsb((ioaddr + XP_DATA), tail, len);
4477 tail += len;
4478 }
4479 portp->tx.tail = tail;
4480 }
4481}
4482
4483/*****************************************************************************/
4484
4485/*
4486 * Receive character interrupt handler. Determine if we have good chars
4487 * or bad chars and then process appropriately. Good chars are easy
4488 * just shove the lot into the RX buffer and set all status byte to 0.
4489 * If a bad RX char then process as required. This routine needs to be
4490 * fast! In practice it is possible that we get an interrupt on a port
4491 * that is closed. This can happen on hangups - since they completely
4492 * shutdown a port not in user context. Need to handle this case.
4493 */
4494
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004495static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496{
4497 struct tty_struct *tty;
4498 unsigned int len, buflen, ioaddr;
4499
Jiri Slabya0564e12006-12-08 02:38:37 -08004500 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501
4502 tty = portp->tty;
4503 ioaddr = portp->ioaddr;
4504 outb(GIBCR, (ioaddr + XP_ADDR));
4505 len = inb(ioaddr + XP_DATA) + 1;
4506
4507 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004508 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08004509 len = min(len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510 outb(GRXFIFO, (ioaddr + XP_ADDR));
4511 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4512 portp->stats.rxlost += len;
4513 portp->stats.rxtotal += len;
4514 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004515 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004517 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004519 tty_prepare_flip_string(tty, &ptr, len);
4520 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 tty_schedule_flip(tty);
4522 portp->stats.rxtotal += len;
4523 }
4524 }
4525 } else {
4526 stl_sc26198rxbadchars(portp);
4527 }
4528
4529/*
4530 * If we are TX flow controlled and in IXANY mode then we may need
4531 * to unflow control here. We gotta do this because of the automatic
4532 * flow control modes of the sc26198.
4533 */
4534 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004535 if ((tty != NULL) &&
4536 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537 (tty->termios->c_iflag & IXANY)) {
4538 stl_sc26198txunflow(portp, tty);
4539 }
4540 }
4541}
4542
4543/*****************************************************************************/
4544
4545/*
4546 * Process an RX bad character.
4547 */
4548
Jiri Slaby60be4812006-12-08 02:38:40 -08004549static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550{
4551 struct tty_struct *tty;
4552 unsigned int ioaddr;
4553
4554 tty = portp->tty;
4555 ioaddr = portp->ioaddr;
4556
4557 if (status & SR_RXPARITY)
4558 portp->stats.rxparity++;
4559 if (status & SR_RXFRAMING)
4560 portp->stats.rxframing++;
4561 if (status & SR_RXOVERRUN)
4562 portp->stats.rxoverrun++;
4563 if (status & SR_RXBREAK)
4564 portp->stats.rxbreaks++;
4565
Jiri Slaby615e4a72006-12-08 02:38:38 -08004566 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 ((portp->rxignoremsk & status) == 0)) {
4568 if (portp->rxmarkmsk & status) {
4569 if (status & SR_RXBREAK) {
4570 status = TTY_BREAK;
4571 if (portp->flags & ASYNC_SAK) {
4572 do_SAK(tty);
4573 BRDENABLE(portp->brdnr, portp->pagenr);
4574 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004575 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004577 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004579 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004581 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004583 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585
Alan Cox33f0f882006-01-09 20:54:13 -08004586 tty_insert_flip_char(tty, ch, status);
4587 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588
4589 if (status == 0)
4590 portp->stats.rxtotal++;
4591 }
4592}
4593
4594/*****************************************************************************/
4595
4596/*
4597 * Process all characters in the RX FIFO of the UART. Check all char
4598 * status bytes as well, and process as required. We need to check
4599 * all bytes in the FIFO, in case some more enter the FIFO while we
4600 * are here. To get the exact character error type we need to switch
4601 * into CHAR error mode (that is why we need to make sure we empty
4602 * the FIFO).
4603 */
4604
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004605static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606{
4607 unsigned char status, mr1;
4608 char ch;
4609
4610/*
4611 * To get the precise error type for each character we must switch
4612 * back into CHAR error mode.
4613 */
4614 mr1 = stl_sc26198getreg(portp, MR1);
4615 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4616
4617 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4618 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4619 ch = stl_sc26198getreg(portp, RXFIFO);
4620 stl_sc26198rxbadch(portp, status, ch);
4621 }
4622
4623/*
4624 * To get correct interrupt class we must switch back into BLOCK
4625 * error mode.
4626 */
4627 stl_sc26198setreg(portp, MR1, mr1);
4628}
4629
4630/*****************************************************************************/
4631
4632/*
4633 * Other interrupt handler. This includes modem signals, flow
4634 * control actions, etc. Most stuff is left to off-level interrupt
4635 * processing time.
4636 */
4637
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004638static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004639{
4640 unsigned char cir, ipr, xisr;
4641
Jiri Slabya0564e12006-12-08 02:38:37 -08004642 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643
4644 cir = stl_sc26198getglobreg(portp, CIR);
4645
4646 switch (cir & CIR_SUBTYPEMASK) {
4647 case CIR_SUBCOS:
4648 ipr = stl_sc26198getreg(portp, IPR);
4649 if (ipr & IPR_DCDCHANGE) {
4650 set_bit(ASYI_DCDCHANGE, &portp->istate);
4651 schedule_work(&portp->tqueue);
4652 portp->stats.modem++;
4653 }
4654 break;
4655 case CIR_SUBXONXOFF:
4656 xisr = stl_sc26198getreg(portp, XISR);
4657 if (xisr & XISR_RXXONGOT) {
4658 set_bit(ASYI_TXFLOWED, &portp->istate);
4659 portp->stats.txxoff++;
4660 }
4661 if (xisr & XISR_RXXOFFGOT) {
4662 clear_bit(ASYI_TXFLOWED, &portp->istate);
4663 portp->stats.txxon++;
4664 }
4665 break;
4666 case CIR_SUBBREAK:
4667 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4668 stl_sc26198rxbadchars(portp);
4669 break;
4670 default:
4671 break;
4672 }
4673}
4674
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004675static void stl_free_isabrds(void)
4676{
4677 struct stlbrd *brdp;
4678 unsigned int i;
4679
4680 for (i = 0; i < stl_nrbrds; i++) {
4681 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4682 continue;
4683
4684 free_irq(brdp->irq, brdp);
4685
4686 stl_cleanup_panels(brdp);
4687
4688 release_region(brdp->ioaddr1, brdp->iosize1);
4689 if (brdp->iosize2 > 0)
4690 release_region(brdp->ioaddr2, brdp->iosize2);
4691
4692 kfree(brdp);
4693 stl_brds[i] = NULL;
4694 }
4695}
4696
Jiri Slaby23b85a12006-12-08 02:38:40 -08004697/*
4698 * Loadable module initialization stuff.
4699 */
4700static int __init stallion_module_init(void)
4701{
Jiri Slaby843b5682006-12-08 02:39:12 -08004702 struct stlbrd *brdp;
4703 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004704 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004705 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004706
4707 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4708
4709 spin_lock_init(&stallion_lock);
4710 spin_lock_init(&brd_lock);
4711
Jiri Slabye4151092007-06-08 13:46:52 -07004712 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4713 if (!stl_serial) {
4714 retval = -ENOMEM;
4715 goto err;
4716 }
4717
4718 stl_serial->owner = THIS_MODULE;
4719 stl_serial->driver_name = stl_drvname;
4720 stl_serial->name = "ttyE";
4721 stl_serial->major = STL_SERIALMAJOR;
4722 stl_serial->minor_start = 0;
4723 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4724 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4725 stl_serial->init_termios = stl_deftermios;
4726 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4727 tty_set_operations(stl_serial, &stl_ops);
4728
4729 retval = tty_register_driver(stl_serial);
4730 if (retval) {
4731 printk("STALLION: failed to register serial driver\n");
4732 goto err_frtty;
4733 }
4734
Jiri Slaby843b5682006-12-08 02:39:12 -08004735/*
4736 * Find any dynamically supported boards. That is via module load
4737 * line options.
4738 */
4739 for (i = stl_nrbrds; i < stl_nargs; i++) {
4740 memset(&conf, 0, sizeof(conf));
4741 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4742 continue;
4743 if ((brdp = stl_allocbrd()) == NULL)
4744 continue;
4745 brdp->brdnr = i;
4746 brdp->brdtype = conf.brdtype;
4747 brdp->ioaddr1 = conf.ioaddr1;
4748 brdp->ioaddr2 = conf.ioaddr2;
4749 brdp->irq = conf.irq;
4750 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004751 stl_brds[brdp->brdnr] = brdp;
4752 if (stl_brdinit(brdp)) {
4753 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004754 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004755 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004756 for (j = 0; j < brdp->nrports; j++)
4757 tty_register_device(stl_serial,
4758 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004759 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004760 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004761 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004762
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004763 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004764 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004765 if (retval && stl_nrbrds == 0) {
4766 printk(KERN_ERR "STALLION: can't register pci driver\n");
4767 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004768 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004769
4770/*
4771 * Set up a character driver for per board stuff. This is mainly used
4772 * to do stats ioctls on the ports.
4773 */
4774 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4775 printk("STALLION: failed to register serial board device\n");
4776
4777 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004778 if (IS_ERR(stallion_class))
4779 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004780 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004781 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4782 "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004783
Jiri Slaby23b85a12006-12-08 02:38:40 -08004784 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004785err_unrtty:
4786 tty_unregister_driver(stl_serial);
4787err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004788 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004789err:
4790 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004791}
4792
4793static void __exit stallion_module_exit(void)
4794{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004795 struct stlbrd *brdp;
4796 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004797
4798 pr_debug("cleanup_module()\n");
4799
4800 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4801 stl_drvversion);
4802
4803/*
4804 * Free up all allocated resources used by the ports. This includes
4805 * memory and interrupts. As part of this process we will also do
4806 * a hangup on every open port - to try to flush out any processes
4807 * hanging onto ports.
4808 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004809 for (i = 0; i < stl_nrbrds; i++) {
4810 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4811 continue;
4812 for (j = 0; j < brdp->nrports; j++)
4813 tty_unregister_device(stl_serial,
4814 brdp->brdnr * STL_MAXPORTS + j);
4815 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004816
Jiri Slaby23b85a12006-12-08 02:38:40 -08004817 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004818 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004819 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004820 class_destroy(stallion_class);
4821
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004822 pci_unregister_driver(&stl_pcidriver);
4823
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004824 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004825
4826 tty_unregister_driver(stl_serial);
4827 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004828}
4829
4830module_init(stallion_module_init);
4831module_exit(stallion_module_exit);
4832
4833MODULE_AUTHOR("Greg Ungerer");
4834MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4835MODULE_LICENSE("GPL");