blob: f49f145e20ee267819b54e1e59c33ee234494f15 [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>
44
45#include <asm/io.h>
46#include <asm/uaccess.h>
47
48#ifdef CONFIG_PCI
49#include <linux/pci.h>
50#endif
51
52/*****************************************************************************/
53
54/*
55 * Define different board types. Use the standard Stallion "assigned"
56 * board numbers. Boards supported in this driver are abbreviated as
57 * EIO = EasyIO and ECH = EasyConnection 8/32.
58 */
59#define BRD_EASYIO 20
60#define BRD_ECH 21
61#define BRD_ECHMC 22
62#define BRD_ECHPCI 26
63#define BRD_ECH64PCI 27
64#define BRD_EASYIOPCI 28
65
66/*
67 * Define a configuration structure to hold the board configuration.
68 * Need to set this up in the code (for now) with the boards that are
69 * to be configured into the system. This is what needs to be modified
70 * when adding/removing/modifying boards. Each line entry in the
71 * stl_brdconf[] array is a board. Each line contains io/irq/memory
72 * ranges for that board (as well as what type of board it is).
73 * Some examples:
74 * { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
75 * This line would configure an EasyIO board (4 or 8, no difference),
76 * at io address 2a0 and irq 10.
77 * Another example:
78 * { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 },
79 * This line will configure an EasyConnection 8/32 board at primary io
80 * address 2a8, secondary io address 280 and irq 12.
81 * Enter as many lines into this array as you want (only the first 4
82 * will actually be used!). Any combination of EasyIO and EasyConnection
83 * boards can be specified. EasyConnection 8/32 boards can share their
84 * secondary io addresses between each other.
85 *
86 * NOTE: there is no need to put any entries in this table for PCI
87 * boards. They will be found automatically by the driver - provided
88 * PCI BIOS32 support is compiled into the kernel.
89 */
90
Jiri Slabyca7ed0f2006-12-08 02:38:39 -080091static struct stlconf {
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 int brdtype;
93 int ioaddr1;
94 int ioaddr2;
95 unsigned long memaddr;
96 int irq;
97 int irqtype;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -080098} stl_brdconf[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
100};
101
Tobias Klauserfe971072006-01-09 20:54:02 -0800102static int stl_nrbrds = ARRAY_SIZE(stl_brdconf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104/*****************************************************************************/
105
106/*
107 * Define some important driver characteristics. Device major numbers
108 * allocated as per Linux Device Registry.
109 */
110#ifndef STL_SIOMEMMAJOR
111#define STL_SIOMEMMAJOR 28
112#endif
113#ifndef STL_SERIALMAJOR
114#define STL_SERIALMAJOR 24
115#endif
116#ifndef STL_CALLOUTMAJOR
117#define STL_CALLOUTMAJOR 25
118#endif
119
120/*
121 * Set the TX buffer size. Bigger is better, but we don't want
122 * to chew too much memory with buffers!
123 */
124#define STL_TXBUFLOW 512
125#define STL_TXBUFSIZE 4096
126
127/*****************************************************************************/
128
129/*
130 * Define our local driver identity first. Set up stuff to deal with
131 * all the local structures required by a serial tty driver.
132 */
133static char *stl_drvtitle = "Stallion Multiport Serial Driver";
134static char *stl_drvname = "stallion";
135static char *stl_drvversion = "5.6.0";
136
137static struct tty_driver *stl_serial;
138
139/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 * Define a local default termios struct. All ports will be created
141 * with this termios initially. Basically all it defines is a raw port
142 * at 9600, 8 data bits, 1 stop bit.
143 */
144static struct termios stl_deftermios = {
145 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
146 .c_cc = INIT_C_CC,
147};
148
149/*
150 * Define global stats structures. Not used often, and can be
151 * re-used for each stats call.
152 */
153static comstats_t stl_comstats;
154static combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800155static struct stlbrd stl_dummybrd;
156static struct stlport stl_dummyport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
158/*
159 * Define global place to put buffer overflow characters.
160 */
161static char stl_unwanted[SC26198_RXFIFOSIZE];
162
163/*****************************************************************************/
164
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800165static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167/*
168 * Per board state flags. Used with the state field of the board struct.
169 * Not really much here!
170 */
171#define BRD_FOUND 0x1
172
173/*
174 * Define the port structure istate flags. These set of flags are
175 * modified at interrupt time - so setting and reseting them needs
176 * to be atomic. Use the bit clear/setting routines for this.
177 */
178#define ASYI_TXBUSY 1
179#define ASYI_TXLOW 2
180#define ASYI_DCDCHANGE 3
181#define ASYI_TXFLOWED 4
182
183/*
184 * Define an array of board names as printable strings. Handy for
185 * referencing boards when printing trace and stuff.
186 */
187static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800188 NULL,
189 NULL,
190 NULL,
191 NULL,
192 NULL,
193 NULL,
194 NULL,
195 NULL,
196 NULL,
197 NULL,
198 NULL,
199 NULL,
200 NULL,
201 NULL,
202 NULL,
203 NULL,
204 NULL,
205 NULL,
206 NULL,
207 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 "EasyIO",
209 "EC8/32-AT",
210 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800211 NULL,
212 NULL,
213 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 "EC8/32-PCI",
215 "EC8/64-PCI",
216 "EasyIO-PCI",
217};
218
219/*****************************************************************************/
220
221/*
222 * Define some string labels for arguments passed from the module
223 * load line. These allow for easy board definitions, and easy
224 * modification of the io, memory and irq resoucres.
225 */
226static int stl_nargs = 0;
227static char *board0[4];
228static char *board1[4];
229static char *board2[4];
230static char *board3[4];
231
232static char **stl_brdsp[] = {
233 (char **) &board0,
234 (char **) &board1,
235 (char **) &board2,
236 (char **) &board3
237};
238
239/*
240 * Define a set of common board names, and types. This is used to
241 * parse any module arguments.
242 */
243
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800244static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 char *name;
246 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800247} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 { "easyio", BRD_EASYIO },
249 { "eio", BRD_EASYIO },
250 { "20", BRD_EASYIO },
251 { "ec8/32", BRD_ECH },
252 { "ec8/32-at", BRD_ECH },
253 { "ec8/32-isa", BRD_ECH },
254 { "ech", BRD_ECH },
255 { "echat", BRD_ECH },
256 { "21", BRD_ECH },
257 { "ec8/32-mc", BRD_ECHMC },
258 { "ec8/32-mca", BRD_ECHMC },
259 { "echmc", BRD_ECHMC },
260 { "echmca", BRD_ECHMC },
261 { "22", BRD_ECHMC },
262 { "ec8/32-pc", BRD_ECHPCI },
263 { "ec8/32-pci", BRD_ECHPCI },
264 { "26", BRD_ECHPCI },
265 { "ec8/64-pc", BRD_ECH64PCI },
266 { "ec8/64-pci", BRD_ECH64PCI },
267 { "ech-pci", BRD_ECH64PCI },
268 { "echpci", BRD_ECH64PCI },
269 { "echpc", BRD_ECH64PCI },
270 { "27", BRD_ECH64PCI },
271 { "easyio-pc", BRD_EASYIOPCI },
272 { "easyio-pci", BRD_EASYIOPCI },
273 { "eio-pci", BRD_EASYIOPCI },
274 { "eiopci", BRD_EASYIOPCI },
275 { "28", BRD_EASYIOPCI },
276};
277
278/*
279 * Define the module agruments.
280 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
282module_param_array(board0, charp, &stl_nargs, 0);
283MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
284module_param_array(board1, charp, &stl_nargs, 0);
285MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
286module_param_array(board2, charp, &stl_nargs, 0);
287MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
288module_param_array(board3, charp, &stl_nargs, 0);
289MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
290
291/*****************************************************************************/
292
293/*
294 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
295 * to the directly accessible io ports of these boards (not the uarts -
296 * they are in cd1400.h and sc26198.h).
297 */
298#define EIO_8PORTRS 0x04
299#define EIO_4PORTRS 0x05
300#define EIO_8PORTDI 0x00
301#define EIO_8PORTM 0x06
302#define EIO_MK3 0x03
303#define EIO_IDBITMASK 0x07
304
305#define EIO_BRDMASK 0xf0
306#define ID_BRD4 0x10
307#define ID_BRD8 0x20
308#define ID_BRD16 0x30
309
310#define EIO_INTRPEND 0x08
311#define EIO_INTEDGE 0x00
312#define EIO_INTLEVEL 0x08
313#define EIO_0WS 0x10
314
315#define ECH_ID 0xa0
316#define ECH_IDBITMASK 0xe0
317#define ECH_BRDENABLE 0x08
318#define ECH_BRDDISABLE 0x00
319#define ECH_INTENABLE 0x01
320#define ECH_INTDISABLE 0x00
321#define ECH_INTLEVEL 0x02
322#define ECH_INTEDGE 0x00
323#define ECH_INTRPEND 0x01
324#define ECH_BRDRESET 0x01
325
326#define ECHMC_INTENABLE 0x01
327#define ECHMC_BRDRESET 0x02
328
329#define ECH_PNLSTATUS 2
330#define ECH_PNL16PORT 0x20
331#define ECH_PNLIDMASK 0x07
332#define ECH_PNLXPID 0x40
333#define ECH_PNLINTRPEND 0x80
334
335#define ECH_ADDR2MASK 0x1e0
336
337/*
338 * Define the vector mapping bits for the programmable interrupt board
339 * hardware. These bits encode the interrupt for the board to use - it
340 * is software selectable (except the EIO-8M).
341 */
342static unsigned char stl_vecmap[] = {
343 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
344 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
345};
346
347/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700348 * Lock ordering is that you may not take stallion_lock holding
349 * brd_lock.
350 */
351
352static spinlock_t brd_lock; /* Guard the board mapping */
353static spinlock_t stallion_lock; /* Guard the tty driver */
354
355/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 * Set up enable and disable macros for the ECH boards. They require
357 * the secondary io address space to be activated and deactivated.
358 * This way all ECH boards can share their secondary io region.
359 * If this is an ECH-PCI board then also need to set the page pointer
360 * to point to the correct page.
361 */
362#define BRDENABLE(brdnr,pagenr) \
363 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
364 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
365 stl_brds[(brdnr)]->ioctrl); \
366 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
367 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
368
369#define BRDDISABLE(brdnr) \
370 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
371 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
372 stl_brds[(brdnr)]->ioctrl);
373
374#define STL_CD1400MAXBAUD 230400
375#define STL_SC26198MAXBAUD 460800
376
377#define STL_BAUDBASE 115200
378#define STL_CLOSEDELAY (5 * HZ / 10)
379
380/*****************************************************************************/
381
382#ifdef CONFIG_PCI
383
384/*
385 * Define the Stallion PCI vendor and device IDs.
386 */
387#ifndef PCI_VENDOR_ID_STALLION
388#define PCI_VENDOR_ID_STALLION 0x124d
389#endif
390#ifndef PCI_DEVICE_ID_ECHPCI832
391#define PCI_DEVICE_ID_ECHPCI832 0x0000
392#endif
393#ifndef PCI_DEVICE_ID_ECHPCI864
394#define PCI_DEVICE_ID_ECHPCI864 0x0002
395#endif
396#ifndef PCI_DEVICE_ID_EIOPCI
397#define PCI_DEVICE_ID_EIOPCI 0x0003
398#endif
399
400/*
401 * Define structure to hold all Stallion PCI boards.
402 */
403typedef struct stlpcibrd {
404 unsigned short vendid;
405 unsigned short devid;
406 int brdtype;
407} stlpcibrd_t;
408
409static stlpcibrd_t stl_pcibrds[] = {
410 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI },
411 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI },
412 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI },
413 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
414};
415
Tobias Klauserfe971072006-01-09 20:54:02 -0800416static int stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
418#endif
419
420/*****************************************************************************/
421
422/*
423 * Define macros to extract a brd/port number from a minor number.
424 */
425#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
426#define MINOR2PORT(min) ((min) & 0x3f)
427
428/*
429 * Define a baud rate table that converts termios baud rate selector
430 * into the actual baud rate value. All baud rate calculations are
431 * based on the actual baud rate required.
432 */
433static unsigned int stl_baudrates[] = {
434 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
435 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
436};
437
438/*
439 * Define some handy local macros...
440 */
441#undef MIN
442#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
443
444#undef TOLOWER
445#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
446
447/*****************************************************************************/
448
449/*
450 * Declare all those functions in this driver!
451 */
452
453static void stl_argbrds(void);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800454static int stl_parsebrd(struct stlconf *confp, char **argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
456static unsigned long stl_atol(char *str);
457
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458static int stl_open(struct tty_struct *tty, struct file *filp);
459static void stl_close(struct tty_struct *tty, struct file *filp);
460static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count);
461static void stl_putchar(struct tty_struct *tty, unsigned char ch);
462static void stl_flushchars(struct tty_struct *tty);
463static int stl_writeroom(struct tty_struct *tty);
464static int stl_charsinbuffer(struct tty_struct *tty);
465static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
466static void stl_settermios(struct tty_struct *tty, struct termios *old);
467static void stl_throttle(struct tty_struct *tty);
468static void stl_unthrottle(struct tty_struct *tty);
469static void stl_stop(struct tty_struct *tty);
470static void stl_start(struct tty_struct *tty);
471static void stl_flushbuffer(struct tty_struct *tty);
472static void stl_breakctl(struct tty_struct *tty, int state);
473static void stl_waituntilsent(struct tty_struct *tty, int timeout);
474static void stl_sendxchar(struct tty_struct *tty, char ch);
475static void stl_hangup(struct tty_struct *tty);
476static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800477static int stl_portinfo(struct stlport *portp, int portnr, char *pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data);
479
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800480static int stl_brdinit(struct stlbrd *brdp);
481static int stl_initports(struct stlbrd *brdp, struct stlpanel *panelp);
482static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp);
483static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484static int stl_getbrdstats(combrd_t __user *bp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800485static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
486static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
487static int stl_getportstruct(struct stlport __user *arg);
488static int stl_getbrdstruct(struct stlbrd __user *arg);
489static int stl_waitcarrier(struct stlport *portp, struct file *filp);
490static int stl_eiointr(struct stlbrd *brdp);
491static int stl_echatintr(struct stlbrd *brdp);
492static int stl_echmcaintr(struct stlbrd *brdp);
493static int stl_echpciintr(struct stlbrd *brdp);
494static int stl_echpci64intr(struct stlbrd *brdp);
Al Viro3e577a82006-12-06 18:41:45 +0000495static void stl_offintr(struct work_struct *);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800496static struct stlbrd *stl_allocbrd(void);
497static struct stlport *stl_getport(int brdnr, int panelnr, int portnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
499static inline int stl_initbrds(void);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800500static inline int stl_initeio(struct stlbrd *brdp);
501static inline int stl_initech(struct stlbrd *brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502static inline int stl_getbrdnr(void);
503
504#ifdef CONFIG_PCI
505static inline int stl_findpcibrds(void);
506static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp);
507#endif
508
509/*
510 * CD1400 uart specific handling functions.
511 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800512static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
513static int stl_cd1400getreg(struct stlport *portp, int regnr);
514static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
515static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
516static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
517static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp);
518static int stl_cd1400getsignals(struct stlport *portp);
519static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
520static void stl_cd1400ccrwait(struct stlport *portp);
521static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
522static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
523static void stl_cd1400disableintrs(struct stlport *portp);
524static void stl_cd1400sendbreak(struct stlport *portp, int len);
525static void stl_cd1400flowctrl(struct stlport *portp, int state);
526static void stl_cd1400sendflow(struct stlport *portp, int state);
527static void stl_cd1400flush(struct stlport *portp);
528static int stl_cd1400datastate(struct stlport *portp);
529static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
530static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
531static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
532static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
533static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800535static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537/*
538 * SC26198 uart specific handling functions.
539 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800540static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
541static int stl_sc26198getreg(struct stlport *portp, int regnr);
542static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
543static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
544static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
545static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
546static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp);
547static int stl_sc26198getsignals(struct stlport *portp);
548static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
549static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
550static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
551static void stl_sc26198disableintrs(struct stlport *portp);
552static void stl_sc26198sendbreak(struct stlport *portp, int len);
553static void stl_sc26198flowctrl(struct stlport *portp, int state);
554static void stl_sc26198sendflow(struct stlport *portp, int state);
555static void stl_sc26198flush(struct stlport *portp);
556static int stl_sc26198datastate(struct stlport *portp);
557static void stl_sc26198wait(struct stlport *portp);
558static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
559static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
560static void stl_sc26198txisr(struct stlport *port);
561static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
562static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
563static void stl_sc26198rxbadchars(struct stlport *portp);
564static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
566/*****************************************************************************/
567
568/*
569 * Generic UART support structure.
570 */
571typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800572 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
573 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
574 void (*setport)(struct stlport *portp, struct termios *tiosp);
575 int (*getsignals)(struct stlport *portp);
576 void (*setsignals)(struct stlport *portp, int dtr, int rts);
577 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
578 void (*startrxtx)(struct stlport *portp, int rx, int tx);
579 void (*disableintrs)(struct stlport *portp);
580 void (*sendbreak)(struct stlport *portp, int len);
581 void (*flowctrl)(struct stlport *portp, int state);
582 void (*sendflow)(struct stlport *portp, int state);
583 void (*flush)(struct stlport *portp);
584 int (*datastate)(struct stlport *portp);
585 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586} uart_t;
587
588/*
589 * Define some macros to make calling these functions nice and clean.
590 */
591#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
592#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
593#define stl_setport (* ((uart_t *) portp->uartp)->setport)
594#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
595#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
596#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
597#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
598#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
599#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
600#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
601#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
602#define stl_flush (* ((uart_t *) portp->uartp)->flush)
603#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
604
605/*****************************************************************************/
606
607/*
608 * CD1400 UART specific data initialization.
609 */
610static uart_t stl_cd1400uart = {
611 stl_cd1400panelinit,
612 stl_cd1400portinit,
613 stl_cd1400setport,
614 stl_cd1400getsignals,
615 stl_cd1400setsignals,
616 stl_cd1400enablerxtx,
617 stl_cd1400startrxtx,
618 stl_cd1400disableintrs,
619 stl_cd1400sendbreak,
620 stl_cd1400flowctrl,
621 stl_cd1400sendflow,
622 stl_cd1400flush,
623 stl_cd1400datastate,
624 stl_cd1400eiointr
625};
626
627/*
628 * Define the offsets within the register bank of a cd1400 based panel.
629 * These io address offsets are common to the EasyIO board as well.
630 */
631#define EREG_ADDR 0
632#define EREG_DATA 4
633#define EREG_RXACK 5
634#define EREG_TXACK 6
635#define EREG_MDACK 7
636
637#define EREG_BANKSIZE 8
638
639#define CD1400_CLK 25000000
640#define CD1400_CLK8M 20000000
641
642/*
643 * Define the cd1400 baud rate clocks. These are used when calculating
644 * what clock and divisor to use for the required baud rate. Also
645 * define the maximum baud rate allowed, and the default base baud.
646 */
647static int stl_cd1400clkdivs[] = {
648 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
649};
650
651/*****************************************************************************/
652
653/*
654 * SC26198 UART specific data initization.
655 */
656static uart_t stl_sc26198uart = {
657 stl_sc26198panelinit,
658 stl_sc26198portinit,
659 stl_sc26198setport,
660 stl_sc26198getsignals,
661 stl_sc26198setsignals,
662 stl_sc26198enablerxtx,
663 stl_sc26198startrxtx,
664 stl_sc26198disableintrs,
665 stl_sc26198sendbreak,
666 stl_sc26198flowctrl,
667 stl_sc26198sendflow,
668 stl_sc26198flush,
669 stl_sc26198datastate,
670 stl_sc26198intr
671};
672
673/*
674 * Define the offsets within the register bank of a sc26198 based panel.
675 */
676#define XP_DATA 0
677#define XP_ADDR 1
678#define XP_MODID 2
679#define XP_STATUS 2
680#define XP_IACK 3
681
682#define XP_BANKSIZE 4
683
684/*
685 * Define the sc26198 baud rate table. Offsets within the table
686 * represent the actual baud rate selector of sc26198 registers.
687 */
688static unsigned int sc26198_baudtable[] = {
689 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
690 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
691 230400, 460800, 921600
692};
693
Tobias Klauserfe971072006-01-09 20:54:02 -0800694#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
696/*****************************************************************************/
697
698/*
699 * Define the driver info for a user level control device. Used mainly
700 * to get at port stats - only not using the port device itself.
701 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700702static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 .owner = THIS_MODULE,
704 .ioctl = stl_memioctl,
705};
706
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800707static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 * Check for any arguments passed in on the module load command line.
711 */
712
713static void stl_argbrds(void)
714{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800715 struct stlconf conf;
716 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 int i;
718
Jiri Slabya0564e12006-12-08 02:38:37 -0800719 pr_debug("stl_argbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 for (i = stl_nrbrds; (i < stl_nargs); i++) {
722 memset(&conf, 0, sizeof(conf));
723 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
724 continue;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800725 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 continue;
727 stl_nrbrds = i + 1;
728 brdp->brdnr = i;
729 brdp->brdtype = conf.brdtype;
730 brdp->ioaddr1 = conf.ioaddr1;
731 brdp->ioaddr2 = conf.ioaddr2;
732 brdp->irq = conf.irq;
733 brdp->irqtype = conf.irqtype;
734 stl_brdinit(brdp);
735 }
736}
737
738/*****************************************************************************/
739
740/*
741 * Convert an ascii string number into an unsigned long.
742 */
743
744static unsigned long stl_atol(char *str)
745{
746 unsigned long val;
747 int base, c;
748 char *sp;
749
750 val = 0;
751 sp = str;
752 if ((*sp == '0') && (*(sp+1) == 'x')) {
753 base = 16;
754 sp += 2;
755 } else if (*sp == '0') {
756 base = 8;
757 sp++;
758 } else {
759 base = 10;
760 }
761
762 for (; (*sp != 0); sp++) {
763 c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
764 if ((c < 0) || (c >= base)) {
765 printk("STALLION: invalid argument %s\n", str);
766 val = 0;
767 break;
768 }
769 val = (val * base) + c;
770 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100771 return val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772}
773
774/*****************************************************************************/
775
776/*
777 * Parse the supplied argument string, into the board conf struct.
778 */
779
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800780static int stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781{
782 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800783 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Jiri Slabya0564e12006-12-08 02:38:37 -0800785 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Jiri Slaby615e4a72006-12-08 02:38:38 -0800787 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100788 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
790 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
791 *sp = TOLOWER(*sp);
792
Tobias Klauserfe971072006-01-09 20:54:02 -0800793 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
795 break;
796 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800797 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800799 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 }
801
802 confp->brdtype = stl_brdstr[i].type;
803
804 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800805 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 confp->ioaddr1 = stl_atol(argp[i]);
807 i++;
808 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800809 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 confp->ioaddr2 = stl_atol(argp[i]);
811 i++;
812 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800813 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 confp->irq = stl_atol(argp[i]);
Jesper Juhl014c2542006-01-15 02:37:08 +0100815 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816}
817
818/*****************************************************************************/
819
820/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 * Allocate a new board structure. Fill out the basic info in it.
822 */
823
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800824static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800826 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800828 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800829 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700830 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800831 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800832 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 }
834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100836 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837}
838
839/*****************************************************************************/
840
841static int stl_open(struct tty_struct *tty, struct file *filp)
842{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800843 struct stlport *portp;
844 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 unsigned int minordev;
846 int brdnr, panelnr, portnr, rc;
847
Jiri Slabya0564e12006-12-08 02:38:37 -0800848 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
850 minordev = tty->index;
851 brdnr = MINOR2BRD(minordev);
852 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100853 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800855 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100856 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 minordev = MINOR2PORT(minordev);
858 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800859 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 break;
861 if (minordev < brdp->panels[panelnr]->nrports) {
862 portnr = minordev;
863 break;
864 }
865 minordev -= brdp->panels[panelnr]->nrports;
866 }
867 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100868 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
870 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800871 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100872 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
874/*
875 * On the first open of the device setup the port hardware, and
876 * initialize the per port data structure.
877 */
878 portp->tty = tty;
879 tty->driver_data = portp;
880 portp->refcount++;
881
882 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800883 if (!portp->tx.buf) {
884 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
885 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100886 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 portp->tx.head = portp->tx.buf;
888 portp->tx.tail = portp->tx.buf;
889 }
890 stl_setport(portp, tty->termios);
891 portp->sigs = stl_getsignals(portp);
892 stl_setsignals(portp, 1, 1);
893 stl_enablerxtx(portp, 1, 1);
894 stl_startrxtx(portp, 1, 0);
895 clear_bit(TTY_IO_ERROR, &tty->flags);
896 portp->flags |= ASYNC_INITIALIZED;
897 }
898
899/*
900 * Check if this port is in the middle of closing. If so then wait
901 * until it is closed then return error status, based on flag settings.
902 * The sleep here does not need interrupt protection since the wakeup
903 * for it is done with the same context.
904 */
905 if (portp->flags & ASYNC_CLOSING) {
906 interruptible_sleep_on(&portp->close_wait);
907 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100908 return -EAGAIN;
909 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
911
912/*
913 * Based on type of open being done check if it can overlap with any
914 * previous opens still in effect. If we are a normal serial device
915 * then also we might have to wait for carrier.
916 */
917 if (!(filp->f_flags & O_NONBLOCK)) {
918 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100919 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921 portp->flags |= ASYNC_NORMAL_ACTIVE;
922
Jesper Juhl014c2542006-01-15 02:37:08 +0100923 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924}
925
926/*****************************************************************************/
927
928/*
929 * Possibly need to wait for carrier (DCD signal) to come high. Say
930 * maybe because if we are clocal then we don't need to wait...
931 */
932
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800933static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934{
935 unsigned long flags;
936 int rc, doclocal;
937
Jiri Slabya0564e12006-12-08 02:38:37 -0800938 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
940 rc = 0;
941 doclocal = 0;
942
Alan Coxb65b5b52006-06-27 02:54:05 -0700943 spin_lock_irqsave(&stallion_lock, flags);
944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 if (portp->tty->termios->c_cflag & CLOCAL)
946 doclocal++;
947
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 portp->openwaitcnt++;
949 if (! tty_hung_up_p(filp))
950 portp->refcount--;
951
952 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700953 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 stl_setsignals(portp, 1, 1);
955 if (tty_hung_up_p(filp) ||
956 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
957 if (portp->flags & ASYNC_HUP_NOTIFY)
958 rc = -EBUSY;
959 else
960 rc = -ERESTARTSYS;
961 break;
962 }
963 if (((portp->flags & ASYNC_CLOSING) == 0) &&
964 (doclocal || (portp->sigs & TIOCM_CD))) {
965 break;
966 }
967 if (signal_pending(current)) {
968 rc = -ERESTARTSYS;
969 break;
970 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700971 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 interruptible_sleep_on(&portp->open_wait);
973 }
974
975 if (! tty_hung_up_p(filp))
976 portp->refcount++;
977 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700978 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Jesper Juhl014c2542006-01-15 02:37:08 +0100980 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981}
982
983/*****************************************************************************/
984
985static void stl_close(struct tty_struct *tty, struct file *filp)
986{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800987 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 unsigned long flags;
989
Jiri Slabya0564e12006-12-08 02:38:37 -0800990 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
992 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800993 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 return;
995
Alan Coxb65b5b52006-06-27 02:54:05 -0700996 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700998 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 return;
1000 }
1001 if ((tty->count == 1) && (portp->refcount != 1))
1002 portp->refcount = 1;
1003 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -07001004 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 return;
1006 }
1007
1008 portp->refcount = 0;
1009 portp->flags |= ASYNC_CLOSING;
1010
1011/*
1012 * May want to wait for any data to drain before closing. The BUSY
1013 * flag keeps track of whether we are still sending or not - it is
1014 * very accurate for the cd1400, not quite so for the sc26198.
1015 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
1016 */
1017 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -07001018
1019 spin_unlock_irqrestore(&stallion_lock, flags);
1020
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1022 tty_wait_until_sent(tty, portp->closing_wait);
1023 stl_waituntilsent(tty, (HZ / 2));
1024
Alan Coxb65b5b52006-06-27 02:54:05 -07001025
1026 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -07001028 spin_unlock_irqrestore(&stallion_lock, flags);
1029
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 stl_disableintrs(portp);
1031 if (tty->termios->c_cflag & HUPCL)
1032 stl_setsignals(portp, 0, 0);
1033 stl_enablerxtx(portp, 0, 0);
1034 stl_flushbuffer(tty);
1035 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001036 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001038 portp->tx.buf = NULL;
1039 portp->tx.head = NULL;
1040 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 }
1042 set_bit(TTY_IO_ERROR, &tty->flags);
1043 tty_ldisc_flush(tty);
1044
1045 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001046 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
1048 if (portp->openwaitcnt) {
1049 if (portp->close_delay)
1050 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
1051 wake_up_interruptible(&portp->open_wait);
1052 }
1053
1054 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1055 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056}
1057
1058/*****************************************************************************/
1059
1060/*
1061 * Write routine. Take data and stuff it in to the TX ring queue.
1062 * If transmit interrupts are not running then start them.
1063 */
1064
1065static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
1066{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001067 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 unsigned int len, stlen;
1069 unsigned char *chbuf;
1070 char *head, *tail;
1071
Jiri Slabya0564e12006-12-08 02:38:37 -08001072 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001075 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001076 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001077 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001078 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
1080/*
1081 * If copying direct from user space we must cater for page faults,
1082 * causing us to "sleep" here for a while. To handle this copy in all
1083 * the data we need now, into a local buffer. Then when we got it all
1084 * copy it into the TX buffer.
1085 */
1086 chbuf = (unsigned char *) buf;
1087
1088 head = portp->tx.head;
1089 tail = portp->tx.tail;
1090 if (head >= tail) {
1091 len = STL_TXBUFSIZE - (head - tail) - 1;
1092 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1093 } else {
1094 len = tail - head - 1;
1095 stlen = len;
1096 }
1097
1098 len = MIN(len, count);
1099 count = 0;
1100 while (len > 0) {
1101 stlen = MIN(len, stlen);
1102 memcpy(head, chbuf, stlen);
1103 len -= stlen;
1104 chbuf += stlen;
1105 count += stlen;
1106 head += stlen;
1107 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1108 head = portp->tx.buf;
1109 stlen = tail - head;
1110 }
1111 }
1112 portp->tx.head = head;
1113
1114 clear_bit(ASYI_TXLOW, &portp->istate);
1115 stl_startrxtx(portp, -1, 1);
1116
Jesper Juhl014c2542006-01-15 02:37:08 +01001117 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118}
1119
1120/*****************************************************************************/
1121
1122static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1123{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001124 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 unsigned int len;
1126 char *head, *tail;
1127
Jiri Slabya0564e12006-12-08 02:38:37 -08001128 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
Jiri Slaby615e4a72006-12-08 02:38:38 -08001130 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 return;
1132 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001133 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001135 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 return;
1137
1138 head = portp->tx.head;
1139 tail = portp->tx.tail;
1140
1141 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1142 len--;
1143
1144 if (len > 0) {
1145 *head++ = ch;
1146 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1147 head = portp->tx.buf;
1148 }
1149 portp->tx.head = head;
1150}
1151
1152/*****************************************************************************/
1153
1154/*
1155 * If there are any characters in the buffer then make sure that TX
1156 * interrupts are on and get'em out. Normally used after the putchar
1157 * routine has been called.
1158 */
1159
1160static void stl_flushchars(struct tty_struct *tty)
1161{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001162 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Jiri Slabya0564e12006-12-08 02:38:37 -08001164 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
Jiri Slaby615e4a72006-12-08 02:38:38 -08001166 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 return;
1168 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001169 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001171 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 return;
1173
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 stl_startrxtx(portp, -1, 1);
1175}
1176
1177/*****************************************************************************/
1178
1179static int stl_writeroom(struct tty_struct *tty)
1180{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001181 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 char *head, *tail;
1183
Jiri Slabya0564e12006-12-08 02:38:37 -08001184 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
Jiri Slaby615e4a72006-12-08 02:38:38 -08001186 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001187 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001189 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001190 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001191 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001192 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
1194 head = portp->tx.head;
1195 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001196 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197}
1198
1199/*****************************************************************************/
1200
1201/*
1202 * Return number of chars in the TX buffer. Normally we would just
1203 * calculate the number of chars in the buffer and return that, but if
1204 * the buffer is empty and TX interrupts are still on then we return
1205 * that the buffer still has 1 char in it. This way whoever called us
1206 * will not think that ALL chars have drained - since the UART still
1207 * must have some chars in it (we are busy after all).
1208 */
1209
1210static int stl_charsinbuffer(struct tty_struct *tty)
1211{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001212 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 unsigned int size;
1214 char *head, *tail;
1215
Jiri Slabya0564e12006-12-08 02:38:37 -08001216 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
Jiri Slaby615e4a72006-12-08 02:38:38 -08001218 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001219 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001221 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001222 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001223 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001224 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
1226 head = portp->tx.head;
1227 tail = portp->tx.tail;
1228 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1229 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1230 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001231 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232}
1233
1234/*****************************************************************************/
1235
1236/*
1237 * Generate the serial struct info.
1238 */
1239
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001240static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241{
1242 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001243 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
Jiri Slabya0564e12006-12-08 02:38:37 -08001245 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
1247 memset(&sio, 0, sizeof(struct serial_struct));
1248 sio.line = portp->portnr;
1249 sio.port = portp->ioaddr;
1250 sio.flags = portp->flags;
1251 sio.baud_base = portp->baud_base;
1252 sio.close_delay = portp->close_delay;
1253 sio.closing_wait = portp->closing_wait;
1254 sio.custom_divisor = portp->custom_divisor;
1255 sio.hub6 = 0;
1256 if (portp->uartp == &stl_cd1400uart) {
1257 sio.type = PORT_CIRRUS;
1258 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1259 } else {
1260 sio.type = PORT_UNKNOWN;
1261 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1262 }
1263
1264 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001265 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 sio.irq = brdp->irq;
1267
1268 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1269}
1270
1271/*****************************************************************************/
1272
1273/*
1274 * Set port according to the serial struct info.
1275 * At this point we do not do any auto-configure stuff, so we will
1276 * just quietly ignore any requests to change irq, etc.
1277 */
1278
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001279static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280{
1281 struct serial_struct sio;
1282
Jiri Slabya0564e12006-12-08 02:38:37 -08001283 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
1285 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1286 return -EFAULT;
1287 if (!capable(CAP_SYS_ADMIN)) {
1288 if ((sio.baud_base != portp->baud_base) ||
1289 (sio.close_delay != portp->close_delay) ||
1290 ((sio.flags & ~ASYNC_USR_MASK) !=
1291 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001292 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 }
1294
1295 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1296 (sio.flags & ASYNC_USR_MASK);
1297 portp->baud_base = sio.baud_base;
1298 portp->close_delay = sio.close_delay;
1299 portp->closing_wait = sio.closing_wait;
1300 portp->custom_divisor = sio.custom_divisor;
1301 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001302 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303}
1304
1305/*****************************************************************************/
1306
1307static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1308{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001309 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Jiri Slaby615e4a72006-12-08 02:38:38 -08001311 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001312 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001314 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001315 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001317 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
1319 return stl_getsignals(portp);
1320}
1321
1322static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1323 unsigned int set, unsigned int clear)
1324{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001325 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 int rts = -1, dtr = -1;
1327
Jiri Slaby615e4a72006-12-08 02:38:38 -08001328 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001329 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001331 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001332 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001334 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
1336 if (set & TIOCM_RTS)
1337 rts = 1;
1338 if (set & TIOCM_DTR)
1339 dtr = 1;
1340 if (clear & TIOCM_RTS)
1341 rts = 0;
1342 if (clear & TIOCM_DTR)
1343 dtr = 0;
1344
1345 stl_setsignals(portp, dtr, rts);
1346 return 0;
1347}
1348
1349static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1350{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001351 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 unsigned int ival;
1353 int rc;
1354 void __user *argp = (void __user *)arg;
1355
Jiri Slabya0564e12006-12-08 02:38:37 -08001356 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1357 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Jiri Slaby615e4a72006-12-08 02:38:38 -08001359 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001360 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001362 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001363 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1366 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1367 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001368 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 }
1370
1371 rc = 0;
1372
1373 switch (cmd) {
1374 case TIOCGSOFTCAR:
1375 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1376 (unsigned __user *) argp);
1377 break;
1378 case TIOCSSOFTCAR:
1379 if (get_user(ival, (unsigned int __user *) arg))
1380 return -EFAULT;
1381 tty->termios->c_cflag =
1382 (tty->termios->c_cflag & ~CLOCAL) |
1383 (ival ? CLOCAL : 0);
1384 break;
1385 case TIOCGSERIAL:
1386 rc = stl_getserial(portp, argp);
1387 break;
1388 case TIOCSSERIAL:
1389 rc = stl_setserial(portp, argp);
1390 break;
1391 case COM_GETPORTSTATS:
1392 rc = stl_getportstats(portp, argp);
1393 break;
1394 case COM_CLRPORTSTATS:
1395 rc = stl_clrportstats(portp, argp);
1396 break;
1397 case TIOCSERCONFIG:
1398 case TIOCSERGWILD:
1399 case TIOCSERSWILD:
1400 case TIOCSERGETLSR:
1401 case TIOCSERGSTRUCT:
1402 case TIOCSERGETMULTI:
1403 case TIOCSERSETMULTI:
1404 default:
1405 rc = -ENOIOCTLCMD;
1406 break;
1407 }
1408
Jesper Juhl014c2542006-01-15 02:37:08 +01001409 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410}
1411
1412/*****************************************************************************/
1413
1414static void stl_settermios(struct tty_struct *tty, struct termios *old)
1415{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001416 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 struct termios *tiosp;
1418
Jiri Slabya0564e12006-12-08 02:38:37 -08001419 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
Jiri Slaby615e4a72006-12-08 02:38:38 -08001421 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 return;
1423 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001424 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 return;
1426
1427 tiosp = tty->termios;
1428 if ((tiosp->c_cflag == old->c_cflag) &&
1429 (tiosp->c_iflag == old->c_iflag))
1430 return;
1431
1432 stl_setport(portp, tiosp);
1433 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1434 -1);
1435 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1436 tty->hw_stopped = 0;
1437 stl_start(tty);
1438 }
1439 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1440 wake_up_interruptible(&portp->open_wait);
1441}
1442
1443/*****************************************************************************/
1444
1445/*
1446 * Attempt to flow control who ever is sending us data. Based on termios
1447 * settings use software or/and hardware flow control.
1448 */
1449
1450static void stl_throttle(struct tty_struct *tty)
1451{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001452 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Jiri Slabya0564e12006-12-08 02:38:37 -08001454 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
Jiri Slaby615e4a72006-12-08 02:38:38 -08001456 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 return;
1458 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001459 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 return;
1461 stl_flowctrl(portp, 0);
1462}
1463
1464/*****************************************************************************/
1465
1466/*
1467 * Unflow control the device sending us data...
1468 */
1469
1470static void stl_unthrottle(struct tty_struct *tty)
1471{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001472 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
Jiri Slabya0564e12006-12-08 02:38:37 -08001474 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
Jiri Slaby615e4a72006-12-08 02:38:38 -08001476 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 return;
1478 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001479 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 return;
1481 stl_flowctrl(portp, 1);
1482}
1483
1484/*****************************************************************************/
1485
1486/*
1487 * Stop the transmitter. Basically to do this we will just turn TX
1488 * interrupts off.
1489 */
1490
1491static void stl_stop(struct tty_struct *tty)
1492{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001493 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
Jiri Slabya0564e12006-12-08 02:38:37 -08001495 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496
Jiri Slaby615e4a72006-12-08 02:38:38 -08001497 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 return;
1499 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001500 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 return;
1502 stl_startrxtx(portp, -1, 0);
1503}
1504
1505/*****************************************************************************/
1506
1507/*
1508 * Start the transmitter again. Just turn TX interrupts back on.
1509 */
1510
1511static void stl_start(struct tty_struct *tty)
1512{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001513 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
Jiri Slabya0564e12006-12-08 02:38:37 -08001515 pr_debug("stl_start(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
Jiri Slaby615e4a72006-12-08 02:38:38 -08001517 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 return;
1519 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001520 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 return;
1522 stl_startrxtx(portp, -1, 1);
1523}
1524
1525/*****************************************************************************/
1526
1527/*
1528 * Hangup this port. This is pretty much like closing the port, only
1529 * a little more brutal. No waiting for data to drain. Shutdown the
1530 * port and maybe drop signals.
1531 */
1532
1533static void stl_hangup(struct tty_struct *tty)
1534{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001535 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Jiri Slabya0564e12006-12-08 02:38:37 -08001537 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Jiri Slaby615e4a72006-12-08 02:38:38 -08001539 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 return;
1541 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001542 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 return;
1544
1545 portp->flags &= ~ASYNC_INITIALIZED;
1546 stl_disableintrs(portp);
1547 if (tty->termios->c_cflag & HUPCL)
1548 stl_setsignals(portp, 0, 0);
1549 stl_enablerxtx(portp, 0, 0);
1550 stl_flushbuffer(tty);
1551 portp->istate = 0;
1552 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001553 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001555 portp->tx.buf = NULL;
1556 portp->tx.head = NULL;
1557 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001559 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1561 portp->refcount = 0;
1562 wake_up_interruptible(&portp->open_wait);
1563}
1564
1565/*****************************************************************************/
1566
1567static void stl_flushbuffer(struct tty_struct *tty)
1568{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001569 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
Jiri Slabya0564e12006-12-08 02:38:37 -08001571 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
Jiri Slaby615e4a72006-12-08 02:38:38 -08001573 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 return;
1575 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001576 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 return;
1578
1579 stl_flush(portp);
1580 tty_wakeup(tty);
1581}
1582
1583/*****************************************************************************/
1584
1585static void stl_breakctl(struct tty_struct *tty, int state)
1586{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001587 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
Jiri Slabya0564e12006-12-08 02:38:37 -08001589 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590
Jiri Slaby615e4a72006-12-08 02:38:38 -08001591 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 return;
1593 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001594 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 return;
1596
1597 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1598}
1599
1600/*****************************************************************************/
1601
1602static void stl_waituntilsent(struct tty_struct *tty, int timeout)
1603{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001604 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 unsigned long tend;
1606
Jiri Slabya0564e12006-12-08 02:38:37 -08001607 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608
Jiri Slaby615e4a72006-12-08 02:38:38 -08001609 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 return;
1611 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001612 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 return;
1614
1615 if (timeout == 0)
1616 timeout = HZ;
1617 tend = jiffies + timeout;
1618
1619 while (stl_datastate(portp)) {
1620 if (signal_pending(current))
1621 break;
1622 msleep_interruptible(20);
1623 if (time_after_eq(jiffies, tend))
1624 break;
1625 }
1626}
1627
1628/*****************************************************************************/
1629
1630static void stl_sendxchar(struct tty_struct *tty, char ch)
1631{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001632 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
Jiri Slabya0564e12006-12-08 02:38:37 -08001634 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635
Jiri Slaby615e4a72006-12-08 02:38:38 -08001636 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 return;
1638 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001639 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 return;
1641
1642 if (ch == STOP_CHAR(tty))
1643 stl_sendflow(portp, 0);
1644 else if (ch == START_CHAR(tty))
1645 stl_sendflow(portp, 1);
1646 else
1647 stl_putchar(tty, ch);
1648}
1649
1650/*****************************************************************************/
1651
1652#define MAXLINE 80
1653
1654/*
1655 * Format info for a specified port. The line is deliberately limited
1656 * to 80 characters. (If it is too long it will be truncated, if too
1657 * short then padded with spaces).
1658 */
1659
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001660static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661{
1662 char *sp;
1663 int sigs, cnt;
1664
1665 sp = pos;
1666 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1667 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1668 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1669
1670 if (portp->stats.rxframing)
1671 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1672 if (portp->stats.rxparity)
1673 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1674 if (portp->stats.rxbreaks)
1675 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1676 if (portp->stats.rxoverrun)
1677 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1678
1679 sigs = stl_getsignals(portp);
1680 cnt = sprintf(sp, "%s%s%s%s%s ",
1681 (sigs & TIOCM_RTS) ? "|RTS" : "",
1682 (sigs & TIOCM_CTS) ? "|CTS" : "",
1683 (sigs & TIOCM_DTR) ? "|DTR" : "",
1684 (sigs & TIOCM_CD) ? "|DCD" : "",
1685 (sigs & TIOCM_DSR) ? "|DSR" : "");
1686 *sp = ' ';
1687 sp += cnt;
1688
1689 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1690 *sp++ = ' ';
1691 if (cnt >= MAXLINE)
1692 pos[(MAXLINE - 2)] = '+';
1693 pos[(MAXLINE - 1)] = '\n';
1694
Jesper Juhl014c2542006-01-15 02:37:08 +01001695 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696}
1697
1698/*****************************************************************************/
1699
1700/*
1701 * Port info, read from the /proc file system.
1702 */
1703
1704static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1705{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001706 struct stlbrd *brdp;
1707 struct stlpanel *panelp;
1708 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 int brdnr, panelnr, portnr, totalport;
1710 int curoff, maxoff;
1711 char *pos;
1712
Jiri Slabya0564e12006-12-08 02:38:37 -08001713 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1714 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715
1716 pos = page;
1717 totalport = 0;
1718 curoff = 0;
1719
1720 if (off == 0) {
1721 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1722 stl_drvversion);
1723 while (pos < (page + MAXLINE - 1))
1724 *pos++ = ' ';
1725 *pos++ = '\n';
1726 }
1727 curoff = MAXLINE;
1728
1729/*
1730 * We scan through for each board, panel and port. The offset is
1731 * calculated on the fly, and irrelevant ports are skipped.
1732 */
1733 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1734 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001735 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 continue;
1737 if (brdp->state == 0)
1738 continue;
1739
1740 maxoff = curoff + (brdp->nrports * MAXLINE);
1741 if (off >= maxoff) {
1742 curoff = maxoff;
1743 continue;
1744 }
1745
1746 totalport = brdnr * STL_MAXPORTS;
1747 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1748 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001749 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 continue;
1751
1752 maxoff = curoff + (panelp->nrports * MAXLINE);
1753 if (off >= maxoff) {
1754 curoff = maxoff;
1755 totalport += panelp->nrports;
1756 continue;
1757 }
1758
1759 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1760 totalport++) {
1761 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001762 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 continue;
1764 if (off >= (curoff += MAXLINE))
1765 continue;
1766 if ((pos - page + MAXLINE) > count)
1767 goto stl_readdone;
1768 pos += stl_portinfo(portp, totalport, pos);
1769 }
1770 }
1771 }
1772
1773 *eof = 1;
1774
1775stl_readdone:
1776 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001777 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778}
1779
1780/*****************************************************************************/
1781
1782/*
1783 * All board interrupts are vectored through here first. This code then
1784 * calls off to the approrpriate board interrupt handlers.
1785 */
1786
David Howells7d12e782006-10-05 14:55:46 +01001787static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001789 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790
Jiri Slabya0564e12006-12-08 02:38:37 -08001791 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792
1793 return IRQ_RETVAL((* brdp->isr)(brdp));
1794}
1795
1796/*****************************************************************************/
1797
1798/*
1799 * Interrupt service routine for EasyIO board types.
1800 */
1801
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001802static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001804 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 unsigned int iobase;
1806 int handled = 0;
1807
Alan Coxb65b5b52006-06-27 02:54:05 -07001808 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 panelp = brdp->panels[0];
1810 iobase = panelp->iobase;
1811 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1812 handled = 1;
1813 (* panelp->isr)(panelp, iobase);
1814 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001815 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 return handled;
1817}
1818
1819/*****************************************************************************/
1820
1821/*
1822 * Interrupt service routine for ECH-AT board types.
1823 */
1824
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001825static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001827 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 unsigned int ioaddr;
1829 int bnknr;
1830 int handled = 0;
1831
1832 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1833
1834 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1835 handled = 1;
1836 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1837 ioaddr = brdp->bnkstataddr[bnknr];
1838 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1839 panelp = brdp->bnk2panel[bnknr];
1840 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1841 }
1842 }
1843 }
1844
1845 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1846
1847 return handled;
1848}
1849
1850/*****************************************************************************/
1851
1852/*
1853 * Interrupt service routine for ECH-MCA board types.
1854 */
1855
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001856static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001858 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 unsigned int ioaddr;
1860 int bnknr;
1861 int handled = 0;
1862
1863 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1864 handled = 1;
1865 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1866 ioaddr = brdp->bnkstataddr[bnknr];
1867 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1868 panelp = brdp->bnk2panel[bnknr];
1869 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1870 }
1871 }
1872 }
1873 return handled;
1874}
1875
1876/*****************************************************************************/
1877
1878/*
1879 * Interrupt service routine for ECH-PCI board types.
1880 */
1881
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001882static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001884 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 unsigned int ioaddr;
1886 int bnknr, recheck;
1887 int handled = 0;
1888
1889 while (1) {
1890 recheck = 0;
1891 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1892 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1893 ioaddr = brdp->bnkstataddr[bnknr];
1894 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1895 panelp = brdp->bnk2panel[bnknr];
1896 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1897 recheck++;
1898 handled = 1;
1899 }
1900 }
1901 if (! recheck)
1902 break;
1903 }
1904 return handled;
1905}
1906
1907/*****************************************************************************/
1908
1909/*
1910 * Interrupt service routine for ECH-8/64-PCI board types.
1911 */
1912
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001913static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001915 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 unsigned int ioaddr;
1917 int bnknr;
1918 int handled = 0;
1919
1920 while (inb(brdp->ioctrl) & 0x1) {
1921 handled = 1;
1922 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1923 ioaddr = brdp->bnkstataddr[bnknr];
1924 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1925 panelp = brdp->bnk2panel[bnknr];
1926 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1927 }
1928 }
1929 }
1930
1931 return handled;
1932}
1933
1934/*****************************************************************************/
1935
1936/*
1937 * Service an off-level request for some channel.
1938 */
Al Viro3e577a82006-12-06 18:41:45 +00001939static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001941 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 struct tty_struct *tty;
1943 unsigned int oldsigs;
1944
Jiri Slabya0564e12006-12-08 02:38:37 -08001945 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
Jiri Slaby615e4a72006-12-08 02:38:38 -08001947 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 return;
1949
1950 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001951 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 return;
1953
1954 lock_kernel();
1955 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1956 tty_wakeup(tty);
1957 }
1958 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1959 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1960 oldsigs = portp->sigs;
1961 portp->sigs = stl_getsignals(portp);
1962 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1963 wake_up_interruptible(&portp->open_wait);
1964 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1965 if (portp->flags & ASYNC_CHECK_CD)
1966 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1967 }
1968 }
1969 unlock_kernel();
1970}
1971
1972/*****************************************************************************/
1973
1974/*
1975 * Initialize all the ports on a panel.
1976 */
1977
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001978static int __init stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001980 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 int chipmask, i;
1982
Jiri Slabya0564e12006-12-08 02:38:37 -08001983 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
1985 chipmask = stl_panelinit(brdp, panelp);
1986
1987/*
1988 * All UART's are initialized (if found!). Now go through and setup
1989 * each ports data structures.
1990 */
1991 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001992 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001993 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001995 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 break;
1997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
1999 portp->magic = STL_PORTMAGIC;
2000 portp->portnr = i;
2001 portp->brdnr = panelp->brdnr;
2002 portp->panelnr = panelp->panelnr;
2003 portp->uartp = panelp->uartp;
2004 portp->clk = brdp->clk;
2005 portp->baud_base = STL_BAUDBASE;
2006 portp->close_delay = STL_CLOSEDELAY;
2007 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00002008 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 init_waitqueue_head(&portp->open_wait);
2010 init_waitqueue_head(&portp->close_wait);
2011 portp->stats.brd = portp->brdnr;
2012 portp->stats.panel = portp->panelnr;
2013 portp->stats.port = portp->portnr;
2014 panelp->ports[i] = portp;
2015 stl_portinit(brdp, panelp, portp);
2016 }
2017
2018 return(0);
2019}
2020
2021/*****************************************************************************/
2022
2023/*
2024 * Try to find and initialize an EasyIO board.
2025 */
2026
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002027static inline int stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002029 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 unsigned int status;
2031 char *name;
2032 int rc;
2033
Jiri Slabya0564e12006-12-08 02:38:37 -08002034 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035
2036 brdp->ioctrl = brdp->ioaddr1 + 1;
2037 brdp->iostatus = brdp->ioaddr1 + 2;
2038
2039 status = inb(brdp->iostatus);
2040 if ((status & EIO_IDBITMASK) == EIO_MK3)
2041 brdp->ioctrl++;
2042
2043/*
2044 * Handle board specific stuff now. The real difference is PCI
2045 * or not PCI.
2046 */
2047 if (brdp->brdtype == BRD_EASYIOPCI) {
2048 brdp->iosize1 = 0x80;
2049 brdp->iosize2 = 0x80;
2050 name = "serial(EIO-PCI)";
2051 outb(0x41, (brdp->ioaddr2 + 0x4c));
2052 } else {
2053 brdp->iosize1 = 8;
2054 name = "serial(EIO)";
2055 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2056 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2057 printk("STALLION: invalid irq=%d for brd=%d\n",
2058 brdp->irq, brdp->brdnr);
2059 return(-EINVAL);
2060 }
2061 outb((stl_vecmap[brdp->irq] | EIO_0WS |
2062 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
2063 brdp->ioctrl);
2064 }
2065
2066 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2067 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2068 "%x conflicts with another device\n", brdp->brdnr,
2069 brdp->ioaddr1);
2070 return(-EBUSY);
2071 }
2072
2073 if (brdp->iosize2 > 0)
2074 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2075 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2076 "address %x conflicts with another device\n",
2077 brdp->brdnr, brdp->ioaddr2);
2078 printk(KERN_WARNING "STALLION: Warning, also "
2079 "releasing board %d I/O address %x \n",
2080 brdp->brdnr, brdp->ioaddr1);
2081 release_region(brdp->ioaddr1, brdp->iosize1);
2082 return(-EBUSY);
2083 }
2084
2085/*
2086 * Everything looks OK, so let's go ahead and probe for the hardware.
2087 */
2088 brdp->clk = CD1400_CLK;
2089 brdp->isr = stl_eiointr;
2090
2091 switch (status & EIO_IDBITMASK) {
2092 case EIO_8PORTM:
2093 brdp->clk = CD1400_CLK8M;
2094 /* fall thru */
2095 case EIO_8PORTRS:
2096 case EIO_8PORTDI:
2097 brdp->nrports = 8;
2098 break;
2099 case EIO_4PORTRS:
2100 brdp->nrports = 4;
2101 break;
2102 case EIO_MK3:
2103 switch (status & EIO_BRDMASK) {
2104 case ID_BRD4:
2105 brdp->nrports = 4;
2106 break;
2107 case ID_BRD8:
2108 brdp->nrports = 8;
2109 break;
2110 case ID_BRD16:
2111 brdp->nrports = 16;
2112 break;
2113 default:
2114 return(-ENODEV);
2115 }
2116 break;
2117 default:
2118 return(-ENODEV);
2119 }
2120
2121/*
2122 * We have verified that the board is actually present, so now we
2123 * can complete the setup.
2124 */
2125
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002126 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002127 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002129 "(size=%Zd)\n", sizeof(struct stlpanel));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002130 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132
2133 panelp->magic = STL_PANELMAGIC;
2134 panelp->brdnr = brdp->brdnr;
2135 panelp->panelnr = 0;
2136 panelp->nrports = brdp->nrports;
2137 panelp->iobase = brdp->ioaddr1;
2138 panelp->hwid = status;
2139 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002140 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 panelp->isr = stl_sc26198intr;
2142 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002143 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 panelp->isr = stl_cd1400eiointr;
2145 }
2146
2147 brdp->panels[0] = panelp;
2148 brdp->nrpanels = 1;
2149 brdp->state |= BRD_FOUND;
2150 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002151 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 printk("STALLION: failed to register interrupt "
2153 "routine for %s irq=%d\n", name, brdp->irq);
2154 rc = -ENODEV;
2155 } else {
2156 rc = 0;
2157 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002158 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159}
2160
2161/*****************************************************************************/
2162
2163/*
2164 * Try to find an ECH board and initialize it. This code is capable of
2165 * dealing with all types of ECH board.
2166 */
2167
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002168static inline int stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002170 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 unsigned int status, nxtid, ioaddr, conflict;
2172 int panelnr, banknr, i;
2173 char *name;
2174
Jiri Slabya0564e12006-12-08 02:38:37 -08002175 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176
2177 status = 0;
2178 conflict = 0;
2179
2180/*
2181 * Set up the initial board register contents for boards. This varies a
2182 * bit between the different board types. So we need to handle each
2183 * separately. Also do a check that the supplied IRQ is good.
2184 */
2185 switch (brdp->brdtype) {
2186
2187 case BRD_ECH:
2188 brdp->isr = stl_echatintr;
2189 brdp->ioctrl = brdp->ioaddr1 + 1;
2190 brdp->iostatus = brdp->ioaddr1 + 1;
2191 status = inb(brdp->iostatus);
2192 if ((status & ECH_IDBITMASK) != ECH_ID)
2193 return(-ENODEV);
2194 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2195 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2196 printk("STALLION: invalid irq=%d for brd=%d\n",
2197 brdp->irq, brdp->brdnr);
2198 return(-EINVAL);
2199 }
2200 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2201 status |= (stl_vecmap[brdp->irq] << 1);
2202 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2203 brdp->ioctrlval = ECH_INTENABLE |
2204 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2205 for (i = 0; (i < 10); i++)
2206 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2207 brdp->iosize1 = 2;
2208 brdp->iosize2 = 32;
2209 name = "serial(EC8/32)";
2210 outb(status, brdp->ioaddr1);
2211 break;
2212
2213 case BRD_ECHMC:
2214 brdp->isr = stl_echmcaintr;
2215 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2216 brdp->iostatus = brdp->ioctrl;
2217 status = inb(brdp->iostatus);
2218 if ((status & ECH_IDBITMASK) != ECH_ID)
2219 return(-ENODEV);
2220 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2221 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2222 printk("STALLION: invalid irq=%d for brd=%d\n",
2223 brdp->irq, brdp->brdnr);
2224 return(-EINVAL);
2225 }
2226 outb(ECHMC_BRDRESET, brdp->ioctrl);
2227 outb(ECHMC_INTENABLE, brdp->ioctrl);
2228 brdp->iosize1 = 64;
2229 name = "serial(EC8/32-MC)";
2230 break;
2231
2232 case BRD_ECHPCI:
2233 brdp->isr = stl_echpciintr;
2234 brdp->ioctrl = brdp->ioaddr1 + 2;
2235 brdp->iosize1 = 4;
2236 brdp->iosize2 = 8;
2237 name = "serial(EC8/32-PCI)";
2238 break;
2239
2240 case BRD_ECH64PCI:
2241 brdp->isr = stl_echpci64intr;
2242 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2243 outb(0x43, (brdp->ioaddr1 + 0x4c));
2244 brdp->iosize1 = 0x80;
2245 brdp->iosize2 = 0x80;
2246 name = "serial(EC8/64-PCI)";
2247 break;
2248
2249 default:
2250 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
2251 return(-EINVAL);
2252 break;
2253 }
2254
2255/*
2256 * Check boards for possible IO address conflicts and return fail status
2257 * if an IO conflict found.
2258 */
2259 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2260 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2261 "%x conflicts with another device\n", brdp->brdnr,
2262 brdp->ioaddr1);
2263 return(-EBUSY);
2264 }
2265
2266 if (brdp->iosize2 > 0)
2267 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2268 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2269 "address %x conflicts with another device\n",
2270 brdp->brdnr, brdp->ioaddr2);
2271 printk(KERN_WARNING "STALLION: Warning, also "
2272 "releasing board %d I/O address %x \n",
2273 brdp->brdnr, brdp->ioaddr1);
2274 release_region(brdp->ioaddr1, brdp->iosize1);
2275 return(-EBUSY);
2276 }
2277
2278/*
2279 * Scan through the secondary io address space looking for panels.
2280 * As we find'em allocate and initialize panel structures for each.
2281 */
2282 brdp->clk = CD1400_CLK;
2283 brdp->hwid = status;
2284
2285 ioaddr = brdp->ioaddr2;
2286 banknr = 0;
2287 panelnr = 0;
2288 nxtid = 0;
2289
2290 for (i = 0; (i < STL_MAXPANELS); i++) {
2291 if (brdp->brdtype == BRD_ECHPCI) {
2292 outb(nxtid, brdp->ioctrl);
2293 ioaddr = brdp->ioaddr2;
2294 }
2295 status = inb(ioaddr + ECH_PNLSTATUS);
2296 if ((status & ECH_PNLIDMASK) != nxtid)
2297 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002298 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002299 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002301 "(size=%Zd)\n", sizeof(struct stlpanel));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 break;
2303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 panelp->magic = STL_PANELMAGIC;
2305 panelp->brdnr = brdp->brdnr;
2306 panelp->panelnr = panelnr;
2307 panelp->iobase = ioaddr;
2308 panelp->pagenr = nxtid;
2309 panelp->hwid = status;
2310 brdp->bnk2panel[banknr] = panelp;
2311 brdp->bnkpageaddr[banknr] = nxtid;
2312 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2313
2314 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002315 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 panelp->isr = stl_sc26198intr;
2317 if (status & ECH_PNL16PORT) {
2318 panelp->nrports = 16;
2319 brdp->bnk2panel[banknr] = panelp;
2320 brdp->bnkpageaddr[banknr] = nxtid;
2321 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2322 ECH_PNLSTATUS;
2323 } else {
2324 panelp->nrports = 8;
2325 }
2326 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002327 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 panelp->isr = stl_cd1400echintr;
2329 if (status & ECH_PNL16PORT) {
2330 panelp->nrports = 16;
2331 panelp->ackmask = 0x80;
2332 if (brdp->brdtype != BRD_ECHPCI)
2333 ioaddr += EREG_BANKSIZE;
2334 brdp->bnk2panel[banknr] = panelp;
2335 brdp->bnkpageaddr[banknr] = ++nxtid;
2336 brdp->bnkstataddr[banknr++] = ioaddr +
2337 ECH_PNLSTATUS;
2338 } else {
2339 panelp->nrports = 8;
2340 panelp->ackmask = 0xc0;
2341 }
2342 }
2343
2344 nxtid++;
2345 ioaddr += EREG_BANKSIZE;
2346 brdp->nrports += panelp->nrports;
2347 brdp->panels[panelnr++] = panelp;
2348 if ((brdp->brdtype != BRD_ECHPCI) &&
2349 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
2350 break;
2351 }
2352
2353 brdp->nrpanels = panelnr;
2354 brdp->nrbnks = banknr;
2355 if (brdp->brdtype == BRD_ECH)
2356 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2357
2358 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002359 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 printk("STALLION: failed to register interrupt "
2361 "routine for %s irq=%d\n", name, brdp->irq);
2362 i = -ENODEV;
2363 } else {
2364 i = 0;
2365 }
2366
2367 return(i);
2368}
2369
2370/*****************************************************************************/
2371
2372/*
2373 * Initialize and configure the specified board.
2374 * Scan through all the boards in the configuration and see what we
2375 * can find. Handle EIO and the ECH boards a little differently here
2376 * since the initial search and setup is very different.
2377 */
2378
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002379static int __init stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380{
2381 int i;
2382
Jiri Slabya0564e12006-12-08 02:38:37 -08002383 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384
2385 switch (brdp->brdtype) {
2386 case BRD_EASYIO:
2387 case BRD_EASYIOPCI:
2388 stl_initeio(brdp);
2389 break;
2390 case BRD_ECH:
2391 case BRD_ECHMC:
2392 case BRD_ECHPCI:
2393 case BRD_ECH64PCI:
2394 stl_initech(brdp);
2395 break;
2396 default:
2397 printk("STALLION: board=%d is unknown board type=%d\n",
2398 brdp->brdnr, brdp->brdtype);
2399 return(ENODEV);
2400 }
2401
2402 stl_brds[brdp->brdnr] = brdp;
2403 if ((brdp->state & BRD_FOUND) == 0) {
2404 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2405 stl_brdnames[brdp->brdtype], brdp->brdnr,
2406 brdp->ioaddr1, brdp->irq);
2407 return(ENODEV);
2408 }
2409
2410 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002411 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 stl_initports(brdp, brdp->panels[i]);
2413
2414 printk("STALLION: %s found, board=%d io=%x irq=%d "
2415 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2416 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2417 brdp->nrports);
2418 return(0);
2419}
2420
2421/*****************************************************************************/
2422
2423/*
2424 * Find the next available board number that is free.
2425 */
2426
2427static inline int stl_getbrdnr(void)
2428{
2429 int i;
2430
2431 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002432 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 if (i >= stl_nrbrds)
2434 stl_nrbrds = i + 1;
2435 return(i);
2436 }
2437 }
2438 return(-1);
2439}
2440
2441/*****************************************************************************/
2442
2443#ifdef CONFIG_PCI
2444
2445/*
2446 * We have a Stallion board. Allocate a board structure and
2447 * initialize it. Read its IO and IRQ resources from PCI
2448 * configuration space.
2449 */
2450
2451static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp)
2452{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002453 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
Jiri Slabya0564e12006-12-08 02:38:37 -08002455 pr_debug("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 devp->bus->number, devp->devfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457
2458 if (pci_enable_device(devp))
2459 return(-EIO);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002460 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 return(-ENOMEM);
2462 if ((brdp->brdnr = stl_getbrdnr()) < 0) {
2463 printk("STALLION: too many boards found, "
2464 "maximum supported %d\n", STL_MAXBRDS);
2465 return(0);
2466 }
2467 brdp->brdtype = brdtype;
2468
2469/*
2470 * Different Stallion boards use the BAR registers in different ways,
2471 * so set up io addresses based on board type.
2472 */
Jiri Slabya0564e12006-12-08 02:38:37 -08002473 pr_debug("%s(%d): BAR[]=%Lx,%Lx,%Lx,%Lx IRQ=%x\n", __FILE__, __LINE__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 pci_resource_start(devp, 0), pci_resource_start(devp, 1),
2475 pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
2477/*
2478 * We have all resources from the board, so let's setup the actual
2479 * board structure now.
2480 */
2481 switch (brdtype) {
2482 case BRD_ECHPCI:
2483 brdp->ioaddr2 = pci_resource_start(devp, 0);
2484 brdp->ioaddr1 = pci_resource_start(devp, 1);
2485 break;
2486 case BRD_ECH64PCI:
2487 brdp->ioaddr2 = pci_resource_start(devp, 2);
2488 brdp->ioaddr1 = pci_resource_start(devp, 1);
2489 break;
2490 case BRD_EASYIOPCI:
2491 brdp->ioaddr1 = pci_resource_start(devp, 2);
2492 brdp->ioaddr2 = pci_resource_start(devp, 1);
2493 break;
2494 default:
2495 printk("STALLION: unknown PCI board type=%d\n", brdtype);
2496 break;
2497 }
2498
2499 brdp->irq = devp->irq;
2500 stl_brdinit(brdp);
2501
2502 return(0);
2503}
2504
2505/*****************************************************************************/
2506
2507/*
2508 * Find all Stallion PCI boards that might be installed. Initialize each
2509 * one as it is found.
2510 */
2511
2512
2513static inline int stl_findpcibrds(void)
2514{
2515 struct pci_dev *dev = NULL;
2516 int i, rc;
2517
Jiri Slabya0564e12006-12-08 02:38:37 -08002518 pr_debug("stl_findpcibrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 for (i = 0; (i < stl_nrpcibrds); i++)
2521 while ((dev = pci_find_device(stl_pcibrds[i].vendid,
2522 stl_pcibrds[i].devid, dev))) {
2523
2524/*
2525 * Found a device on the PCI bus that has our vendor and
2526 * device ID. Need to check now that it is really us.
2527 */
2528 if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
2529 continue;
2530
2531 rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
2532 if (rc)
2533 return(rc);
2534 }
2535
2536 return(0);
2537}
2538
2539#endif
2540
2541/*****************************************************************************/
2542
2543/*
2544 * Scan through all the boards in the configuration and see what we
2545 * can find. Handle EIO and the ECH boards a little differently here
2546 * since the initial search and setup is too different.
2547 */
2548
2549static inline int stl_initbrds(void)
2550{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002551 struct stlbrd *brdp;
2552 struct stlconf *confp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 int i;
2554
Jiri Slabya0564e12006-12-08 02:38:37 -08002555 pr_debug("stl_initbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
2557 if (stl_nrbrds > STL_MAXBRDS) {
2558 printk("STALLION: too many boards in configuration table, "
2559 "truncating to %d\n", STL_MAXBRDS);
2560 stl_nrbrds = STL_MAXBRDS;
2561 }
2562
2563/*
2564 * Firstly scan the list of static boards configured. Allocate
2565 * resources and initialize the boards as found.
2566 */
2567 for (i = 0; (i < stl_nrbrds); i++) {
2568 confp = &stl_brdconf[i];
2569 stl_parsebrd(confp, stl_brdsp[i]);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002570 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 return(-ENOMEM);
2572 brdp->brdnr = i;
2573 brdp->brdtype = confp->brdtype;
2574 brdp->ioaddr1 = confp->ioaddr1;
2575 brdp->ioaddr2 = confp->ioaddr2;
2576 brdp->irq = confp->irq;
2577 brdp->irqtype = confp->irqtype;
2578 stl_brdinit(brdp);
2579 }
2580
2581/*
2582 * Find any dynamically supported boards. That is via module load
2583 * line options or auto-detected on the PCI bus.
2584 */
2585 stl_argbrds();
2586#ifdef CONFIG_PCI
2587 stl_findpcibrds();
2588#endif
2589
2590 return(0);
2591}
2592
2593/*****************************************************************************/
2594
2595/*
2596 * Return the board stats structure to user app.
2597 */
2598
2599static int stl_getbrdstats(combrd_t __user *bp)
2600{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002601 struct stlbrd *brdp;
2602 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 int i;
2604
2605 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2606 return -EFAULT;
2607 if (stl_brdstats.brd >= STL_MAXBRDS)
2608 return(-ENODEV);
2609 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002610 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 return(-ENODEV);
2612
2613 memset(&stl_brdstats, 0, sizeof(combrd_t));
2614 stl_brdstats.brd = brdp->brdnr;
2615 stl_brdstats.type = brdp->brdtype;
2616 stl_brdstats.hwid = brdp->hwid;
2617 stl_brdstats.state = brdp->state;
2618 stl_brdstats.ioaddr = brdp->ioaddr1;
2619 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2620 stl_brdstats.irq = brdp->irq;
2621 stl_brdstats.nrpanels = brdp->nrpanels;
2622 stl_brdstats.nrports = brdp->nrports;
2623 for (i = 0; (i < brdp->nrpanels); i++) {
2624 panelp = brdp->panels[i];
2625 stl_brdstats.panels[i].panel = i;
2626 stl_brdstats.panels[i].hwid = panelp->hwid;
2627 stl_brdstats.panels[i].nrports = panelp->nrports;
2628 }
2629
2630 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2631}
2632
2633/*****************************************************************************/
2634
2635/*
2636 * Resolve the referenced port number into a port struct pointer.
2637 */
2638
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002639static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002641 struct stlbrd *brdp;
2642 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643
2644 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002645 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002647 if (brdp == NULL)
2648 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002650 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002652 if (panelp == NULL)
2653 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002655 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 return(panelp->ports[portnr]);
2657}
2658
2659/*****************************************************************************/
2660
2661/*
2662 * Return the port stats structure to user app. A NULL port struct
2663 * pointer passed in means that we need to find out from the app
2664 * what port to get stats for (used through board control device).
2665 */
2666
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002667static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668{
2669 unsigned char *head, *tail;
2670 unsigned long flags;
2671
2672 if (!portp) {
2673 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2674 return -EFAULT;
2675 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2676 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002677 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 return(-ENODEV);
2679 }
2680
2681 portp->stats.state = portp->istate;
2682 portp->stats.flags = portp->flags;
2683 portp->stats.hwid = portp->hwid;
2684
2685 portp->stats.ttystate = 0;
2686 portp->stats.cflags = 0;
2687 portp->stats.iflags = 0;
2688 portp->stats.oflags = 0;
2689 portp->stats.lflags = 0;
2690 portp->stats.rxbuffered = 0;
2691
Alan Coxb65b5b52006-06-27 02:54:05 -07002692 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002693 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 if (portp->tty->driver_data == portp) {
2695 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002696 /* No longer available as a statistic */
2697 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002698 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 portp->stats.cflags = portp->tty->termios->c_cflag;
2700 portp->stats.iflags = portp->tty->termios->c_iflag;
2701 portp->stats.oflags = portp->tty->termios->c_oflag;
2702 portp->stats.lflags = portp->tty->termios->c_lflag;
2703 }
2704 }
2705 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002706 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707
2708 head = portp->tx.head;
2709 tail = portp->tx.tail;
2710 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2711 (STL_TXBUFSIZE - (tail - head)));
2712
2713 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2714
2715 return copy_to_user(cp, &portp->stats,
2716 sizeof(comstats_t)) ? -EFAULT : 0;
2717}
2718
2719/*****************************************************************************/
2720
2721/*
2722 * Clear the port stats structure. We also return it zeroed out...
2723 */
2724
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002725static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726{
2727 if (!portp) {
2728 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2729 return -EFAULT;
2730 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2731 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002732 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 return(-ENODEV);
2734 }
2735
2736 memset(&portp->stats, 0, sizeof(comstats_t));
2737 portp->stats.brd = portp->brdnr;
2738 portp->stats.panel = portp->panelnr;
2739 portp->stats.port = portp->portnr;
2740 return copy_to_user(cp, &portp->stats,
2741 sizeof(comstats_t)) ? -EFAULT : 0;
2742}
2743
2744/*****************************************************************************/
2745
2746/*
2747 * Return the entire driver ports structure to a user app.
2748 */
2749
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002750static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002752 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002754 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 return -EFAULT;
2756 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2757 stl_dummyport.portnr);
2758 if (!portp)
2759 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002760 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761}
2762
2763/*****************************************************************************/
2764
2765/*
2766 * Return the entire driver board structure to a user app.
2767 */
2768
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002769static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002771 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002773 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 return -EFAULT;
2775 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2776 return -ENODEV;
2777 brdp = stl_brds[stl_dummybrd.brdnr];
2778 if (!brdp)
2779 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002780 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781}
2782
2783/*****************************************************************************/
2784
2785/*
2786 * The "staliomem" device is also required to do some special operations
2787 * on the board and/or ports. In this driver it is mostly used for stats
2788 * collection.
2789 */
2790
2791static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2792{
2793 int brdnr, rc;
2794 void __user *argp = (void __user *)arg;
2795
Jiri Slabya0564e12006-12-08 02:38:37 -08002796 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798 brdnr = iminor(ip);
2799 if (brdnr >= STL_MAXBRDS)
2800 return(-ENODEV);
2801 rc = 0;
2802
2803 switch (cmd) {
2804 case COM_GETPORTSTATS:
2805 rc = stl_getportstats(NULL, argp);
2806 break;
2807 case COM_CLRPORTSTATS:
2808 rc = stl_clrportstats(NULL, argp);
2809 break;
2810 case COM_GETBRDSTATS:
2811 rc = stl_getbrdstats(argp);
2812 break;
2813 case COM_READPORT:
2814 rc = stl_getportstruct(argp);
2815 break;
2816 case COM_READBOARD:
2817 rc = stl_getbrdstruct(argp);
2818 break;
2819 default:
2820 rc = -ENOIOCTLCMD;
2821 break;
2822 }
2823
2824 return(rc);
2825}
2826
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002827static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 .open = stl_open,
2829 .close = stl_close,
2830 .write = stl_write,
2831 .put_char = stl_putchar,
2832 .flush_chars = stl_flushchars,
2833 .write_room = stl_writeroom,
2834 .chars_in_buffer = stl_charsinbuffer,
2835 .ioctl = stl_ioctl,
2836 .set_termios = stl_settermios,
2837 .throttle = stl_throttle,
2838 .unthrottle = stl_unthrottle,
2839 .stop = stl_stop,
2840 .start = stl_start,
2841 .hangup = stl_hangup,
2842 .flush_buffer = stl_flushbuffer,
2843 .break_ctl = stl_breakctl,
2844 .wait_until_sent = stl_waituntilsent,
2845 .send_xchar = stl_sendxchar,
2846 .read_proc = stl_readproc,
2847 .tiocmget = stl_tiocmget,
2848 .tiocmset = stl_tiocmset,
2849};
2850
2851/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852/* CD1400 HARDWARE FUNCTIONS */
2853/*****************************************************************************/
2854
2855/*
2856 * These functions get/set/update the registers of the cd1400 UARTs.
2857 * Access to the cd1400 registers is via an address/data io port pair.
2858 * (Maybe should make this inline...)
2859 */
2860
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002861static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862{
2863 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002864 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865}
2866
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002867static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868{
2869 outb((regnr + portp->uartaddr), portp->ioaddr);
2870 outb(value, portp->ioaddr + EREG_DATA);
2871}
2872
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002873static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874{
2875 outb((regnr + portp->uartaddr), portp->ioaddr);
2876 if (inb(portp->ioaddr + EREG_DATA) != value) {
2877 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002878 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002880 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881}
2882
2883/*****************************************************************************/
2884
2885/*
2886 * Inbitialize the UARTs in a panel. We don't care what sort of board
2887 * these ports are on - since the port io registers are almost
2888 * identical when dealing with ports.
2889 */
2890
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002891static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892{
2893 unsigned int gfrcr;
2894 int chipmask, i, j;
2895 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002896 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897
Jiri Slabya0564e12006-12-08 02:38:37 -08002898 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899
Alan Coxb65b5b52006-06-27 02:54:05 -07002900 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901 BRDENABLE(panelp->brdnr, panelp->pagenr);
2902
2903/*
2904 * Check that each chip is present and started up OK.
2905 */
2906 chipmask = 0;
2907 nrchips = panelp->nrports / CD1400_PORTS;
2908 for (i = 0; (i < nrchips); i++) {
2909 if (brdp->brdtype == BRD_ECHPCI) {
2910 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2911 ioaddr = panelp->iobase;
2912 } else {
2913 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2914 }
2915 uartaddr = (i & 0x01) ? 0x080 : 0;
2916 outb((GFRCR + uartaddr), ioaddr);
2917 outb(0, (ioaddr + EREG_DATA));
2918 outb((CCR + uartaddr), ioaddr);
2919 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2920 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2921 outb((GFRCR + uartaddr), ioaddr);
2922 for (j = 0; (j < CCR_MAXWAIT); j++) {
2923 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2924 break;
2925 }
2926 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2927 printk("STALLION: cd1400 not responding, "
2928 "brd=%d panel=%d chip=%d\n",
2929 panelp->brdnr, panelp->panelnr, i);
2930 continue;
2931 }
2932 chipmask |= (0x1 << i);
2933 outb((PPR + uartaddr), ioaddr);
2934 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2935 }
2936
2937 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002938 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002939 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940}
2941
2942/*****************************************************************************/
2943
2944/*
2945 * Initialize hardware specific port registers.
2946 */
2947
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002948static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949{
Alan Coxb65b5b52006-06-27 02:54:05 -07002950 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002951 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2952 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953
Jiri Slaby615e4a72006-12-08 02:38:38 -08002954 if ((brdp == NULL) || (panelp == NULL) ||
2955 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956 return;
2957
Alan Coxb65b5b52006-06-27 02:54:05 -07002958 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2960 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2961 portp->uartaddr = (portp->portnr & 0x04) << 5;
2962 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2963
2964 BRDENABLE(portp->brdnr, portp->pagenr);
2965 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2966 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2967 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2968 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002969 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970}
2971
2972/*****************************************************************************/
2973
2974/*
2975 * Wait for the command register to be ready. We will poll this,
2976 * since it won't usually take too long to be ready.
2977 */
2978
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002979static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980{
2981 int i;
2982
2983 for (i = 0; (i < CCR_MAXWAIT); i++) {
2984 if (stl_cd1400getreg(portp, CCR) == 0) {
2985 return;
2986 }
2987 }
2988
2989 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2990 portp->portnr, portp->panelnr, portp->brdnr);
2991}
2992
2993/*****************************************************************************/
2994
2995/*
2996 * Set up the cd1400 registers for a port based on the termios port
2997 * settings.
2998 */
2999
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003000static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003002 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 unsigned long flags;
3004 unsigned int clkdiv, baudrate;
3005 unsigned char cor1, cor2, cor3;
3006 unsigned char cor4, cor5, ccr;
3007 unsigned char srer, sreron, sreroff;
3008 unsigned char mcor1, mcor2, rtpr;
3009 unsigned char clk, div;
3010
3011 cor1 = 0;
3012 cor2 = 0;
3013 cor3 = 0;
3014 cor4 = 0;
3015 cor5 = 0;
3016 ccr = 0;
3017 rtpr = 0;
3018 clk = 0;
3019 div = 0;
3020 mcor1 = 0;
3021 mcor2 = 0;
3022 sreron = 0;
3023 sreroff = 0;
3024
3025 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003026 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 return;
3028
3029/*
3030 * Set up the RX char ignore mask with those RX error types we
3031 * can ignore. We can get the cd1400 to help us out a little here,
3032 * it will ignore parity errors and breaks for us.
3033 */
3034 portp->rxignoremsk = 0;
3035 if (tiosp->c_iflag & IGNPAR) {
3036 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
3037 cor1 |= COR1_PARIGNORE;
3038 }
3039 if (tiosp->c_iflag & IGNBRK) {
3040 portp->rxignoremsk |= ST_BREAK;
3041 cor4 |= COR4_IGNBRK;
3042 }
3043
3044 portp->rxmarkmsk = ST_OVERRUN;
3045 if (tiosp->c_iflag & (INPCK | PARMRK))
3046 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
3047 if (tiosp->c_iflag & BRKINT)
3048 portp->rxmarkmsk |= ST_BREAK;
3049
3050/*
3051 * Go through the char size, parity and stop bits and set all the
3052 * option register appropriately.
3053 */
3054 switch (tiosp->c_cflag & CSIZE) {
3055 case CS5:
3056 cor1 |= COR1_CHL5;
3057 break;
3058 case CS6:
3059 cor1 |= COR1_CHL6;
3060 break;
3061 case CS7:
3062 cor1 |= COR1_CHL7;
3063 break;
3064 default:
3065 cor1 |= COR1_CHL8;
3066 break;
3067 }
3068
3069 if (tiosp->c_cflag & CSTOPB)
3070 cor1 |= COR1_STOP2;
3071 else
3072 cor1 |= COR1_STOP1;
3073
3074 if (tiosp->c_cflag & PARENB) {
3075 if (tiosp->c_cflag & PARODD)
3076 cor1 |= (COR1_PARENB | COR1_PARODD);
3077 else
3078 cor1 |= (COR1_PARENB | COR1_PAREVEN);
3079 } else {
3080 cor1 |= COR1_PARNONE;
3081 }
3082
3083/*
3084 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
3085 * space for hardware flow control and the like. This should be set to
3086 * VMIN. Also here we will set the RX data timeout to 10ms - this should
3087 * really be based on VTIME.
3088 */
3089 cor3 |= FIFO_RXTHRESHOLD;
3090 rtpr = 2;
3091
3092/*
3093 * Calculate the baud rate timers. For now we will just assume that
3094 * the input and output baud are the same. Could have used a baud
3095 * table here, but this way we can generate virtually any baud rate
3096 * we like!
3097 */
3098 baudrate = tiosp->c_cflag & CBAUD;
3099 if (baudrate & CBAUDEX) {
3100 baudrate &= ~CBAUDEX;
3101 if ((baudrate < 1) || (baudrate > 4))
3102 tiosp->c_cflag &= ~CBAUDEX;
3103 else
3104 baudrate += 15;
3105 }
3106 baudrate = stl_baudrates[baudrate];
3107 if ((tiosp->c_cflag & CBAUD) == B38400) {
3108 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3109 baudrate = 57600;
3110 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3111 baudrate = 115200;
3112 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3113 baudrate = 230400;
3114 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3115 baudrate = 460800;
3116 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3117 baudrate = (portp->baud_base / portp->custom_divisor);
3118 }
3119 if (baudrate > STL_CD1400MAXBAUD)
3120 baudrate = STL_CD1400MAXBAUD;
3121
3122 if (baudrate > 0) {
3123 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
3124 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
3125 if (clkdiv < 0x100)
3126 break;
3127 }
3128 div = (unsigned char) clkdiv;
3129 }
3130
3131/*
3132 * Check what form of modem signaling is required and set it up.
3133 */
3134 if ((tiosp->c_cflag & CLOCAL) == 0) {
3135 mcor1 |= MCOR1_DCD;
3136 mcor2 |= MCOR2_DCD;
3137 sreron |= SRER_MODEM;
3138 portp->flags |= ASYNC_CHECK_CD;
3139 } else {
3140 portp->flags &= ~ASYNC_CHECK_CD;
3141 }
3142
3143/*
3144 * Setup cd1400 enhanced modes if we can. In particular we want to
3145 * handle as much of the flow control as possible automatically. As
3146 * well as saving a few CPU cycles it will also greatly improve flow
3147 * control reliability.
3148 */
3149 if (tiosp->c_iflag & IXON) {
3150 cor2 |= COR2_TXIBE;
3151 cor3 |= COR3_SCD12;
3152 if (tiosp->c_iflag & IXANY)
3153 cor2 |= COR2_IXM;
3154 }
3155
3156 if (tiosp->c_cflag & CRTSCTS) {
3157 cor2 |= COR2_CTSAE;
3158 mcor1 |= FIFO_RTSTHRESHOLD;
3159 }
3160
3161/*
3162 * All cd1400 register values calculated so go through and set
3163 * them all up.
3164 */
3165
Jiri Slabya0564e12006-12-08 02:38:37 -08003166 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003168 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003170 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003172 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3173 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3175 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176
Alan Coxb65b5b52006-06-27 02:54:05 -07003177 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 BRDENABLE(portp->brdnr, portp->pagenr);
3179 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3180 srer = stl_cd1400getreg(portp, SRER);
3181 stl_cd1400setreg(portp, SRER, 0);
3182 if (stl_cd1400updatereg(portp, COR1, cor1))
3183 ccr = 1;
3184 if (stl_cd1400updatereg(portp, COR2, cor2))
3185 ccr = 1;
3186 if (stl_cd1400updatereg(portp, COR3, cor3))
3187 ccr = 1;
3188 if (ccr) {
3189 stl_cd1400ccrwait(portp);
3190 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3191 }
3192 stl_cd1400setreg(portp, COR4, cor4);
3193 stl_cd1400setreg(portp, COR5, cor5);
3194 stl_cd1400setreg(portp, MCOR1, mcor1);
3195 stl_cd1400setreg(portp, MCOR2, mcor2);
3196 if (baudrate > 0) {
3197 stl_cd1400setreg(portp, TCOR, clk);
3198 stl_cd1400setreg(portp, TBPR, div);
3199 stl_cd1400setreg(portp, RCOR, clk);
3200 stl_cd1400setreg(portp, RBPR, div);
3201 }
3202 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3203 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3204 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3205 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3206 stl_cd1400setreg(portp, RTPR, rtpr);
3207 mcor1 = stl_cd1400getreg(portp, MSVR1);
3208 if (mcor1 & MSVR1_DCD)
3209 portp->sigs |= TIOCM_CD;
3210 else
3211 portp->sigs &= ~TIOCM_CD;
3212 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3213 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003214 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215}
3216
3217/*****************************************************************************/
3218
3219/*
3220 * Set the state of the DTR and RTS signals.
3221 */
3222
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003223static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224{
3225 unsigned char msvr1, msvr2;
3226 unsigned long flags;
3227
Jiri Slabya0564e12006-12-08 02:38:37 -08003228 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3229 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
3231 msvr1 = 0;
3232 msvr2 = 0;
3233 if (dtr > 0)
3234 msvr1 = MSVR1_DTR;
3235 if (rts > 0)
3236 msvr2 = MSVR2_RTS;
3237
Alan Coxb65b5b52006-06-27 02:54:05 -07003238 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 BRDENABLE(portp->brdnr, portp->pagenr);
3240 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3241 if (rts >= 0)
3242 stl_cd1400setreg(portp, MSVR2, msvr2);
3243 if (dtr >= 0)
3244 stl_cd1400setreg(portp, MSVR1, msvr1);
3245 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003246 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247}
3248
3249/*****************************************************************************/
3250
3251/*
3252 * Return the state of the signals.
3253 */
3254
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003255static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256{
3257 unsigned char msvr1, msvr2;
3258 unsigned long flags;
3259 int sigs;
3260
Jiri Slabya0564e12006-12-08 02:38:37 -08003261 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262
Alan Coxb65b5b52006-06-27 02:54:05 -07003263 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264 BRDENABLE(portp->brdnr, portp->pagenr);
3265 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3266 msvr1 = stl_cd1400getreg(portp, MSVR1);
3267 msvr2 = stl_cd1400getreg(portp, MSVR2);
3268 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003269 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270
3271 sigs = 0;
3272 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3273 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3274 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3275 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3276#if 0
3277 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3278 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3279#else
3280 sigs |= TIOCM_DSR;
3281#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003282 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283}
3284
3285/*****************************************************************************/
3286
3287/*
3288 * Enable/Disable the Transmitter and/or Receiver.
3289 */
3290
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003291static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292{
3293 unsigned char ccr;
3294 unsigned long flags;
3295
Jiri Slabya0564e12006-12-08 02:38:37 -08003296 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3297
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 ccr = 0;
3299
3300 if (tx == 0)
3301 ccr |= CCR_TXDISABLE;
3302 else if (tx > 0)
3303 ccr |= CCR_TXENABLE;
3304 if (rx == 0)
3305 ccr |= CCR_RXDISABLE;
3306 else if (rx > 0)
3307 ccr |= CCR_RXENABLE;
3308
Alan Coxb65b5b52006-06-27 02:54:05 -07003309 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310 BRDENABLE(portp->brdnr, portp->pagenr);
3311 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3312 stl_cd1400ccrwait(portp);
3313 stl_cd1400setreg(portp, CCR, ccr);
3314 stl_cd1400ccrwait(portp);
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 * Start/stop the Transmitter and/or Receiver.
3323 */
3324
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003325static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326{
3327 unsigned char sreron, sreroff;
3328 unsigned long flags;
3329
Jiri Slabya0564e12006-12-08 02:38:37 -08003330 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331
3332 sreron = 0;
3333 sreroff = 0;
3334 if (tx == 0)
3335 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3336 else if (tx == 1)
3337 sreron |= SRER_TXDATA;
3338 else if (tx >= 2)
3339 sreron |= SRER_TXEMPTY;
3340 if (rx == 0)
3341 sreroff |= SRER_RXDATA;
3342 else if (rx > 0)
3343 sreron |= SRER_RXDATA;
3344
Alan Coxb65b5b52006-06-27 02:54:05 -07003345 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 BRDENABLE(portp->brdnr, portp->pagenr);
3347 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3348 stl_cd1400setreg(portp, SRER,
3349 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3350 BRDDISABLE(portp->brdnr);
3351 if (tx > 0)
3352 set_bit(ASYI_TXBUSY, &portp->istate);
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
3358/*
3359 * Disable all interrupts from this port.
3360 */
3361
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003362static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363{
3364 unsigned long flags;
3365
Jiri Slabya0564e12006-12-08 02:38:37 -08003366 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3367
Alan Coxb65b5b52006-06-27 02:54:05 -07003368 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369 BRDENABLE(portp->brdnr, portp->pagenr);
3370 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3371 stl_cd1400setreg(portp, SRER, 0);
3372 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003373 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374}
3375
3376/*****************************************************************************/
3377
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003378static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379{
3380 unsigned long flags;
3381
Jiri Slabya0564e12006-12-08 02:38:37 -08003382 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383
Alan Coxb65b5b52006-06-27 02:54:05 -07003384 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 BRDENABLE(portp->brdnr, portp->pagenr);
3386 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3387 stl_cd1400setreg(portp, SRER,
3388 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3389 SRER_TXEMPTY));
3390 BRDDISABLE(portp->brdnr);
3391 portp->brklen = len;
3392 if (len == 1)
3393 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003394 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395}
3396
3397/*****************************************************************************/
3398
3399/*
3400 * Take flow control actions...
3401 */
3402
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003403static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404{
3405 struct tty_struct *tty;
3406 unsigned long flags;
3407
Jiri Slabya0564e12006-12-08 02:38:37 -08003408 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
Jiri Slaby615e4a72006-12-08 02:38:38 -08003410 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 return;
3412 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003413 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 return;
3415
Alan Coxb65b5b52006-06-27 02:54:05 -07003416 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 BRDENABLE(portp->brdnr, portp->pagenr);
3418 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3419
3420 if (state) {
3421 if (tty->termios->c_iflag & IXOFF) {
3422 stl_cd1400ccrwait(portp);
3423 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3424 portp->stats.rxxon++;
3425 stl_cd1400ccrwait(portp);
3426 }
3427/*
3428 * Question: should we return RTS to what it was before? It may
3429 * have been set by an ioctl... Suppose not, since if you have
3430 * hardware flow control set then it is pretty silly to go and
3431 * set the RTS line by hand.
3432 */
3433 if (tty->termios->c_cflag & CRTSCTS) {
3434 stl_cd1400setreg(portp, MCOR1,
3435 (stl_cd1400getreg(portp, MCOR1) |
3436 FIFO_RTSTHRESHOLD));
3437 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3438 portp->stats.rxrtson++;
3439 }
3440 } else {
3441 if (tty->termios->c_iflag & IXOFF) {
3442 stl_cd1400ccrwait(portp);
3443 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3444 portp->stats.rxxoff++;
3445 stl_cd1400ccrwait(portp);
3446 }
3447 if (tty->termios->c_cflag & CRTSCTS) {
3448 stl_cd1400setreg(portp, MCOR1,
3449 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3450 stl_cd1400setreg(portp, MSVR2, 0);
3451 portp->stats.rxrtsoff++;
3452 }
3453 }
3454
3455 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003456 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457}
3458
3459/*****************************************************************************/
3460
3461/*
3462 * Send a flow control character...
3463 */
3464
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003465static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466{
3467 struct tty_struct *tty;
3468 unsigned long flags;
3469
Jiri Slabya0564e12006-12-08 02:38:37 -08003470 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471
Jiri Slaby615e4a72006-12-08 02:38:38 -08003472 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473 return;
3474 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003475 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 return;
3477
Alan Coxb65b5b52006-06-27 02:54:05 -07003478 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 BRDENABLE(portp->brdnr, portp->pagenr);
3480 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3481 if (state) {
3482 stl_cd1400ccrwait(portp);
3483 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3484 portp->stats.rxxon++;
3485 stl_cd1400ccrwait(portp);
3486 } else {
3487 stl_cd1400ccrwait(portp);
3488 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3489 portp->stats.rxxoff++;
3490 stl_cd1400ccrwait(portp);
3491 }
3492 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003493 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494}
3495
3496/*****************************************************************************/
3497
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003498static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499{
3500 unsigned long flags;
3501
Jiri Slabya0564e12006-12-08 02:38:37 -08003502 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503
Jiri Slaby615e4a72006-12-08 02:38:38 -08003504 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 return;
3506
Alan Coxb65b5b52006-06-27 02:54:05 -07003507 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508 BRDENABLE(portp->brdnr, portp->pagenr);
3509 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3510 stl_cd1400ccrwait(portp);
3511 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3512 stl_cd1400ccrwait(portp);
3513 portp->tx.tail = portp->tx.head;
3514 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003515 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516}
3517
3518/*****************************************************************************/
3519
3520/*
3521 * Return the current state of data flow on this port. This is only
3522 * really interresting when determining if data has fully completed
3523 * transmission or not... This is easy for the cd1400, it accurately
3524 * maintains the busy port flag.
3525 */
3526
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003527static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528{
Jiri Slabya0564e12006-12-08 02:38:37 -08003529 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530
Jiri Slaby615e4a72006-12-08 02:38:38 -08003531 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003532 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533
Jesper Juhl014c2542006-01-15 02:37:08 +01003534 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535}
3536
3537/*****************************************************************************/
3538
3539/*
3540 * Interrupt service routine for cd1400 EasyIO boards.
3541 */
3542
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003543static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544{
3545 unsigned char svrtype;
3546
Jiri Slabya0564e12006-12-08 02:38:37 -08003547 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548
Alan Coxb65b5b52006-06-27 02:54:05 -07003549 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 outb(SVRR, iobase);
3551 svrtype = inb(iobase + EREG_DATA);
3552 if (panelp->nrports > 4) {
3553 outb((SVRR + 0x80), iobase);
3554 svrtype |= inb(iobase + EREG_DATA);
3555 }
3556
3557 if (svrtype & SVRR_RX)
3558 stl_cd1400rxisr(panelp, iobase);
3559 else if (svrtype & SVRR_TX)
3560 stl_cd1400txisr(panelp, iobase);
3561 else if (svrtype & SVRR_MDM)
3562 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003563
3564 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565}
3566
3567/*****************************************************************************/
3568
3569/*
3570 * Interrupt service routine for cd1400 panels.
3571 */
3572
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003573static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574{
3575 unsigned char svrtype;
3576
Jiri Slabya0564e12006-12-08 02:38:37 -08003577 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
3579 outb(SVRR, iobase);
3580 svrtype = inb(iobase + EREG_DATA);
3581 outb((SVRR + 0x80), iobase);
3582 svrtype |= inb(iobase + EREG_DATA);
3583 if (svrtype & SVRR_RX)
3584 stl_cd1400rxisr(panelp, iobase);
3585 else if (svrtype & SVRR_TX)
3586 stl_cd1400txisr(panelp, iobase);
3587 else if (svrtype & SVRR_MDM)
3588 stl_cd1400mdmisr(panelp, iobase);
3589}
3590
3591
3592/*****************************************************************************/
3593
3594/*
3595 * Unfortunately we need to handle breaks in the TX data stream, since
3596 * this is the only way to generate them on the cd1400.
3597 */
3598
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003599static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600{
3601 if (portp->brklen == 1) {
3602 outb((COR2 + portp->uartaddr), ioaddr);
3603 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3604 (ioaddr + EREG_DATA));
3605 outb((TDR + portp->uartaddr), ioaddr);
3606 outb(ETC_CMD, (ioaddr + EREG_DATA));
3607 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3608 outb((SRER + portp->uartaddr), ioaddr);
3609 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3610 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003611 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 } else if (portp->brklen > 1) {
3613 outb((TDR + portp->uartaddr), ioaddr);
3614 outb(ETC_CMD, (ioaddr + EREG_DATA));
3615 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3616 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003617 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 } else {
3619 outb((COR2 + portp->uartaddr), ioaddr);
3620 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3621 (ioaddr + EREG_DATA));
3622 portp->brklen = 0;
3623 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003624 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625}
3626
3627/*****************************************************************************/
3628
3629/*
3630 * Transmit interrupt handler. This has gotta be fast! Handling TX
3631 * chars is pretty simple, stuff as many as possible from the TX buffer
3632 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3633 * are embedded as commands in the data stream. Oh no, had to use a goto!
3634 * This could be optimized more, will do when I get time...
3635 * In practice it is possible that interrupts are enabled but that the
3636 * port has been hung up. Need to handle not having any TX buffer here,
3637 * this is done by using the side effect that head and tail will also
3638 * be NULL if the buffer has been freed.
3639 */
3640
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003641static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003643 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 int len, stlen;
3645 char *head, *tail;
3646 unsigned char ioack, srer;
3647
Jiri Slabya0564e12006-12-08 02:38:37 -08003648 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649
3650 ioack = inb(ioaddr + EREG_TXACK);
3651 if (((ioack & panelp->ackmask) != 0) ||
3652 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3653 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3654 return;
3655 }
3656 portp = panelp->ports[(ioack >> 3)];
3657
3658/*
3659 * Unfortunately we need to handle breaks in the data stream, since
3660 * this is the only way to generate them on the cd1400. Do it now if
3661 * a break is to be sent.
3662 */
3663 if (portp->brklen != 0)
3664 if (stl_cd1400breakisr(portp, ioaddr))
3665 goto stl_txalldone;
3666
3667 head = portp->tx.head;
3668 tail = portp->tx.tail;
3669 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3670 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3671 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3672 set_bit(ASYI_TXLOW, &portp->istate);
3673 schedule_work(&portp->tqueue);
3674 }
3675
3676 if (len == 0) {
3677 outb((SRER + portp->uartaddr), ioaddr);
3678 srer = inb(ioaddr + EREG_DATA);
3679 if (srer & SRER_TXDATA) {
3680 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3681 } else {
3682 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3683 clear_bit(ASYI_TXBUSY, &portp->istate);
3684 }
3685 outb(srer, (ioaddr + EREG_DATA));
3686 } else {
3687 len = MIN(len, CD1400_TXFIFOSIZE);
3688 portp->stats.txtotal += len;
3689 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
3690 outb((TDR + portp->uartaddr), ioaddr);
3691 outsb((ioaddr + EREG_DATA), tail, stlen);
3692 len -= stlen;
3693 tail += stlen;
3694 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3695 tail = portp->tx.buf;
3696 if (len > 0) {
3697 outsb((ioaddr + EREG_DATA), tail, len);
3698 tail += len;
3699 }
3700 portp->tx.tail = tail;
3701 }
3702
3703stl_txalldone:
3704 outb((EOSRR + portp->uartaddr), ioaddr);
3705 outb(0, (ioaddr + EREG_DATA));
3706}
3707
3708/*****************************************************************************/
3709
3710/*
3711 * Receive character interrupt handler. Determine if we have good chars
3712 * or bad chars and then process appropriately. Good chars are easy
3713 * just shove the lot into the RX buffer and set all status byte to 0.
3714 * If a bad RX char then process as required. This routine needs to be
3715 * fast! In practice it is possible that we get an interrupt on a port
3716 * that is closed. This can happen on hangups - since they completely
3717 * shutdown a port not in user context. Need to handle this case.
3718 */
3719
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003720static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003722 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723 struct tty_struct *tty;
3724 unsigned int ioack, len, buflen;
3725 unsigned char status;
3726 char ch;
3727
Jiri Slabya0564e12006-12-08 02:38:37 -08003728 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729
3730 ioack = inb(ioaddr + EREG_RXACK);
3731 if ((ioack & panelp->ackmask) != 0) {
3732 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3733 return;
3734 }
3735 portp = panelp->ports[(ioack >> 3)];
3736 tty = portp->tty;
3737
3738 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3739 outb((RDCR + portp->uartaddr), ioaddr);
3740 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003741 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 len = MIN(len, sizeof(stl_unwanted));
3743 outb((RDSR + portp->uartaddr), ioaddr);
3744 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3745 portp->stats.rxlost += len;
3746 portp->stats.rxtotal += len;
3747 } else {
3748 len = MIN(len, buflen);
3749 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003750 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003752 tty_prepare_flip_string(tty, &ptr, len);
3753 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754 tty_schedule_flip(tty);
3755 portp->stats.rxtotal += len;
3756 }
3757 }
3758 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3759 outb((RDSR + portp->uartaddr), ioaddr);
3760 status = inb(ioaddr + EREG_DATA);
3761 ch = inb(ioaddr + EREG_DATA);
3762 if (status & ST_PARITY)
3763 portp->stats.rxparity++;
3764 if (status & ST_FRAMING)
3765 portp->stats.rxframing++;
3766 if (status & ST_OVERRUN)
3767 portp->stats.rxoverrun++;
3768 if (status & ST_BREAK)
3769 portp->stats.rxbreaks++;
3770 if (status & ST_SCHARMASK) {
3771 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3772 portp->stats.txxon++;
3773 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3774 portp->stats.txxoff++;
3775 goto stl_rxalldone;
3776 }
Alan Cox33f0f882006-01-09 20:54:13 -08003777 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 if (portp->rxmarkmsk & status) {
3779 if (status & ST_BREAK) {
3780 status = TTY_BREAK;
3781 if (portp->flags & ASYNC_SAK) {
3782 do_SAK(tty);
3783 BRDENABLE(portp->brdnr, portp->pagenr);
3784 }
3785 } else if (status & ST_PARITY) {
3786 status = TTY_PARITY;
3787 } else if (status & ST_FRAMING) {
3788 status = TTY_FRAME;
3789 } else if(status & ST_OVERRUN) {
3790 status = TTY_OVERRUN;
3791 } else {
3792 status = 0;
3793 }
3794 } else {
3795 status = 0;
3796 }
Alan Cox33f0f882006-01-09 20:54:13 -08003797 tty_insert_flip_char(tty, ch, status);
3798 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 }
3800 } else {
3801 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3802 return;
3803 }
3804
3805stl_rxalldone:
3806 outb((EOSRR + portp->uartaddr), ioaddr);
3807 outb(0, (ioaddr + EREG_DATA));
3808}
3809
3810/*****************************************************************************/
3811
3812/*
3813 * Modem interrupt handler. The is called when the modem signal line
3814 * (DCD) has changed state. Leave most of the work to the off-level
3815 * processing routine.
3816 */
3817
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003818static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003820 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 unsigned int ioack;
3822 unsigned char misr;
3823
Jiri Slabya0564e12006-12-08 02:38:37 -08003824 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825
3826 ioack = inb(ioaddr + EREG_MDACK);
3827 if (((ioack & panelp->ackmask) != 0) ||
3828 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3829 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3830 return;
3831 }
3832 portp = panelp->ports[(ioack >> 3)];
3833
3834 outb((MISR + portp->uartaddr), ioaddr);
3835 misr = inb(ioaddr + EREG_DATA);
3836 if (misr & MISR_DCD) {
3837 set_bit(ASYI_DCDCHANGE, &portp->istate);
3838 schedule_work(&portp->tqueue);
3839 portp->stats.modem++;
3840 }
3841
3842 outb((EOSRR + portp->uartaddr), ioaddr);
3843 outb(0, (ioaddr + EREG_DATA));
3844}
3845
3846/*****************************************************************************/
3847/* SC26198 HARDWARE FUNCTIONS */
3848/*****************************************************************************/
3849
3850/*
3851 * These functions get/set/update the registers of the sc26198 UARTs.
3852 * Access to the sc26198 registers is via an address/data io port pair.
3853 * (Maybe should make this inline...)
3854 */
3855
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003856static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857{
3858 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003859 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860}
3861
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003862static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863{
3864 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3865 outb(value, (portp->ioaddr + XP_DATA));
3866}
3867
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003868static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869{
3870 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3871 if (inb(portp->ioaddr + XP_DATA) != value) {
3872 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003873 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003875 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876}
3877
3878/*****************************************************************************/
3879
3880/*
3881 * Functions to get and set the sc26198 global registers.
3882 */
3883
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003884static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885{
3886 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003887 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888}
3889
3890#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003891static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892{
3893 outb(regnr, (portp->ioaddr + XP_ADDR));
3894 outb(value, (portp->ioaddr + XP_DATA));
3895}
3896#endif
3897
3898/*****************************************************************************/
3899
3900/*
3901 * Inbitialize the UARTs in a panel. We don't care what sort of board
3902 * these ports are on - since the port io registers are almost
3903 * identical when dealing with ports.
3904 */
3905
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003906static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907{
3908 int chipmask, i;
3909 int nrchips, ioaddr;
3910
Jiri Slabya0564e12006-12-08 02:38:37 -08003911 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912
3913 BRDENABLE(panelp->brdnr, panelp->pagenr);
3914
3915/*
3916 * Check that each chip is present and started up OK.
3917 */
3918 chipmask = 0;
3919 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3920 if (brdp->brdtype == BRD_ECHPCI)
3921 outb(panelp->pagenr, brdp->ioctrl);
3922
3923 for (i = 0; (i < nrchips); i++) {
3924 ioaddr = panelp->iobase + (i * 4);
3925 outb(SCCR, (ioaddr + XP_ADDR));
3926 outb(CR_RESETALL, (ioaddr + XP_DATA));
3927 outb(TSTR, (ioaddr + XP_ADDR));
3928 if (inb(ioaddr + XP_DATA) != 0) {
3929 printk("STALLION: sc26198 not responding, "
3930 "brd=%d panel=%d chip=%d\n",
3931 panelp->brdnr, panelp->panelnr, i);
3932 continue;
3933 }
3934 chipmask |= (0x1 << i);
3935 outb(GCCR, (ioaddr + XP_ADDR));
3936 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3937 outb(WDTRCR, (ioaddr + XP_ADDR));
3938 outb(0xff, (ioaddr + XP_DATA));
3939 }
3940
3941 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003942 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943}
3944
3945/*****************************************************************************/
3946
3947/*
3948 * Initialize hardware specific port registers.
3949 */
3950
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003951static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952{
Jiri Slabya0564e12006-12-08 02:38:37 -08003953 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3954 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955
Jiri Slaby615e4a72006-12-08 02:38:38 -08003956 if ((brdp == NULL) || (panelp == NULL) ||
3957 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 return;
3959
3960 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3961 portp->uartaddr = (portp->portnr & 0x07) << 4;
3962 portp->pagenr = panelp->pagenr;
3963 portp->hwid = 0x1;
3964
3965 BRDENABLE(portp->brdnr, portp->pagenr);
3966 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3967 BRDDISABLE(portp->brdnr);
3968}
3969
3970/*****************************************************************************/
3971
3972/*
3973 * Set up the sc26198 registers for a port based on the termios port
3974 * settings.
3975 */
3976
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003977static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003979 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 unsigned long flags;
3981 unsigned int baudrate;
3982 unsigned char mr0, mr1, mr2, clk;
3983 unsigned char imron, imroff, iopr, ipr;
3984
3985 mr0 = 0;
3986 mr1 = 0;
3987 mr2 = 0;
3988 clk = 0;
3989 iopr = 0;
3990 imron = 0;
3991 imroff = 0;
3992
3993 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003994 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 return;
3996
3997/*
3998 * Set up the RX char ignore mask with those RX error types we
3999 * can ignore.
4000 */
4001 portp->rxignoremsk = 0;
4002 if (tiosp->c_iflag & IGNPAR)
4003 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
4004 SR_RXOVERRUN);
4005 if (tiosp->c_iflag & IGNBRK)
4006 portp->rxignoremsk |= SR_RXBREAK;
4007
4008 portp->rxmarkmsk = SR_RXOVERRUN;
4009 if (tiosp->c_iflag & (INPCK | PARMRK))
4010 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
4011 if (tiosp->c_iflag & BRKINT)
4012 portp->rxmarkmsk |= SR_RXBREAK;
4013
4014/*
4015 * Go through the char size, parity and stop bits and set all the
4016 * option register appropriately.
4017 */
4018 switch (tiosp->c_cflag & CSIZE) {
4019 case CS5:
4020 mr1 |= MR1_CS5;
4021 break;
4022 case CS6:
4023 mr1 |= MR1_CS6;
4024 break;
4025 case CS7:
4026 mr1 |= MR1_CS7;
4027 break;
4028 default:
4029 mr1 |= MR1_CS8;
4030 break;
4031 }
4032
4033 if (tiosp->c_cflag & CSTOPB)
4034 mr2 |= MR2_STOP2;
4035 else
4036 mr2 |= MR2_STOP1;
4037
4038 if (tiosp->c_cflag & PARENB) {
4039 if (tiosp->c_cflag & PARODD)
4040 mr1 |= (MR1_PARENB | MR1_PARODD);
4041 else
4042 mr1 |= (MR1_PARENB | MR1_PAREVEN);
4043 } else {
4044 mr1 |= MR1_PARNONE;
4045 }
4046
4047 mr1 |= MR1_ERRBLOCK;
4048
4049/*
4050 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
4051 * space for hardware flow control and the like. This should be set to
4052 * VMIN.
4053 */
4054 mr2 |= MR2_RXFIFOHALF;
4055
4056/*
4057 * Calculate the baud rate timers. For now we will just assume that
4058 * the input and output baud are the same. The sc26198 has a fixed
4059 * baud rate table, so only discrete baud rates possible.
4060 */
4061 baudrate = tiosp->c_cflag & CBAUD;
4062 if (baudrate & CBAUDEX) {
4063 baudrate &= ~CBAUDEX;
4064 if ((baudrate < 1) || (baudrate > 4))
4065 tiosp->c_cflag &= ~CBAUDEX;
4066 else
4067 baudrate += 15;
4068 }
4069 baudrate = stl_baudrates[baudrate];
4070 if ((tiosp->c_cflag & CBAUD) == B38400) {
4071 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
4072 baudrate = 57600;
4073 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
4074 baudrate = 115200;
4075 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
4076 baudrate = 230400;
4077 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
4078 baudrate = 460800;
4079 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
4080 baudrate = (portp->baud_base / portp->custom_divisor);
4081 }
4082 if (baudrate > STL_SC26198MAXBAUD)
4083 baudrate = STL_SC26198MAXBAUD;
4084
4085 if (baudrate > 0) {
4086 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
4087 if (baudrate <= sc26198_baudtable[clk])
4088 break;
4089 }
4090 }
4091
4092/*
4093 * Check what form of modem signaling is required and set it up.
4094 */
4095 if (tiosp->c_cflag & CLOCAL) {
4096 portp->flags &= ~ASYNC_CHECK_CD;
4097 } else {
4098 iopr |= IOPR_DCDCOS;
4099 imron |= IR_IOPORT;
4100 portp->flags |= ASYNC_CHECK_CD;
4101 }
4102
4103/*
4104 * Setup sc26198 enhanced modes if we can. In particular we want to
4105 * handle as much of the flow control as possible automatically. As
4106 * well as saving a few CPU cycles it will also greatly improve flow
4107 * control reliability.
4108 */
4109 if (tiosp->c_iflag & IXON) {
4110 mr0 |= MR0_SWFTX | MR0_SWFT;
4111 imron |= IR_XONXOFF;
4112 } else {
4113 imroff |= IR_XONXOFF;
4114 }
4115 if (tiosp->c_iflag & IXOFF)
4116 mr0 |= MR0_SWFRX;
4117
4118 if (tiosp->c_cflag & CRTSCTS) {
4119 mr2 |= MR2_AUTOCTS;
4120 mr1 |= MR1_AUTORTS;
4121 }
4122
4123/*
4124 * All sc26198 register values calculated so go through and set
4125 * them all up.
4126 */
4127
Jiri Slabya0564e12006-12-08 02:38:37 -08004128 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08004130 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
4131 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
4132 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4134 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135
Alan Coxb65b5b52006-06-27 02:54:05 -07004136 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 BRDENABLE(portp->brdnr, portp->pagenr);
4138 stl_sc26198setreg(portp, IMR, 0);
4139 stl_sc26198updatereg(portp, MR0, mr0);
4140 stl_sc26198updatereg(portp, MR1, mr1);
4141 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4142 stl_sc26198updatereg(portp, MR2, mr2);
4143 stl_sc26198updatereg(portp, IOPIOR,
4144 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4145
4146 if (baudrate > 0) {
4147 stl_sc26198setreg(portp, TXCSR, clk);
4148 stl_sc26198setreg(portp, RXCSR, clk);
4149 }
4150
4151 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4152 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4153
4154 ipr = stl_sc26198getreg(portp, IPR);
4155 if (ipr & IPR_DCD)
4156 portp->sigs &= ~TIOCM_CD;
4157 else
4158 portp->sigs |= TIOCM_CD;
4159
4160 portp->imr = (portp->imr & ~imroff) | imron;
4161 stl_sc26198setreg(portp, IMR, portp->imr);
4162 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004163 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164}
4165
4166/*****************************************************************************/
4167
4168/*
4169 * Set the state of the DTR and RTS signals.
4170 */
4171
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004172static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173{
4174 unsigned char iopioron, iopioroff;
4175 unsigned long flags;
4176
Jiri Slabya0564e12006-12-08 02:38:37 -08004177 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4178 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
4180 iopioron = 0;
4181 iopioroff = 0;
4182 if (dtr == 0)
4183 iopioroff |= IPR_DTR;
4184 else if (dtr > 0)
4185 iopioron |= IPR_DTR;
4186 if (rts == 0)
4187 iopioroff |= IPR_RTS;
4188 else if (rts > 0)
4189 iopioron |= IPR_RTS;
4190
Alan Coxb65b5b52006-06-27 02:54:05 -07004191 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 BRDENABLE(portp->brdnr, portp->pagenr);
4193 stl_sc26198setreg(portp, IOPIOR,
4194 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4195 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004196 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197}
4198
4199/*****************************************************************************/
4200
4201/*
4202 * Return the state of the signals.
4203 */
4204
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004205static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206{
4207 unsigned char ipr;
4208 unsigned long flags;
4209 int sigs;
4210
Jiri Slabya0564e12006-12-08 02:38:37 -08004211 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212
Alan Coxb65b5b52006-06-27 02:54:05 -07004213 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 BRDENABLE(portp->brdnr, portp->pagenr);
4215 ipr = stl_sc26198getreg(portp, IPR);
4216 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004217 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
4219 sigs = 0;
4220 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4221 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4222 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4223 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4224 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004225 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226}
4227
4228/*****************************************************************************/
4229
4230/*
4231 * Enable/Disable the Transmitter and/or Receiver.
4232 */
4233
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004234static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235{
4236 unsigned char ccr;
4237 unsigned long flags;
4238
Jiri Slabya0564e12006-12-08 02:38:37 -08004239 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240
4241 ccr = portp->crenable;
4242 if (tx == 0)
4243 ccr &= ~CR_TXENABLE;
4244 else if (tx > 0)
4245 ccr |= CR_TXENABLE;
4246 if (rx == 0)
4247 ccr &= ~CR_RXENABLE;
4248 else if (rx > 0)
4249 ccr |= CR_RXENABLE;
4250
Alan Coxb65b5b52006-06-27 02:54:05 -07004251 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252 BRDENABLE(portp->brdnr, portp->pagenr);
4253 stl_sc26198setreg(portp, SCCR, ccr);
4254 BRDDISABLE(portp->brdnr);
4255 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004256 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257}
4258
4259/*****************************************************************************/
4260
4261/*
4262 * Start/stop the Transmitter and/or Receiver.
4263 */
4264
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004265static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266{
4267 unsigned char imr;
4268 unsigned long flags;
4269
Jiri Slabya0564e12006-12-08 02:38:37 -08004270 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271
4272 imr = portp->imr;
4273 if (tx == 0)
4274 imr &= ~IR_TXRDY;
4275 else if (tx == 1)
4276 imr |= IR_TXRDY;
4277 if (rx == 0)
4278 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4279 else if (rx > 0)
4280 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4281
Alan Coxb65b5b52006-06-27 02:54:05 -07004282 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 BRDENABLE(portp->brdnr, portp->pagenr);
4284 stl_sc26198setreg(portp, IMR, imr);
4285 BRDDISABLE(portp->brdnr);
4286 portp->imr = imr;
4287 if (tx > 0)
4288 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004289 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290}
4291
4292/*****************************************************************************/
4293
4294/*
4295 * Disable all interrupts from this port.
4296 */
4297
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004298static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299{
4300 unsigned long flags;
4301
Jiri Slabya0564e12006-12-08 02:38:37 -08004302 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303
Alan Coxb65b5b52006-06-27 02:54:05 -07004304 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 BRDENABLE(portp->brdnr, portp->pagenr);
4306 portp->imr = 0;
4307 stl_sc26198setreg(portp, IMR, 0);
4308 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004309 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310}
4311
4312/*****************************************************************************/
4313
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004314static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315{
4316 unsigned long flags;
4317
Jiri Slabya0564e12006-12-08 02:38:37 -08004318 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319
Alan Coxb65b5b52006-06-27 02:54:05 -07004320 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321 BRDENABLE(portp->brdnr, portp->pagenr);
4322 if (len == 1) {
4323 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4324 portp->stats.txbreaks++;
4325 } else {
4326 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4327 }
4328 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004329 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330}
4331
4332/*****************************************************************************/
4333
4334/*
4335 * Take flow control actions...
4336 */
4337
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004338static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339{
4340 struct tty_struct *tty;
4341 unsigned long flags;
4342 unsigned char mr0;
4343
Jiri Slabya0564e12006-12-08 02:38:37 -08004344 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
Jiri Slaby615e4a72006-12-08 02:38:38 -08004346 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 return;
4348 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004349 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 return;
4351
Alan Coxb65b5b52006-06-27 02:54:05 -07004352 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353 BRDENABLE(portp->brdnr, portp->pagenr);
4354
4355 if (state) {
4356 if (tty->termios->c_iflag & IXOFF) {
4357 mr0 = stl_sc26198getreg(portp, MR0);
4358 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4359 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4360 mr0 |= MR0_SWFRX;
4361 portp->stats.rxxon++;
4362 stl_sc26198wait(portp);
4363 stl_sc26198setreg(portp, MR0, mr0);
4364 }
4365/*
4366 * Question: should we return RTS to what it was before? It may
4367 * have been set by an ioctl... Suppose not, since if you have
4368 * hardware flow control set then it is pretty silly to go and
4369 * set the RTS line by hand.
4370 */
4371 if (tty->termios->c_cflag & CRTSCTS) {
4372 stl_sc26198setreg(portp, MR1,
4373 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4374 stl_sc26198setreg(portp, IOPIOR,
4375 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4376 portp->stats.rxrtson++;
4377 }
4378 } else {
4379 if (tty->termios->c_iflag & IXOFF) {
4380 mr0 = stl_sc26198getreg(portp, MR0);
4381 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4382 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4383 mr0 &= ~MR0_SWFRX;
4384 portp->stats.rxxoff++;
4385 stl_sc26198wait(portp);
4386 stl_sc26198setreg(portp, MR0, mr0);
4387 }
4388 if (tty->termios->c_cflag & CRTSCTS) {
4389 stl_sc26198setreg(portp, MR1,
4390 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4391 stl_sc26198setreg(portp, IOPIOR,
4392 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4393 portp->stats.rxrtsoff++;
4394 }
4395 }
4396
4397 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004398 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399}
4400
4401/*****************************************************************************/
4402
4403/*
4404 * Send a flow control character.
4405 */
4406
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004407static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408{
4409 struct tty_struct *tty;
4410 unsigned long flags;
4411 unsigned char mr0;
4412
Jiri Slabya0564e12006-12-08 02:38:37 -08004413 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414
Jiri Slaby615e4a72006-12-08 02:38:38 -08004415 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416 return;
4417 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004418 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 return;
4420
Alan Coxb65b5b52006-06-27 02:54:05 -07004421 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 BRDENABLE(portp->brdnr, portp->pagenr);
4423 if (state) {
4424 mr0 = stl_sc26198getreg(portp, MR0);
4425 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4426 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4427 mr0 |= MR0_SWFRX;
4428 portp->stats.rxxon++;
4429 stl_sc26198wait(portp);
4430 stl_sc26198setreg(portp, MR0, mr0);
4431 } else {
4432 mr0 = stl_sc26198getreg(portp, MR0);
4433 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4434 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4435 mr0 &= ~MR0_SWFRX;
4436 portp->stats.rxxoff++;
4437 stl_sc26198wait(portp);
4438 stl_sc26198setreg(portp, MR0, mr0);
4439 }
4440 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004441 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442}
4443
4444/*****************************************************************************/
4445
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004446static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447{
4448 unsigned long flags;
4449
Jiri Slabya0564e12006-12-08 02:38:37 -08004450 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451
Jiri Slaby615e4a72006-12-08 02:38:38 -08004452 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 return;
4454
Alan Coxb65b5b52006-06-27 02:54:05 -07004455 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 BRDENABLE(portp->brdnr, portp->pagenr);
4457 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4458 stl_sc26198setreg(portp, SCCR, portp->crenable);
4459 BRDDISABLE(portp->brdnr);
4460 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004461 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462}
4463
4464/*****************************************************************************/
4465
4466/*
4467 * Return the current state of data flow on this port. This is only
4468 * really interresting when determining if data has fully completed
4469 * transmission or not... The sc26198 interrupt scheme cannot
4470 * determine when all data has actually drained, so we need to
4471 * check the port statusy register to be sure.
4472 */
4473
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004474static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475{
4476 unsigned long flags;
4477 unsigned char sr;
4478
Jiri Slabya0564e12006-12-08 02:38:37 -08004479 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480
Jiri Slaby615e4a72006-12-08 02:38:38 -08004481 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004482 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004484 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485
Alan Coxb65b5b52006-06-27 02:54:05 -07004486 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487 BRDENABLE(portp->brdnr, portp->pagenr);
4488 sr = stl_sc26198getreg(portp, SR);
4489 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004490 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Jesper Juhl014c2542006-01-15 02:37:08 +01004492 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493}
4494
4495/*****************************************************************************/
4496
4497/*
4498 * Delay for a small amount of time, to give the sc26198 a chance
4499 * to process a command...
4500 */
4501
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004502static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503{
4504 int i;
4505
Jiri Slabya0564e12006-12-08 02:38:37 -08004506 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507
Jiri Slaby615e4a72006-12-08 02:38:38 -08004508 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509 return;
4510
4511 for (i = 0; (i < 20); i++)
4512 stl_sc26198getglobreg(portp, TSTR);
4513}
4514
4515/*****************************************************************************/
4516
4517/*
4518 * If we are TX flow controlled and in IXANY mode then we may
4519 * need to unflow control here. We gotta do this because of the
4520 * automatic flow control modes of the sc26198.
4521 */
4522
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004523static inline void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524{
4525 unsigned char mr0;
4526
4527 mr0 = stl_sc26198getreg(portp, MR0);
4528 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4529 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4530 stl_sc26198wait(portp);
4531 stl_sc26198setreg(portp, MR0, mr0);
4532 clear_bit(ASYI_TXFLOWED, &portp->istate);
4533}
4534
4535/*****************************************************************************/
4536
4537/*
4538 * Interrupt service routine for sc26198 panels.
4539 */
4540
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004541static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004543 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544 unsigned int iack;
4545
Alan Coxb65b5b52006-06-27 02:54:05 -07004546 spin_lock(&brd_lock);
4547
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548/*
4549 * Work around bug in sc26198 chip... Cannot have A6 address
4550 * line of UART high, else iack will be returned as 0.
4551 */
4552 outb(0, (iobase + 1));
4553
4554 iack = inb(iobase + XP_IACK);
4555 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4556
4557 if (iack & IVR_RXDATA)
4558 stl_sc26198rxisr(portp, iack);
4559 else if (iack & IVR_TXDATA)
4560 stl_sc26198txisr(portp);
4561 else
4562 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004563
4564 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565}
4566
4567/*****************************************************************************/
4568
4569/*
4570 * Transmit interrupt handler. This has gotta be fast! Handling TX
4571 * chars is pretty simple, stuff as many as possible from the TX buffer
4572 * into the sc26198 FIFO.
4573 * In practice it is possible that interrupts are enabled but that the
4574 * port has been hung up. Need to handle not having any TX buffer here,
4575 * this is done by using the side effect that head and tail will also
4576 * be NULL if the buffer has been freed.
4577 */
4578
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004579static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580{
4581 unsigned int ioaddr;
4582 unsigned char mr0;
4583 int len, stlen;
4584 char *head, *tail;
4585
Jiri Slabya0564e12006-12-08 02:38:37 -08004586 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587
4588 ioaddr = portp->ioaddr;
4589 head = portp->tx.head;
4590 tail = portp->tx.tail;
4591 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4592 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4593 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4594 set_bit(ASYI_TXLOW, &portp->istate);
4595 schedule_work(&portp->tqueue);
4596 }
4597
4598 if (len == 0) {
4599 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4600 mr0 = inb(ioaddr + XP_DATA);
4601 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4602 portp->imr &= ~IR_TXRDY;
4603 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4604 outb(portp->imr, (ioaddr + XP_DATA));
4605 clear_bit(ASYI_TXBUSY, &portp->istate);
4606 } else {
4607 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4608 outb(mr0, (ioaddr + XP_DATA));
4609 }
4610 } else {
4611 len = MIN(len, SC26198_TXFIFOSIZE);
4612 portp->stats.txtotal += len;
4613 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
4614 outb(GTXFIFO, (ioaddr + XP_ADDR));
4615 outsb((ioaddr + XP_DATA), tail, stlen);
4616 len -= stlen;
4617 tail += stlen;
4618 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4619 tail = portp->tx.buf;
4620 if (len > 0) {
4621 outsb((ioaddr + XP_DATA), tail, len);
4622 tail += len;
4623 }
4624 portp->tx.tail = tail;
4625 }
4626}
4627
4628/*****************************************************************************/
4629
4630/*
4631 * Receive character interrupt handler. Determine if we have good chars
4632 * or bad chars and then process appropriately. Good chars are easy
4633 * just shove the lot into the RX buffer and set all status byte to 0.
4634 * If a bad RX char then process as required. This routine needs to be
4635 * fast! In practice it is possible that we get an interrupt on a port
4636 * that is closed. This can happen on hangups - since they completely
4637 * shutdown a port not in user context. Need to handle this case.
4638 */
4639
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004640static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641{
4642 struct tty_struct *tty;
4643 unsigned int len, buflen, ioaddr;
4644
Jiri Slabya0564e12006-12-08 02:38:37 -08004645 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004646
4647 tty = portp->tty;
4648 ioaddr = portp->ioaddr;
4649 outb(GIBCR, (ioaddr + XP_ADDR));
4650 len = inb(ioaddr + XP_DATA) + 1;
4651
4652 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004653 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004654 len = MIN(len, sizeof(stl_unwanted));
4655 outb(GRXFIFO, (ioaddr + XP_ADDR));
4656 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4657 portp->stats.rxlost += len;
4658 portp->stats.rxtotal += len;
4659 } else {
4660 len = MIN(len, buflen);
4661 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004662 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004664 tty_prepare_flip_string(tty, &ptr, len);
4665 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004666 tty_schedule_flip(tty);
4667 portp->stats.rxtotal += len;
4668 }
4669 }
4670 } else {
4671 stl_sc26198rxbadchars(portp);
4672 }
4673
4674/*
4675 * If we are TX flow controlled and in IXANY mode then we may need
4676 * to unflow control here. We gotta do this because of the automatic
4677 * flow control modes of the sc26198.
4678 */
4679 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004680 if ((tty != NULL) &&
4681 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004682 (tty->termios->c_iflag & IXANY)) {
4683 stl_sc26198txunflow(portp, tty);
4684 }
4685 }
4686}
4687
4688/*****************************************************************************/
4689
4690/*
4691 * Process an RX bad character.
4692 */
4693
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004694static inline void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695{
4696 struct tty_struct *tty;
4697 unsigned int ioaddr;
4698
4699 tty = portp->tty;
4700 ioaddr = portp->ioaddr;
4701
4702 if (status & SR_RXPARITY)
4703 portp->stats.rxparity++;
4704 if (status & SR_RXFRAMING)
4705 portp->stats.rxframing++;
4706 if (status & SR_RXOVERRUN)
4707 portp->stats.rxoverrun++;
4708 if (status & SR_RXBREAK)
4709 portp->stats.rxbreaks++;
4710
Jiri Slaby615e4a72006-12-08 02:38:38 -08004711 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712 ((portp->rxignoremsk & status) == 0)) {
4713 if (portp->rxmarkmsk & status) {
4714 if (status & SR_RXBREAK) {
4715 status = TTY_BREAK;
4716 if (portp->flags & ASYNC_SAK) {
4717 do_SAK(tty);
4718 BRDENABLE(portp->brdnr, portp->pagenr);
4719 }
4720 } else if (status & SR_RXPARITY) {
4721 status = TTY_PARITY;
4722 } else if (status & SR_RXFRAMING) {
4723 status = TTY_FRAME;
4724 } else if(status & SR_RXOVERRUN) {
4725 status = TTY_OVERRUN;
4726 } else {
4727 status = 0;
4728 }
4729 } else {
4730 status = 0;
4731 }
4732
Alan Cox33f0f882006-01-09 20:54:13 -08004733 tty_insert_flip_char(tty, ch, status);
4734 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735
4736 if (status == 0)
4737 portp->stats.rxtotal++;
4738 }
4739}
4740
4741/*****************************************************************************/
4742
4743/*
4744 * Process all characters in the RX FIFO of the UART. Check all char
4745 * status bytes as well, and process as required. We need to check
4746 * all bytes in the FIFO, in case some more enter the FIFO while we
4747 * are here. To get the exact character error type we need to switch
4748 * into CHAR error mode (that is why we need to make sure we empty
4749 * the FIFO).
4750 */
4751
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004752static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753{
4754 unsigned char status, mr1;
4755 char ch;
4756
4757/*
4758 * To get the precise error type for each character we must switch
4759 * back into CHAR error mode.
4760 */
4761 mr1 = stl_sc26198getreg(portp, MR1);
4762 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4763
4764 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4765 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4766 ch = stl_sc26198getreg(portp, RXFIFO);
4767 stl_sc26198rxbadch(portp, status, ch);
4768 }
4769
4770/*
4771 * To get correct interrupt class we must switch back into BLOCK
4772 * error mode.
4773 */
4774 stl_sc26198setreg(portp, MR1, mr1);
4775}
4776
4777/*****************************************************************************/
4778
4779/*
4780 * Other interrupt handler. This includes modem signals, flow
4781 * control actions, etc. Most stuff is left to off-level interrupt
4782 * processing time.
4783 */
4784
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004785static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004786{
4787 unsigned char cir, ipr, xisr;
4788
Jiri Slabya0564e12006-12-08 02:38:37 -08004789 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004790
4791 cir = stl_sc26198getglobreg(portp, CIR);
4792
4793 switch (cir & CIR_SUBTYPEMASK) {
4794 case CIR_SUBCOS:
4795 ipr = stl_sc26198getreg(portp, IPR);
4796 if (ipr & IPR_DCDCHANGE) {
4797 set_bit(ASYI_DCDCHANGE, &portp->istate);
4798 schedule_work(&portp->tqueue);
4799 portp->stats.modem++;
4800 }
4801 break;
4802 case CIR_SUBXONXOFF:
4803 xisr = stl_sc26198getreg(portp, XISR);
4804 if (xisr & XISR_RXXONGOT) {
4805 set_bit(ASYI_TXFLOWED, &portp->istate);
4806 portp->stats.txxoff++;
4807 }
4808 if (xisr & XISR_RXXOFFGOT) {
4809 clear_bit(ASYI_TXFLOWED, &portp->istate);
4810 portp->stats.txxon++;
4811 }
4812 break;
4813 case CIR_SUBBREAK:
4814 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4815 stl_sc26198rxbadchars(portp);
4816 break;
4817 default:
4818 break;
4819 }
4820}
4821
Jiri Slaby23b85a12006-12-08 02:38:40 -08004822/*
4823 * Loadable module initialization stuff.
4824 */
4825static int __init stallion_module_init(void)
4826{
4827 unsigned int i;
4828
4829 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4830
4831 spin_lock_init(&stallion_lock);
4832 spin_lock_init(&brd_lock);
4833
4834 stl_initbrds();
4835
4836 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4837 if (!stl_serial)
4838 return -1;
4839
4840/*
4841 * Set up a character driver for per board stuff. This is mainly used
4842 * to do stats ioctls on the ports.
4843 */
4844 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4845 printk("STALLION: failed to register serial board device\n");
4846
4847 stallion_class = class_create(THIS_MODULE, "staliomem");
4848 for (i = 0; i < 4; i++)
4849 class_device_create(stallion_class, NULL,
4850 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4851 "staliomem%d", i);
4852
4853 stl_serial->owner = THIS_MODULE;
4854 stl_serial->driver_name = stl_drvname;
4855 stl_serial->name = "ttyE";
4856 stl_serial->major = STL_SERIALMAJOR;
4857 stl_serial->minor_start = 0;
4858 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4859 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4860 stl_serial->init_termios = stl_deftermios;
4861 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4862 tty_set_operations(stl_serial, &stl_ops);
4863
4864 if (tty_register_driver(stl_serial)) {
4865 put_tty_driver(stl_serial);
4866 printk("STALLION: failed to register serial driver\n");
4867 return -1;
4868 }
4869
4870 return 0;
4871}
4872
4873static void __exit stallion_module_exit(void)
4874{
4875 struct stlbrd *brdp;
4876 struct stlpanel *panelp;
4877 struct stlport *portp;
4878 int i, j, k;
4879
4880 pr_debug("cleanup_module()\n");
4881
4882 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4883 stl_drvversion);
4884
4885/*
4886 * Free up all allocated resources used by the ports. This includes
4887 * memory and interrupts. As part of this process we will also do
4888 * a hangup on every open port - to try to flush out any processes
4889 * hanging onto ports.
4890 */
4891 i = tty_unregister_driver(stl_serial);
4892 put_tty_driver(stl_serial);
4893 if (i) {
4894 printk("STALLION: failed to un-register tty driver, "
4895 "errno=%d\n", -i);
4896 return;
4897 }
4898 for (i = 0; i < 4; i++)
4899 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4900 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4901 printk("STALLION: failed to un-register serial memory device, "
4902 "errno=%d\n", -i);
4903 class_destroy(stallion_class);
4904
4905 for (i = 0; (i < stl_nrbrds); i++) {
4906 if ((brdp = stl_brds[i]) == NULL)
4907 continue;
4908
4909 free_irq(brdp->irq, brdp);
4910
4911 for (j = 0; (j < STL_MAXPANELS); j++) {
4912 panelp = brdp->panels[j];
4913 if (panelp == NULL)
4914 continue;
4915 for (k = 0; (k < STL_PORTSPERPANEL); k++) {
4916 portp = panelp->ports[k];
4917 if (portp == NULL)
4918 continue;
4919 if (portp->tty != NULL)
4920 stl_hangup(portp->tty);
4921 kfree(portp->tx.buf);
4922 kfree(portp);
4923 }
4924 kfree(panelp);
4925 }
4926
4927 release_region(brdp->ioaddr1, brdp->iosize1);
4928 if (brdp->iosize2 > 0)
4929 release_region(brdp->ioaddr2, brdp->iosize2);
4930
4931 kfree(brdp);
4932 stl_brds[i] = NULL;
4933 }
4934}
4935
4936module_init(stallion_module_init);
4937module_exit(stallion_module_exit);
4938
4939MODULE_AUTHOR("Greg Ungerer");
4940MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4941MODULE_LICENSE("GPL");