blob: c476da100b0091dc59b8a616be4caf83bf0e81ce [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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499/*
500 * CD1400 uart specific handling functions.
501 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800502static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
503static int stl_cd1400getreg(struct stlport *portp, int regnr);
504static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
505static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
506static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
507static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp);
508static int stl_cd1400getsignals(struct stlport *portp);
509static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
510static void stl_cd1400ccrwait(struct stlport *portp);
511static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
512static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
513static void stl_cd1400disableintrs(struct stlport *portp);
514static void stl_cd1400sendbreak(struct stlport *portp, int len);
515static void stl_cd1400flowctrl(struct stlport *portp, int state);
516static void stl_cd1400sendflow(struct stlport *portp, int state);
517static void stl_cd1400flush(struct stlport *portp);
518static int stl_cd1400datastate(struct stlport *portp);
519static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
520static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
521static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
522static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
523static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800525static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
527/*
528 * SC26198 uart specific handling functions.
529 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800530static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
531static int stl_sc26198getreg(struct stlport *portp, int regnr);
532static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
533static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
534static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
535static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
536static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp);
537static int stl_sc26198getsignals(struct stlport *portp);
538static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
539static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
540static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
541static void stl_sc26198disableintrs(struct stlport *portp);
542static void stl_sc26198sendbreak(struct stlport *portp, int len);
543static void stl_sc26198flowctrl(struct stlport *portp, int state);
544static void stl_sc26198sendflow(struct stlport *portp, int state);
545static void stl_sc26198flush(struct stlport *portp);
546static int stl_sc26198datastate(struct stlport *portp);
547static void stl_sc26198wait(struct stlport *portp);
548static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
549static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
550static void stl_sc26198txisr(struct stlport *port);
551static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
552static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
553static void stl_sc26198rxbadchars(struct stlport *portp);
554static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
556/*****************************************************************************/
557
558/*
559 * Generic UART support structure.
560 */
561typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800562 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
563 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
564 void (*setport)(struct stlport *portp, struct termios *tiosp);
565 int (*getsignals)(struct stlport *portp);
566 void (*setsignals)(struct stlport *portp, int dtr, int rts);
567 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
568 void (*startrxtx)(struct stlport *portp, int rx, int tx);
569 void (*disableintrs)(struct stlport *portp);
570 void (*sendbreak)(struct stlport *portp, int len);
571 void (*flowctrl)(struct stlport *portp, int state);
572 void (*sendflow)(struct stlport *portp, int state);
573 void (*flush)(struct stlport *portp);
574 int (*datastate)(struct stlport *portp);
575 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576} uart_t;
577
578/*
579 * Define some macros to make calling these functions nice and clean.
580 */
581#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
582#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
583#define stl_setport (* ((uart_t *) portp->uartp)->setport)
584#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
585#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
586#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
587#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
588#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
589#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
590#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
591#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
592#define stl_flush (* ((uart_t *) portp->uartp)->flush)
593#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
594
595/*****************************************************************************/
596
597/*
598 * CD1400 UART specific data initialization.
599 */
600static uart_t stl_cd1400uart = {
601 stl_cd1400panelinit,
602 stl_cd1400portinit,
603 stl_cd1400setport,
604 stl_cd1400getsignals,
605 stl_cd1400setsignals,
606 stl_cd1400enablerxtx,
607 stl_cd1400startrxtx,
608 stl_cd1400disableintrs,
609 stl_cd1400sendbreak,
610 stl_cd1400flowctrl,
611 stl_cd1400sendflow,
612 stl_cd1400flush,
613 stl_cd1400datastate,
614 stl_cd1400eiointr
615};
616
617/*
618 * Define the offsets within the register bank of a cd1400 based panel.
619 * These io address offsets are common to the EasyIO board as well.
620 */
621#define EREG_ADDR 0
622#define EREG_DATA 4
623#define EREG_RXACK 5
624#define EREG_TXACK 6
625#define EREG_MDACK 7
626
627#define EREG_BANKSIZE 8
628
629#define CD1400_CLK 25000000
630#define CD1400_CLK8M 20000000
631
632/*
633 * Define the cd1400 baud rate clocks. These are used when calculating
634 * what clock and divisor to use for the required baud rate. Also
635 * define the maximum baud rate allowed, and the default base baud.
636 */
637static int stl_cd1400clkdivs[] = {
638 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
639};
640
641/*****************************************************************************/
642
643/*
644 * SC26198 UART specific data initization.
645 */
646static uart_t stl_sc26198uart = {
647 stl_sc26198panelinit,
648 stl_sc26198portinit,
649 stl_sc26198setport,
650 stl_sc26198getsignals,
651 stl_sc26198setsignals,
652 stl_sc26198enablerxtx,
653 stl_sc26198startrxtx,
654 stl_sc26198disableintrs,
655 stl_sc26198sendbreak,
656 stl_sc26198flowctrl,
657 stl_sc26198sendflow,
658 stl_sc26198flush,
659 stl_sc26198datastate,
660 stl_sc26198intr
661};
662
663/*
664 * Define the offsets within the register bank of a sc26198 based panel.
665 */
666#define XP_DATA 0
667#define XP_ADDR 1
668#define XP_MODID 2
669#define XP_STATUS 2
670#define XP_IACK 3
671
672#define XP_BANKSIZE 4
673
674/*
675 * Define the sc26198 baud rate table. Offsets within the table
676 * represent the actual baud rate selector of sc26198 registers.
677 */
678static unsigned int sc26198_baudtable[] = {
679 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
680 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
681 230400, 460800, 921600
682};
683
Tobias Klauserfe971072006-01-09 20:54:02 -0800684#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
686/*****************************************************************************/
687
688/*
689 * Define the driver info for a user level control device. Used mainly
690 * to get at port stats - only not using the port device itself.
691 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700692static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 .owner = THIS_MODULE,
694 .ioctl = stl_memioctl,
695};
696
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800697static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
699/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 * Check for any arguments passed in on the module load command line.
701 */
702
Jiri Slaby40e82652006-12-08 02:38:41 -0800703static void __init stl_argbrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800705 struct stlconf conf;
706 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 int i;
708
Jiri Slabya0564e12006-12-08 02:38:37 -0800709 pr_debug("stl_argbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711 for (i = stl_nrbrds; (i < stl_nargs); i++) {
712 memset(&conf, 0, sizeof(conf));
713 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
714 continue;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800715 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 continue;
717 stl_nrbrds = i + 1;
718 brdp->brdnr = i;
719 brdp->brdtype = conf.brdtype;
720 brdp->ioaddr1 = conf.ioaddr1;
721 brdp->ioaddr2 = conf.ioaddr2;
722 brdp->irq = conf.irq;
723 brdp->irqtype = conf.irqtype;
724 stl_brdinit(brdp);
725 }
726}
727
728/*****************************************************************************/
729
730/*
731 * Convert an ascii string number into an unsigned long.
732 */
733
734static unsigned long stl_atol(char *str)
735{
736 unsigned long val;
737 int base, c;
738 char *sp;
739
740 val = 0;
741 sp = str;
742 if ((*sp == '0') && (*(sp+1) == 'x')) {
743 base = 16;
744 sp += 2;
745 } else if (*sp == '0') {
746 base = 8;
747 sp++;
748 } else {
749 base = 10;
750 }
751
752 for (; (*sp != 0); sp++) {
753 c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
754 if ((c < 0) || (c >= base)) {
755 printk("STALLION: invalid argument %s\n", str);
756 val = 0;
757 break;
758 }
759 val = (val * base) + c;
760 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100761 return val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762}
763
764/*****************************************************************************/
765
766/*
767 * Parse the supplied argument string, into the board conf struct.
768 */
769
Jiri Slaby40e82652006-12-08 02:38:41 -0800770static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771{
772 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800773 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Jiri Slabya0564e12006-12-08 02:38:37 -0800775 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
Jiri Slaby615e4a72006-12-08 02:38:38 -0800777 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100778 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779
780 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
781 *sp = TOLOWER(*sp);
782
Tobias Klauserfe971072006-01-09 20:54:02 -0800783 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
785 break;
786 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800787 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800789 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 }
791
792 confp->brdtype = stl_brdstr[i].type;
793
794 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800795 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 confp->ioaddr1 = stl_atol(argp[i]);
797 i++;
798 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800799 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 confp->ioaddr2 = stl_atol(argp[i]);
801 i++;
802 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800803 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 confp->irq = stl_atol(argp[i]);
Jesper Juhl014c2542006-01-15 02:37:08 +0100805 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806}
807
808/*****************************************************************************/
809
810/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 * Allocate a new board structure. Fill out the basic info in it.
812 */
813
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800814static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800816 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800818 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800819 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700820 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800821 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800822 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 }
824
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100826 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827}
828
829/*****************************************************************************/
830
831static int stl_open(struct tty_struct *tty, struct file *filp)
832{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800833 struct stlport *portp;
834 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 unsigned int minordev;
836 int brdnr, panelnr, portnr, rc;
837
Jiri Slabya0564e12006-12-08 02:38:37 -0800838 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839
840 minordev = tty->index;
841 brdnr = MINOR2BRD(minordev);
842 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100843 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800845 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100846 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 minordev = MINOR2PORT(minordev);
848 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800849 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 break;
851 if (minordev < brdp->panels[panelnr]->nrports) {
852 portnr = minordev;
853 break;
854 }
855 minordev -= brdp->panels[panelnr]->nrports;
856 }
857 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100858 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
860 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800861 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100862 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
864/*
865 * On the first open of the device setup the port hardware, and
866 * initialize the per port data structure.
867 */
868 portp->tty = tty;
869 tty->driver_data = portp;
870 portp->refcount++;
871
872 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800873 if (!portp->tx.buf) {
874 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
875 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100876 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 portp->tx.head = portp->tx.buf;
878 portp->tx.tail = portp->tx.buf;
879 }
880 stl_setport(portp, tty->termios);
881 portp->sigs = stl_getsignals(portp);
882 stl_setsignals(portp, 1, 1);
883 stl_enablerxtx(portp, 1, 1);
884 stl_startrxtx(portp, 1, 0);
885 clear_bit(TTY_IO_ERROR, &tty->flags);
886 portp->flags |= ASYNC_INITIALIZED;
887 }
888
889/*
890 * Check if this port is in the middle of closing. If so then wait
891 * until it is closed then return error status, based on flag settings.
892 * The sleep here does not need interrupt protection since the wakeup
893 * for it is done with the same context.
894 */
895 if (portp->flags & ASYNC_CLOSING) {
896 interruptible_sleep_on(&portp->close_wait);
897 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100898 return -EAGAIN;
899 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 }
901
902/*
903 * Based on type of open being done check if it can overlap with any
904 * previous opens still in effect. If we are a normal serial device
905 * then also we might have to wait for carrier.
906 */
907 if (!(filp->f_flags & O_NONBLOCK)) {
908 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100909 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
911 portp->flags |= ASYNC_NORMAL_ACTIVE;
912
Jesper Juhl014c2542006-01-15 02:37:08 +0100913 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914}
915
916/*****************************************************************************/
917
918/*
919 * Possibly need to wait for carrier (DCD signal) to come high. Say
920 * maybe because if we are clocal then we don't need to wait...
921 */
922
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800923static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924{
925 unsigned long flags;
926 int rc, doclocal;
927
Jiri Slabya0564e12006-12-08 02:38:37 -0800928 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
930 rc = 0;
931 doclocal = 0;
932
Alan Coxb65b5b52006-06-27 02:54:05 -0700933 spin_lock_irqsave(&stallion_lock, flags);
934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 if (portp->tty->termios->c_cflag & CLOCAL)
936 doclocal++;
937
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 portp->openwaitcnt++;
939 if (! tty_hung_up_p(filp))
940 portp->refcount--;
941
942 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700943 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 stl_setsignals(portp, 1, 1);
945 if (tty_hung_up_p(filp) ||
946 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
947 if (portp->flags & ASYNC_HUP_NOTIFY)
948 rc = -EBUSY;
949 else
950 rc = -ERESTARTSYS;
951 break;
952 }
953 if (((portp->flags & ASYNC_CLOSING) == 0) &&
954 (doclocal || (portp->sigs & TIOCM_CD))) {
955 break;
956 }
957 if (signal_pending(current)) {
958 rc = -ERESTARTSYS;
959 break;
960 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700961 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 interruptible_sleep_on(&portp->open_wait);
963 }
964
965 if (! tty_hung_up_p(filp))
966 portp->refcount++;
967 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700968 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969
Jesper Juhl014c2542006-01-15 02:37:08 +0100970 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971}
972
973/*****************************************************************************/
974
975static void stl_close(struct tty_struct *tty, struct file *filp)
976{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800977 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 unsigned long flags;
979
Jiri Slabya0564e12006-12-08 02:38:37 -0800980 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
982 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800983 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 return;
985
Alan Coxb65b5b52006-06-27 02:54:05 -0700986 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700988 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 return;
990 }
991 if ((tty->count == 1) && (portp->refcount != 1))
992 portp->refcount = 1;
993 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700994 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 return;
996 }
997
998 portp->refcount = 0;
999 portp->flags |= ASYNC_CLOSING;
1000
1001/*
1002 * May want to wait for any data to drain before closing. The BUSY
1003 * flag keeps track of whether we are still sending or not - it is
1004 * very accurate for the cd1400, not quite so for the sc26198.
1005 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
1006 */
1007 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -07001008
1009 spin_unlock_irqrestore(&stallion_lock, flags);
1010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1012 tty_wait_until_sent(tty, portp->closing_wait);
1013 stl_waituntilsent(tty, (HZ / 2));
1014
Alan Coxb65b5b52006-06-27 02:54:05 -07001015
1016 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -07001018 spin_unlock_irqrestore(&stallion_lock, flags);
1019
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 stl_disableintrs(portp);
1021 if (tty->termios->c_cflag & HUPCL)
1022 stl_setsignals(portp, 0, 0);
1023 stl_enablerxtx(portp, 0, 0);
1024 stl_flushbuffer(tty);
1025 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001026 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001028 portp->tx.buf = NULL;
1029 portp->tx.head = NULL;
1030 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 }
1032 set_bit(TTY_IO_ERROR, &tty->flags);
1033 tty_ldisc_flush(tty);
1034
1035 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001036 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
1038 if (portp->openwaitcnt) {
1039 if (portp->close_delay)
1040 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
1041 wake_up_interruptible(&portp->open_wait);
1042 }
1043
1044 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1045 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046}
1047
1048/*****************************************************************************/
1049
1050/*
1051 * Write routine. Take data and stuff it in to the TX ring queue.
1052 * If transmit interrupts are not running then start them.
1053 */
1054
1055static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
1056{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001057 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 unsigned int len, stlen;
1059 unsigned char *chbuf;
1060 char *head, *tail;
1061
Jiri Slabya0564e12006-12-08 02:38:37 -08001062 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001065 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001066 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001067 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001068 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070/*
1071 * If copying direct from user space we must cater for page faults,
1072 * causing us to "sleep" here for a while. To handle this copy in all
1073 * the data we need now, into a local buffer. Then when we got it all
1074 * copy it into the TX buffer.
1075 */
1076 chbuf = (unsigned char *) buf;
1077
1078 head = portp->tx.head;
1079 tail = portp->tx.tail;
1080 if (head >= tail) {
1081 len = STL_TXBUFSIZE - (head - tail) - 1;
1082 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1083 } else {
1084 len = tail - head - 1;
1085 stlen = len;
1086 }
1087
1088 len = MIN(len, count);
1089 count = 0;
1090 while (len > 0) {
1091 stlen = MIN(len, stlen);
1092 memcpy(head, chbuf, stlen);
1093 len -= stlen;
1094 chbuf += stlen;
1095 count += stlen;
1096 head += stlen;
1097 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1098 head = portp->tx.buf;
1099 stlen = tail - head;
1100 }
1101 }
1102 portp->tx.head = head;
1103
1104 clear_bit(ASYI_TXLOW, &portp->istate);
1105 stl_startrxtx(portp, -1, 1);
1106
Jesper Juhl014c2542006-01-15 02:37:08 +01001107 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108}
1109
1110/*****************************************************************************/
1111
1112static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1113{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001114 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 unsigned int len;
1116 char *head, *tail;
1117
Jiri Slabya0564e12006-12-08 02:38:37 -08001118 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Jiri Slaby615e4a72006-12-08 02:38:38 -08001120 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 return;
1122 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001123 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001125 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 return;
1127
1128 head = portp->tx.head;
1129 tail = portp->tx.tail;
1130
1131 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1132 len--;
1133
1134 if (len > 0) {
1135 *head++ = ch;
1136 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1137 head = portp->tx.buf;
1138 }
1139 portp->tx.head = head;
1140}
1141
1142/*****************************************************************************/
1143
1144/*
1145 * If there are any characters in the buffer then make sure that TX
1146 * interrupts are on and get'em out. Normally used after the putchar
1147 * routine has been called.
1148 */
1149
1150static void stl_flushchars(struct tty_struct *tty)
1151{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001152 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
Jiri Slabya0564e12006-12-08 02:38:37 -08001154 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155
Jiri Slaby615e4a72006-12-08 02:38:38 -08001156 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 return;
1158 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001159 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001161 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 return;
1163
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 stl_startrxtx(portp, -1, 1);
1165}
1166
1167/*****************************************************************************/
1168
1169static int stl_writeroom(struct tty_struct *tty)
1170{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001171 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 char *head, *tail;
1173
Jiri Slabya0564e12006-12-08 02:38:37 -08001174 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
Jiri Slaby615e4a72006-12-08 02:38:38 -08001176 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001177 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001179 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001180 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001181 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001182 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
1184 head = portp->tx.head;
1185 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001186 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187}
1188
1189/*****************************************************************************/
1190
1191/*
1192 * Return number of chars in the TX buffer. Normally we would just
1193 * calculate the number of chars in the buffer and return that, but if
1194 * the buffer is empty and TX interrupts are still on then we return
1195 * that the buffer still has 1 char in it. This way whoever called us
1196 * will not think that ALL chars have drained - since the UART still
1197 * must have some chars in it (we are busy after all).
1198 */
1199
1200static int stl_charsinbuffer(struct tty_struct *tty)
1201{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001202 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 unsigned int size;
1204 char *head, *tail;
1205
Jiri Slabya0564e12006-12-08 02:38:37 -08001206 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Jiri Slaby615e4a72006-12-08 02:38:38 -08001208 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001209 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001211 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001212 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001213 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001214 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 head = portp->tx.head;
1217 tail = portp->tx.tail;
1218 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1219 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1220 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001221 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222}
1223
1224/*****************************************************************************/
1225
1226/*
1227 * Generate the serial struct info.
1228 */
1229
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001230static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231{
1232 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001233 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
Jiri Slabya0564e12006-12-08 02:38:37 -08001235 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
1237 memset(&sio, 0, sizeof(struct serial_struct));
1238 sio.line = portp->portnr;
1239 sio.port = portp->ioaddr;
1240 sio.flags = portp->flags;
1241 sio.baud_base = portp->baud_base;
1242 sio.close_delay = portp->close_delay;
1243 sio.closing_wait = portp->closing_wait;
1244 sio.custom_divisor = portp->custom_divisor;
1245 sio.hub6 = 0;
1246 if (portp->uartp == &stl_cd1400uart) {
1247 sio.type = PORT_CIRRUS;
1248 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1249 } else {
1250 sio.type = PORT_UNKNOWN;
1251 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1252 }
1253
1254 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001255 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 sio.irq = brdp->irq;
1257
1258 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1259}
1260
1261/*****************************************************************************/
1262
1263/*
1264 * Set port according to the serial struct info.
1265 * At this point we do not do any auto-configure stuff, so we will
1266 * just quietly ignore any requests to change irq, etc.
1267 */
1268
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001269static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270{
1271 struct serial_struct sio;
1272
Jiri Slabya0564e12006-12-08 02:38:37 -08001273 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
1275 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1276 return -EFAULT;
1277 if (!capable(CAP_SYS_ADMIN)) {
1278 if ((sio.baud_base != portp->baud_base) ||
1279 (sio.close_delay != portp->close_delay) ||
1280 ((sio.flags & ~ASYNC_USR_MASK) !=
1281 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001282 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 }
1284
1285 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1286 (sio.flags & ASYNC_USR_MASK);
1287 portp->baud_base = sio.baud_base;
1288 portp->close_delay = sio.close_delay;
1289 portp->closing_wait = sio.closing_wait;
1290 portp->custom_divisor = sio.custom_divisor;
1291 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001292 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293}
1294
1295/*****************************************************************************/
1296
1297static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1298{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001299 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
Jiri Slaby615e4a72006-12-08 02:38:38 -08001301 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001302 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001304 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001305 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001307 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
1309 return stl_getsignals(portp);
1310}
1311
1312static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1313 unsigned int set, unsigned int clear)
1314{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001315 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 int rts = -1, dtr = -1;
1317
Jiri Slaby615e4a72006-12-08 02:38:38 -08001318 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001319 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001321 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001322 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001324 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
1326 if (set & TIOCM_RTS)
1327 rts = 1;
1328 if (set & TIOCM_DTR)
1329 dtr = 1;
1330 if (clear & TIOCM_RTS)
1331 rts = 0;
1332 if (clear & TIOCM_DTR)
1333 dtr = 0;
1334
1335 stl_setsignals(portp, dtr, rts);
1336 return 0;
1337}
1338
1339static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1340{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001341 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 unsigned int ival;
1343 int rc;
1344 void __user *argp = (void __user *)arg;
1345
Jiri Slabya0564e12006-12-08 02:38:37 -08001346 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1347 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Jiri Slaby615e4a72006-12-08 02:38:38 -08001349 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001350 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001352 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001353 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
1355 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1356 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1357 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001358 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 }
1360
1361 rc = 0;
1362
1363 switch (cmd) {
1364 case TIOCGSOFTCAR:
1365 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1366 (unsigned __user *) argp);
1367 break;
1368 case TIOCSSOFTCAR:
1369 if (get_user(ival, (unsigned int __user *) arg))
1370 return -EFAULT;
1371 tty->termios->c_cflag =
1372 (tty->termios->c_cflag & ~CLOCAL) |
1373 (ival ? CLOCAL : 0);
1374 break;
1375 case TIOCGSERIAL:
1376 rc = stl_getserial(portp, argp);
1377 break;
1378 case TIOCSSERIAL:
1379 rc = stl_setserial(portp, argp);
1380 break;
1381 case COM_GETPORTSTATS:
1382 rc = stl_getportstats(portp, argp);
1383 break;
1384 case COM_CLRPORTSTATS:
1385 rc = stl_clrportstats(portp, argp);
1386 break;
1387 case TIOCSERCONFIG:
1388 case TIOCSERGWILD:
1389 case TIOCSERSWILD:
1390 case TIOCSERGETLSR:
1391 case TIOCSERGSTRUCT:
1392 case TIOCSERGETMULTI:
1393 case TIOCSERSETMULTI:
1394 default:
1395 rc = -ENOIOCTLCMD;
1396 break;
1397 }
1398
Jesper Juhl014c2542006-01-15 02:37:08 +01001399 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400}
1401
1402/*****************************************************************************/
1403
1404static void stl_settermios(struct tty_struct *tty, struct termios *old)
1405{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001406 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 struct termios *tiosp;
1408
Jiri Slabya0564e12006-12-08 02:38:37 -08001409 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Jiri Slaby615e4a72006-12-08 02:38:38 -08001411 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 return;
1413 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001414 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 return;
1416
1417 tiosp = tty->termios;
1418 if ((tiosp->c_cflag == old->c_cflag) &&
1419 (tiosp->c_iflag == old->c_iflag))
1420 return;
1421
1422 stl_setport(portp, tiosp);
1423 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1424 -1);
1425 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1426 tty->hw_stopped = 0;
1427 stl_start(tty);
1428 }
1429 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1430 wake_up_interruptible(&portp->open_wait);
1431}
1432
1433/*****************************************************************************/
1434
1435/*
1436 * Attempt to flow control who ever is sending us data. Based on termios
1437 * settings use software or/and hardware flow control.
1438 */
1439
1440static void stl_throttle(struct tty_struct *tty)
1441{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001442 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Jiri Slabya0564e12006-12-08 02:38:37 -08001444 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
Jiri Slaby615e4a72006-12-08 02:38:38 -08001446 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 return;
1448 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001449 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 return;
1451 stl_flowctrl(portp, 0);
1452}
1453
1454/*****************************************************************************/
1455
1456/*
1457 * Unflow control the device sending us data...
1458 */
1459
1460static void stl_unthrottle(struct tty_struct *tty)
1461{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001462 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
Jiri Slabya0564e12006-12-08 02:38:37 -08001464 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
Jiri Slaby615e4a72006-12-08 02:38:38 -08001466 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 return;
1468 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001469 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 return;
1471 stl_flowctrl(portp, 1);
1472}
1473
1474/*****************************************************************************/
1475
1476/*
1477 * Stop the transmitter. Basically to do this we will just turn TX
1478 * interrupts off.
1479 */
1480
1481static void stl_stop(struct tty_struct *tty)
1482{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001483 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Jiri Slabya0564e12006-12-08 02:38:37 -08001485 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
Jiri Slaby615e4a72006-12-08 02:38:38 -08001487 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 return;
1489 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001490 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 return;
1492 stl_startrxtx(portp, -1, 0);
1493}
1494
1495/*****************************************************************************/
1496
1497/*
1498 * Start the transmitter again. Just turn TX interrupts back on.
1499 */
1500
1501static void stl_start(struct tty_struct *tty)
1502{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001503 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
Jiri Slabya0564e12006-12-08 02:38:37 -08001505 pr_debug("stl_start(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
Jiri Slaby615e4a72006-12-08 02:38:38 -08001507 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 return;
1509 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001510 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 return;
1512 stl_startrxtx(portp, -1, 1);
1513}
1514
1515/*****************************************************************************/
1516
1517/*
1518 * Hangup this port. This is pretty much like closing the port, only
1519 * a little more brutal. No waiting for data to drain. Shutdown the
1520 * port and maybe drop signals.
1521 */
1522
1523static void stl_hangup(struct tty_struct *tty)
1524{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001525 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
Jiri Slabya0564e12006-12-08 02:38:37 -08001527 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
Jiri Slaby615e4a72006-12-08 02:38:38 -08001529 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 return;
1531 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001532 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 return;
1534
1535 portp->flags &= ~ASYNC_INITIALIZED;
1536 stl_disableintrs(portp);
1537 if (tty->termios->c_cflag & HUPCL)
1538 stl_setsignals(portp, 0, 0);
1539 stl_enablerxtx(portp, 0, 0);
1540 stl_flushbuffer(tty);
1541 portp->istate = 0;
1542 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001543 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001545 portp->tx.buf = NULL;
1546 portp->tx.head = NULL;
1547 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001549 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1551 portp->refcount = 0;
1552 wake_up_interruptible(&portp->open_wait);
1553}
1554
1555/*****************************************************************************/
1556
1557static void stl_flushbuffer(struct tty_struct *tty)
1558{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001559 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
Jiri Slabya0564e12006-12-08 02:38:37 -08001561 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
Jiri Slaby615e4a72006-12-08 02:38:38 -08001563 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 return;
1565 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001566 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 return;
1568
1569 stl_flush(portp);
1570 tty_wakeup(tty);
1571}
1572
1573/*****************************************************************************/
1574
1575static void stl_breakctl(struct tty_struct *tty, int state)
1576{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001577 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578
Jiri Slabya0564e12006-12-08 02:38:37 -08001579 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Jiri Slaby615e4a72006-12-08 02:38:38 -08001581 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 return;
1583 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001584 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 return;
1586
1587 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1588}
1589
1590/*****************************************************************************/
1591
1592static void stl_waituntilsent(struct tty_struct *tty, int timeout)
1593{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001594 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 unsigned long tend;
1596
Jiri Slabya0564e12006-12-08 02:38:37 -08001597 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
Jiri Slaby615e4a72006-12-08 02:38:38 -08001599 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 return;
1601 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001602 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 return;
1604
1605 if (timeout == 0)
1606 timeout = HZ;
1607 tend = jiffies + timeout;
1608
1609 while (stl_datastate(portp)) {
1610 if (signal_pending(current))
1611 break;
1612 msleep_interruptible(20);
1613 if (time_after_eq(jiffies, tend))
1614 break;
1615 }
1616}
1617
1618/*****************************************************************************/
1619
1620static void stl_sendxchar(struct tty_struct *tty, char ch)
1621{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001622 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Jiri Slabya0564e12006-12-08 02:38:37 -08001624 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
Jiri Slaby615e4a72006-12-08 02:38:38 -08001626 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 return;
1628 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001629 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 return;
1631
1632 if (ch == STOP_CHAR(tty))
1633 stl_sendflow(portp, 0);
1634 else if (ch == START_CHAR(tty))
1635 stl_sendflow(portp, 1);
1636 else
1637 stl_putchar(tty, ch);
1638}
1639
1640/*****************************************************************************/
1641
1642#define MAXLINE 80
1643
1644/*
1645 * Format info for a specified port. The line is deliberately limited
1646 * to 80 characters. (If it is too long it will be truncated, if too
1647 * short then padded with spaces).
1648 */
1649
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001650static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651{
1652 char *sp;
1653 int sigs, cnt;
1654
1655 sp = pos;
1656 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1657 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1658 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1659
1660 if (portp->stats.rxframing)
1661 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1662 if (portp->stats.rxparity)
1663 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1664 if (portp->stats.rxbreaks)
1665 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1666 if (portp->stats.rxoverrun)
1667 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1668
1669 sigs = stl_getsignals(portp);
1670 cnt = sprintf(sp, "%s%s%s%s%s ",
1671 (sigs & TIOCM_RTS) ? "|RTS" : "",
1672 (sigs & TIOCM_CTS) ? "|CTS" : "",
1673 (sigs & TIOCM_DTR) ? "|DTR" : "",
1674 (sigs & TIOCM_CD) ? "|DCD" : "",
1675 (sigs & TIOCM_DSR) ? "|DSR" : "");
1676 *sp = ' ';
1677 sp += cnt;
1678
1679 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1680 *sp++ = ' ';
1681 if (cnt >= MAXLINE)
1682 pos[(MAXLINE - 2)] = '+';
1683 pos[(MAXLINE - 1)] = '\n';
1684
Jesper Juhl014c2542006-01-15 02:37:08 +01001685 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686}
1687
1688/*****************************************************************************/
1689
1690/*
1691 * Port info, read from the /proc file system.
1692 */
1693
1694static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1695{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001696 struct stlbrd *brdp;
1697 struct stlpanel *panelp;
1698 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 int brdnr, panelnr, portnr, totalport;
1700 int curoff, maxoff;
1701 char *pos;
1702
Jiri Slabya0564e12006-12-08 02:38:37 -08001703 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1704 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
1706 pos = page;
1707 totalport = 0;
1708 curoff = 0;
1709
1710 if (off == 0) {
1711 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1712 stl_drvversion);
1713 while (pos < (page + MAXLINE - 1))
1714 *pos++ = ' ';
1715 *pos++ = '\n';
1716 }
1717 curoff = MAXLINE;
1718
1719/*
1720 * We scan through for each board, panel and port. The offset is
1721 * calculated on the fly, and irrelevant ports are skipped.
1722 */
1723 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1724 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001725 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 continue;
1727 if (brdp->state == 0)
1728 continue;
1729
1730 maxoff = curoff + (brdp->nrports * MAXLINE);
1731 if (off >= maxoff) {
1732 curoff = maxoff;
1733 continue;
1734 }
1735
1736 totalport = brdnr * STL_MAXPORTS;
1737 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1738 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001739 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 continue;
1741
1742 maxoff = curoff + (panelp->nrports * MAXLINE);
1743 if (off >= maxoff) {
1744 curoff = maxoff;
1745 totalport += panelp->nrports;
1746 continue;
1747 }
1748
1749 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1750 totalport++) {
1751 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001752 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 continue;
1754 if (off >= (curoff += MAXLINE))
1755 continue;
1756 if ((pos - page + MAXLINE) > count)
1757 goto stl_readdone;
1758 pos += stl_portinfo(portp, totalport, pos);
1759 }
1760 }
1761 }
1762
1763 *eof = 1;
1764
1765stl_readdone:
1766 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001767 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768}
1769
1770/*****************************************************************************/
1771
1772/*
1773 * All board interrupts are vectored through here first. This code then
1774 * calls off to the approrpriate board interrupt handlers.
1775 */
1776
David Howells7d12e782006-10-05 14:55:46 +01001777static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001779 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
Jiri Slabya0564e12006-12-08 02:38:37 -08001781 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
1783 return IRQ_RETVAL((* brdp->isr)(brdp));
1784}
1785
1786/*****************************************************************************/
1787
1788/*
1789 * Interrupt service routine for EasyIO board types.
1790 */
1791
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001792static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001794 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 unsigned int iobase;
1796 int handled = 0;
1797
Alan Coxb65b5b52006-06-27 02:54:05 -07001798 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 panelp = brdp->panels[0];
1800 iobase = panelp->iobase;
1801 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1802 handled = 1;
1803 (* panelp->isr)(panelp, iobase);
1804 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001805 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 return handled;
1807}
1808
1809/*****************************************************************************/
1810
1811/*
1812 * Interrupt service routine for ECH-AT board types.
1813 */
1814
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001815static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001817 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 unsigned int ioaddr;
1819 int bnknr;
1820 int handled = 0;
1821
1822 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1823
1824 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1825 handled = 1;
1826 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1827 ioaddr = brdp->bnkstataddr[bnknr];
1828 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1829 panelp = brdp->bnk2panel[bnknr];
1830 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1831 }
1832 }
1833 }
1834
1835 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1836
1837 return handled;
1838}
1839
1840/*****************************************************************************/
1841
1842/*
1843 * Interrupt service routine for ECH-MCA board types.
1844 */
1845
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001846static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001848 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 unsigned int ioaddr;
1850 int bnknr;
1851 int handled = 0;
1852
1853 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1854 handled = 1;
1855 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1856 ioaddr = brdp->bnkstataddr[bnknr];
1857 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1858 panelp = brdp->bnk2panel[bnknr];
1859 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1860 }
1861 }
1862 }
1863 return handled;
1864}
1865
1866/*****************************************************************************/
1867
1868/*
1869 * Interrupt service routine for ECH-PCI board types.
1870 */
1871
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001872static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001874 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 unsigned int ioaddr;
1876 int bnknr, recheck;
1877 int handled = 0;
1878
1879 while (1) {
1880 recheck = 0;
1881 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1882 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1883 ioaddr = brdp->bnkstataddr[bnknr];
1884 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1885 panelp = brdp->bnk2panel[bnknr];
1886 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1887 recheck++;
1888 handled = 1;
1889 }
1890 }
1891 if (! recheck)
1892 break;
1893 }
1894 return handled;
1895}
1896
1897/*****************************************************************************/
1898
1899/*
1900 * Interrupt service routine for ECH-8/64-PCI board types.
1901 */
1902
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001903static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001905 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 unsigned int ioaddr;
1907 int bnknr;
1908 int handled = 0;
1909
1910 while (inb(brdp->ioctrl) & 0x1) {
1911 handled = 1;
1912 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1913 ioaddr = brdp->bnkstataddr[bnknr];
1914 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1915 panelp = brdp->bnk2panel[bnknr];
1916 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1917 }
1918 }
1919 }
1920
1921 return handled;
1922}
1923
1924/*****************************************************************************/
1925
1926/*
1927 * Service an off-level request for some channel.
1928 */
Al Viro3e577a82006-12-06 18:41:45 +00001929static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001931 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 struct tty_struct *tty;
1933 unsigned int oldsigs;
1934
Jiri Slabya0564e12006-12-08 02:38:37 -08001935 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Jiri Slaby615e4a72006-12-08 02:38:38 -08001937 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 return;
1939
1940 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001941 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 return;
1943
1944 lock_kernel();
1945 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1946 tty_wakeup(tty);
1947 }
1948 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1949 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1950 oldsigs = portp->sigs;
1951 portp->sigs = stl_getsignals(portp);
1952 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1953 wake_up_interruptible(&portp->open_wait);
1954 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1955 if (portp->flags & ASYNC_CHECK_CD)
1956 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1957 }
1958 }
1959 unlock_kernel();
1960}
1961
1962/*****************************************************************************/
1963
1964/*
1965 * Initialize all the ports on a panel.
1966 */
1967
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001968static int __init stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001970 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 int chipmask, i;
1972
Jiri Slabya0564e12006-12-08 02:38:37 -08001973 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
1975 chipmask = stl_panelinit(brdp, panelp);
1976
1977/*
1978 * All UART's are initialized (if found!). Now go through and setup
1979 * each ports data structures.
1980 */
1981 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001982 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001983 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001985 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 break;
1987 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
1989 portp->magic = STL_PORTMAGIC;
1990 portp->portnr = i;
1991 portp->brdnr = panelp->brdnr;
1992 portp->panelnr = panelp->panelnr;
1993 portp->uartp = panelp->uartp;
1994 portp->clk = brdp->clk;
1995 portp->baud_base = STL_BAUDBASE;
1996 portp->close_delay = STL_CLOSEDELAY;
1997 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001998 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 init_waitqueue_head(&portp->open_wait);
2000 init_waitqueue_head(&portp->close_wait);
2001 portp->stats.brd = portp->brdnr;
2002 portp->stats.panel = portp->panelnr;
2003 portp->stats.port = portp->portnr;
2004 panelp->ports[i] = portp;
2005 stl_portinit(brdp, panelp, portp);
2006 }
2007
2008 return(0);
2009}
2010
2011/*****************************************************************************/
2012
2013/*
2014 * Try to find and initialize an EasyIO board.
2015 */
2016
Jiri Slaby40e82652006-12-08 02:38:41 -08002017static int __init stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002019 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 unsigned int status;
2021 char *name;
2022 int rc;
2023
Jiri Slabya0564e12006-12-08 02:38:37 -08002024 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
2026 brdp->ioctrl = brdp->ioaddr1 + 1;
2027 brdp->iostatus = brdp->ioaddr1 + 2;
2028
2029 status = inb(brdp->iostatus);
2030 if ((status & EIO_IDBITMASK) == EIO_MK3)
2031 brdp->ioctrl++;
2032
2033/*
2034 * Handle board specific stuff now. The real difference is PCI
2035 * or not PCI.
2036 */
2037 if (brdp->brdtype == BRD_EASYIOPCI) {
2038 brdp->iosize1 = 0x80;
2039 brdp->iosize2 = 0x80;
2040 name = "serial(EIO-PCI)";
2041 outb(0x41, (brdp->ioaddr2 + 0x4c));
2042 } else {
2043 brdp->iosize1 = 8;
2044 name = "serial(EIO)";
2045 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2046 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2047 printk("STALLION: invalid irq=%d for brd=%d\n",
2048 brdp->irq, brdp->brdnr);
2049 return(-EINVAL);
2050 }
2051 outb((stl_vecmap[brdp->irq] | EIO_0WS |
2052 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
2053 brdp->ioctrl);
2054 }
2055
2056 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2057 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2058 "%x conflicts with another device\n", brdp->brdnr,
2059 brdp->ioaddr1);
2060 return(-EBUSY);
2061 }
2062
2063 if (brdp->iosize2 > 0)
2064 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2065 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2066 "address %x conflicts with another device\n",
2067 brdp->brdnr, brdp->ioaddr2);
2068 printk(KERN_WARNING "STALLION: Warning, also "
2069 "releasing board %d I/O address %x \n",
2070 brdp->brdnr, brdp->ioaddr1);
2071 release_region(brdp->ioaddr1, brdp->iosize1);
2072 return(-EBUSY);
2073 }
2074
2075/*
2076 * Everything looks OK, so let's go ahead and probe for the hardware.
2077 */
2078 brdp->clk = CD1400_CLK;
2079 brdp->isr = stl_eiointr;
2080
2081 switch (status & EIO_IDBITMASK) {
2082 case EIO_8PORTM:
2083 brdp->clk = CD1400_CLK8M;
2084 /* fall thru */
2085 case EIO_8PORTRS:
2086 case EIO_8PORTDI:
2087 brdp->nrports = 8;
2088 break;
2089 case EIO_4PORTRS:
2090 brdp->nrports = 4;
2091 break;
2092 case EIO_MK3:
2093 switch (status & EIO_BRDMASK) {
2094 case ID_BRD4:
2095 brdp->nrports = 4;
2096 break;
2097 case ID_BRD8:
2098 brdp->nrports = 8;
2099 break;
2100 case ID_BRD16:
2101 brdp->nrports = 16;
2102 break;
2103 default:
2104 return(-ENODEV);
2105 }
2106 break;
2107 default:
2108 return(-ENODEV);
2109 }
2110
2111/*
2112 * We have verified that the board is actually present, so now we
2113 * can complete the setup.
2114 */
2115
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002116 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002117 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002119 "(size=%Zd)\n", sizeof(struct stlpanel));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002120 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122
2123 panelp->magic = STL_PANELMAGIC;
2124 panelp->brdnr = brdp->brdnr;
2125 panelp->panelnr = 0;
2126 panelp->nrports = brdp->nrports;
2127 panelp->iobase = brdp->ioaddr1;
2128 panelp->hwid = status;
2129 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002130 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 panelp->isr = stl_sc26198intr;
2132 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002133 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 panelp->isr = stl_cd1400eiointr;
2135 }
2136
2137 brdp->panels[0] = panelp;
2138 brdp->nrpanels = 1;
2139 brdp->state |= BRD_FOUND;
2140 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002141 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 printk("STALLION: failed to register interrupt "
2143 "routine for %s irq=%d\n", name, brdp->irq);
2144 rc = -ENODEV;
2145 } else {
2146 rc = 0;
2147 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002148 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149}
2150
2151/*****************************************************************************/
2152
2153/*
2154 * Try to find an ECH board and initialize it. This code is capable of
2155 * dealing with all types of ECH board.
2156 */
2157
Jiri Slaby40e82652006-12-08 02:38:41 -08002158static int __init stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002160 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 unsigned int status, nxtid, ioaddr, conflict;
2162 int panelnr, banknr, i;
2163 char *name;
2164
Jiri Slabya0564e12006-12-08 02:38:37 -08002165 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
2167 status = 0;
2168 conflict = 0;
2169
2170/*
2171 * Set up the initial board register contents for boards. This varies a
2172 * bit between the different board types. So we need to handle each
2173 * separately. Also do a check that the supplied IRQ is good.
2174 */
2175 switch (brdp->brdtype) {
2176
2177 case BRD_ECH:
2178 brdp->isr = stl_echatintr;
2179 brdp->ioctrl = brdp->ioaddr1 + 1;
2180 brdp->iostatus = brdp->ioaddr1 + 1;
2181 status = inb(brdp->iostatus);
2182 if ((status & ECH_IDBITMASK) != ECH_ID)
2183 return(-ENODEV);
2184 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2185 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2186 printk("STALLION: invalid irq=%d for brd=%d\n",
2187 brdp->irq, brdp->brdnr);
2188 return(-EINVAL);
2189 }
2190 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2191 status |= (stl_vecmap[brdp->irq] << 1);
2192 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2193 brdp->ioctrlval = ECH_INTENABLE |
2194 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2195 for (i = 0; (i < 10); i++)
2196 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2197 brdp->iosize1 = 2;
2198 brdp->iosize2 = 32;
2199 name = "serial(EC8/32)";
2200 outb(status, brdp->ioaddr1);
2201 break;
2202
2203 case BRD_ECHMC:
2204 brdp->isr = stl_echmcaintr;
2205 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2206 brdp->iostatus = brdp->ioctrl;
2207 status = inb(brdp->iostatus);
2208 if ((status & ECH_IDBITMASK) != ECH_ID)
2209 return(-ENODEV);
2210 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2211 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2212 printk("STALLION: invalid irq=%d for brd=%d\n",
2213 brdp->irq, brdp->brdnr);
2214 return(-EINVAL);
2215 }
2216 outb(ECHMC_BRDRESET, brdp->ioctrl);
2217 outb(ECHMC_INTENABLE, brdp->ioctrl);
2218 brdp->iosize1 = 64;
2219 name = "serial(EC8/32-MC)";
2220 break;
2221
2222 case BRD_ECHPCI:
2223 brdp->isr = stl_echpciintr;
2224 brdp->ioctrl = brdp->ioaddr1 + 2;
2225 brdp->iosize1 = 4;
2226 brdp->iosize2 = 8;
2227 name = "serial(EC8/32-PCI)";
2228 break;
2229
2230 case BRD_ECH64PCI:
2231 brdp->isr = stl_echpci64intr;
2232 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2233 outb(0x43, (brdp->ioaddr1 + 0x4c));
2234 brdp->iosize1 = 0x80;
2235 brdp->iosize2 = 0x80;
2236 name = "serial(EC8/64-PCI)";
2237 break;
2238
2239 default:
2240 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
2241 return(-EINVAL);
2242 break;
2243 }
2244
2245/*
2246 * Check boards for possible IO address conflicts and return fail status
2247 * if an IO conflict found.
2248 */
2249 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2250 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2251 "%x conflicts with another device\n", brdp->brdnr,
2252 brdp->ioaddr1);
2253 return(-EBUSY);
2254 }
2255
2256 if (brdp->iosize2 > 0)
2257 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2258 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2259 "address %x conflicts with another device\n",
2260 brdp->brdnr, brdp->ioaddr2);
2261 printk(KERN_WARNING "STALLION: Warning, also "
2262 "releasing board %d I/O address %x \n",
2263 brdp->brdnr, brdp->ioaddr1);
2264 release_region(brdp->ioaddr1, brdp->iosize1);
2265 return(-EBUSY);
2266 }
2267
2268/*
2269 * Scan through the secondary io address space looking for panels.
2270 * As we find'em allocate and initialize panel structures for each.
2271 */
2272 brdp->clk = CD1400_CLK;
2273 brdp->hwid = status;
2274
2275 ioaddr = brdp->ioaddr2;
2276 banknr = 0;
2277 panelnr = 0;
2278 nxtid = 0;
2279
2280 for (i = 0; (i < STL_MAXPANELS); i++) {
2281 if (brdp->brdtype == BRD_ECHPCI) {
2282 outb(nxtid, brdp->ioctrl);
2283 ioaddr = brdp->ioaddr2;
2284 }
2285 status = inb(ioaddr + ECH_PNLSTATUS);
2286 if ((status & ECH_PNLIDMASK) != nxtid)
2287 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002288 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002289 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002291 "(size=%Zd)\n", sizeof(struct stlpanel));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 break;
2293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 panelp->magic = STL_PANELMAGIC;
2295 panelp->brdnr = brdp->brdnr;
2296 panelp->panelnr = panelnr;
2297 panelp->iobase = ioaddr;
2298 panelp->pagenr = nxtid;
2299 panelp->hwid = status;
2300 brdp->bnk2panel[banknr] = panelp;
2301 brdp->bnkpageaddr[banknr] = nxtid;
2302 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2303
2304 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002305 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 panelp->isr = stl_sc26198intr;
2307 if (status & ECH_PNL16PORT) {
2308 panelp->nrports = 16;
2309 brdp->bnk2panel[banknr] = panelp;
2310 brdp->bnkpageaddr[banknr] = nxtid;
2311 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2312 ECH_PNLSTATUS;
2313 } else {
2314 panelp->nrports = 8;
2315 }
2316 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002317 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 panelp->isr = stl_cd1400echintr;
2319 if (status & ECH_PNL16PORT) {
2320 panelp->nrports = 16;
2321 panelp->ackmask = 0x80;
2322 if (brdp->brdtype != BRD_ECHPCI)
2323 ioaddr += EREG_BANKSIZE;
2324 brdp->bnk2panel[banknr] = panelp;
2325 brdp->bnkpageaddr[banknr] = ++nxtid;
2326 brdp->bnkstataddr[banknr++] = ioaddr +
2327 ECH_PNLSTATUS;
2328 } else {
2329 panelp->nrports = 8;
2330 panelp->ackmask = 0xc0;
2331 }
2332 }
2333
2334 nxtid++;
2335 ioaddr += EREG_BANKSIZE;
2336 brdp->nrports += panelp->nrports;
2337 brdp->panels[panelnr++] = panelp;
2338 if ((brdp->brdtype != BRD_ECHPCI) &&
2339 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
2340 break;
2341 }
2342
2343 brdp->nrpanels = panelnr;
2344 brdp->nrbnks = banknr;
2345 if (brdp->brdtype == BRD_ECH)
2346 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2347
2348 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002349 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 printk("STALLION: failed to register interrupt "
2351 "routine for %s irq=%d\n", name, brdp->irq);
2352 i = -ENODEV;
2353 } else {
2354 i = 0;
2355 }
2356
2357 return(i);
2358}
2359
2360/*****************************************************************************/
2361
2362/*
2363 * Initialize and configure the specified board.
2364 * Scan through all the boards in the configuration and see what we
2365 * can find. Handle EIO and the ECH boards a little differently here
2366 * since the initial search and setup is very different.
2367 */
2368
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002369static int __init stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370{
2371 int i;
2372
Jiri Slabya0564e12006-12-08 02:38:37 -08002373 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
2375 switch (brdp->brdtype) {
2376 case BRD_EASYIO:
2377 case BRD_EASYIOPCI:
2378 stl_initeio(brdp);
2379 break;
2380 case BRD_ECH:
2381 case BRD_ECHMC:
2382 case BRD_ECHPCI:
2383 case BRD_ECH64PCI:
2384 stl_initech(brdp);
2385 break;
2386 default:
2387 printk("STALLION: board=%d is unknown board type=%d\n",
2388 brdp->brdnr, brdp->brdtype);
2389 return(ENODEV);
2390 }
2391
2392 stl_brds[brdp->brdnr] = brdp;
2393 if ((brdp->state & BRD_FOUND) == 0) {
2394 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2395 stl_brdnames[brdp->brdtype], brdp->brdnr,
2396 brdp->ioaddr1, brdp->irq);
2397 return(ENODEV);
2398 }
2399
2400 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002401 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 stl_initports(brdp, brdp->panels[i]);
2403
2404 printk("STALLION: %s found, board=%d io=%x irq=%d "
2405 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2406 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2407 brdp->nrports);
2408 return(0);
2409}
2410
2411/*****************************************************************************/
2412
2413/*
2414 * Find the next available board number that is free.
2415 */
2416
Jiri Slaby40e82652006-12-08 02:38:41 -08002417static int __init stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418{
2419 int i;
2420
2421 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002422 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 if (i >= stl_nrbrds)
2424 stl_nrbrds = i + 1;
2425 return(i);
2426 }
2427 }
2428 return(-1);
2429}
2430
2431/*****************************************************************************/
2432
2433#ifdef CONFIG_PCI
2434
2435/*
2436 * We have a Stallion board. Allocate a board structure and
2437 * initialize it. Read its IO and IRQ resources from PCI
2438 * configuration space.
2439 */
2440
Jiri Slaby40e82652006-12-08 02:38:41 -08002441static int __init stl_initpcibrd(int brdtype, struct pci_dev *devp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002443 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444
Jiri Slabya0564e12006-12-08 02:38:37 -08002445 pr_debug("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 devp->bus->number, devp->devfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
2448 if (pci_enable_device(devp))
2449 return(-EIO);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002450 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 return(-ENOMEM);
2452 if ((brdp->brdnr = stl_getbrdnr()) < 0) {
2453 printk("STALLION: too many boards found, "
2454 "maximum supported %d\n", STL_MAXBRDS);
2455 return(0);
2456 }
2457 brdp->brdtype = brdtype;
2458
2459/*
2460 * Different Stallion boards use the BAR registers in different ways,
2461 * so set up io addresses based on board type.
2462 */
Jiri Slabya0564e12006-12-08 02:38:37 -08002463 pr_debug("%s(%d): BAR[]=%Lx,%Lx,%Lx,%Lx IRQ=%x\n", __FILE__, __LINE__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 pci_resource_start(devp, 0), pci_resource_start(devp, 1),
2465 pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466
2467/*
2468 * We have all resources from the board, so let's setup the actual
2469 * board structure now.
2470 */
2471 switch (brdtype) {
2472 case BRD_ECHPCI:
2473 brdp->ioaddr2 = pci_resource_start(devp, 0);
2474 brdp->ioaddr1 = pci_resource_start(devp, 1);
2475 break;
2476 case BRD_ECH64PCI:
2477 brdp->ioaddr2 = pci_resource_start(devp, 2);
2478 brdp->ioaddr1 = pci_resource_start(devp, 1);
2479 break;
2480 case BRD_EASYIOPCI:
2481 brdp->ioaddr1 = pci_resource_start(devp, 2);
2482 brdp->ioaddr2 = pci_resource_start(devp, 1);
2483 break;
2484 default:
2485 printk("STALLION: unknown PCI board type=%d\n", brdtype);
2486 break;
2487 }
2488
2489 brdp->irq = devp->irq;
2490 stl_brdinit(brdp);
2491
2492 return(0);
2493}
2494
2495/*****************************************************************************/
2496
2497/*
2498 * Find all Stallion PCI boards that might be installed. Initialize each
2499 * one as it is found.
2500 */
2501
2502
Jiri Slaby40e82652006-12-08 02:38:41 -08002503static int __init stl_findpcibrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504{
2505 struct pci_dev *dev = NULL;
2506 int i, rc;
2507
Jiri Slabya0564e12006-12-08 02:38:37 -08002508 pr_debug("stl_findpcibrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
2510 for (i = 0; (i < stl_nrpcibrds); i++)
2511 while ((dev = pci_find_device(stl_pcibrds[i].vendid,
2512 stl_pcibrds[i].devid, dev))) {
2513
2514/*
2515 * Found a device on the PCI bus that has our vendor and
2516 * device ID. Need to check now that it is really us.
2517 */
2518 if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
2519 continue;
2520
2521 rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
2522 if (rc)
2523 return(rc);
2524 }
2525
2526 return(0);
2527}
2528
2529#endif
2530
2531/*****************************************************************************/
2532
2533/*
2534 * Scan through all the boards in the configuration and see what we
2535 * can find. Handle EIO and the ECH boards a little differently here
2536 * since the initial search and setup is too different.
2537 */
2538
Jiri Slaby40e82652006-12-08 02:38:41 -08002539static int __init stl_initbrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002541 struct stlbrd *brdp;
2542 struct stlconf *confp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 int i;
2544
Jiri Slabya0564e12006-12-08 02:38:37 -08002545 pr_debug("stl_initbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
2547 if (stl_nrbrds > STL_MAXBRDS) {
2548 printk("STALLION: too many boards in configuration table, "
2549 "truncating to %d\n", STL_MAXBRDS);
2550 stl_nrbrds = STL_MAXBRDS;
2551 }
2552
2553/*
2554 * Firstly scan the list of static boards configured. Allocate
2555 * resources and initialize the boards as found.
2556 */
2557 for (i = 0; (i < stl_nrbrds); i++) {
2558 confp = &stl_brdconf[i];
2559 stl_parsebrd(confp, stl_brdsp[i]);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002560 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 return(-ENOMEM);
2562 brdp->brdnr = i;
2563 brdp->brdtype = confp->brdtype;
2564 brdp->ioaddr1 = confp->ioaddr1;
2565 brdp->ioaddr2 = confp->ioaddr2;
2566 brdp->irq = confp->irq;
2567 brdp->irqtype = confp->irqtype;
2568 stl_brdinit(brdp);
2569 }
2570
2571/*
2572 * Find any dynamically supported boards. That is via module load
2573 * line options or auto-detected on the PCI bus.
2574 */
2575 stl_argbrds();
2576#ifdef CONFIG_PCI
2577 stl_findpcibrds();
2578#endif
2579
2580 return(0);
2581}
2582
2583/*****************************************************************************/
2584
2585/*
2586 * Return the board stats structure to user app.
2587 */
2588
2589static int stl_getbrdstats(combrd_t __user *bp)
2590{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002591 struct stlbrd *brdp;
2592 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 int i;
2594
2595 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2596 return -EFAULT;
2597 if (stl_brdstats.brd >= STL_MAXBRDS)
2598 return(-ENODEV);
2599 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002600 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 return(-ENODEV);
2602
2603 memset(&stl_brdstats, 0, sizeof(combrd_t));
2604 stl_brdstats.brd = brdp->brdnr;
2605 stl_brdstats.type = brdp->brdtype;
2606 stl_brdstats.hwid = brdp->hwid;
2607 stl_brdstats.state = brdp->state;
2608 stl_brdstats.ioaddr = brdp->ioaddr1;
2609 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2610 stl_brdstats.irq = brdp->irq;
2611 stl_brdstats.nrpanels = brdp->nrpanels;
2612 stl_brdstats.nrports = brdp->nrports;
2613 for (i = 0; (i < brdp->nrpanels); i++) {
2614 panelp = brdp->panels[i];
2615 stl_brdstats.panels[i].panel = i;
2616 stl_brdstats.panels[i].hwid = panelp->hwid;
2617 stl_brdstats.panels[i].nrports = panelp->nrports;
2618 }
2619
2620 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2621}
2622
2623/*****************************************************************************/
2624
2625/*
2626 * Resolve the referenced port number into a port struct pointer.
2627 */
2628
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002629static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002631 struct stlbrd *brdp;
2632 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
2634 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002635 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002637 if (brdp == NULL)
2638 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002640 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002642 if (panelp == NULL)
2643 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002645 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 return(panelp->ports[portnr]);
2647}
2648
2649/*****************************************************************************/
2650
2651/*
2652 * Return the port stats structure to user app. A NULL port struct
2653 * pointer passed in means that we need to find out from the app
2654 * what port to get stats for (used through board control device).
2655 */
2656
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002657static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658{
2659 unsigned char *head, *tail;
2660 unsigned long flags;
2661
2662 if (!portp) {
2663 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2664 return -EFAULT;
2665 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2666 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002667 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 return(-ENODEV);
2669 }
2670
2671 portp->stats.state = portp->istate;
2672 portp->stats.flags = portp->flags;
2673 portp->stats.hwid = portp->hwid;
2674
2675 portp->stats.ttystate = 0;
2676 portp->stats.cflags = 0;
2677 portp->stats.iflags = 0;
2678 portp->stats.oflags = 0;
2679 portp->stats.lflags = 0;
2680 portp->stats.rxbuffered = 0;
2681
Alan Coxb65b5b52006-06-27 02:54:05 -07002682 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002683 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 if (portp->tty->driver_data == portp) {
2685 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002686 /* No longer available as a statistic */
2687 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002688 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 portp->stats.cflags = portp->tty->termios->c_cflag;
2690 portp->stats.iflags = portp->tty->termios->c_iflag;
2691 portp->stats.oflags = portp->tty->termios->c_oflag;
2692 portp->stats.lflags = portp->tty->termios->c_lflag;
2693 }
2694 }
2695 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002696 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697
2698 head = portp->tx.head;
2699 tail = portp->tx.tail;
2700 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2701 (STL_TXBUFSIZE - (tail - head)));
2702
2703 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2704
2705 return copy_to_user(cp, &portp->stats,
2706 sizeof(comstats_t)) ? -EFAULT : 0;
2707}
2708
2709/*****************************************************************************/
2710
2711/*
2712 * Clear the port stats structure. We also return it zeroed out...
2713 */
2714
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002715static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716{
2717 if (!portp) {
2718 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2719 return -EFAULT;
2720 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2721 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002722 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 return(-ENODEV);
2724 }
2725
2726 memset(&portp->stats, 0, sizeof(comstats_t));
2727 portp->stats.brd = portp->brdnr;
2728 portp->stats.panel = portp->panelnr;
2729 portp->stats.port = portp->portnr;
2730 return copy_to_user(cp, &portp->stats,
2731 sizeof(comstats_t)) ? -EFAULT : 0;
2732}
2733
2734/*****************************************************************************/
2735
2736/*
2737 * Return the entire driver ports structure to a user app.
2738 */
2739
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002740static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002742 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002744 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 return -EFAULT;
2746 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2747 stl_dummyport.portnr);
2748 if (!portp)
2749 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002750 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751}
2752
2753/*****************************************************************************/
2754
2755/*
2756 * Return the entire driver board structure to a user app.
2757 */
2758
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002759static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002761 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002763 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 return -EFAULT;
2765 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2766 return -ENODEV;
2767 brdp = stl_brds[stl_dummybrd.brdnr];
2768 if (!brdp)
2769 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002770 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771}
2772
2773/*****************************************************************************/
2774
2775/*
2776 * The "staliomem" device is also required to do some special operations
2777 * on the board and/or ports. In this driver it is mostly used for stats
2778 * collection.
2779 */
2780
2781static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2782{
2783 int brdnr, rc;
2784 void __user *argp = (void __user *)arg;
2785
Jiri Slabya0564e12006-12-08 02:38:37 -08002786 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787
2788 brdnr = iminor(ip);
2789 if (brdnr >= STL_MAXBRDS)
2790 return(-ENODEV);
2791 rc = 0;
2792
2793 switch (cmd) {
2794 case COM_GETPORTSTATS:
2795 rc = stl_getportstats(NULL, argp);
2796 break;
2797 case COM_CLRPORTSTATS:
2798 rc = stl_clrportstats(NULL, argp);
2799 break;
2800 case COM_GETBRDSTATS:
2801 rc = stl_getbrdstats(argp);
2802 break;
2803 case COM_READPORT:
2804 rc = stl_getportstruct(argp);
2805 break;
2806 case COM_READBOARD:
2807 rc = stl_getbrdstruct(argp);
2808 break;
2809 default:
2810 rc = -ENOIOCTLCMD;
2811 break;
2812 }
2813
2814 return(rc);
2815}
2816
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002817static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 .open = stl_open,
2819 .close = stl_close,
2820 .write = stl_write,
2821 .put_char = stl_putchar,
2822 .flush_chars = stl_flushchars,
2823 .write_room = stl_writeroom,
2824 .chars_in_buffer = stl_charsinbuffer,
2825 .ioctl = stl_ioctl,
2826 .set_termios = stl_settermios,
2827 .throttle = stl_throttle,
2828 .unthrottle = stl_unthrottle,
2829 .stop = stl_stop,
2830 .start = stl_start,
2831 .hangup = stl_hangup,
2832 .flush_buffer = stl_flushbuffer,
2833 .break_ctl = stl_breakctl,
2834 .wait_until_sent = stl_waituntilsent,
2835 .send_xchar = stl_sendxchar,
2836 .read_proc = stl_readproc,
2837 .tiocmget = stl_tiocmget,
2838 .tiocmset = stl_tiocmset,
2839};
2840
2841/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842/* CD1400 HARDWARE FUNCTIONS */
2843/*****************************************************************************/
2844
2845/*
2846 * These functions get/set/update the registers of the cd1400 UARTs.
2847 * Access to the cd1400 registers is via an address/data io port pair.
2848 * (Maybe should make this inline...)
2849 */
2850
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002851static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852{
2853 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002854 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855}
2856
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002857static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858{
2859 outb((regnr + portp->uartaddr), portp->ioaddr);
2860 outb(value, portp->ioaddr + EREG_DATA);
2861}
2862
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002863static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864{
2865 outb((regnr + portp->uartaddr), portp->ioaddr);
2866 if (inb(portp->ioaddr + EREG_DATA) != value) {
2867 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002868 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002870 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871}
2872
2873/*****************************************************************************/
2874
2875/*
2876 * Inbitialize the UARTs in a panel. We don't care what sort of board
2877 * these ports are on - since the port io registers are almost
2878 * identical when dealing with ports.
2879 */
2880
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002881static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882{
2883 unsigned int gfrcr;
2884 int chipmask, i, j;
2885 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002886 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
Jiri Slabya0564e12006-12-08 02:38:37 -08002888 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889
Alan Coxb65b5b52006-06-27 02:54:05 -07002890 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 BRDENABLE(panelp->brdnr, panelp->pagenr);
2892
2893/*
2894 * Check that each chip is present and started up OK.
2895 */
2896 chipmask = 0;
2897 nrchips = panelp->nrports / CD1400_PORTS;
2898 for (i = 0; (i < nrchips); i++) {
2899 if (brdp->brdtype == BRD_ECHPCI) {
2900 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2901 ioaddr = panelp->iobase;
2902 } else {
2903 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2904 }
2905 uartaddr = (i & 0x01) ? 0x080 : 0;
2906 outb((GFRCR + uartaddr), ioaddr);
2907 outb(0, (ioaddr + EREG_DATA));
2908 outb((CCR + uartaddr), ioaddr);
2909 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2910 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2911 outb((GFRCR + uartaddr), ioaddr);
2912 for (j = 0; (j < CCR_MAXWAIT); j++) {
2913 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2914 break;
2915 }
2916 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2917 printk("STALLION: cd1400 not responding, "
2918 "brd=%d panel=%d chip=%d\n",
2919 panelp->brdnr, panelp->panelnr, i);
2920 continue;
2921 }
2922 chipmask |= (0x1 << i);
2923 outb((PPR + uartaddr), ioaddr);
2924 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2925 }
2926
2927 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002928 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002929 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930}
2931
2932/*****************************************************************************/
2933
2934/*
2935 * Initialize hardware specific port registers.
2936 */
2937
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002938static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939{
Alan Coxb65b5b52006-06-27 02:54:05 -07002940 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002941 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2942 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943
Jiri Slaby615e4a72006-12-08 02:38:38 -08002944 if ((brdp == NULL) || (panelp == NULL) ||
2945 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 return;
2947
Alan Coxb65b5b52006-06-27 02:54:05 -07002948 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2950 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2951 portp->uartaddr = (portp->portnr & 0x04) << 5;
2952 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2953
2954 BRDENABLE(portp->brdnr, portp->pagenr);
2955 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2956 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2957 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2958 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002959 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960}
2961
2962/*****************************************************************************/
2963
2964/*
2965 * Wait for the command register to be ready. We will poll this,
2966 * since it won't usually take too long to be ready.
2967 */
2968
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002969static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970{
2971 int i;
2972
2973 for (i = 0; (i < CCR_MAXWAIT); i++) {
2974 if (stl_cd1400getreg(portp, CCR) == 0) {
2975 return;
2976 }
2977 }
2978
2979 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2980 portp->portnr, portp->panelnr, portp->brdnr);
2981}
2982
2983/*****************************************************************************/
2984
2985/*
2986 * Set up the cd1400 registers for a port based on the termios port
2987 * settings.
2988 */
2989
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002990static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002992 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 unsigned long flags;
2994 unsigned int clkdiv, baudrate;
2995 unsigned char cor1, cor2, cor3;
2996 unsigned char cor4, cor5, ccr;
2997 unsigned char srer, sreron, sreroff;
2998 unsigned char mcor1, mcor2, rtpr;
2999 unsigned char clk, div;
3000
3001 cor1 = 0;
3002 cor2 = 0;
3003 cor3 = 0;
3004 cor4 = 0;
3005 cor5 = 0;
3006 ccr = 0;
3007 rtpr = 0;
3008 clk = 0;
3009 div = 0;
3010 mcor1 = 0;
3011 mcor2 = 0;
3012 sreron = 0;
3013 sreroff = 0;
3014
3015 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003016 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 return;
3018
3019/*
3020 * Set up the RX char ignore mask with those RX error types we
3021 * can ignore. We can get the cd1400 to help us out a little here,
3022 * it will ignore parity errors and breaks for us.
3023 */
3024 portp->rxignoremsk = 0;
3025 if (tiosp->c_iflag & IGNPAR) {
3026 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
3027 cor1 |= COR1_PARIGNORE;
3028 }
3029 if (tiosp->c_iflag & IGNBRK) {
3030 portp->rxignoremsk |= ST_BREAK;
3031 cor4 |= COR4_IGNBRK;
3032 }
3033
3034 portp->rxmarkmsk = ST_OVERRUN;
3035 if (tiosp->c_iflag & (INPCK | PARMRK))
3036 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
3037 if (tiosp->c_iflag & BRKINT)
3038 portp->rxmarkmsk |= ST_BREAK;
3039
3040/*
3041 * Go through the char size, parity and stop bits and set all the
3042 * option register appropriately.
3043 */
3044 switch (tiosp->c_cflag & CSIZE) {
3045 case CS5:
3046 cor1 |= COR1_CHL5;
3047 break;
3048 case CS6:
3049 cor1 |= COR1_CHL6;
3050 break;
3051 case CS7:
3052 cor1 |= COR1_CHL7;
3053 break;
3054 default:
3055 cor1 |= COR1_CHL8;
3056 break;
3057 }
3058
3059 if (tiosp->c_cflag & CSTOPB)
3060 cor1 |= COR1_STOP2;
3061 else
3062 cor1 |= COR1_STOP1;
3063
3064 if (tiosp->c_cflag & PARENB) {
3065 if (tiosp->c_cflag & PARODD)
3066 cor1 |= (COR1_PARENB | COR1_PARODD);
3067 else
3068 cor1 |= (COR1_PARENB | COR1_PAREVEN);
3069 } else {
3070 cor1 |= COR1_PARNONE;
3071 }
3072
3073/*
3074 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
3075 * space for hardware flow control and the like. This should be set to
3076 * VMIN. Also here we will set the RX data timeout to 10ms - this should
3077 * really be based on VTIME.
3078 */
3079 cor3 |= FIFO_RXTHRESHOLD;
3080 rtpr = 2;
3081
3082/*
3083 * Calculate the baud rate timers. For now we will just assume that
3084 * the input and output baud are the same. Could have used a baud
3085 * table here, but this way we can generate virtually any baud rate
3086 * we like!
3087 */
3088 baudrate = tiosp->c_cflag & CBAUD;
3089 if (baudrate & CBAUDEX) {
3090 baudrate &= ~CBAUDEX;
3091 if ((baudrate < 1) || (baudrate > 4))
3092 tiosp->c_cflag &= ~CBAUDEX;
3093 else
3094 baudrate += 15;
3095 }
3096 baudrate = stl_baudrates[baudrate];
3097 if ((tiosp->c_cflag & CBAUD) == B38400) {
3098 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3099 baudrate = 57600;
3100 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3101 baudrate = 115200;
3102 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3103 baudrate = 230400;
3104 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3105 baudrate = 460800;
3106 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3107 baudrate = (portp->baud_base / portp->custom_divisor);
3108 }
3109 if (baudrate > STL_CD1400MAXBAUD)
3110 baudrate = STL_CD1400MAXBAUD;
3111
3112 if (baudrate > 0) {
3113 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
3114 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
3115 if (clkdiv < 0x100)
3116 break;
3117 }
3118 div = (unsigned char) clkdiv;
3119 }
3120
3121/*
3122 * Check what form of modem signaling is required and set it up.
3123 */
3124 if ((tiosp->c_cflag & CLOCAL) == 0) {
3125 mcor1 |= MCOR1_DCD;
3126 mcor2 |= MCOR2_DCD;
3127 sreron |= SRER_MODEM;
3128 portp->flags |= ASYNC_CHECK_CD;
3129 } else {
3130 portp->flags &= ~ASYNC_CHECK_CD;
3131 }
3132
3133/*
3134 * Setup cd1400 enhanced modes if we can. In particular we want to
3135 * handle as much of the flow control as possible automatically. As
3136 * well as saving a few CPU cycles it will also greatly improve flow
3137 * control reliability.
3138 */
3139 if (tiosp->c_iflag & IXON) {
3140 cor2 |= COR2_TXIBE;
3141 cor3 |= COR3_SCD12;
3142 if (tiosp->c_iflag & IXANY)
3143 cor2 |= COR2_IXM;
3144 }
3145
3146 if (tiosp->c_cflag & CRTSCTS) {
3147 cor2 |= COR2_CTSAE;
3148 mcor1 |= FIFO_RTSTHRESHOLD;
3149 }
3150
3151/*
3152 * All cd1400 register values calculated so go through and set
3153 * them all up.
3154 */
3155
Jiri Slabya0564e12006-12-08 02:38:37 -08003156 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003158 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003160 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003162 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3163 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3165 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166
Alan Coxb65b5b52006-06-27 02:54:05 -07003167 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 BRDENABLE(portp->brdnr, portp->pagenr);
3169 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3170 srer = stl_cd1400getreg(portp, SRER);
3171 stl_cd1400setreg(portp, SRER, 0);
3172 if (stl_cd1400updatereg(portp, COR1, cor1))
3173 ccr = 1;
3174 if (stl_cd1400updatereg(portp, COR2, cor2))
3175 ccr = 1;
3176 if (stl_cd1400updatereg(portp, COR3, cor3))
3177 ccr = 1;
3178 if (ccr) {
3179 stl_cd1400ccrwait(portp);
3180 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3181 }
3182 stl_cd1400setreg(portp, COR4, cor4);
3183 stl_cd1400setreg(portp, COR5, cor5);
3184 stl_cd1400setreg(portp, MCOR1, mcor1);
3185 stl_cd1400setreg(portp, MCOR2, mcor2);
3186 if (baudrate > 0) {
3187 stl_cd1400setreg(portp, TCOR, clk);
3188 stl_cd1400setreg(portp, TBPR, div);
3189 stl_cd1400setreg(portp, RCOR, clk);
3190 stl_cd1400setreg(portp, RBPR, div);
3191 }
3192 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3193 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3194 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3195 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3196 stl_cd1400setreg(portp, RTPR, rtpr);
3197 mcor1 = stl_cd1400getreg(portp, MSVR1);
3198 if (mcor1 & MSVR1_DCD)
3199 portp->sigs |= TIOCM_CD;
3200 else
3201 portp->sigs &= ~TIOCM_CD;
3202 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3203 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003204 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205}
3206
3207/*****************************************************************************/
3208
3209/*
3210 * Set the state of the DTR and RTS signals.
3211 */
3212
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003213static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214{
3215 unsigned char msvr1, msvr2;
3216 unsigned long flags;
3217
Jiri Slabya0564e12006-12-08 02:38:37 -08003218 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3219 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220
3221 msvr1 = 0;
3222 msvr2 = 0;
3223 if (dtr > 0)
3224 msvr1 = MSVR1_DTR;
3225 if (rts > 0)
3226 msvr2 = MSVR2_RTS;
3227
Alan Coxb65b5b52006-06-27 02:54:05 -07003228 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 BRDENABLE(portp->brdnr, portp->pagenr);
3230 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3231 if (rts >= 0)
3232 stl_cd1400setreg(portp, MSVR2, msvr2);
3233 if (dtr >= 0)
3234 stl_cd1400setreg(portp, MSVR1, msvr1);
3235 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003236 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237}
3238
3239/*****************************************************************************/
3240
3241/*
3242 * Return the state of the signals.
3243 */
3244
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003245static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246{
3247 unsigned char msvr1, msvr2;
3248 unsigned long flags;
3249 int sigs;
3250
Jiri Slabya0564e12006-12-08 02:38:37 -08003251 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252
Alan Coxb65b5b52006-06-27 02:54:05 -07003253 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 BRDENABLE(portp->brdnr, portp->pagenr);
3255 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3256 msvr1 = stl_cd1400getreg(portp, MSVR1);
3257 msvr2 = stl_cd1400getreg(portp, MSVR2);
3258 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003259 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260
3261 sigs = 0;
3262 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3263 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3264 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3265 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3266#if 0
3267 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3268 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3269#else
3270 sigs |= TIOCM_DSR;
3271#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003272 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273}
3274
3275/*****************************************************************************/
3276
3277/*
3278 * Enable/Disable the Transmitter and/or Receiver.
3279 */
3280
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003281static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282{
3283 unsigned char ccr;
3284 unsigned long flags;
3285
Jiri Slabya0564e12006-12-08 02:38:37 -08003286 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3287
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288 ccr = 0;
3289
3290 if (tx == 0)
3291 ccr |= CCR_TXDISABLE;
3292 else if (tx > 0)
3293 ccr |= CCR_TXENABLE;
3294 if (rx == 0)
3295 ccr |= CCR_RXDISABLE;
3296 else if (rx > 0)
3297 ccr |= CCR_RXENABLE;
3298
Alan Coxb65b5b52006-06-27 02:54:05 -07003299 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300 BRDENABLE(portp->brdnr, portp->pagenr);
3301 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3302 stl_cd1400ccrwait(portp);
3303 stl_cd1400setreg(portp, CCR, ccr);
3304 stl_cd1400ccrwait(portp);
3305 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003306 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307}
3308
3309/*****************************************************************************/
3310
3311/*
3312 * Start/stop the Transmitter and/or Receiver.
3313 */
3314
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003315static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316{
3317 unsigned char sreron, sreroff;
3318 unsigned long flags;
3319
Jiri Slabya0564e12006-12-08 02:38:37 -08003320 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
3322 sreron = 0;
3323 sreroff = 0;
3324 if (tx == 0)
3325 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3326 else if (tx == 1)
3327 sreron |= SRER_TXDATA;
3328 else if (tx >= 2)
3329 sreron |= SRER_TXEMPTY;
3330 if (rx == 0)
3331 sreroff |= SRER_RXDATA;
3332 else if (rx > 0)
3333 sreron |= SRER_RXDATA;
3334
Alan Coxb65b5b52006-06-27 02:54:05 -07003335 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 BRDENABLE(portp->brdnr, portp->pagenr);
3337 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3338 stl_cd1400setreg(portp, SRER,
3339 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3340 BRDDISABLE(portp->brdnr);
3341 if (tx > 0)
3342 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003343 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344}
3345
3346/*****************************************************************************/
3347
3348/*
3349 * Disable all interrupts from this port.
3350 */
3351
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003352static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353{
3354 unsigned long flags;
3355
Jiri Slabya0564e12006-12-08 02:38:37 -08003356 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3357
Alan Coxb65b5b52006-06-27 02:54:05 -07003358 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 BRDENABLE(portp->brdnr, portp->pagenr);
3360 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3361 stl_cd1400setreg(portp, SRER, 0);
3362 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003363 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364}
3365
3366/*****************************************************************************/
3367
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003368static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369{
3370 unsigned long flags;
3371
Jiri Slabya0564e12006-12-08 02:38:37 -08003372 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
Alan Coxb65b5b52006-06-27 02:54:05 -07003374 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 BRDENABLE(portp->brdnr, portp->pagenr);
3376 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3377 stl_cd1400setreg(portp, SRER,
3378 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3379 SRER_TXEMPTY));
3380 BRDDISABLE(portp->brdnr);
3381 portp->brklen = len;
3382 if (len == 1)
3383 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003384 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385}
3386
3387/*****************************************************************************/
3388
3389/*
3390 * Take flow control actions...
3391 */
3392
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003393static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394{
3395 struct tty_struct *tty;
3396 unsigned long flags;
3397
Jiri Slabya0564e12006-12-08 02:38:37 -08003398 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399
Jiri Slaby615e4a72006-12-08 02:38:38 -08003400 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 return;
3402 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003403 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404 return;
3405
Alan Coxb65b5b52006-06-27 02:54:05 -07003406 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 BRDENABLE(portp->brdnr, portp->pagenr);
3408 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3409
3410 if (state) {
3411 if (tty->termios->c_iflag & IXOFF) {
3412 stl_cd1400ccrwait(portp);
3413 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3414 portp->stats.rxxon++;
3415 stl_cd1400ccrwait(portp);
3416 }
3417/*
3418 * Question: should we return RTS to what it was before? It may
3419 * have been set by an ioctl... Suppose not, since if you have
3420 * hardware flow control set then it is pretty silly to go and
3421 * set the RTS line by hand.
3422 */
3423 if (tty->termios->c_cflag & CRTSCTS) {
3424 stl_cd1400setreg(portp, MCOR1,
3425 (stl_cd1400getreg(portp, MCOR1) |
3426 FIFO_RTSTHRESHOLD));
3427 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3428 portp->stats.rxrtson++;
3429 }
3430 } else {
3431 if (tty->termios->c_iflag & IXOFF) {
3432 stl_cd1400ccrwait(portp);
3433 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3434 portp->stats.rxxoff++;
3435 stl_cd1400ccrwait(portp);
3436 }
3437 if (tty->termios->c_cflag & CRTSCTS) {
3438 stl_cd1400setreg(portp, MCOR1,
3439 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3440 stl_cd1400setreg(portp, MSVR2, 0);
3441 portp->stats.rxrtsoff++;
3442 }
3443 }
3444
3445 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003446 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447}
3448
3449/*****************************************************************************/
3450
3451/*
3452 * Send a flow control character...
3453 */
3454
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003455static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456{
3457 struct tty_struct *tty;
3458 unsigned long flags;
3459
Jiri Slabya0564e12006-12-08 02:38:37 -08003460 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461
Jiri Slaby615e4a72006-12-08 02:38:38 -08003462 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463 return;
3464 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003465 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 return;
3467
Alan Coxb65b5b52006-06-27 02:54:05 -07003468 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 BRDENABLE(portp->brdnr, portp->pagenr);
3470 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3471 if (state) {
3472 stl_cd1400ccrwait(portp);
3473 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3474 portp->stats.rxxon++;
3475 stl_cd1400ccrwait(portp);
3476 } else {
3477 stl_cd1400ccrwait(portp);
3478 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3479 portp->stats.rxxoff++;
3480 stl_cd1400ccrwait(portp);
3481 }
3482 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003483 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484}
3485
3486/*****************************************************************************/
3487
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003488static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489{
3490 unsigned long flags;
3491
Jiri Slabya0564e12006-12-08 02:38:37 -08003492 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493
Jiri Slaby615e4a72006-12-08 02:38:38 -08003494 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495 return;
3496
Alan Coxb65b5b52006-06-27 02:54:05 -07003497 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 BRDENABLE(portp->brdnr, portp->pagenr);
3499 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3500 stl_cd1400ccrwait(portp);
3501 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3502 stl_cd1400ccrwait(portp);
3503 portp->tx.tail = portp->tx.head;
3504 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003505 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506}
3507
3508/*****************************************************************************/
3509
3510/*
3511 * Return the current state of data flow on this port. This is only
3512 * really interresting when determining if data has fully completed
3513 * transmission or not... This is easy for the cd1400, it accurately
3514 * maintains the busy port flag.
3515 */
3516
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003517static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518{
Jiri Slabya0564e12006-12-08 02:38:37 -08003519 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520
Jiri Slaby615e4a72006-12-08 02:38:38 -08003521 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003522 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523
Jesper Juhl014c2542006-01-15 02:37:08 +01003524 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525}
3526
3527/*****************************************************************************/
3528
3529/*
3530 * Interrupt service routine for cd1400 EasyIO boards.
3531 */
3532
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003533static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534{
3535 unsigned char svrtype;
3536
Jiri Slabya0564e12006-12-08 02:38:37 -08003537 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538
Alan Coxb65b5b52006-06-27 02:54:05 -07003539 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540 outb(SVRR, iobase);
3541 svrtype = inb(iobase + EREG_DATA);
3542 if (panelp->nrports > 4) {
3543 outb((SVRR + 0x80), iobase);
3544 svrtype |= inb(iobase + EREG_DATA);
3545 }
3546
3547 if (svrtype & SVRR_RX)
3548 stl_cd1400rxisr(panelp, iobase);
3549 else if (svrtype & SVRR_TX)
3550 stl_cd1400txisr(panelp, iobase);
3551 else if (svrtype & SVRR_MDM)
3552 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003553
3554 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555}
3556
3557/*****************************************************************************/
3558
3559/*
3560 * Interrupt service routine for cd1400 panels.
3561 */
3562
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003563static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564{
3565 unsigned char svrtype;
3566
Jiri Slabya0564e12006-12-08 02:38:37 -08003567 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568
3569 outb(SVRR, iobase);
3570 svrtype = inb(iobase + EREG_DATA);
3571 outb((SVRR + 0x80), iobase);
3572 svrtype |= inb(iobase + EREG_DATA);
3573 if (svrtype & SVRR_RX)
3574 stl_cd1400rxisr(panelp, iobase);
3575 else if (svrtype & SVRR_TX)
3576 stl_cd1400txisr(panelp, iobase);
3577 else if (svrtype & SVRR_MDM)
3578 stl_cd1400mdmisr(panelp, iobase);
3579}
3580
3581
3582/*****************************************************************************/
3583
3584/*
3585 * Unfortunately we need to handle breaks in the TX data stream, since
3586 * this is the only way to generate them on the cd1400.
3587 */
3588
Jiri Slaby60be4812006-12-08 02:38:40 -08003589static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590{
3591 if (portp->brklen == 1) {
3592 outb((COR2 + portp->uartaddr), ioaddr);
3593 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3594 (ioaddr + EREG_DATA));
3595 outb((TDR + portp->uartaddr), ioaddr);
3596 outb(ETC_CMD, (ioaddr + EREG_DATA));
3597 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3598 outb((SRER + portp->uartaddr), ioaddr);
3599 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3600 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003601 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602 } else if (portp->brklen > 1) {
3603 outb((TDR + portp->uartaddr), ioaddr);
3604 outb(ETC_CMD, (ioaddr + EREG_DATA));
3605 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3606 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003607 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 } else {
3609 outb((COR2 + portp->uartaddr), ioaddr);
3610 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3611 (ioaddr + EREG_DATA));
3612 portp->brklen = 0;
3613 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003614 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615}
3616
3617/*****************************************************************************/
3618
3619/*
3620 * Transmit interrupt handler. This has gotta be fast! Handling TX
3621 * chars is pretty simple, stuff as many as possible from the TX buffer
3622 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3623 * are embedded as commands in the data stream. Oh no, had to use a goto!
3624 * This could be optimized more, will do when I get time...
3625 * In practice it is possible that interrupts are enabled but that the
3626 * port has been hung up. Need to handle not having any TX buffer here,
3627 * this is done by using the side effect that head and tail will also
3628 * be NULL if the buffer has been freed.
3629 */
3630
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003631static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003633 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 int len, stlen;
3635 char *head, *tail;
3636 unsigned char ioack, srer;
3637
Jiri Slabya0564e12006-12-08 02:38:37 -08003638 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639
3640 ioack = inb(ioaddr + EREG_TXACK);
3641 if (((ioack & panelp->ackmask) != 0) ||
3642 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3643 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3644 return;
3645 }
3646 portp = panelp->ports[(ioack >> 3)];
3647
3648/*
3649 * Unfortunately we need to handle breaks in the data stream, since
3650 * this is the only way to generate them on the cd1400. Do it now if
3651 * a break is to be sent.
3652 */
3653 if (portp->brklen != 0)
3654 if (stl_cd1400breakisr(portp, ioaddr))
3655 goto stl_txalldone;
3656
3657 head = portp->tx.head;
3658 tail = portp->tx.tail;
3659 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3660 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3661 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3662 set_bit(ASYI_TXLOW, &portp->istate);
3663 schedule_work(&portp->tqueue);
3664 }
3665
3666 if (len == 0) {
3667 outb((SRER + portp->uartaddr), ioaddr);
3668 srer = inb(ioaddr + EREG_DATA);
3669 if (srer & SRER_TXDATA) {
3670 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3671 } else {
3672 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3673 clear_bit(ASYI_TXBUSY, &portp->istate);
3674 }
3675 outb(srer, (ioaddr + EREG_DATA));
3676 } else {
3677 len = MIN(len, CD1400_TXFIFOSIZE);
3678 portp->stats.txtotal += len;
3679 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
3680 outb((TDR + portp->uartaddr), ioaddr);
3681 outsb((ioaddr + EREG_DATA), tail, stlen);
3682 len -= stlen;
3683 tail += stlen;
3684 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3685 tail = portp->tx.buf;
3686 if (len > 0) {
3687 outsb((ioaddr + EREG_DATA), tail, len);
3688 tail += len;
3689 }
3690 portp->tx.tail = tail;
3691 }
3692
3693stl_txalldone:
3694 outb((EOSRR + portp->uartaddr), ioaddr);
3695 outb(0, (ioaddr + EREG_DATA));
3696}
3697
3698/*****************************************************************************/
3699
3700/*
3701 * Receive character interrupt handler. Determine if we have good chars
3702 * or bad chars and then process appropriately. Good chars are easy
3703 * just shove the lot into the RX buffer and set all status byte to 0.
3704 * If a bad RX char then process as required. This routine needs to be
3705 * fast! In practice it is possible that we get an interrupt on a port
3706 * that is closed. This can happen on hangups - since they completely
3707 * shutdown a port not in user context. Need to handle this case.
3708 */
3709
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003710static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003712 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 struct tty_struct *tty;
3714 unsigned int ioack, len, buflen;
3715 unsigned char status;
3716 char ch;
3717
Jiri Slabya0564e12006-12-08 02:38:37 -08003718 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719
3720 ioack = inb(ioaddr + EREG_RXACK);
3721 if ((ioack & panelp->ackmask) != 0) {
3722 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3723 return;
3724 }
3725 portp = panelp->ports[(ioack >> 3)];
3726 tty = portp->tty;
3727
3728 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3729 outb((RDCR + portp->uartaddr), ioaddr);
3730 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003731 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732 len = MIN(len, sizeof(stl_unwanted));
3733 outb((RDSR + portp->uartaddr), ioaddr);
3734 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3735 portp->stats.rxlost += len;
3736 portp->stats.rxtotal += len;
3737 } else {
3738 len = MIN(len, buflen);
3739 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003740 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003742 tty_prepare_flip_string(tty, &ptr, len);
3743 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744 tty_schedule_flip(tty);
3745 portp->stats.rxtotal += len;
3746 }
3747 }
3748 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3749 outb((RDSR + portp->uartaddr), ioaddr);
3750 status = inb(ioaddr + EREG_DATA);
3751 ch = inb(ioaddr + EREG_DATA);
3752 if (status & ST_PARITY)
3753 portp->stats.rxparity++;
3754 if (status & ST_FRAMING)
3755 portp->stats.rxframing++;
3756 if (status & ST_OVERRUN)
3757 portp->stats.rxoverrun++;
3758 if (status & ST_BREAK)
3759 portp->stats.rxbreaks++;
3760 if (status & ST_SCHARMASK) {
3761 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3762 portp->stats.txxon++;
3763 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3764 portp->stats.txxoff++;
3765 goto stl_rxalldone;
3766 }
Alan Cox33f0f882006-01-09 20:54:13 -08003767 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 if (portp->rxmarkmsk & status) {
3769 if (status & ST_BREAK) {
3770 status = TTY_BREAK;
3771 if (portp->flags & ASYNC_SAK) {
3772 do_SAK(tty);
3773 BRDENABLE(portp->brdnr, portp->pagenr);
3774 }
3775 } else if (status & ST_PARITY) {
3776 status = TTY_PARITY;
3777 } else if (status & ST_FRAMING) {
3778 status = TTY_FRAME;
3779 } else if(status & ST_OVERRUN) {
3780 status = TTY_OVERRUN;
3781 } else {
3782 status = 0;
3783 }
3784 } else {
3785 status = 0;
3786 }
Alan Cox33f0f882006-01-09 20:54:13 -08003787 tty_insert_flip_char(tty, ch, status);
3788 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 }
3790 } else {
3791 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3792 return;
3793 }
3794
3795stl_rxalldone:
3796 outb((EOSRR + portp->uartaddr), ioaddr);
3797 outb(0, (ioaddr + EREG_DATA));
3798}
3799
3800/*****************************************************************************/
3801
3802/*
3803 * Modem interrupt handler. The is called when the modem signal line
3804 * (DCD) has changed state. Leave most of the work to the off-level
3805 * processing routine.
3806 */
3807
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003808static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003810 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811 unsigned int ioack;
3812 unsigned char misr;
3813
Jiri Slabya0564e12006-12-08 02:38:37 -08003814 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815
3816 ioack = inb(ioaddr + EREG_MDACK);
3817 if (((ioack & panelp->ackmask) != 0) ||
3818 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3819 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3820 return;
3821 }
3822 portp = panelp->ports[(ioack >> 3)];
3823
3824 outb((MISR + portp->uartaddr), ioaddr);
3825 misr = inb(ioaddr + EREG_DATA);
3826 if (misr & MISR_DCD) {
3827 set_bit(ASYI_DCDCHANGE, &portp->istate);
3828 schedule_work(&portp->tqueue);
3829 portp->stats.modem++;
3830 }
3831
3832 outb((EOSRR + portp->uartaddr), ioaddr);
3833 outb(0, (ioaddr + EREG_DATA));
3834}
3835
3836/*****************************************************************************/
3837/* SC26198 HARDWARE FUNCTIONS */
3838/*****************************************************************************/
3839
3840/*
3841 * These functions get/set/update the registers of the sc26198 UARTs.
3842 * Access to the sc26198 registers is via an address/data io port pair.
3843 * (Maybe should make this inline...)
3844 */
3845
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003846static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847{
3848 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003849 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850}
3851
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003852static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853{
3854 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3855 outb(value, (portp->ioaddr + XP_DATA));
3856}
3857
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003858static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859{
3860 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3861 if (inb(portp->ioaddr + XP_DATA) != value) {
3862 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003863 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003865 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866}
3867
3868/*****************************************************************************/
3869
3870/*
3871 * Functions to get and set the sc26198 global registers.
3872 */
3873
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003874static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875{
3876 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003877 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878}
3879
3880#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003881static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882{
3883 outb(regnr, (portp->ioaddr + XP_ADDR));
3884 outb(value, (portp->ioaddr + XP_DATA));
3885}
3886#endif
3887
3888/*****************************************************************************/
3889
3890/*
3891 * Inbitialize the UARTs in a panel. We don't care what sort of board
3892 * these ports are on - since the port io registers are almost
3893 * identical when dealing with ports.
3894 */
3895
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003896static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897{
3898 int chipmask, i;
3899 int nrchips, ioaddr;
3900
Jiri Slabya0564e12006-12-08 02:38:37 -08003901 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
3903 BRDENABLE(panelp->brdnr, panelp->pagenr);
3904
3905/*
3906 * Check that each chip is present and started up OK.
3907 */
3908 chipmask = 0;
3909 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3910 if (brdp->brdtype == BRD_ECHPCI)
3911 outb(panelp->pagenr, brdp->ioctrl);
3912
3913 for (i = 0; (i < nrchips); i++) {
3914 ioaddr = panelp->iobase + (i * 4);
3915 outb(SCCR, (ioaddr + XP_ADDR));
3916 outb(CR_RESETALL, (ioaddr + XP_DATA));
3917 outb(TSTR, (ioaddr + XP_ADDR));
3918 if (inb(ioaddr + XP_DATA) != 0) {
3919 printk("STALLION: sc26198 not responding, "
3920 "brd=%d panel=%d chip=%d\n",
3921 panelp->brdnr, panelp->panelnr, i);
3922 continue;
3923 }
3924 chipmask |= (0x1 << i);
3925 outb(GCCR, (ioaddr + XP_ADDR));
3926 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3927 outb(WDTRCR, (ioaddr + XP_ADDR));
3928 outb(0xff, (ioaddr + XP_DATA));
3929 }
3930
3931 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003932 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933}
3934
3935/*****************************************************************************/
3936
3937/*
3938 * Initialize hardware specific port registers.
3939 */
3940
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003941static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942{
Jiri Slabya0564e12006-12-08 02:38:37 -08003943 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3944 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945
Jiri Slaby615e4a72006-12-08 02:38:38 -08003946 if ((brdp == NULL) || (panelp == NULL) ||
3947 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 return;
3949
3950 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3951 portp->uartaddr = (portp->portnr & 0x07) << 4;
3952 portp->pagenr = panelp->pagenr;
3953 portp->hwid = 0x1;
3954
3955 BRDENABLE(portp->brdnr, portp->pagenr);
3956 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3957 BRDDISABLE(portp->brdnr);
3958}
3959
3960/*****************************************************************************/
3961
3962/*
3963 * Set up the sc26198 registers for a port based on the termios port
3964 * settings.
3965 */
3966
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003967static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003969 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 unsigned long flags;
3971 unsigned int baudrate;
3972 unsigned char mr0, mr1, mr2, clk;
3973 unsigned char imron, imroff, iopr, ipr;
3974
3975 mr0 = 0;
3976 mr1 = 0;
3977 mr2 = 0;
3978 clk = 0;
3979 iopr = 0;
3980 imron = 0;
3981 imroff = 0;
3982
3983 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003984 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 return;
3986
3987/*
3988 * Set up the RX char ignore mask with those RX error types we
3989 * can ignore.
3990 */
3991 portp->rxignoremsk = 0;
3992 if (tiosp->c_iflag & IGNPAR)
3993 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3994 SR_RXOVERRUN);
3995 if (tiosp->c_iflag & IGNBRK)
3996 portp->rxignoremsk |= SR_RXBREAK;
3997
3998 portp->rxmarkmsk = SR_RXOVERRUN;
3999 if (tiosp->c_iflag & (INPCK | PARMRK))
4000 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
4001 if (tiosp->c_iflag & BRKINT)
4002 portp->rxmarkmsk |= SR_RXBREAK;
4003
4004/*
4005 * Go through the char size, parity and stop bits and set all the
4006 * option register appropriately.
4007 */
4008 switch (tiosp->c_cflag & CSIZE) {
4009 case CS5:
4010 mr1 |= MR1_CS5;
4011 break;
4012 case CS6:
4013 mr1 |= MR1_CS6;
4014 break;
4015 case CS7:
4016 mr1 |= MR1_CS7;
4017 break;
4018 default:
4019 mr1 |= MR1_CS8;
4020 break;
4021 }
4022
4023 if (tiosp->c_cflag & CSTOPB)
4024 mr2 |= MR2_STOP2;
4025 else
4026 mr2 |= MR2_STOP1;
4027
4028 if (tiosp->c_cflag & PARENB) {
4029 if (tiosp->c_cflag & PARODD)
4030 mr1 |= (MR1_PARENB | MR1_PARODD);
4031 else
4032 mr1 |= (MR1_PARENB | MR1_PAREVEN);
4033 } else {
4034 mr1 |= MR1_PARNONE;
4035 }
4036
4037 mr1 |= MR1_ERRBLOCK;
4038
4039/*
4040 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
4041 * space for hardware flow control and the like. This should be set to
4042 * VMIN.
4043 */
4044 mr2 |= MR2_RXFIFOHALF;
4045
4046/*
4047 * Calculate the baud rate timers. For now we will just assume that
4048 * the input and output baud are the same. The sc26198 has a fixed
4049 * baud rate table, so only discrete baud rates possible.
4050 */
4051 baudrate = tiosp->c_cflag & CBAUD;
4052 if (baudrate & CBAUDEX) {
4053 baudrate &= ~CBAUDEX;
4054 if ((baudrate < 1) || (baudrate > 4))
4055 tiosp->c_cflag &= ~CBAUDEX;
4056 else
4057 baudrate += 15;
4058 }
4059 baudrate = stl_baudrates[baudrate];
4060 if ((tiosp->c_cflag & CBAUD) == B38400) {
4061 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
4062 baudrate = 57600;
4063 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
4064 baudrate = 115200;
4065 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
4066 baudrate = 230400;
4067 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
4068 baudrate = 460800;
4069 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
4070 baudrate = (portp->baud_base / portp->custom_divisor);
4071 }
4072 if (baudrate > STL_SC26198MAXBAUD)
4073 baudrate = STL_SC26198MAXBAUD;
4074
4075 if (baudrate > 0) {
4076 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
4077 if (baudrate <= sc26198_baudtable[clk])
4078 break;
4079 }
4080 }
4081
4082/*
4083 * Check what form of modem signaling is required and set it up.
4084 */
4085 if (tiosp->c_cflag & CLOCAL) {
4086 portp->flags &= ~ASYNC_CHECK_CD;
4087 } else {
4088 iopr |= IOPR_DCDCOS;
4089 imron |= IR_IOPORT;
4090 portp->flags |= ASYNC_CHECK_CD;
4091 }
4092
4093/*
4094 * Setup sc26198 enhanced modes if we can. In particular we want to
4095 * handle as much of the flow control as possible automatically. As
4096 * well as saving a few CPU cycles it will also greatly improve flow
4097 * control reliability.
4098 */
4099 if (tiosp->c_iflag & IXON) {
4100 mr0 |= MR0_SWFTX | MR0_SWFT;
4101 imron |= IR_XONXOFF;
4102 } else {
4103 imroff |= IR_XONXOFF;
4104 }
4105 if (tiosp->c_iflag & IXOFF)
4106 mr0 |= MR0_SWFRX;
4107
4108 if (tiosp->c_cflag & CRTSCTS) {
4109 mr2 |= MR2_AUTOCTS;
4110 mr1 |= MR1_AUTORTS;
4111 }
4112
4113/*
4114 * All sc26198 register values calculated so go through and set
4115 * them all up.
4116 */
4117
Jiri Slabya0564e12006-12-08 02:38:37 -08004118 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08004120 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
4121 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
4122 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4124 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
Alan Coxb65b5b52006-06-27 02:54:05 -07004126 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 BRDENABLE(portp->brdnr, portp->pagenr);
4128 stl_sc26198setreg(portp, IMR, 0);
4129 stl_sc26198updatereg(portp, MR0, mr0);
4130 stl_sc26198updatereg(portp, MR1, mr1);
4131 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4132 stl_sc26198updatereg(portp, MR2, mr2);
4133 stl_sc26198updatereg(portp, IOPIOR,
4134 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4135
4136 if (baudrate > 0) {
4137 stl_sc26198setreg(portp, TXCSR, clk);
4138 stl_sc26198setreg(portp, RXCSR, clk);
4139 }
4140
4141 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4142 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4143
4144 ipr = stl_sc26198getreg(portp, IPR);
4145 if (ipr & IPR_DCD)
4146 portp->sigs &= ~TIOCM_CD;
4147 else
4148 portp->sigs |= TIOCM_CD;
4149
4150 portp->imr = (portp->imr & ~imroff) | imron;
4151 stl_sc26198setreg(portp, IMR, portp->imr);
4152 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004153 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154}
4155
4156/*****************************************************************************/
4157
4158/*
4159 * Set the state of the DTR and RTS signals.
4160 */
4161
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004162static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163{
4164 unsigned char iopioron, iopioroff;
4165 unsigned long flags;
4166
Jiri Slabya0564e12006-12-08 02:38:37 -08004167 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4168 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169
4170 iopioron = 0;
4171 iopioroff = 0;
4172 if (dtr == 0)
4173 iopioroff |= IPR_DTR;
4174 else if (dtr > 0)
4175 iopioron |= IPR_DTR;
4176 if (rts == 0)
4177 iopioroff |= IPR_RTS;
4178 else if (rts > 0)
4179 iopioron |= IPR_RTS;
4180
Alan Coxb65b5b52006-06-27 02:54:05 -07004181 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 BRDENABLE(portp->brdnr, portp->pagenr);
4183 stl_sc26198setreg(portp, IOPIOR,
4184 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4185 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004186 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187}
4188
4189/*****************************************************************************/
4190
4191/*
4192 * Return the state of the signals.
4193 */
4194
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004195static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196{
4197 unsigned char ipr;
4198 unsigned long flags;
4199 int sigs;
4200
Jiri Slabya0564e12006-12-08 02:38:37 -08004201 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202
Alan Coxb65b5b52006-06-27 02:54:05 -07004203 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 BRDENABLE(portp->brdnr, portp->pagenr);
4205 ipr = stl_sc26198getreg(portp, IPR);
4206 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004207 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208
4209 sigs = 0;
4210 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4211 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4212 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4213 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4214 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004215 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216}
4217
4218/*****************************************************************************/
4219
4220/*
4221 * Enable/Disable the Transmitter and/or Receiver.
4222 */
4223
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004224static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225{
4226 unsigned char ccr;
4227 unsigned long flags;
4228
Jiri Slabya0564e12006-12-08 02:38:37 -08004229 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
4231 ccr = portp->crenable;
4232 if (tx == 0)
4233 ccr &= ~CR_TXENABLE;
4234 else if (tx > 0)
4235 ccr |= CR_TXENABLE;
4236 if (rx == 0)
4237 ccr &= ~CR_RXENABLE;
4238 else if (rx > 0)
4239 ccr |= CR_RXENABLE;
4240
Alan Coxb65b5b52006-06-27 02:54:05 -07004241 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 BRDENABLE(portp->brdnr, portp->pagenr);
4243 stl_sc26198setreg(portp, SCCR, ccr);
4244 BRDDISABLE(portp->brdnr);
4245 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004246 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247}
4248
4249/*****************************************************************************/
4250
4251/*
4252 * Start/stop the Transmitter and/or Receiver.
4253 */
4254
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004255static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256{
4257 unsigned char imr;
4258 unsigned long flags;
4259
Jiri Slabya0564e12006-12-08 02:38:37 -08004260 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261
4262 imr = portp->imr;
4263 if (tx == 0)
4264 imr &= ~IR_TXRDY;
4265 else if (tx == 1)
4266 imr |= IR_TXRDY;
4267 if (rx == 0)
4268 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4269 else if (rx > 0)
4270 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4271
Alan Coxb65b5b52006-06-27 02:54:05 -07004272 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 BRDENABLE(portp->brdnr, portp->pagenr);
4274 stl_sc26198setreg(portp, IMR, imr);
4275 BRDDISABLE(portp->brdnr);
4276 portp->imr = imr;
4277 if (tx > 0)
4278 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004279 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280}
4281
4282/*****************************************************************************/
4283
4284/*
4285 * Disable all interrupts from this port.
4286 */
4287
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004288static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289{
4290 unsigned long flags;
4291
Jiri Slabya0564e12006-12-08 02:38:37 -08004292 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
Alan Coxb65b5b52006-06-27 02:54:05 -07004294 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295 BRDENABLE(portp->brdnr, portp->pagenr);
4296 portp->imr = 0;
4297 stl_sc26198setreg(portp, IMR, 0);
4298 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004299 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300}
4301
4302/*****************************************************************************/
4303
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004304static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305{
4306 unsigned long flags;
4307
Jiri Slabya0564e12006-12-08 02:38:37 -08004308 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309
Alan Coxb65b5b52006-06-27 02:54:05 -07004310 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 BRDENABLE(portp->brdnr, portp->pagenr);
4312 if (len == 1) {
4313 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4314 portp->stats.txbreaks++;
4315 } else {
4316 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4317 }
4318 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004319 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320}
4321
4322/*****************************************************************************/
4323
4324/*
4325 * Take flow control actions...
4326 */
4327
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004328static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329{
4330 struct tty_struct *tty;
4331 unsigned long flags;
4332 unsigned char mr0;
4333
Jiri Slabya0564e12006-12-08 02:38:37 -08004334 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335
Jiri Slaby615e4a72006-12-08 02:38:38 -08004336 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 return;
4338 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004339 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340 return;
4341
Alan Coxb65b5b52006-06-27 02:54:05 -07004342 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 BRDENABLE(portp->brdnr, portp->pagenr);
4344
4345 if (state) {
4346 if (tty->termios->c_iflag & IXOFF) {
4347 mr0 = stl_sc26198getreg(portp, MR0);
4348 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4349 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4350 mr0 |= MR0_SWFRX;
4351 portp->stats.rxxon++;
4352 stl_sc26198wait(portp);
4353 stl_sc26198setreg(portp, MR0, mr0);
4354 }
4355/*
4356 * Question: should we return RTS to what it was before? It may
4357 * have been set by an ioctl... Suppose not, since if you have
4358 * hardware flow control set then it is pretty silly to go and
4359 * set the RTS line by hand.
4360 */
4361 if (tty->termios->c_cflag & CRTSCTS) {
4362 stl_sc26198setreg(portp, MR1,
4363 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4364 stl_sc26198setreg(portp, IOPIOR,
4365 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4366 portp->stats.rxrtson++;
4367 }
4368 } else {
4369 if (tty->termios->c_iflag & IXOFF) {
4370 mr0 = stl_sc26198getreg(portp, MR0);
4371 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4372 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4373 mr0 &= ~MR0_SWFRX;
4374 portp->stats.rxxoff++;
4375 stl_sc26198wait(portp);
4376 stl_sc26198setreg(portp, MR0, mr0);
4377 }
4378 if (tty->termios->c_cflag & CRTSCTS) {
4379 stl_sc26198setreg(portp, MR1,
4380 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4381 stl_sc26198setreg(portp, IOPIOR,
4382 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4383 portp->stats.rxrtsoff++;
4384 }
4385 }
4386
4387 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004388 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389}
4390
4391/*****************************************************************************/
4392
4393/*
4394 * Send a flow control character.
4395 */
4396
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004397static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398{
4399 struct tty_struct *tty;
4400 unsigned long flags;
4401 unsigned char mr0;
4402
Jiri Slabya0564e12006-12-08 02:38:37 -08004403 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404
Jiri Slaby615e4a72006-12-08 02:38:38 -08004405 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 return;
4407 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004408 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409 return;
4410
Alan Coxb65b5b52006-06-27 02:54:05 -07004411 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 BRDENABLE(portp->brdnr, portp->pagenr);
4413 if (state) {
4414 mr0 = stl_sc26198getreg(portp, MR0);
4415 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4416 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4417 mr0 |= MR0_SWFRX;
4418 portp->stats.rxxon++;
4419 stl_sc26198wait(portp);
4420 stl_sc26198setreg(portp, MR0, mr0);
4421 } else {
4422 mr0 = stl_sc26198getreg(portp, MR0);
4423 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4424 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4425 mr0 &= ~MR0_SWFRX;
4426 portp->stats.rxxoff++;
4427 stl_sc26198wait(portp);
4428 stl_sc26198setreg(portp, MR0, mr0);
4429 }
4430 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004431 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432}
4433
4434/*****************************************************************************/
4435
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004436static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437{
4438 unsigned long flags;
4439
Jiri Slabya0564e12006-12-08 02:38:37 -08004440 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
Jiri Slaby615e4a72006-12-08 02:38:38 -08004442 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 return;
4444
Alan Coxb65b5b52006-06-27 02:54:05 -07004445 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 BRDENABLE(portp->brdnr, portp->pagenr);
4447 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4448 stl_sc26198setreg(portp, SCCR, portp->crenable);
4449 BRDDISABLE(portp->brdnr);
4450 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004451 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452}
4453
4454/*****************************************************************************/
4455
4456/*
4457 * Return the current state of data flow on this port. This is only
4458 * really interresting when determining if data has fully completed
4459 * transmission or not... The sc26198 interrupt scheme cannot
4460 * determine when all data has actually drained, so we need to
4461 * check the port statusy register to be sure.
4462 */
4463
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004464static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465{
4466 unsigned long flags;
4467 unsigned char sr;
4468
Jiri Slabya0564e12006-12-08 02:38:37 -08004469 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470
Jiri Slaby615e4a72006-12-08 02:38:38 -08004471 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004472 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004474 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475
Alan Coxb65b5b52006-06-27 02:54:05 -07004476 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477 BRDENABLE(portp->brdnr, portp->pagenr);
4478 sr = stl_sc26198getreg(portp, SR);
4479 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004480 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481
Jesper Juhl014c2542006-01-15 02:37:08 +01004482 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483}
4484
4485/*****************************************************************************/
4486
4487/*
4488 * Delay for a small amount of time, to give the sc26198 a chance
4489 * to process a command...
4490 */
4491
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004492static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493{
4494 int i;
4495
Jiri Slabya0564e12006-12-08 02:38:37 -08004496 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497
Jiri Slaby615e4a72006-12-08 02:38:38 -08004498 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499 return;
4500
4501 for (i = 0; (i < 20); i++)
4502 stl_sc26198getglobreg(portp, TSTR);
4503}
4504
4505/*****************************************************************************/
4506
4507/*
4508 * If we are TX flow controlled and in IXANY mode then we may
4509 * need to unflow control here. We gotta do this because of the
4510 * automatic flow control modes of the sc26198.
4511 */
4512
Jiri Slaby60be4812006-12-08 02:38:40 -08004513static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514{
4515 unsigned char mr0;
4516
4517 mr0 = stl_sc26198getreg(portp, MR0);
4518 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4519 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4520 stl_sc26198wait(portp);
4521 stl_sc26198setreg(portp, MR0, mr0);
4522 clear_bit(ASYI_TXFLOWED, &portp->istate);
4523}
4524
4525/*****************************************************************************/
4526
4527/*
4528 * Interrupt service routine for sc26198 panels.
4529 */
4530
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004531static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004533 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534 unsigned int iack;
4535
Alan Coxb65b5b52006-06-27 02:54:05 -07004536 spin_lock(&brd_lock);
4537
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538/*
4539 * Work around bug in sc26198 chip... Cannot have A6 address
4540 * line of UART high, else iack will be returned as 0.
4541 */
4542 outb(0, (iobase + 1));
4543
4544 iack = inb(iobase + XP_IACK);
4545 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4546
4547 if (iack & IVR_RXDATA)
4548 stl_sc26198rxisr(portp, iack);
4549 else if (iack & IVR_TXDATA)
4550 stl_sc26198txisr(portp);
4551 else
4552 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004553
4554 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555}
4556
4557/*****************************************************************************/
4558
4559/*
4560 * Transmit interrupt handler. This has gotta be fast! Handling TX
4561 * chars is pretty simple, stuff as many as possible from the TX buffer
4562 * into the sc26198 FIFO.
4563 * In practice it is possible that interrupts are enabled but that the
4564 * port has been hung up. Need to handle not having any TX buffer here,
4565 * this is done by using the side effect that head and tail will also
4566 * be NULL if the buffer has been freed.
4567 */
4568
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004569static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570{
4571 unsigned int ioaddr;
4572 unsigned char mr0;
4573 int len, stlen;
4574 char *head, *tail;
4575
Jiri Slabya0564e12006-12-08 02:38:37 -08004576 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577
4578 ioaddr = portp->ioaddr;
4579 head = portp->tx.head;
4580 tail = portp->tx.tail;
4581 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4582 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4583 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4584 set_bit(ASYI_TXLOW, &portp->istate);
4585 schedule_work(&portp->tqueue);
4586 }
4587
4588 if (len == 0) {
4589 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4590 mr0 = inb(ioaddr + XP_DATA);
4591 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4592 portp->imr &= ~IR_TXRDY;
4593 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4594 outb(portp->imr, (ioaddr + XP_DATA));
4595 clear_bit(ASYI_TXBUSY, &portp->istate);
4596 } else {
4597 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4598 outb(mr0, (ioaddr + XP_DATA));
4599 }
4600 } else {
4601 len = MIN(len, SC26198_TXFIFOSIZE);
4602 portp->stats.txtotal += len;
4603 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
4604 outb(GTXFIFO, (ioaddr + XP_ADDR));
4605 outsb((ioaddr + XP_DATA), tail, stlen);
4606 len -= stlen;
4607 tail += stlen;
4608 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4609 tail = portp->tx.buf;
4610 if (len > 0) {
4611 outsb((ioaddr + XP_DATA), tail, len);
4612 tail += len;
4613 }
4614 portp->tx.tail = tail;
4615 }
4616}
4617
4618/*****************************************************************************/
4619
4620/*
4621 * Receive character interrupt handler. Determine if we have good chars
4622 * or bad chars and then process appropriately. Good chars are easy
4623 * just shove the lot into the RX buffer and set all status byte to 0.
4624 * If a bad RX char then process as required. This routine needs to be
4625 * fast! In practice it is possible that we get an interrupt on a port
4626 * that is closed. This can happen on hangups - since they completely
4627 * shutdown a port not in user context. Need to handle this case.
4628 */
4629
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004630static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004631{
4632 struct tty_struct *tty;
4633 unsigned int len, buflen, ioaddr;
4634
Jiri Slabya0564e12006-12-08 02:38:37 -08004635 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636
4637 tty = portp->tty;
4638 ioaddr = portp->ioaddr;
4639 outb(GIBCR, (ioaddr + XP_ADDR));
4640 len = inb(ioaddr + XP_DATA) + 1;
4641
4642 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004643 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644 len = MIN(len, sizeof(stl_unwanted));
4645 outb(GRXFIFO, (ioaddr + XP_ADDR));
4646 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4647 portp->stats.rxlost += len;
4648 portp->stats.rxtotal += len;
4649 } else {
4650 len = MIN(len, buflen);
4651 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004652 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004654 tty_prepare_flip_string(tty, &ptr, len);
4655 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656 tty_schedule_flip(tty);
4657 portp->stats.rxtotal += len;
4658 }
4659 }
4660 } else {
4661 stl_sc26198rxbadchars(portp);
4662 }
4663
4664/*
4665 * If we are TX flow controlled and in IXANY mode then we may need
4666 * to unflow control here. We gotta do this because of the automatic
4667 * flow control modes of the sc26198.
4668 */
4669 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004670 if ((tty != NULL) &&
4671 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004672 (tty->termios->c_iflag & IXANY)) {
4673 stl_sc26198txunflow(portp, tty);
4674 }
4675 }
4676}
4677
4678/*****************************************************************************/
4679
4680/*
4681 * Process an RX bad character.
4682 */
4683
Jiri Slaby60be4812006-12-08 02:38:40 -08004684static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685{
4686 struct tty_struct *tty;
4687 unsigned int ioaddr;
4688
4689 tty = portp->tty;
4690 ioaddr = portp->ioaddr;
4691
4692 if (status & SR_RXPARITY)
4693 portp->stats.rxparity++;
4694 if (status & SR_RXFRAMING)
4695 portp->stats.rxframing++;
4696 if (status & SR_RXOVERRUN)
4697 portp->stats.rxoverrun++;
4698 if (status & SR_RXBREAK)
4699 portp->stats.rxbreaks++;
4700
Jiri Slaby615e4a72006-12-08 02:38:38 -08004701 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702 ((portp->rxignoremsk & status) == 0)) {
4703 if (portp->rxmarkmsk & status) {
4704 if (status & SR_RXBREAK) {
4705 status = TTY_BREAK;
4706 if (portp->flags & ASYNC_SAK) {
4707 do_SAK(tty);
4708 BRDENABLE(portp->brdnr, portp->pagenr);
4709 }
4710 } else if (status & SR_RXPARITY) {
4711 status = TTY_PARITY;
4712 } else if (status & SR_RXFRAMING) {
4713 status = TTY_FRAME;
4714 } else if(status & SR_RXOVERRUN) {
4715 status = TTY_OVERRUN;
4716 } else {
4717 status = 0;
4718 }
4719 } else {
4720 status = 0;
4721 }
4722
Alan Cox33f0f882006-01-09 20:54:13 -08004723 tty_insert_flip_char(tty, ch, status);
4724 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725
4726 if (status == 0)
4727 portp->stats.rxtotal++;
4728 }
4729}
4730
4731/*****************************************************************************/
4732
4733/*
4734 * Process all characters in the RX FIFO of the UART. Check all char
4735 * status bytes as well, and process as required. We need to check
4736 * all bytes in the FIFO, in case some more enter the FIFO while we
4737 * are here. To get the exact character error type we need to switch
4738 * into CHAR error mode (that is why we need to make sure we empty
4739 * the FIFO).
4740 */
4741
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004742static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743{
4744 unsigned char status, mr1;
4745 char ch;
4746
4747/*
4748 * To get the precise error type for each character we must switch
4749 * back into CHAR error mode.
4750 */
4751 mr1 = stl_sc26198getreg(portp, MR1);
4752 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4753
4754 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4755 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4756 ch = stl_sc26198getreg(portp, RXFIFO);
4757 stl_sc26198rxbadch(portp, status, ch);
4758 }
4759
4760/*
4761 * To get correct interrupt class we must switch back into BLOCK
4762 * error mode.
4763 */
4764 stl_sc26198setreg(portp, MR1, mr1);
4765}
4766
4767/*****************************************************************************/
4768
4769/*
4770 * Other interrupt handler. This includes modem signals, flow
4771 * control actions, etc. Most stuff is left to off-level interrupt
4772 * processing time.
4773 */
4774
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004775static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776{
4777 unsigned char cir, ipr, xisr;
4778
Jiri Slabya0564e12006-12-08 02:38:37 -08004779 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004780
4781 cir = stl_sc26198getglobreg(portp, CIR);
4782
4783 switch (cir & CIR_SUBTYPEMASK) {
4784 case CIR_SUBCOS:
4785 ipr = stl_sc26198getreg(portp, IPR);
4786 if (ipr & IPR_DCDCHANGE) {
4787 set_bit(ASYI_DCDCHANGE, &portp->istate);
4788 schedule_work(&portp->tqueue);
4789 portp->stats.modem++;
4790 }
4791 break;
4792 case CIR_SUBXONXOFF:
4793 xisr = stl_sc26198getreg(portp, XISR);
4794 if (xisr & XISR_RXXONGOT) {
4795 set_bit(ASYI_TXFLOWED, &portp->istate);
4796 portp->stats.txxoff++;
4797 }
4798 if (xisr & XISR_RXXOFFGOT) {
4799 clear_bit(ASYI_TXFLOWED, &portp->istate);
4800 portp->stats.txxon++;
4801 }
4802 break;
4803 case CIR_SUBBREAK:
4804 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4805 stl_sc26198rxbadchars(portp);
4806 break;
4807 default:
4808 break;
4809 }
4810}
4811
Jiri Slaby23b85a12006-12-08 02:38:40 -08004812/*
4813 * Loadable module initialization stuff.
4814 */
4815static int __init stallion_module_init(void)
4816{
4817 unsigned int i;
4818
4819 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4820
4821 spin_lock_init(&stallion_lock);
4822 spin_lock_init(&brd_lock);
4823
4824 stl_initbrds();
4825
4826 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4827 if (!stl_serial)
4828 return -1;
4829
4830/*
4831 * Set up a character driver for per board stuff. This is mainly used
4832 * to do stats ioctls on the ports.
4833 */
4834 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4835 printk("STALLION: failed to register serial board device\n");
4836
4837 stallion_class = class_create(THIS_MODULE, "staliomem");
4838 for (i = 0; i < 4; i++)
4839 class_device_create(stallion_class, NULL,
4840 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4841 "staliomem%d", i);
4842
4843 stl_serial->owner = THIS_MODULE;
4844 stl_serial->driver_name = stl_drvname;
4845 stl_serial->name = "ttyE";
4846 stl_serial->major = STL_SERIALMAJOR;
4847 stl_serial->minor_start = 0;
4848 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4849 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4850 stl_serial->init_termios = stl_deftermios;
4851 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4852 tty_set_operations(stl_serial, &stl_ops);
4853
4854 if (tty_register_driver(stl_serial)) {
4855 put_tty_driver(stl_serial);
4856 printk("STALLION: failed to register serial driver\n");
4857 return -1;
4858 }
4859
4860 return 0;
4861}
4862
4863static void __exit stallion_module_exit(void)
4864{
4865 struct stlbrd *brdp;
4866 struct stlpanel *panelp;
4867 struct stlport *portp;
4868 int i, j, k;
4869
4870 pr_debug("cleanup_module()\n");
4871
4872 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4873 stl_drvversion);
4874
4875/*
4876 * Free up all allocated resources used by the ports. This includes
4877 * memory and interrupts. As part of this process we will also do
4878 * a hangup on every open port - to try to flush out any processes
4879 * hanging onto ports.
4880 */
4881 i = tty_unregister_driver(stl_serial);
4882 put_tty_driver(stl_serial);
4883 if (i) {
4884 printk("STALLION: failed to un-register tty driver, "
4885 "errno=%d\n", -i);
4886 return;
4887 }
4888 for (i = 0; i < 4; i++)
4889 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4890 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4891 printk("STALLION: failed to un-register serial memory device, "
4892 "errno=%d\n", -i);
4893 class_destroy(stallion_class);
4894
4895 for (i = 0; (i < stl_nrbrds); i++) {
4896 if ((brdp = stl_brds[i]) == NULL)
4897 continue;
4898
4899 free_irq(brdp->irq, brdp);
4900
4901 for (j = 0; (j < STL_MAXPANELS); j++) {
4902 panelp = brdp->panels[j];
4903 if (panelp == NULL)
4904 continue;
4905 for (k = 0; (k < STL_PORTSPERPANEL); k++) {
4906 portp = panelp->ports[k];
4907 if (portp == NULL)
4908 continue;
4909 if (portp->tty != NULL)
4910 stl_hangup(portp->tty);
4911 kfree(portp->tx.buf);
4912 kfree(portp);
4913 }
4914 kfree(panelp);
4915 }
4916
4917 release_region(brdp->ioaddr1, brdp->iosize1);
4918 if (brdp->iosize2 > 0)
4919 release_region(brdp->ioaddr2, brdp->iosize2);
4920
4921 kfree(brdp);
4922 stl_brds[i] = NULL;
4923 }
4924}
4925
4926module_init(stallion_module_init);
4927module_exit(stallion_module_exit);
4928
4929MODULE_AUTHOR("Greg Ungerer");
4930MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4931MODULE_LICENSE("GPL");