blob: a547c0c8fb2af7226474ca697526983bee850b0a [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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800454static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800455static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
456static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800457static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459/*
460 * CD1400 uart specific handling functions.
461 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800462static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
463static int stl_cd1400getreg(struct stlport *portp, int regnr);
464static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
465static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
466static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
467static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp);
468static int stl_cd1400getsignals(struct stlport *portp);
469static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
470static void stl_cd1400ccrwait(struct stlport *portp);
471static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
472static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
473static void stl_cd1400disableintrs(struct stlport *portp);
474static void stl_cd1400sendbreak(struct stlport *portp, int len);
475static void stl_cd1400flowctrl(struct stlport *portp, int state);
476static void stl_cd1400sendflow(struct stlport *portp, int state);
477static void stl_cd1400flush(struct stlport *portp);
478static int stl_cd1400datastate(struct stlport *portp);
479static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
480static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
481static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
482static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
483static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800485static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
487/*
488 * SC26198 uart specific handling functions.
489 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800490static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
491static int stl_sc26198getreg(struct stlport *portp, int regnr);
492static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
493static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
494static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
495static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
496static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp);
497static int stl_sc26198getsignals(struct stlport *portp);
498static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
499static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
500static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
501static void stl_sc26198disableintrs(struct stlport *portp);
502static void stl_sc26198sendbreak(struct stlport *portp, int len);
503static void stl_sc26198flowctrl(struct stlport *portp, int state);
504static void stl_sc26198sendflow(struct stlport *portp, int state);
505static void stl_sc26198flush(struct stlport *portp);
506static int stl_sc26198datastate(struct stlport *portp);
507static void stl_sc26198wait(struct stlport *portp);
508static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
509static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
510static void stl_sc26198txisr(struct stlport *port);
511static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
512static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
513static void stl_sc26198rxbadchars(struct stlport *portp);
514static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
516/*****************************************************************************/
517
518/*
519 * Generic UART support structure.
520 */
521typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800522 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
523 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
524 void (*setport)(struct stlport *portp, struct termios *tiosp);
525 int (*getsignals)(struct stlport *portp);
526 void (*setsignals)(struct stlport *portp, int dtr, int rts);
527 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
528 void (*startrxtx)(struct stlport *portp, int rx, int tx);
529 void (*disableintrs)(struct stlport *portp);
530 void (*sendbreak)(struct stlport *portp, int len);
531 void (*flowctrl)(struct stlport *portp, int state);
532 void (*sendflow)(struct stlport *portp, int state);
533 void (*flush)(struct stlport *portp);
534 int (*datastate)(struct stlport *portp);
535 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536} uart_t;
537
538/*
539 * Define some macros to make calling these functions nice and clean.
540 */
541#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
542#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
543#define stl_setport (* ((uart_t *) portp->uartp)->setport)
544#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
545#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
546#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
547#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
548#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
549#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
550#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
551#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
552#define stl_flush (* ((uart_t *) portp->uartp)->flush)
553#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
554
555/*****************************************************************************/
556
557/*
558 * CD1400 UART specific data initialization.
559 */
560static uart_t stl_cd1400uart = {
561 stl_cd1400panelinit,
562 stl_cd1400portinit,
563 stl_cd1400setport,
564 stl_cd1400getsignals,
565 stl_cd1400setsignals,
566 stl_cd1400enablerxtx,
567 stl_cd1400startrxtx,
568 stl_cd1400disableintrs,
569 stl_cd1400sendbreak,
570 stl_cd1400flowctrl,
571 stl_cd1400sendflow,
572 stl_cd1400flush,
573 stl_cd1400datastate,
574 stl_cd1400eiointr
575};
576
577/*
578 * Define the offsets within the register bank of a cd1400 based panel.
579 * These io address offsets are common to the EasyIO board as well.
580 */
581#define EREG_ADDR 0
582#define EREG_DATA 4
583#define EREG_RXACK 5
584#define EREG_TXACK 6
585#define EREG_MDACK 7
586
587#define EREG_BANKSIZE 8
588
589#define CD1400_CLK 25000000
590#define CD1400_CLK8M 20000000
591
592/*
593 * Define the cd1400 baud rate clocks. These are used when calculating
594 * what clock and divisor to use for the required baud rate. Also
595 * define the maximum baud rate allowed, and the default base baud.
596 */
597static int stl_cd1400clkdivs[] = {
598 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
599};
600
601/*****************************************************************************/
602
603/*
604 * SC26198 UART specific data initization.
605 */
606static uart_t stl_sc26198uart = {
607 stl_sc26198panelinit,
608 stl_sc26198portinit,
609 stl_sc26198setport,
610 stl_sc26198getsignals,
611 stl_sc26198setsignals,
612 stl_sc26198enablerxtx,
613 stl_sc26198startrxtx,
614 stl_sc26198disableintrs,
615 stl_sc26198sendbreak,
616 stl_sc26198flowctrl,
617 stl_sc26198sendflow,
618 stl_sc26198flush,
619 stl_sc26198datastate,
620 stl_sc26198intr
621};
622
623/*
624 * Define the offsets within the register bank of a sc26198 based panel.
625 */
626#define XP_DATA 0
627#define XP_ADDR 1
628#define XP_MODID 2
629#define XP_STATUS 2
630#define XP_IACK 3
631
632#define XP_BANKSIZE 4
633
634/*
635 * Define the sc26198 baud rate table. Offsets within the table
636 * represent the actual baud rate selector of sc26198 registers.
637 */
638static unsigned int sc26198_baudtable[] = {
639 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
640 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
641 230400, 460800, 921600
642};
643
Tobias Klauserfe971072006-01-09 20:54:02 -0800644#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
646/*****************************************************************************/
647
648/*
649 * Define the driver info for a user level control device. Used mainly
650 * to get at port stats - only not using the port device itself.
651 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700652static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 .owner = THIS_MODULE,
654 .ioctl = stl_memioctl,
655};
656
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800657static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 * Check for any arguments passed in on the module load command line.
661 */
662
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663/*****************************************************************************/
664
665/*
666 * Convert an ascii string number into an unsigned long.
667 */
668
669static unsigned long stl_atol(char *str)
670{
671 unsigned long val;
672 int base, c;
673 char *sp;
674
675 val = 0;
676 sp = str;
677 if ((*sp == '0') && (*(sp+1) == 'x')) {
678 base = 16;
679 sp += 2;
680 } else if (*sp == '0') {
681 base = 8;
682 sp++;
683 } else {
684 base = 10;
685 }
686
687 for (; (*sp != 0); sp++) {
688 c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
689 if ((c < 0) || (c >= base)) {
690 printk("STALLION: invalid argument %s\n", str);
691 val = 0;
692 break;
693 }
694 val = (val * base) + c;
695 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100696 return val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697}
698
699/*****************************************************************************/
700
701/*
702 * Parse the supplied argument string, into the board conf struct.
703 */
704
Jiri Slaby40e82652006-12-08 02:38:41 -0800705static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
707 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800708 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Jiri Slabya0564e12006-12-08 02:38:37 -0800710 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Jiri Slaby615e4a72006-12-08 02:38:38 -0800712 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100713 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
715 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
716 *sp = TOLOWER(*sp);
717
Tobias Klauserfe971072006-01-09 20:54:02 -0800718 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
720 break;
721 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800722 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800724 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 }
726
727 confp->brdtype = stl_brdstr[i].type;
728
729 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800730 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 confp->ioaddr1 = stl_atol(argp[i]);
732 i++;
733 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800734 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 confp->ioaddr2 = stl_atol(argp[i]);
736 i++;
737 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800738 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 confp->irq = stl_atol(argp[i]);
Jesper Juhl014c2542006-01-15 02:37:08 +0100740 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741}
742
743/*****************************************************************************/
744
745/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 * Allocate a new board structure. Fill out the basic info in it.
747 */
748
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800749static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800751 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800753 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800754 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700755 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800756 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800757 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 }
759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100761 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762}
763
Jiri Slaby96b066b2006-12-08 02:38:42 -0800764static void __init stl_argbrds(void)
765{
766 struct stlconf conf;
767 struct stlbrd *brdp;
768 int i;
769
770 pr_debug("stl_argbrds()\n");
771
772 for (i = stl_nrbrds; (i < stl_nargs); i++) {
773 memset(&conf, 0, sizeof(conf));
774 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
775 continue;
776 if ((brdp = stl_allocbrd()) == NULL)
777 continue;
778 stl_nrbrds = i + 1;
779 brdp->brdnr = i;
780 brdp->brdtype = conf.brdtype;
781 brdp->ioaddr1 = conf.ioaddr1;
782 brdp->ioaddr2 = conf.ioaddr2;
783 brdp->irq = conf.irq;
784 brdp->irqtype = conf.irqtype;
785 stl_brdinit(brdp);
786 }
787}
788
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789/*****************************************************************************/
790
791static int stl_open(struct tty_struct *tty, struct file *filp)
792{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800793 struct stlport *portp;
794 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 unsigned int minordev;
796 int brdnr, panelnr, portnr, rc;
797
Jiri Slabya0564e12006-12-08 02:38:37 -0800798 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
800 minordev = tty->index;
801 brdnr = MINOR2BRD(minordev);
802 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100803 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800805 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100806 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 minordev = MINOR2PORT(minordev);
808 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800809 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 break;
811 if (minordev < brdp->panels[panelnr]->nrports) {
812 portnr = minordev;
813 break;
814 }
815 minordev -= brdp->panels[panelnr]->nrports;
816 }
817 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100818 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
820 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800821 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100822 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
824/*
825 * On the first open of the device setup the port hardware, and
826 * initialize the per port data structure.
827 */
828 portp->tty = tty;
829 tty->driver_data = portp;
830 portp->refcount++;
831
832 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800833 if (!portp->tx.buf) {
834 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
835 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100836 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 portp->tx.head = portp->tx.buf;
838 portp->tx.tail = portp->tx.buf;
839 }
840 stl_setport(portp, tty->termios);
841 portp->sigs = stl_getsignals(portp);
842 stl_setsignals(portp, 1, 1);
843 stl_enablerxtx(portp, 1, 1);
844 stl_startrxtx(portp, 1, 0);
845 clear_bit(TTY_IO_ERROR, &tty->flags);
846 portp->flags |= ASYNC_INITIALIZED;
847 }
848
849/*
850 * Check if this port is in the middle of closing. If so then wait
851 * until it is closed then return error status, based on flag settings.
852 * The sleep here does not need interrupt protection since the wakeup
853 * for it is done with the same context.
854 */
855 if (portp->flags & ASYNC_CLOSING) {
856 interruptible_sleep_on(&portp->close_wait);
857 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100858 return -EAGAIN;
859 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 }
861
862/*
863 * Based on type of open being done check if it can overlap with any
864 * previous opens still in effect. If we are a normal serial device
865 * then also we might have to wait for carrier.
866 */
867 if (!(filp->f_flags & O_NONBLOCK)) {
868 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100869 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 }
871 portp->flags |= ASYNC_NORMAL_ACTIVE;
872
Jesper Juhl014c2542006-01-15 02:37:08 +0100873 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874}
875
876/*****************************************************************************/
877
878/*
879 * Possibly need to wait for carrier (DCD signal) to come high. Say
880 * maybe because if we are clocal then we don't need to wait...
881 */
882
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800883static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884{
885 unsigned long flags;
886 int rc, doclocal;
887
Jiri Slabya0564e12006-12-08 02:38:37 -0800888 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
890 rc = 0;
891 doclocal = 0;
892
Alan Coxb65b5b52006-06-27 02:54:05 -0700893 spin_lock_irqsave(&stallion_lock, flags);
894
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 if (portp->tty->termios->c_cflag & CLOCAL)
896 doclocal++;
897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 portp->openwaitcnt++;
899 if (! tty_hung_up_p(filp))
900 portp->refcount--;
901
902 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700903 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 stl_setsignals(portp, 1, 1);
905 if (tty_hung_up_p(filp) ||
906 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
907 if (portp->flags & ASYNC_HUP_NOTIFY)
908 rc = -EBUSY;
909 else
910 rc = -ERESTARTSYS;
911 break;
912 }
913 if (((portp->flags & ASYNC_CLOSING) == 0) &&
914 (doclocal || (portp->sigs & TIOCM_CD))) {
915 break;
916 }
917 if (signal_pending(current)) {
918 rc = -ERESTARTSYS;
919 break;
920 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700921 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 interruptible_sleep_on(&portp->open_wait);
923 }
924
925 if (! tty_hung_up_p(filp))
926 portp->refcount++;
927 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700928 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Jesper Juhl014c2542006-01-15 02:37:08 +0100930 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931}
932
933/*****************************************************************************/
934
Jiri Slaby96b066b2006-12-08 02:38:42 -0800935static void stl_flushbuffer(struct tty_struct *tty)
936{
937 struct stlport *portp;
938
939 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
940
941 if (tty == NULL)
942 return;
943 portp = tty->driver_data;
944 if (portp == NULL)
945 return;
946
947 stl_flush(portp);
948 tty_wakeup(tty);
949}
950
951/*****************************************************************************/
952
953static void stl_waituntilsent(struct tty_struct *tty, int timeout)
954{
955 struct stlport *portp;
956 unsigned long tend;
957
958 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
959
960 if (tty == NULL)
961 return;
962 portp = tty->driver_data;
963 if (portp == NULL)
964 return;
965
966 if (timeout == 0)
967 timeout = HZ;
968 tend = jiffies + timeout;
969
970 while (stl_datastate(portp)) {
971 if (signal_pending(current))
972 break;
973 msleep_interruptible(20);
974 if (time_after_eq(jiffies, tend))
975 break;
976 }
977}
978
979/*****************************************************************************/
980
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981static void stl_close(struct tty_struct *tty, struct file *filp)
982{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800983 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 unsigned long flags;
985
Jiri Slabya0564e12006-12-08 02:38:37 -0800986 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
988 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800989 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 return;
991
Alan Coxb65b5b52006-06-27 02:54:05 -0700992 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 if (tty_hung_up_p(filp)) {
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 if ((tty->count == 1) && (portp->refcount != 1))
998 portp->refcount = 1;
999 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -07001000 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 return;
1002 }
1003
1004 portp->refcount = 0;
1005 portp->flags |= ASYNC_CLOSING;
1006
1007/*
1008 * May want to wait for any data to drain before closing. The BUSY
1009 * flag keeps track of whether we are still sending or not - it is
1010 * very accurate for the cd1400, not quite so for the sc26198.
1011 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
1012 */
1013 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -07001014
1015 spin_unlock_irqrestore(&stallion_lock, flags);
1016
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1018 tty_wait_until_sent(tty, portp->closing_wait);
1019 stl_waituntilsent(tty, (HZ / 2));
1020
Alan Coxb65b5b52006-06-27 02:54:05 -07001021
1022 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -07001024 spin_unlock_irqrestore(&stallion_lock, flags);
1025
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 stl_disableintrs(portp);
1027 if (tty->termios->c_cflag & HUPCL)
1028 stl_setsignals(portp, 0, 0);
1029 stl_enablerxtx(portp, 0, 0);
1030 stl_flushbuffer(tty);
1031 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001032 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001034 portp->tx.buf = NULL;
1035 portp->tx.head = NULL;
1036 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 }
1038 set_bit(TTY_IO_ERROR, &tty->flags);
1039 tty_ldisc_flush(tty);
1040
1041 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001042 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
1044 if (portp->openwaitcnt) {
1045 if (portp->close_delay)
1046 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
1047 wake_up_interruptible(&portp->open_wait);
1048 }
1049
1050 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1051 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052}
1053
1054/*****************************************************************************/
1055
1056/*
1057 * Write routine. Take data and stuff it in to the TX ring queue.
1058 * If transmit interrupts are not running then start them.
1059 */
1060
1061static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
1062{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001063 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 unsigned int len, stlen;
1065 unsigned char *chbuf;
1066 char *head, *tail;
1067
Jiri Slabya0564e12006-12-08 02:38:37 -08001068 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001071 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001072 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001073 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001074 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
1076/*
1077 * If copying direct from user space we must cater for page faults,
1078 * causing us to "sleep" here for a while. To handle this copy in all
1079 * the data we need now, into a local buffer. Then when we got it all
1080 * copy it into the TX buffer.
1081 */
1082 chbuf = (unsigned char *) buf;
1083
1084 head = portp->tx.head;
1085 tail = portp->tx.tail;
1086 if (head >= tail) {
1087 len = STL_TXBUFSIZE - (head - tail) - 1;
1088 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1089 } else {
1090 len = tail - head - 1;
1091 stlen = len;
1092 }
1093
1094 len = MIN(len, count);
1095 count = 0;
1096 while (len > 0) {
1097 stlen = MIN(len, stlen);
1098 memcpy(head, chbuf, stlen);
1099 len -= stlen;
1100 chbuf += stlen;
1101 count += stlen;
1102 head += stlen;
1103 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1104 head = portp->tx.buf;
1105 stlen = tail - head;
1106 }
1107 }
1108 portp->tx.head = head;
1109
1110 clear_bit(ASYI_TXLOW, &portp->istate);
1111 stl_startrxtx(portp, -1, 1);
1112
Jesper Juhl014c2542006-01-15 02:37:08 +01001113 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114}
1115
1116/*****************************************************************************/
1117
1118static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1119{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001120 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 unsigned int len;
1122 char *head, *tail;
1123
Jiri Slabya0564e12006-12-08 02:38:37 -08001124 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
Jiri Slaby615e4a72006-12-08 02:38:38 -08001126 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 return;
1128 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001129 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001131 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 return;
1133
1134 head = portp->tx.head;
1135 tail = portp->tx.tail;
1136
1137 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1138 len--;
1139
1140 if (len > 0) {
1141 *head++ = ch;
1142 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1143 head = portp->tx.buf;
1144 }
1145 portp->tx.head = head;
1146}
1147
1148/*****************************************************************************/
1149
1150/*
1151 * If there are any characters in the buffer then make sure that TX
1152 * interrupts are on and get'em out. Normally used after the putchar
1153 * routine has been called.
1154 */
1155
1156static void stl_flushchars(struct tty_struct *tty)
1157{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001158 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
Jiri Slabya0564e12006-12-08 02:38:37 -08001160 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Jiri Slaby615e4a72006-12-08 02:38:38 -08001162 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return;
1164 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001165 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001167 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 return;
1169
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 stl_startrxtx(portp, -1, 1);
1171}
1172
1173/*****************************************************************************/
1174
1175static int stl_writeroom(struct tty_struct *tty)
1176{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001177 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 char *head, *tail;
1179
Jiri Slabya0564e12006-12-08 02:38:37 -08001180 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
Jiri Slaby615e4a72006-12-08 02:38:38 -08001182 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001183 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001185 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001186 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001187 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001188 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
1190 head = portp->tx.head;
1191 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001192 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193}
1194
1195/*****************************************************************************/
1196
1197/*
1198 * Return number of chars in the TX buffer. Normally we would just
1199 * calculate the number of chars in the buffer and return that, but if
1200 * the buffer is empty and TX interrupts are still on then we return
1201 * that the buffer still has 1 char in it. This way whoever called us
1202 * will not think that ALL chars have drained - since the UART still
1203 * must have some chars in it (we are busy after all).
1204 */
1205
1206static int stl_charsinbuffer(struct tty_struct *tty)
1207{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001208 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 unsigned int size;
1210 char *head, *tail;
1211
Jiri Slabya0564e12006-12-08 02:38:37 -08001212 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
Jiri Slaby615e4a72006-12-08 02:38:38 -08001214 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001215 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001217 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001218 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001219 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001220 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222 head = portp->tx.head;
1223 tail = portp->tx.tail;
1224 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1225 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1226 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001227 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228}
1229
1230/*****************************************************************************/
1231
1232/*
1233 * Generate the serial struct info.
1234 */
1235
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001236static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237{
1238 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001239 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Jiri Slabya0564e12006-12-08 02:38:37 -08001241 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243 memset(&sio, 0, sizeof(struct serial_struct));
1244 sio.line = portp->portnr;
1245 sio.port = portp->ioaddr;
1246 sio.flags = portp->flags;
1247 sio.baud_base = portp->baud_base;
1248 sio.close_delay = portp->close_delay;
1249 sio.closing_wait = portp->closing_wait;
1250 sio.custom_divisor = portp->custom_divisor;
1251 sio.hub6 = 0;
1252 if (portp->uartp == &stl_cd1400uart) {
1253 sio.type = PORT_CIRRUS;
1254 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1255 } else {
1256 sio.type = PORT_UNKNOWN;
1257 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1258 }
1259
1260 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001261 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 sio.irq = brdp->irq;
1263
1264 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1265}
1266
1267/*****************************************************************************/
1268
1269/*
1270 * Set port according to the serial struct info.
1271 * At this point we do not do any auto-configure stuff, so we will
1272 * just quietly ignore any requests to change irq, etc.
1273 */
1274
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001275static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276{
1277 struct serial_struct sio;
1278
Jiri Slabya0564e12006-12-08 02:38:37 -08001279 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
1281 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1282 return -EFAULT;
1283 if (!capable(CAP_SYS_ADMIN)) {
1284 if ((sio.baud_base != portp->baud_base) ||
1285 (sio.close_delay != portp->close_delay) ||
1286 ((sio.flags & ~ASYNC_USR_MASK) !=
1287 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001288 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 }
1290
1291 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1292 (sio.flags & ASYNC_USR_MASK);
1293 portp->baud_base = sio.baud_base;
1294 portp->close_delay = sio.close_delay;
1295 portp->closing_wait = sio.closing_wait;
1296 portp->custom_divisor = sio.custom_divisor;
1297 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001298 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299}
1300
1301/*****************************************************************************/
1302
1303static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1304{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001305 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Jiri Slaby615e4a72006-12-08 02:38:38 -08001307 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001308 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001310 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001311 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001313 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
1315 return stl_getsignals(portp);
1316}
1317
1318static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1319 unsigned int set, unsigned int clear)
1320{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001321 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 int rts = -1, dtr = -1;
1323
Jiri Slaby615e4a72006-12-08 02:38:38 -08001324 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001325 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001327 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001328 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001330 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331
1332 if (set & TIOCM_RTS)
1333 rts = 1;
1334 if (set & TIOCM_DTR)
1335 dtr = 1;
1336 if (clear & TIOCM_RTS)
1337 rts = 0;
1338 if (clear & TIOCM_DTR)
1339 dtr = 0;
1340
1341 stl_setsignals(portp, dtr, rts);
1342 return 0;
1343}
1344
1345static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1346{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001347 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 unsigned int ival;
1349 int rc;
1350 void __user *argp = (void __user *)arg;
1351
Jiri Slabya0564e12006-12-08 02:38:37 -08001352 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1353 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Jiri Slaby615e4a72006-12-08 02:38:38 -08001355 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001356 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001358 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001359 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1362 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1363 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001364 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 }
1366
1367 rc = 0;
1368
1369 switch (cmd) {
1370 case TIOCGSOFTCAR:
1371 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1372 (unsigned __user *) argp);
1373 break;
1374 case TIOCSSOFTCAR:
1375 if (get_user(ival, (unsigned int __user *) arg))
1376 return -EFAULT;
1377 tty->termios->c_cflag =
1378 (tty->termios->c_cflag & ~CLOCAL) |
1379 (ival ? CLOCAL : 0);
1380 break;
1381 case TIOCGSERIAL:
1382 rc = stl_getserial(portp, argp);
1383 break;
1384 case TIOCSSERIAL:
1385 rc = stl_setserial(portp, argp);
1386 break;
1387 case COM_GETPORTSTATS:
1388 rc = stl_getportstats(portp, argp);
1389 break;
1390 case COM_CLRPORTSTATS:
1391 rc = stl_clrportstats(portp, argp);
1392 break;
1393 case TIOCSERCONFIG:
1394 case TIOCSERGWILD:
1395 case TIOCSERSWILD:
1396 case TIOCSERGETLSR:
1397 case TIOCSERGSTRUCT:
1398 case TIOCSERGETMULTI:
1399 case TIOCSERSETMULTI:
1400 default:
1401 rc = -ENOIOCTLCMD;
1402 break;
1403 }
1404
Jesper Juhl014c2542006-01-15 02:37:08 +01001405 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406}
1407
1408/*****************************************************************************/
1409
Jiri Slaby96b066b2006-12-08 02:38:42 -08001410/*
1411 * Start the transmitter again. Just turn TX interrupts back on.
1412 */
1413
1414static void stl_start(struct tty_struct *tty)
1415{
1416 struct stlport *portp;
1417
1418 pr_debug("stl_start(tty=%p)\n", tty);
1419
1420 if (tty == NULL)
1421 return;
1422 portp = tty->driver_data;
1423 if (portp == NULL)
1424 return;
1425 stl_startrxtx(portp, -1, 1);
1426}
1427
1428/*****************************************************************************/
1429
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430static void stl_settermios(struct tty_struct *tty, struct termios *old)
1431{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001432 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 struct termios *tiosp;
1434
Jiri Slabya0564e12006-12-08 02:38:37 -08001435 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Jiri Slaby615e4a72006-12-08 02:38:38 -08001437 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 return;
1439 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001440 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 return;
1442
1443 tiosp = tty->termios;
1444 if ((tiosp->c_cflag == old->c_cflag) &&
1445 (tiosp->c_iflag == old->c_iflag))
1446 return;
1447
1448 stl_setport(portp, tiosp);
1449 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1450 -1);
1451 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1452 tty->hw_stopped = 0;
1453 stl_start(tty);
1454 }
1455 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1456 wake_up_interruptible(&portp->open_wait);
1457}
1458
1459/*****************************************************************************/
1460
1461/*
1462 * Attempt to flow control who ever is sending us data. Based on termios
1463 * settings use software or/and hardware flow control.
1464 */
1465
1466static void stl_throttle(struct tty_struct *tty)
1467{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001468 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Jiri Slabya0564e12006-12-08 02:38:37 -08001470 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
Jiri Slaby615e4a72006-12-08 02:38:38 -08001472 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 return;
1474 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001475 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 return;
1477 stl_flowctrl(portp, 0);
1478}
1479
1480/*****************************************************************************/
1481
1482/*
1483 * Unflow control the device sending us data...
1484 */
1485
1486static void stl_unthrottle(struct tty_struct *tty)
1487{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001488 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489
Jiri Slabya0564e12006-12-08 02:38:37 -08001490 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Jiri Slaby615e4a72006-12-08 02:38:38 -08001492 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 return;
1494 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001495 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 return;
1497 stl_flowctrl(portp, 1);
1498}
1499
1500/*****************************************************************************/
1501
1502/*
1503 * Stop the transmitter. Basically to do this we will just turn TX
1504 * interrupts off.
1505 */
1506
1507static void stl_stop(struct tty_struct *tty)
1508{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001509 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
Jiri Slabya0564e12006-12-08 02:38:37 -08001511 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
Jiri Slaby615e4a72006-12-08 02:38:38 -08001513 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 return;
1515 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001516 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 return;
1518 stl_startrxtx(portp, -1, 0);
1519}
1520
1521/*****************************************************************************/
1522
1523/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 * Hangup this port. This is pretty much like closing the port, only
1525 * a little more brutal. No waiting for data to drain. Shutdown the
1526 * port and maybe drop signals.
1527 */
1528
1529static void stl_hangup(struct tty_struct *tty)
1530{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001531 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
Jiri Slabya0564e12006-12-08 02:38:37 -08001533 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Jiri Slaby615e4a72006-12-08 02:38:38 -08001535 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 return;
1537 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001538 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 return;
1540
1541 portp->flags &= ~ASYNC_INITIALIZED;
1542 stl_disableintrs(portp);
1543 if (tty->termios->c_cflag & HUPCL)
1544 stl_setsignals(portp, 0, 0);
1545 stl_enablerxtx(portp, 0, 0);
1546 stl_flushbuffer(tty);
1547 portp->istate = 0;
1548 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001549 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001551 portp->tx.buf = NULL;
1552 portp->tx.head = NULL;
1553 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001555 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1557 portp->refcount = 0;
1558 wake_up_interruptible(&portp->open_wait);
1559}
1560
1561/*****************************************************************************/
1562
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563static void stl_breakctl(struct tty_struct *tty, int state)
1564{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001565 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
Jiri Slabya0564e12006-12-08 02:38:37 -08001567 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
Jiri Slaby615e4a72006-12-08 02:38:38 -08001569 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 return;
1571 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001572 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 return;
1574
1575 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1576}
1577
1578/*****************************************************************************/
1579
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580static void stl_sendxchar(struct tty_struct *tty, char ch)
1581{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001582 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Jiri Slabya0564e12006-12-08 02:38:37 -08001584 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
Jiri Slaby615e4a72006-12-08 02:38:38 -08001586 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 return;
1588 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001589 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 return;
1591
1592 if (ch == STOP_CHAR(tty))
1593 stl_sendflow(portp, 0);
1594 else if (ch == START_CHAR(tty))
1595 stl_sendflow(portp, 1);
1596 else
1597 stl_putchar(tty, ch);
1598}
1599
1600/*****************************************************************************/
1601
1602#define MAXLINE 80
1603
1604/*
1605 * Format info for a specified port. The line is deliberately limited
1606 * to 80 characters. (If it is too long it will be truncated, if too
1607 * short then padded with spaces).
1608 */
1609
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001610static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611{
1612 char *sp;
1613 int sigs, cnt;
1614
1615 sp = pos;
1616 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1617 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1618 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1619
1620 if (portp->stats.rxframing)
1621 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1622 if (portp->stats.rxparity)
1623 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1624 if (portp->stats.rxbreaks)
1625 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1626 if (portp->stats.rxoverrun)
1627 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1628
1629 sigs = stl_getsignals(portp);
1630 cnt = sprintf(sp, "%s%s%s%s%s ",
1631 (sigs & TIOCM_RTS) ? "|RTS" : "",
1632 (sigs & TIOCM_CTS) ? "|CTS" : "",
1633 (sigs & TIOCM_DTR) ? "|DTR" : "",
1634 (sigs & TIOCM_CD) ? "|DCD" : "",
1635 (sigs & TIOCM_DSR) ? "|DSR" : "");
1636 *sp = ' ';
1637 sp += cnt;
1638
1639 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1640 *sp++ = ' ';
1641 if (cnt >= MAXLINE)
1642 pos[(MAXLINE - 2)] = '+';
1643 pos[(MAXLINE - 1)] = '\n';
1644
Jesper Juhl014c2542006-01-15 02:37:08 +01001645 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646}
1647
1648/*****************************************************************************/
1649
1650/*
1651 * Port info, read from the /proc file system.
1652 */
1653
1654static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1655{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001656 struct stlbrd *brdp;
1657 struct stlpanel *panelp;
1658 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 int brdnr, panelnr, portnr, totalport;
1660 int curoff, maxoff;
1661 char *pos;
1662
Jiri Slabya0564e12006-12-08 02:38:37 -08001663 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1664 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
1666 pos = page;
1667 totalport = 0;
1668 curoff = 0;
1669
1670 if (off == 0) {
1671 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1672 stl_drvversion);
1673 while (pos < (page + MAXLINE - 1))
1674 *pos++ = ' ';
1675 *pos++ = '\n';
1676 }
1677 curoff = MAXLINE;
1678
1679/*
1680 * We scan through for each board, panel and port. The offset is
1681 * calculated on the fly, and irrelevant ports are skipped.
1682 */
1683 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1684 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001685 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 continue;
1687 if (brdp->state == 0)
1688 continue;
1689
1690 maxoff = curoff + (brdp->nrports * MAXLINE);
1691 if (off >= maxoff) {
1692 curoff = maxoff;
1693 continue;
1694 }
1695
1696 totalport = brdnr * STL_MAXPORTS;
1697 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1698 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001699 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 continue;
1701
1702 maxoff = curoff + (panelp->nrports * MAXLINE);
1703 if (off >= maxoff) {
1704 curoff = maxoff;
1705 totalport += panelp->nrports;
1706 continue;
1707 }
1708
1709 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1710 totalport++) {
1711 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001712 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 continue;
1714 if (off >= (curoff += MAXLINE))
1715 continue;
1716 if ((pos - page + MAXLINE) > count)
1717 goto stl_readdone;
1718 pos += stl_portinfo(portp, totalport, pos);
1719 }
1720 }
1721 }
1722
1723 *eof = 1;
1724
1725stl_readdone:
1726 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001727 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728}
1729
1730/*****************************************************************************/
1731
1732/*
1733 * All board interrupts are vectored through here first. This code then
1734 * calls off to the approrpriate board interrupt handlers.
1735 */
1736
David Howells7d12e782006-10-05 14:55:46 +01001737static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001739 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
Jiri Slabya0564e12006-12-08 02:38:37 -08001741 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
1743 return IRQ_RETVAL((* brdp->isr)(brdp));
1744}
1745
1746/*****************************************************************************/
1747
1748/*
1749 * Interrupt service routine for EasyIO board types.
1750 */
1751
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001752static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001754 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 unsigned int iobase;
1756 int handled = 0;
1757
Alan Coxb65b5b52006-06-27 02:54:05 -07001758 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 panelp = brdp->panels[0];
1760 iobase = panelp->iobase;
1761 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1762 handled = 1;
1763 (* panelp->isr)(panelp, iobase);
1764 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001765 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 return handled;
1767}
1768
1769/*****************************************************************************/
1770
1771/*
1772 * Interrupt service routine for ECH-AT board types.
1773 */
1774
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001775static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001777 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 unsigned int ioaddr;
1779 int bnknr;
1780 int handled = 0;
1781
1782 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1783
1784 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1785 handled = 1;
1786 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1787 ioaddr = brdp->bnkstataddr[bnknr];
1788 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1789 panelp = brdp->bnk2panel[bnknr];
1790 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1791 }
1792 }
1793 }
1794
1795 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1796
1797 return handled;
1798}
1799
1800/*****************************************************************************/
1801
1802/*
1803 * Interrupt service routine for ECH-MCA board types.
1804 */
1805
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001806static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001808 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 unsigned int ioaddr;
1810 int bnknr;
1811 int handled = 0;
1812
1813 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1814 handled = 1;
1815 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1816 ioaddr = brdp->bnkstataddr[bnknr];
1817 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1818 panelp = brdp->bnk2panel[bnknr];
1819 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1820 }
1821 }
1822 }
1823 return handled;
1824}
1825
1826/*****************************************************************************/
1827
1828/*
1829 * Interrupt service routine for ECH-PCI board types.
1830 */
1831
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001832static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001834 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 unsigned int ioaddr;
1836 int bnknr, recheck;
1837 int handled = 0;
1838
1839 while (1) {
1840 recheck = 0;
1841 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1842 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1843 ioaddr = brdp->bnkstataddr[bnknr];
1844 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1845 panelp = brdp->bnk2panel[bnknr];
1846 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1847 recheck++;
1848 handled = 1;
1849 }
1850 }
1851 if (! recheck)
1852 break;
1853 }
1854 return handled;
1855}
1856
1857/*****************************************************************************/
1858
1859/*
1860 * Interrupt service routine for ECH-8/64-PCI board types.
1861 */
1862
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001863static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001865 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 unsigned int ioaddr;
1867 int bnknr;
1868 int handled = 0;
1869
1870 while (inb(brdp->ioctrl) & 0x1) {
1871 handled = 1;
1872 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1873 ioaddr = brdp->bnkstataddr[bnknr];
1874 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1875 panelp = brdp->bnk2panel[bnknr];
1876 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1877 }
1878 }
1879 }
1880
1881 return handled;
1882}
1883
1884/*****************************************************************************/
1885
1886/*
1887 * Service an off-level request for some channel.
1888 */
Al Viro3e577a82006-12-06 18:41:45 +00001889static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001891 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 struct tty_struct *tty;
1893 unsigned int oldsigs;
1894
Jiri Slabya0564e12006-12-08 02:38:37 -08001895 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
Jiri Slaby615e4a72006-12-08 02:38:38 -08001897 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 return;
1899
1900 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001901 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 return;
1903
1904 lock_kernel();
1905 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1906 tty_wakeup(tty);
1907 }
1908 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1909 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1910 oldsigs = portp->sigs;
1911 portp->sigs = stl_getsignals(portp);
1912 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1913 wake_up_interruptible(&portp->open_wait);
1914 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1915 if (portp->flags & ASYNC_CHECK_CD)
1916 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1917 }
1918 }
1919 unlock_kernel();
1920}
1921
1922/*****************************************************************************/
1923
1924/*
1925 * Initialize all the ports on a panel.
1926 */
1927
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001928static int __init stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001930 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 int chipmask, i;
1932
Jiri Slabya0564e12006-12-08 02:38:37 -08001933 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
1935 chipmask = stl_panelinit(brdp, panelp);
1936
1937/*
1938 * All UART's are initialized (if found!). Now go through and setup
1939 * each ports data structures.
1940 */
1941 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001942 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001943 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001945 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 break;
1947 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948
1949 portp->magic = STL_PORTMAGIC;
1950 portp->portnr = i;
1951 portp->brdnr = panelp->brdnr;
1952 portp->panelnr = panelp->panelnr;
1953 portp->uartp = panelp->uartp;
1954 portp->clk = brdp->clk;
1955 portp->baud_base = STL_BAUDBASE;
1956 portp->close_delay = STL_CLOSEDELAY;
1957 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001958 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 init_waitqueue_head(&portp->open_wait);
1960 init_waitqueue_head(&portp->close_wait);
1961 portp->stats.brd = portp->brdnr;
1962 portp->stats.panel = portp->panelnr;
1963 portp->stats.port = portp->portnr;
1964 panelp->ports[i] = portp;
1965 stl_portinit(brdp, panelp, portp);
1966 }
1967
1968 return(0);
1969}
1970
1971/*****************************************************************************/
1972
1973/*
1974 * Try to find and initialize an EasyIO board.
1975 */
1976
Jiri Slaby40e82652006-12-08 02:38:41 -08001977static int __init stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001979 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 unsigned int status;
1981 char *name;
1982 int rc;
1983
Jiri Slabya0564e12006-12-08 02:38:37 -08001984 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
1986 brdp->ioctrl = brdp->ioaddr1 + 1;
1987 brdp->iostatus = brdp->ioaddr1 + 2;
1988
1989 status = inb(brdp->iostatus);
1990 if ((status & EIO_IDBITMASK) == EIO_MK3)
1991 brdp->ioctrl++;
1992
1993/*
1994 * Handle board specific stuff now. The real difference is PCI
1995 * or not PCI.
1996 */
1997 if (brdp->brdtype == BRD_EASYIOPCI) {
1998 brdp->iosize1 = 0x80;
1999 brdp->iosize2 = 0x80;
2000 name = "serial(EIO-PCI)";
2001 outb(0x41, (brdp->ioaddr2 + 0x4c));
2002 } else {
2003 brdp->iosize1 = 8;
2004 name = "serial(EIO)";
2005 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2006 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2007 printk("STALLION: invalid irq=%d for brd=%d\n",
2008 brdp->irq, brdp->brdnr);
2009 return(-EINVAL);
2010 }
2011 outb((stl_vecmap[brdp->irq] | EIO_0WS |
2012 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
2013 brdp->ioctrl);
2014 }
2015
2016 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2017 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2018 "%x conflicts with another device\n", brdp->brdnr,
2019 brdp->ioaddr1);
2020 return(-EBUSY);
2021 }
2022
2023 if (brdp->iosize2 > 0)
2024 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2025 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2026 "address %x conflicts with another device\n",
2027 brdp->brdnr, brdp->ioaddr2);
2028 printk(KERN_WARNING "STALLION: Warning, also "
2029 "releasing board %d I/O address %x \n",
2030 brdp->brdnr, brdp->ioaddr1);
2031 release_region(brdp->ioaddr1, brdp->iosize1);
2032 return(-EBUSY);
2033 }
2034
2035/*
2036 * Everything looks OK, so let's go ahead and probe for the hardware.
2037 */
2038 brdp->clk = CD1400_CLK;
2039 brdp->isr = stl_eiointr;
2040
2041 switch (status & EIO_IDBITMASK) {
2042 case EIO_8PORTM:
2043 brdp->clk = CD1400_CLK8M;
2044 /* fall thru */
2045 case EIO_8PORTRS:
2046 case EIO_8PORTDI:
2047 brdp->nrports = 8;
2048 break;
2049 case EIO_4PORTRS:
2050 brdp->nrports = 4;
2051 break;
2052 case EIO_MK3:
2053 switch (status & EIO_BRDMASK) {
2054 case ID_BRD4:
2055 brdp->nrports = 4;
2056 break;
2057 case ID_BRD8:
2058 brdp->nrports = 8;
2059 break;
2060 case ID_BRD16:
2061 brdp->nrports = 16;
2062 break;
2063 default:
2064 return(-ENODEV);
2065 }
2066 break;
2067 default:
2068 return(-ENODEV);
2069 }
2070
2071/*
2072 * We have verified that the board is actually present, so now we
2073 * can complete the setup.
2074 */
2075
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002076 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002077 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002079 "(size=%Zd)\n", sizeof(struct stlpanel));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002080 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082
2083 panelp->magic = STL_PANELMAGIC;
2084 panelp->brdnr = brdp->brdnr;
2085 panelp->panelnr = 0;
2086 panelp->nrports = brdp->nrports;
2087 panelp->iobase = brdp->ioaddr1;
2088 panelp->hwid = status;
2089 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002090 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 panelp->isr = stl_sc26198intr;
2092 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002093 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 panelp->isr = stl_cd1400eiointr;
2095 }
2096
2097 brdp->panels[0] = panelp;
2098 brdp->nrpanels = 1;
2099 brdp->state |= BRD_FOUND;
2100 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002101 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 printk("STALLION: failed to register interrupt "
2103 "routine for %s irq=%d\n", name, brdp->irq);
2104 rc = -ENODEV;
2105 } else {
2106 rc = 0;
2107 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002108 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109}
2110
2111/*****************************************************************************/
2112
2113/*
2114 * Try to find an ECH board and initialize it. This code is capable of
2115 * dealing with all types of ECH board.
2116 */
2117
Jiri Slaby40e82652006-12-08 02:38:41 -08002118static int __init stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002120 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 unsigned int status, nxtid, ioaddr, conflict;
2122 int panelnr, banknr, i;
2123 char *name;
2124
Jiri Slabya0564e12006-12-08 02:38:37 -08002125 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
2127 status = 0;
2128 conflict = 0;
2129
2130/*
2131 * Set up the initial board register contents for boards. This varies a
2132 * bit between the different board types. So we need to handle each
2133 * separately. Also do a check that the supplied IRQ is good.
2134 */
2135 switch (brdp->brdtype) {
2136
2137 case BRD_ECH:
2138 brdp->isr = stl_echatintr;
2139 brdp->ioctrl = brdp->ioaddr1 + 1;
2140 brdp->iostatus = brdp->ioaddr1 + 1;
2141 status = inb(brdp->iostatus);
2142 if ((status & ECH_IDBITMASK) != ECH_ID)
2143 return(-ENODEV);
2144 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2145 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2146 printk("STALLION: invalid irq=%d for brd=%d\n",
2147 brdp->irq, brdp->brdnr);
2148 return(-EINVAL);
2149 }
2150 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2151 status |= (stl_vecmap[brdp->irq] << 1);
2152 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2153 brdp->ioctrlval = ECH_INTENABLE |
2154 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2155 for (i = 0; (i < 10); i++)
2156 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2157 brdp->iosize1 = 2;
2158 brdp->iosize2 = 32;
2159 name = "serial(EC8/32)";
2160 outb(status, brdp->ioaddr1);
2161 break;
2162
2163 case BRD_ECHMC:
2164 brdp->isr = stl_echmcaintr;
2165 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2166 brdp->iostatus = brdp->ioctrl;
2167 status = inb(brdp->iostatus);
2168 if ((status & ECH_IDBITMASK) != ECH_ID)
2169 return(-ENODEV);
2170 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2171 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2172 printk("STALLION: invalid irq=%d for brd=%d\n",
2173 brdp->irq, brdp->brdnr);
2174 return(-EINVAL);
2175 }
2176 outb(ECHMC_BRDRESET, brdp->ioctrl);
2177 outb(ECHMC_INTENABLE, brdp->ioctrl);
2178 brdp->iosize1 = 64;
2179 name = "serial(EC8/32-MC)";
2180 break;
2181
2182 case BRD_ECHPCI:
2183 brdp->isr = stl_echpciintr;
2184 brdp->ioctrl = brdp->ioaddr1 + 2;
2185 brdp->iosize1 = 4;
2186 brdp->iosize2 = 8;
2187 name = "serial(EC8/32-PCI)";
2188 break;
2189
2190 case BRD_ECH64PCI:
2191 brdp->isr = stl_echpci64intr;
2192 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2193 outb(0x43, (brdp->ioaddr1 + 0x4c));
2194 brdp->iosize1 = 0x80;
2195 brdp->iosize2 = 0x80;
2196 name = "serial(EC8/64-PCI)";
2197 break;
2198
2199 default:
2200 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
2201 return(-EINVAL);
2202 break;
2203 }
2204
2205/*
2206 * Check boards for possible IO address conflicts and return fail status
2207 * if an IO conflict found.
2208 */
2209 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2210 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2211 "%x conflicts with another device\n", brdp->brdnr,
2212 brdp->ioaddr1);
2213 return(-EBUSY);
2214 }
2215
2216 if (brdp->iosize2 > 0)
2217 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2218 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2219 "address %x conflicts with another device\n",
2220 brdp->brdnr, brdp->ioaddr2);
2221 printk(KERN_WARNING "STALLION: Warning, also "
2222 "releasing board %d I/O address %x \n",
2223 brdp->brdnr, brdp->ioaddr1);
2224 release_region(brdp->ioaddr1, brdp->iosize1);
2225 return(-EBUSY);
2226 }
2227
2228/*
2229 * Scan through the secondary io address space looking for panels.
2230 * As we find'em allocate and initialize panel structures for each.
2231 */
2232 brdp->clk = CD1400_CLK;
2233 brdp->hwid = status;
2234
2235 ioaddr = brdp->ioaddr2;
2236 banknr = 0;
2237 panelnr = 0;
2238 nxtid = 0;
2239
2240 for (i = 0; (i < STL_MAXPANELS); i++) {
2241 if (brdp->brdtype == BRD_ECHPCI) {
2242 outb(nxtid, brdp->ioctrl);
2243 ioaddr = brdp->ioaddr2;
2244 }
2245 status = inb(ioaddr + ECH_PNLSTATUS);
2246 if ((status & ECH_PNLIDMASK) != nxtid)
2247 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002248 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002249 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002251 "(size=%Zd)\n", sizeof(struct stlpanel));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 break;
2253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 panelp->magic = STL_PANELMAGIC;
2255 panelp->brdnr = brdp->brdnr;
2256 panelp->panelnr = panelnr;
2257 panelp->iobase = ioaddr;
2258 panelp->pagenr = nxtid;
2259 panelp->hwid = status;
2260 brdp->bnk2panel[banknr] = panelp;
2261 brdp->bnkpageaddr[banknr] = nxtid;
2262 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2263
2264 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002265 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 panelp->isr = stl_sc26198intr;
2267 if (status & ECH_PNL16PORT) {
2268 panelp->nrports = 16;
2269 brdp->bnk2panel[banknr] = panelp;
2270 brdp->bnkpageaddr[banknr] = nxtid;
2271 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2272 ECH_PNLSTATUS;
2273 } else {
2274 panelp->nrports = 8;
2275 }
2276 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002277 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 panelp->isr = stl_cd1400echintr;
2279 if (status & ECH_PNL16PORT) {
2280 panelp->nrports = 16;
2281 panelp->ackmask = 0x80;
2282 if (brdp->brdtype != BRD_ECHPCI)
2283 ioaddr += EREG_BANKSIZE;
2284 brdp->bnk2panel[banknr] = panelp;
2285 brdp->bnkpageaddr[banknr] = ++nxtid;
2286 brdp->bnkstataddr[banknr++] = ioaddr +
2287 ECH_PNLSTATUS;
2288 } else {
2289 panelp->nrports = 8;
2290 panelp->ackmask = 0xc0;
2291 }
2292 }
2293
2294 nxtid++;
2295 ioaddr += EREG_BANKSIZE;
2296 brdp->nrports += panelp->nrports;
2297 brdp->panels[panelnr++] = panelp;
2298 if ((brdp->brdtype != BRD_ECHPCI) &&
2299 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
2300 break;
2301 }
2302
2303 brdp->nrpanels = panelnr;
2304 brdp->nrbnks = banknr;
2305 if (brdp->brdtype == BRD_ECH)
2306 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2307
2308 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002309 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 printk("STALLION: failed to register interrupt "
2311 "routine for %s irq=%d\n", name, brdp->irq);
2312 i = -ENODEV;
2313 } else {
2314 i = 0;
2315 }
2316
2317 return(i);
2318}
2319
2320/*****************************************************************************/
2321
2322/*
2323 * Initialize and configure the specified board.
2324 * Scan through all the boards in the configuration and see what we
2325 * can find. Handle EIO and the ECH boards a little differently here
2326 * since the initial search and setup is very different.
2327 */
2328
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002329static int __init stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330{
2331 int i;
2332
Jiri Slabya0564e12006-12-08 02:38:37 -08002333 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334
2335 switch (brdp->brdtype) {
2336 case BRD_EASYIO:
2337 case BRD_EASYIOPCI:
2338 stl_initeio(brdp);
2339 break;
2340 case BRD_ECH:
2341 case BRD_ECHMC:
2342 case BRD_ECHPCI:
2343 case BRD_ECH64PCI:
2344 stl_initech(brdp);
2345 break;
2346 default:
2347 printk("STALLION: board=%d is unknown board type=%d\n",
2348 brdp->brdnr, brdp->brdtype);
2349 return(ENODEV);
2350 }
2351
2352 stl_brds[brdp->brdnr] = brdp;
2353 if ((brdp->state & BRD_FOUND) == 0) {
2354 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2355 stl_brdnames[brdp->brdtype], brdp->brdnr,
2356 brdp->ioaddr1, brdp->irq);
2357 return(ENODEV);
2358 }
2359
2360 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002361 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 stl_initports(brdp, brdp->panels[i]);
2363
2364 printk("STALLION: %s found, board=%d io=%x irq=%d "
2365 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2366 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2367 brdp->nrports);
2368 return(0);
2369}
2370
2371/*****************************************************************************/
2372
2373/*
2374 * Find the next available board number that is free.
2375 */
2376
Jiri Slaby40e82652006-12-08 02:38:41 -08002377static int __init stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378{
2379 int i;
2380
2381 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002382 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 if (i >= stl_nrbrds)
2384 stl_nrbrds = i + 1;
2385 return(i);
2386 }
2387 }
2388 return(-1);
2389}
2390
2391/*****************************************************************************/
2392
2393#ifdef CONFIG_PCI
2394
2395/*
2396 * We have a Stallion board. Allocate a board structure and
2397 * initialize it. Read its IO and IRQ resources from PCI
2398 * configuration space.
2399 */
2400
Jiri Slaby40e82652006-12-08 02:38:41 -08002401static int __init stl_initpcibrd(int brdtype, struct pci_dev *devp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002403 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
Jiri Slabya0564e12006-12-08 02:38:37 -08002405 pr_debug("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 devp->bus->number, devp->devfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
2408 if (pci_enable_device(devp))
2409 return(-EIO);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002410 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 return(-ENOMEM);
2412 if ((brdp->brdnr = stl_getbrdnr()) < 0) {
2413 printk("STALLION: too many boards found, "
2414 "maximum supported %d\n", STL_MAXBRDS);
2415 return(0);
2416 }
2417 brdp->brdtype = brdtype;
2418
2419/*
2420 * Different Stallion boards use the BAR registers in different ways,
2421 * so set up io addresses based on board type.
2422 */
Jiri Slabya0564e12006-12-08 02:38:37 -08002423 pr_debug("%s(%d): BAR[]=%Lx,%Lx,%Lx,%Lx IRQ=%x\n", __FILE__, __LINE__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 pci_resource_start(devp, 0), pci_resource_start(devp, 1),
2425 pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
2427/*
2428 * We have all resources from the board, so let's setup the actual
2429 * board structure now.
2430 */
2431 switch (brdtype) {
2432 case BRD_ECHPCI:
2433 brdp->ioaddr2 = pci_resource_start(devp, 0);
2434 brdp->ioaddr1 = pci_resource_start(devp, 1);
2435 break;
2436 case BRD_ECH64PCI:
2437 brdp->ioaddr2 = pci_resource_start(devp, 2);
2438 brdp->ioaddr1 = pci_resource_start(devp, 1);
2439 break;
2440 case BRD_EASYIOPCI:
2441 brdp->ioaddr1 = pci_resource_start(devp, 2);
2442 brdp->ioaddr2 = pci_resource_start(devp, 1);
2443 break;
2444 default:
2445 printk("STALLION: unknown PCI board type=%d\n", brdtype);
2446 break;
2447 }
2448
2449 brdp->irq = devp->irq;
2450 stl_brdinit(brdp);
2451
2452 return(0);
2453}
2454
2455/*****************************************************************************/
2456
2457/*
2458 * Find all Stallion PCI boards that might be installed. Initialize each
2459 * one as it is found.
2460 */
2461
2462
Jiri Slaby40e82652006-12-08 02:38:41 -08002463static int __init stl_findpcibrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464{
2465 struct pci_dev *dev = NULL;
2466 int i, rc;
2467
Jiri Slabya0564e12006-12-08 02:38:37 -08002468 pr_debug("stl_findpcibrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
2470 for (i = 0; (i < stl_nrpcibrds); i++)
2471 while ((dev = pci_find_device(stl_pcibrds[i].vendid,
2472 stl_pcibrds[i].devid, dev))) {
2473
2474/*
2475 * Found a device on the PCI bus that has our vendor and
2476 * device ID. Need to check now that it is really us.
2477 */
2478 if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
2479 continue;
2480
2481 rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
2482 if (rc)
2483 return(rc);
2484 }
2485
2486 return(0);
2487}
2488
2489#endif
2490
2491/*****************************************************************************/
2492
2493/*
2494 * Scan through all the boards in the configuration and see what we
2495 * can find. Handle EIO and the ECH boards a little differently here
2496 * since the initial search and setup is too different.
2497 */
2498
Jiri Slaby40e82652006-12-08 02:38:41 -08002499static int __init stl_initbrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002501 struct stlbrd *brdp;
2502 struct stlconf *confp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 int i;
2504
Jiri Slabya0564e12006-12-08 02:38:37 -08002505 pr_debug("stl_initbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506
2507 if (stl_nrbrds > STL_MAXBRDS) {
2508 printk("STALLION: too many boards in configuration table, "
2509 "truncating to %d\n", STL_MAXBRDS);
2510 stl_nrbrds = STL_MAXBRDS;
2511 }
2512
2513/*
2514 * Firstly scan the list of static boards configured. Allocate
2515 * resources and initialize the boards as found.
2516 */
2517 for (i = 0; (i < stl_nrbrds); i++) {
2518 confp = &stl_brdconf[i];
2519 stl_parsebrd(confp, stl_brdsp[i]);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002520 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 return(-ENOMEM);
2522 brdp->brdnr = i;
2523 brdp->brdtype = confp->brdtype;
2524 brdp->ioaddr1 = confp->ioaddr1;
2525 brdp->ioaddr2 = confp->ioaddr2;
2526 brdp->irq = confp->irq;
2527 brdp->irqtype = confp->irqtype;
2528 stl_brdinit(brdp);
2529 }
2530
2531/*
2532 * Find any dynamically supported boards. That is via module load
2533 * line options or auto-detected on the PCI bus.
2534 */
2535 stl_argbrds();
2536#ifdef CONFIG_PCI
2537 stl_findpcibrds();
2538#endif
2539
2540 return(0);
2541}
2542
2543/*****************************************************************************/
2544
2545/*
2546 * Return the board stats structure to user app.
2547 */
2548
2549static int stl_getbrdstats(combrd_t __user *bp)
2550{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002551 struct stlbrd *brdp;
2552 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 int i;
2554
2555 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2556 return -EFAULT;
2557 if (stl_brdstats.brd >= STL_MAXBRDS)
2558 return(-ENODEV);
2559 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002560 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 return(-ENODEV);
2562
2563 memset(&stl_brdstats, 0, sizeof(combrd_t));
2564 stl_brdstats.brd = brdp->brdnr;
2565 stl_brdstats.type = brdp->brdtype;
2566 stl_brdstats.hwid = brdp->hwid;
2567 stl_brdstats.state = brdp->state;
2568 stl_brdstats.ioaddr = brdp->ioaddr1;
2569 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2570 stl_brdstats.irq = brdp->irq;
2571 stl_brdstats.nrpanels = brdp->nrpanels;
2572 stl_brdstats.nrports = brdp->nrports;
2573 for (i = 0; (i < brdp->nrpanels); i++) {
2574 panelp = brdp->panels[i];
2575 stl_brdstats.panels[i].panel = i;
2576 stl_brdstats.panels[i].hwid = panelp->hwid;
2577 stl_brdstats.panels[i].nrports = panelp->nrports;
2578 }
2579
2580 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2581}
2582
2583/*****************************************************************************/
2584
2585/*
2586 * Resolve the referenced port number into a port struct pointer.
2587 */
2588
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002589static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002591 struct stlbrd *brdp;
2592 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593
2594 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002595 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002597 if (brdp == NULL)
2598 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002600 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002602 if (panelp == NULL)
2603 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002605 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 return(panelp->ports[portnr]);
2607}
2608
2609/*****************************************************************************/
2610
2611/*
2612 * Return the port stats structure to user app. A NULL port struct
2613 * pointer passed in means that we need to find out from the app
2614 * what port to get stats for (used through board control device).
2615 */
2616
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002617static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618{
2619 unsigned char *head, *tail;
2620 unsigned long flags;
2621
2622 if (!portp) {
2623 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2624 return -EFAULT;
2625 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2626 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002627 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 return(-ENODEV);
2629 }
2630
2631 portp->stats.state = portp->istate;
2632 portp->stats.flags = portp->flags;
2633 portp->stats.hwid = portp->hwid;
2634
2635 portp->stats.ttystate = 0;
2636 portp->stats.cflags = 0;
2637 portp->stats.iflags = 0;
2638 portp->stats.oflags = 0;
2639 portp->stats.lflags = 0;
2640 portp->stats.rxbuffered = 0;
2641
Alan Coxb65b5b52006-06-27 02:54:05 -07002642 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002643 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 if (portp->tty->driver_data == portp) {
2645 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002646 /* No longer available as a statistic */
2647 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002648 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 portp->stats.cflags = portp->tty->termios->c_cflag;
2650 portp->stats.iflags = portp->tty->termios->c_iflag;
2651 portp->stats.oflags = portp->tty->termios->c_oflag;
2652 portp->stats.lflags = portp->tty->termios->c_lflag;
2653 }
2654 }
2655 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002656 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657
2658 head = portp->tx.head;
2659 tail = portp->tx.tail;
2660 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2661 (STL_TXBUFSIZE - (tail - head)));
2662
2663 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2664
2665 return copy_to_user(cp, &portp->stats,
2666 sizeof(comstats_t)) ? -EFAULT : 0;
2667}
2668
2669/*****************************************************************************/
2670
2671/*
2672 * Clear the port stats structure. We also return it zeroed out...
2673 */
2674
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002675static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676{
2677 if (!portp) {
2678 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2679 return -EFAULT;
2680 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2681 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002682 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 return(-ENODEV);
2684 }
2685
2686 memset(&portp->stats, 0, sizeof(comstats_t));
2687 portp->stats.brd = portp->brdnr;
2688 portp->stats.panel = portp->panelnr;
2689 portp->stats.port = portp->portnr;
2690 return copy_to_user(cp, &portp->stats,
2691 sizeof(comstats_t)) ? -EFAULT : 0;
2692}
2693
2694/*****************************************************************************/
2695
2696/*
2697 * Return the entire driver ports structure to a user app.
2698 */
2699
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002700static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002702 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002704 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 return -EFAULT;
2706 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2707 stl_dummyport.portnr);
2708 if (!portp)
2709 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002710 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711}
2712
2713/*****************************************************************************/
2714
2715/*
2716 * Return the entire driver board structure to a user app.
2717 */
2718
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002719static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002721 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002723 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 return -EFAULT;
2725 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2726 return -ENODEV;
2727 brdp = stl_brds[stl_dummybrd.brdnr];
2728 if (!brdp)
2729 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002730 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731}
2732
2733/*****************************************************************************/
2734
2735/*
2736 * The "staliomem" device is also required to do some special operations
2737 * on the board and/or ports. In this driver it is mostly used for stats
2738 * collection.
2739 */
2740
2741static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2742{
2743 int brdnr, rc;
2744 void __user *argp = (void __user *)arg;
2745
Jiri Slabya0564e12006-12-08 02:38:37 -08002746 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747
2748 brdnr = iminor(ip);
2749 if (brdnr >= STL_MAXBRDS)
2750 return(-ENODEV);
2751 rc = 0;
2752
2753 switch (cmd) {
2754 case COM_GETPORTSTATS:
2755 rc = stl_getportstats(NULL, argp);
2756 break;
2757 case COM_CLRPORTSTATS:
2758 rc = stl_clrportstats(NULL, argp);
2759 break;
2760 case COM_GETBRDSTATS:
2761 rc = stl_getbrdstats(argp);
2762 break;
2763 case COM_READPORT:
2764 rc = stl_getportstruct(argp);
2765 break;
2766 case COM_READBOARD:
2767 rc = stl_getbrdstruct(argp);
2768 break;
2769 default:
2770 rc = -ENOIOCTLCMD;
2771 break;
2772 }
2773
2774 return(rc);
2775}
2776
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002777static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 .open = stl_open,
2779 .close = stl_close,
2780 .write = stl_write,
2781 .put_char = stl_putchar,
2782 .flush_chars = stl_flushchars,
2783 .write_room = stl_writeroom,
2784 .chars_in_buffer = stl_charsinbuffer,
2785 .ioctl = stl_ioctl,
2786 .set_termios = stl_settermios,
2787 .throttle = stl_throttle,
2788 .unthrottle = stl_unthrottle,
2789 .stop = stl_stop,
2790 .start = stl_start,
2791 .hangup = stl_hangup,
2792 .flush_buffer = stl_flushbuffer,
2793 .break_ctl = stl_breakctl,
2794 .wait_until_sent = stl_waituntilsent,
2795 .send_xchar = stl_sendxchar,
2796 .read_proc = stl_readproc,
2797 .tiocmget = stl_tiocmget,
2798 .tiocmset = stl_tiocmset,
2799};
2800
2801/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802/* CD1400 HARDWARE FUNCTIONS */
2803/*****************************************************************************/
2804
2805/*
2806 * These functions get/set/update the registers of the cd1400 UARTs.
2807 * Access to the cd1400 registers is via an address/data io port pair.
2808 * (Maybe should make this inline...)
2809 */
2810
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002811static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812{
2813 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002814 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815}
2816
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002817static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818{
2819 outb((regnr + portp->uartaddr), portp->ioaddr);
2820 outb(value, portp->ioaddr + EREG_DATA);
2821}
2822
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002823static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824{
2825 outb((regnr + portp->uartaddr), portp->ioaddr);
2826 if (inb(portp->ioaddr + EREG_DATA) != value) {
2827 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002828 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002830 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831}
2832
2833/*****************************************************************************/
2834
2835/*
2836 * Inbitialize the UARTs in a panel. We don't care what sort of board
2837 * these ports are on - since the port io registers are almost
2838 * identical when dealing with ports.
2839 */
2840
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002841static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842{
2843 unsigned int gfrcr;
2844 int chipmask, i, j;
2845 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002846 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847
Jiri Slabya0564e12006-12-08 02:38:37 -08002848 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849
Alan Coxb65b5b52006-06-27 02:54:05 -07002850 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 BRDENABLE(panelp->brdnr, panelp->pagenr);
2852
2853/*
2854 * Check that each chip is present and started up OK.
2855 */
2856 chipmask = 0;
2857 nrchips = panelp->nrports / CD1400_PORTS;
2858 for (i = 0; (i < nrchips); i++) {
2859 if (brdp->brdtype == BRD_ECHPCI) {
2860 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2861 ioaddr = panelp->iobase;
2862 } else {
2863 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2864 }
2865 uartaddr = (i & 0x01) ? 0x080 : 0;
2866 outb((GFRCR + uartaddr), ioaddr);
2867 outb(0, (ioaddr + EREG_DATA));
2868 outb((CCR + uartaddr), ioaddr);
2869 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2870 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2871 outb((GFRCR + uartaddr), ioaddr);
2872 for (j = 0; (j < CCR_MAXWAIT); j++) {
2873 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2874 break;
2875 }
2876 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2877 printk("STALLION: cd1400 not responding, "
2878 "brd=%d panel=%d chip=%d\n",
2879 panelp->brdnr, panelp->panelnr, i);
2880 continue;
2881 }
2882 chipmask |= (0x1 << i);
2883 outb((PPR + uartaddr), ioaddr);
2884 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2885 }
2886
2887 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002888 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002889 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890}
2891
2892/*****************************************************************************/
2893
2894/*
2895 * Initialize hardware specific port registers.
2896 */
2897
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002898static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899{
Alan Coxb65b5b52006-06-27 02:54:05 -07002900 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002901 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2902 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903
Jiri Slaby615e4a72006-12-08 02:38:38 -08002904 if ((brdp == NULL) || (panelp == NULL) ||
2905 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 return;
2907
Alan Coxb65b5b52006-06-27 02:54:05 -07002908 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2910 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2911 portp->uartaddr = (portp->portnr & 0x04) << 5;
2912 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2913
2914 BRDENABLE(portp->brdnr, portp->pagenr);
2915 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2916 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2917 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2918 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002919 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920}
2921
2922/*****************************************************************************/
2923
2924/*
2925 * Wait for the command register to be ready. We will poll this,
2926 * since it won't usually take too long to be ready.
2927 */
2928
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002929static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930{
2931 int i;
2932
2933 for (i = 0; (i < CCR_MAXWAIT); i++) {
2934 if (stl_cd1400getreg(portp, CCR) == 0) {
2935 return;
2936 }
2937 }
2938
2939 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2940 portp->portnr, portp->panelnr, portp->brdnr);
2941}
2942
2943/*****************************************************************************/
2944
2945/*
2946 * Set up the cd1400 registers for a port based on the termios port
2947 * settings.
2948 */
2949
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002950static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002952 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 unsigned long flags;
2954 unsigned int clkdiv, baudrate;
2955 unsigned char cor1, cor2, cor3;
2956 unsigned char cor4, cor5, ccr;
2957 unsigned char srer, sreron, sreroff;
2958 unsigned char mcor1, mcor2, rtpr;
2959 unsigned char clk, div;
2960
2961 cor1 = 0;
2962 cor2 = 0;
2963 cor3 = 0;
2964 cor4 = 0;
2965 cor5 = 0;
2966 ccr = 0;
2967 rtpr = 0;
2968 clk = 0;
2969 div = 0;
2970 mcor1 = 0;
2971 mcor2 = 0;
2972 sreron = 0;
2973 sreroff = 0;
2974
2975 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002976 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 return;
2978
2979/*
2980 * Set up the RX char ignore mask with those RX error types we
2981 * can ignore. We can get the cd1400 to help us out a little here,
2982 * it will ignore parity errors and breaks for us.
2983 */
2984 portp->rxignoremsk = 0;
2985 if (tiosp->c_iflag & IGNPAR) {
2986 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2987 cor1 |= COR1_PARIGNORE;
2988 }
2989 if (tiosp->c_iflag & IGNBRK) {
2990 portp->rxignoremsk |= ST_BREAK;
2991 cor4 |= COR4_IGNBRK;
2992 }
2993
2994 portp->rxmarkmsk = ST_OVERRUN;
2995 if (tiosp->c_iflag & (INPCK | PARMRK))
2996 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2997 if (tiosp->c_iflag & BRKINT)
2998 portp->rxmarkmsk |= ST_BREAK;
2999
3000/*
3001 * Go through the char size, parity and stop bits and set all the
3002 * option register appropriately.
3003 */
3004 switch (tiosp->c_cflag & CSIZE) {
3005 case CS5:
3006 cor1 |= COR1_CHL5;
3007 break;
3008 case CS6:
3009 cor1 |= COR1_CHL6;
3010 break;
3011 case CS7:
3012 cor1 |= COR1_CHL7;
3013 break;
3014 default:
3015 cor1 |= COR1_CHL8;
3016 break;
3017 }
3018
3019 if (tiosp->c_cflag & CSTOPB)
3020 cor1 |= COR1_STOP2;
3021 else
3022 cor1 |= COR1_STOP1;
3023
3024 if (tiosp->c_cflag & PARENB) {
3025 if (tiosp->c_cflag & PARODD)
3026 cor1 |= (COR1_PARENB | COR1_PARODD);
3027 else
3028 cor1 |= (COR1_PARENB | COR1_PAREVEN);
3029 } else {
3030 cor1 |= COR1_PARNONE;
3031 }
3032
3033/*
3034 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
3035 * space for hardware flow control and the like. This should be set to
3036 * VMIN. Also here we will set the RX data timeout to 10ms - this should
3037 * really be based on VTIME.
3038 */
3039 cor3 |= FIFO_RXTHRESHOLD;
3040 rtpr = 2;
3041
3042/*
3043 * Calculate the baud rate timers. For now we will just assume that
3044 * the input and output baud are the same. Could have used a baud
3045 * table here, but this way we can generate virtually any baud rate
3046 * we like!
3047 */
3048 baudrate = tiosp->c_cflag & CBAUD;
3049 if (baudrate & CBAUDEX) {
3050 baudrate &= ~CBAUDEX;
3051 if ((baudrate < 1) || (baudrate > 4))
3052 tiosp->c_cflag &= ~CBAUDEX;
3053 else
3054 baudrate += 15;
3055 }
3056 baudrate = stl_baudrates[baudrate];
3057 if ((tiosp->c_cflag & CBAUD) == B38400) {
3058 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3059 baudrate = 57600;
3060 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3061 baudrate = 115200;
3062 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3063 baudrate = 230400;
3064 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3065 baudrate = 460800;
3066 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3067 baudrate = (portp->baud_base / portp->custom_divisor);
3068 }
3069 if (baudrate > STL_CD1400MAXBAUD)
3070 baudrate = STL_CD1400MAXBAUD;
3071
3072 if (baudrate > 0) {
3073 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
3074 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
3075 if (clkdiv < 0x100)
3076 break;
3077 }
3078 div = (unsigned char) clkdiv;
3079 }
3080
3081/*
3082 * Check what form of modem signaling is required and set it up.
3083 */
3084 if ((tiosp->c_cflag & CLOCAL) == 0) {
3085 mcor1 |= MCOR1_DCD;
3086 mcor2 |= MCOR2_DCD;
3087 sreron |= SRER_MODEM;
3088 portp->flags |= ASYNC_CHECK_CD;
3089 } else {
3090 portp->flags &= ~ASYNC_CHECK_CD;
3091 }
3092
3093/*
3094 * Setup cd1400 enhanced modes if we can. In particular we want to
3095 * handle as much of the flow control as possible automatically. As
3096 * well as saving a few CPU cycles it will also greatly improve flow
3097 * control reliability.
3098 */
3099 if (tiosp->c_iflag & IXON) {
3100 cor2 |= COR2_TXIBE;
3101 cor3 |= COR3_SCD12;
3102 if (tiosp->c_iflag & IXANY)
3103 cor2 |= COR2_IXM;
3104 }
3105
3106 if (tiosp->c_cflag & CRTSCTS) {
3107 cor2 |= COR2_CTSAE;
3108 mcor1 |= FIFO_RTSTHRESHOLD;
3109 }
3110
3111/*
3112 * All cd1400 register values calculated so go through and set
3113 * them all up.
3114 */
3115
Jiri Slabya0564e12006-12-08 02:38:37 -08003116 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003118 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003120 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003122 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3123 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3125 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
Alan Coxb65b5b52006-06-27 02:54:05 -07003127 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 BRDENABLE(portp->brdnr, portp->pagenr);
3129 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3130 srer = stl_cd1400getreg(portp, SRER);
3131 stl_cd1400setreg(portp, SRER, 0);
3132 if (stl_cd1400updatereg(portp, COR1, cor1))
3133 ccr = 1;
3134 if (stl_cd1400updatereg(portp, COR2, cor2))
3135 ccr = 1;
3136 if (stl_cd1400updatereg(portp, COR3, cor3))
3137 ccr = 1;
3138 if (ccr) {
3139 stl_cd1400ccrwait(portp);
3140 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3141 }
3142 stl_cd1400setreg(portp, COR4, cor4);
3143 stl_cd1400setreg(portp, COR5, cor5);
3144 stl_cd1400setreg(portp, MCOR1, mcor1);
3145 stl_cd1400setreg(portp, MCOR2, mcor2);
3146 if (baudrate > 0) {
3147 stl_cd1400setreg(portp, TCOR, clk);
3148 stl_cd1400setreg(portp, TBPR, div);
3149 stl_cd1400setreg(portp, RCOR, clk);
3150 stl_cd1400setreg(portp, RBPR, div);
3151 }
3152 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3153 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3154 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3155 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3156 stl_cd1400setreg(portp, RTPR, rtpr);
3157 mcor1 = stl_cd1400getreg(portp, MSVR1);
3158 if (mcor1 & MSVR1_DCD)
3159 portp->sigs |= TIOCM_CD;
3160 else
3161 portp->sigs &= ~TIOCM_CD;
3162 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3163 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003164 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165}
3166
3167/*****************************************************************************/
3168
3169/*
3170 * Set the state of the DTR and RTS signals.
3171 */
3172
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003173static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174{
3175 unsigned char msvr1, msvr2;
3176 unsigned long flags;
3177
Jiri Slabya0564e12006-12-08 02:38:37 -08003178 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3179 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180
3181 msvr1 = 0;
3182 msvr2 = 0;
3183 if (dtr > 0)
3184 msvr1 = MSVR1_DTR;
3185 if (rts > 0)
3186 msvr2 = MSVR2_RTS;
3187
Alan Coxb65b5b52006-06-27 02:54:05 -07003188 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189 BRDENABLE(portp->brdnr, portp->pagenr);
3190 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3191 if (rts >= 0)
3192 stl_cd1400setreg(portp, MSVR2, msvr2);
3193 if (dtr >= 0)
3194 stl_cd1400setreg(portp, MSVR1, msvr1);
3195 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003196 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197}
3198
3199/*****************************************************************************/
3200
3201/*
3202 * Return the state of the signals.
3203 */
3204
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003205static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206{
3207 unsigned char msvr1, msvr2;
3208 unsigned long flags;
3209 int sigs;
3210
Jiri Slabya0564e12006-12-08 02:38:37 -08003211 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212
Alan Coxb65b5b52006-06-27 02:54:05 -07003213 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214 BRDENABLE(portp->brdnr, portp->pagenr);
3215 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3216 msvr1 = stl_cd1400getreg(portp, MSVR1);
3217 msvr2 = stl_cd1400getreg(portp, MSVR2);
3218 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003219 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220
3221 sigs = 0;
3222 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3223 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3224 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3225 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3226#if 0
3227 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3228 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3229#else
3230 sigs |= TIOCM_DSR;
3231#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003232 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233}
3234
3235/*****************************************************************************/
3236
3237/*
3238 * Enable/Disable the Transmitter and/or Receiver.
3239 */
3240
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003241static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242{
3243 unsigned char ccr;
3244 unsigned long flags;
3245
Jiri Slabya0564e12006-12-08 02:38:37 -08003246 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3247
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 ccr = 0;
3249
3250 if (tx == 0)
3251 ccr |= CCR_TXDISABLE;
3252 else if (tx > 0)
3253 ccr |= CCR_TXENABLE;
3254 if (rx == 0)
3255 ccr |= CCR_RXDISABLE;
3256 else if (rx > 0)
3257 ccr |= CCR_RXENABLE;
3258
Alan Coxb65b5b52006-06-27 02:54:05 -07003259 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 BRDENABLE(portp->brdnr, portp->pagenr);
3261 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3262 stl_cd1400ccrwait(portp);
3263 stl_cd1400setreg(portp, CCR, ccr);
3264 stl_cd1400ccrwait(portp);
3265 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003266 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267}
3268
3269/*****************************************************************************/
3270
3271/*
3272 * Start/stop the Transmitter and/or Receiver.
3273 */
3274
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003275static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276{
3277 unsigned char sreron, sreroff;
3278 unsigned long flags;
3279
Jiri Slabya0564e12006-12-08 02:38:37 -08003280 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
3282 sreron = 0;
3283 sreroff = 0;
3284 if (tx == 0)
3285 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3286 else if (tx == 1)
3287 sreron |= SRER_TXDATA;
3288 else if (tx >= 2)
3289 sreron |= SRER_TXEMPTY;
3290 if (rx == 0)
3291 sreroff |= SRER_RXDATA;
3292 else if (rx > 0)
3293 sreron |= SRER_RXDATA;
3294
Alan Coxb65b5b52006-06-27 02:54:05 -07003295 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 BRDENABLE(portp->brdnr, portp->pagenr);
3297 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3298 stl_cd1400setreg(portp, SRER,
3299 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3300 BRDDISABLE(portp->brdnr);
3301 if (tx > 0)
3302 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003303 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304}
3305
3306/*****************************************************************************/
3307
3308/*
3309 * Disable all interrupts from this port.
3310 */
3311
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003312static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313{
3314 unsigned long flags;
3315
Jiri Slabya0564e12006-12-08 02:38:37 -08003316 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3317
Alan Coxb65b5b52006-06-27 02:54:05 -07003318 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319 BRDENABLE(portp->brdnr, portp->pagenr);
3320 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3321 stl_cd1400setreg(portp, SRER, 0);
3322 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003323 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324}
3325
3326/*****************************************************************************/
3327
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003328static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329{
3330 unsigned long flags;
3331
Jiri Slabya0564e12006-12-08 02:38:37 -08003332 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333
Alan Coxb65b5b52006-06-27 02:54:05 -07003334 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 BRDENABLE(portp->brdnr, portp->pagenr);
3336 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3337 stl_cd1400setreg(portp, SRER,
3338 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3339 SRER_TXEMPTY));
3340 BRDDISABLE(portp->brdnr);
3341 portp->brklen = len;
3342 if (len == 1)
3343 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003344 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345}
3346
3347/*****************************************************************************/
3348
3349/*
3350 * Take flow control actions...
3351 */
3352
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003353static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354{
3355 struct tty_struct *tty;
3356 unsigned long flags;
3357
Jiri Slabya0564e12006-12-08 02:38:37 -08003358 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359
Jiri Slaby615e4a72006-12-08 02:38:38 -08003360 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 return;
3362 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003363 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 return;
3365
Alan Coxb65b5b52006-06-27 02:54:05 -07003366 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 BRDENABLE(portp->brdnr, portp->pagenr);
3368 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3369
3370 if (state) {
3371 if (tty->termios->c_iflag & IXOFF) {
3372 stl_cd1400ccrwait(portp);
3373 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3374 portp->stats.rxxon++;
3375 stl_cd1400ccrwait(portp);
3376 }
3377/*
3378 * Question: should we return RTS to what it was before? It may
3379 * have been set by an ioctl... Suppose not, since if you have
3380 * hardware flow control set then it is pretty silly to go and
3381 * set the RTS line by hand.
3382 */
3383 if (tty->termios->c_cflag & CRTSCTS) {
3384 stl_cd1400setreg(portp, MCOR1,
3385 (stl_cd1400getreg(portp, MCOR1) |
3386 FIFO_RTSTHRESHOLD));
3387 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3388 portp->stats.rxrtson++;
3389 }
3390 } else {
3391 if (tty->termios->c_iflag & IXOFF) {
3392 stl_cd1400ccrwait(portp);
3393 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3394 portp->stats.rxxoff++;
3395 stl_cd1400ccrwait(portp);
3396 }
3397 if (tty->termios->c_cflag & CRTSCTS) {
3398 stl_cd1400setreg(portp, MCOR1,
3399 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3400 stl_cd1400setreg(portp, MSVR2, 0);
3401 portp->stats.rxrtsoff++;
3402 }
3403 }
3404
3405 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003406 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407}
3408
3409/*****************************************************************************/
3410
3411/*
3412 * Send a flow control character...
3413 */
3414
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003415static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416{
3417 struct tty_struct *tty;
3418 unsigned long flags;
3419
Jiri Slabya0564e12006-12-08 02:38:37 -08003420 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421
Jiri Slaby615e4a72006-12-08 02:38:38 -08003422 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423 return;
3424 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003425 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426 return;
3427
Alan Coxb65b5b52006-06-27 02:54:05 -07003428 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 BRDENABLE(portp->brdnr, portp->pagenr);
3430 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3431 if (state) {
3432 stl_cd1400ccrwait(portp);
3433 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3434 portp->stats.rxxon++;
3435 stl_cd1400ccrwait(portp);
3436 } else {
3437 stl_cd1400ccrwait(portp);
3438 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3439 portp->stats.rxxoff++;
3440 stl_cd1400ccrwait(portp);
3441 }
3442 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003443 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444}
3445
3446/*****************************************************************************/
3447
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003448static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449{
3450 unsigned long flags;
3451
Jiri Slabya0564e12006-12-08 02:38:37 -08003452 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453
Jiri Slaby615e4a72006-12-08 02:38:38 -08003454 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 return;
3456
Alan Coxb65b5b52006-06-27 02:54:05 -07003457 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 BRDENABLE(portp->brdnr, portp->pagenr);
3459 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3460 stl_cd1400ccrwait(portp);
3461 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3462 stl_cd1400ccrwait(portp);
3463 portp->tx.tail = portp->tx.head;
3464 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003465 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466}
3467
3468/*****************************************************************************/
3469
3470/*
3471 * Return the current state of data flow on this port. This is only
3472 * really interresting when determining if data has fully completed
3473 * transmission or not... This is easy for the cd1400, it accurately
3474 * maintains the busy port flag.
3475 */
3476
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003477static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478{
Jiri Slabya0564e12006-12-08 02:38:37 -08003479 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480
Jiri Slaby615e4a72006-12-08 02:38:38 -08003481 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003482 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483
Jesper Juhl014c2542006-01-15 02:37:08 +01003484 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485}
3486
3487/*****************************************************************************/
3488
3489/*
3490 * Interrupt service routine for cd1400 EasyIO boards.
3491 */
3492
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003493static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494{
3495 unsigned char svrtype;
3496
Jiri Slabya0564e12006-12-08 02:38:37 -08003497 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498
Alan Coxb65b5b52006-06-27 02:54:05 -07003499 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 outb(SVRR, iobase);
3501 svrtype = inb(iobase + EREG_DATA);
3502 if (panelp->nrports > 4) {
3503 outb((SVRR + 0x80), iobase);
3504 svrtype |= inb(iobase + EREG_DATA);
3505 }
3506
3507 if (svrtype & SVRR_RX)
3508 stl_cd1400rxisr(panelp, iobase);
3509 else if (svrtype & SVRR_TX)
3510 stl_cd1400txisr(panelp, iobase);
3511 else if (svrtype & SVRR_MDM)
3512 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003513
3514 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515}
3516
3517/*****************************************************************************/
3518
3519/*
3520 * Interrupt service routine for cd1400 panels.
3521 */
3522
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003523static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524{
3525 unsigned char svrtype;
3526
Jiri Slabya0564e12006-12-08 02:38:37 -08003527 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528
3529 outb(SVRR, iobase);
3530 svrtype = inb(iobase + EREG_DATA);
3531 outb((SVRR + 0x80), iobase);
3532 svrtype |= inb(iobase + EREG_DATA);
3533 if (svrtype & SVRR_RX)
3534 stl_cd1400rxisr(panelp, iobase);
3535 else if (svrtype & SVRR_TX)
3536 stl_cd1400txisr(panelp, iobase);
3537 else if (svrtype & SVRR_MDM)
3538 stl_cd1400mdmisr(panelp, iobase);
3539}
3540
3541
3542/*****************************************************************************/
3543
3544/*
3545 * Unfortunately we need to handle breaks in the TX data stream, since
3546 * this is the only way to generate them on the cd1400.
3547 */
3548
Jiri Slaby60be4812006-12-08 02:38:40 -08003549static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550{
3551 if (portp->brklen == 1) {
3552 outb((COR2 + portp->uartaddr), ioaddr);
3553 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3554 (ioaddr + EREG_DATA));
3555 outb((TDR + portp->uartaddr), ioaddr);
3556 outb(ETC_CMD, (ioaddr + EREG_DATA));
3557 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3558 outb((SRER + portp->uartaddr), ioaddr);
3559 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3560 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003561 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562 } else if (portp->brklen > 1) {
3563 outb((TDR + portp->uartaddr), ioaddr);
3564 outb(ETC_CMD, (ioaddr + EREG_DATA));
3565 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3566 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003567 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 } else {
3569 outb((COR2 + portp->uartaddr), ioaddr);
3570 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3571 (ioaddr + EREG_DATA));
3572 portp->brklen = 0;
3573 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003574 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575}
3576
3577/*****************************************************************************/
3578
3579/*
3580 * Transmit interrupt handler. This has gotta be fast! Handling TX
3581 * chars is pretty simple, stuff as many as possible from the TX buffer
3582 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3583 * are embedded as commands in the data stream. Oh no, had to use a goto!
3584 * This could be optimized more, will do when I get time...
3585 * In practice it is possible that interrupts are enabled but that the
3586 * port has been hung up. Need to handle not having any TX buffer here,
3587 * this is done by using the side effect that head and tail will also
3588 * be NULL if the buffer has been freed.
3589 */
3590
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003591static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003593 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594 int len, stlen;
3595 char *head, *tail;
3596 unsigned char ioack, srer;
3597
Jiri Slabya0564e12006-12-08 02:38:37 -08003598 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599
3600 ioack = inb(ioaddr + EREG_TXACK);
3601 if (((ioack & panelp->ackmask) != 0) ||
3602 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3603 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3604 return;
3605 }
3606 portp = panelp->ports[(ioack >> 3)];
3607
3608/*
3609 * Unfortunately we need to handle breaks in the data stream, since
3610 * this is the only way to generate them on the cd1400. Do it now if
3611 * a break is to be sent.
3612 */
3613 if (portp->brklen != 0)
3614 if (stl_cd1400breakisr(portp, ioaddr))
3615 goto stl_txalldone;
3616
3617 head = portp->tx.head;
3618 tail = portp->tx.tail;
3619 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3620 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3621 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3622 set_bit(ASYI_TXLOW, &portp->istate);
3623 schedule_work(&portp->tqueue);
3624 }
3625
3626 if (len == 0) {
3627 outb((SRER + portp->uartaddr), ioaddr);
3628 srer = inb(ioaddr + EREG_DATA);
3629 if (srer & SRER_TXDATA) {
3630 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3631 } else {
3632 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3633 clear_bit(ASYI_TXBUSY, &portp->istate);
3634 }
3635 outb(srer, (ioaddr + EREG_DATA));
3636 } else {
3637 len = MIN(len, CD1400_TXFIFOSIZE);
3638 portp->stats.txtotal += len;
3639 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
3640 outb((TDR + portp->uartaddr), ioaddr);
3641 outsb((ioaddr + EREG_DATA), tail, stlen);
3642 len -= stlen;
3643 tail += stlen;
3644 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3645 tail = portp->tx.buf;
3646 if (len > 0) {
3647 outsb((ioaddr + EREG_DATA), tail, len);
3648 tail += len;
3649 }
3650 portp->tx.tail = tail;
3651 }
3652
3653stl_txalldone:
3654 outb((EOSRR + portp->uartaddr), ioaddr);
3655 outb(0, (ioaddr + EREG_DATA));
3656}
3657
3658/*****************************************************************************/
3659
3660/*
3661 * Receive character interrupt handler. Determine if we have good chars
3662 * or bad chars and then process appropriately. Good chars are easy
3663 * just shove the lot into the RX buffer and set all status byte to 0.
3664 * If a bad RX char then process as required. This routine needs to be
3665 * fast! In practice it is possible that we get an interrupt on a port
3666 * that is closed. This can happen on hangups - since they completely
3667 * shutdown a port not in user context. Need to handle this case.
3668 */
3669
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003670static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003672 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 struct tty_struct *tty;
3674 unsigned int ioack, len, buflen;
3675 unsigned char status;
3676 char ch;
3677
Jiri Slabya0564e12006-12-08 02:38:37 -08003678 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679
3680 ioack = inb(ioaddr + EREG_RXACK);
3681 if ((ioack & panelp->ackmask) != 0) {
3682 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3683 return;
3684 }
3685 portp = panelp->ports[(ioack >> 3)];
3686 tty = portp->tty;
3687
3688 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3689 outb((RDCR + portp->uartaddr), ioaddr);
3690 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003691 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 len = MIN(len, sizeof(stl_unwanted));
3693 outb((RDSR + portp->uartaddr), ioaddr);
3694 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3695 portp->stats.rxlost += len;
3696 portp->stats.rxtotal += len;
3697 } else {
3698 len = MIN(len, buflen);
3699 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003700 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003702 tty_prepare_flip_string(tty, &ptr, len);
3703 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 tty_schedule_flip(tty);
3705 portp->stats.rxtotal += len;
3706 }
3707 }
3708 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3709 outb((RDSR + portp->uartaddr), ioaddr);
3710 status = inb(ioaddr + EREG_DATA);
3711 ch = inb(ioaddr + EREG_DATA);
3712 if (status & ST_PARITY)
3713 portp->stats.rxparity++;
3714 if (status & ST_FRAMING)
3715 portp->stats.rxframing++;
3716 if (status & ST_OVERRUN)
3717 portp->stats.rxoverrun++;
3718 if (status & ST_BREAK)
3719 portp->stats.rxbreaks++;
3720 if (status & ST_SCHARMASK) {
3721 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3722 portp->stats.txxon++;
3723 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3724 portp->stats.txxoff++;
3725 goto stl_rxalldone;
3726 }
Alan Cox33f0f882006-01-09 20:54:13 -08003727 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 if (portp->rxmarkmsk & status) {
3729 if (status & ST_BREAK) {
3730 status = TTY_BREAK;
3731 if (portp->flags & ASYNC_SAK) {
3732 do_SAK(tty);
3733 BRDENABLE(portp->brdnr, portp->pagenr);
3734 }
3735 } else if (status & ST_PARITY) {
3736 status = TTY_PARITY;
3737 } else if (status & ST_FRAMING) {
3738 status = TTY_FRAME;
3739 } else if(status & ST_OVERRUN) {
3740 status = TTY_OVERRUN;
3741 } else {
3742 status = 0;
3743 }
3744 } else {
3745 status = 0;
3746 }
Alan Cox33f0f882006-01-09 20:54:13 -08003747 tty_insert_flip_char(tty, ch, status);
3748 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 }
3750 } else {
3751 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3752 return;
3753 }
3754
3755stl_rxalldone:
3756 outb((EOSRR + portp->uartaddr), ioaddr);
3757 outb(0, (ioaddr + EREG_DATA));
3758}
3759
3760/*****************************************************************************/
3761
3762/*
3763 * Modem interrupt handler. The is called when the modem signal line
3764 * (DCD) has changed state. Leave most of the work to the off-level
3765 * processing routine.
3766 */
3767
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003768static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003770 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 unsigned int ioack;
3772 unsigned char misr;
3773
Jiri Slabya0564e12006-12-08 02:38:37 -08003774 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775
3776 ioack = inb(ioaddr + EREG_MDACK);
3777 if (((ioack & panelp->ackmask) != 0) ||
3778 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3779 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3780 return;
3781 }
3782 portp = panelp->ports[(ioack >> 3)];
3783
3784 outb((MISR + portp->uartaddr), ioaddr);
3785 misr = inb(ioaddr + EREG_DATA);
3786 if (misr & MISR_DCD) {
3787 set_bit(ASYI_DCDCHANGE, &portp->istate);
3788 schedule_work(&portp->tqueue);
3789 portp->stats.modem++;
3790 }
3791
3792 outb((EOSRR + portp->uartaddr), ioaddr);
3793 outb(0, (ioaddr + EREG_DATA));
3794}
3795
3796/*****************************************************************************/
3797/* SC26198 HARDWARE FUNCTIONS */
3798/*****************************************************************************/
3799
3800/*
3801 * These functions get/set/update the registers of the sc26198 UARTs.
3802 * Access to the sc26198 registers is via an address/data io port pair.
3803 * (Maybe should make this inline...)
3804 */
3805
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003806static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807{
3808 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003809 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810}
3811
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003812static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813{
3814 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3815 outb(value, (portp->ioaddr + XP_DATA));
3816}
3817
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003818static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819{
3820 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3821 if (inb(portp->ioaddr + XP_DATA) != value) {
3822 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003823 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003825 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826}
3827
3828/*****************************************************************************/
3829
3830/*
3831 * Functions to get and set the sc26198 global registers.
3832 */
3833
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003834static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835{
3836 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003837 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838}
3839
3840#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003841static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842{
3843 outb(regnr, (portp->ioaddr + XP_ADDR));
3844 outb(value, (portp->ioaddr + XP_DATA));
3845}
3846#endif
3847
3848/*****************************************************************************/
3849
3850/*
3851 * Inbitialize the UARTs in a panel. We don't care what sort of board
3852 * these ports are on - since the port io registers are almost
3853 * identical when dealing with ports.
3854 */
3855
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003856static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857{
3858 int chipmask, i;
3859 int nrchips, ioaddr;
3860
Jiri Slabya0564e12006-12-08 02:38:37 -08003861 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
3863 BRDENABLE(panelp->brdnr, panelp->pagenr);
3864
3865/*
3866 * Check that each chip is present and started up OK.
3867 */
3868 chipmask = 0;
3869 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3870 if (brdp->brdtype == BRD_ECHPCI)
3871 outb(panelp->pagenr, brdp->ioctrl);
3872
3873 for (i = 0; (i < nrchips); i++) {
3874 ioaddr = panelp->iobase + (i * 4);
3875 outb(SCCR, (ioaddr + XP_ADDR));
3876 outb(CR_RESETALL, (ioaddr + XP_DATA));
3877 outb(TSTR, (ioaddr + XP_ADDR));
3878 if (inb(ioaddr + XP_DATA) != 0) {
3879 printk("STALLION: sc26198 not responding, "
3880 "brd=%d panel=%d chip=%d\n",
3881 panelp->brdnr, panelp->panelnr, i);
3882 continue;
3883 }
3884 chipmask |= (0x1 << i);
3885 outb(GCCR, (ioaddr + XP_ADDR));
3886 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3887 outb(WDTRCR, (ioaddr + XP_ADDR));
3888 outb(0xff, (ioaddr + XP_DATA));
3889 }
3890
3891 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003892 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893}
3894
3895/*****************************************************************************/
3896
3897/*
3898 * Initialize hardware specific port registers.
3899 */
3900
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003901static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902{
Jiri Slabya0564e12006-12-08 02:38:37 -08003903 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3904 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Jiri Slaby615e4a72006-12-08 02:38:38 -08003906 if ((brdp == NULL) || (panelp == NULL) ||
3907 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 return;
3909
3910 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3911 portp->uartaddr = (portp->portnr & 0x07) << 4;
3912 portp->pagenr = panelp->pagenr;
3913 portp->hwid = 0x1;
3914
3915 BRDENABLE(portp->brdnr, portp->pagenr);
3916 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3917 BRDDISABLE(portp->brdnr);
3918}
3919
3920/*****************************************************************************/
3921
3922/*
3923 * Set up the sc26198 registers for a port based on the termios port
3924 * settings.
3925 */
3926
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003927static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003929 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 unsigned long flags;
3931 unsigned int baudrate;
3932 unsigned char mr0, mr1, mr2, clk;
3933 unsigned char imron, imroff, iopr, ipr;
3934
3935 mr0 = 0;
3936 mr1 = 0;
3937 mr2 = 0;
3938 clk = 0;
3939 iopr = 0;
3940 imron = 0;
3941 imroff = 0;
3942
3943 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003944 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 return;
3946
3947/*
3948 * Set up the RX char ignore mask with those RX error types we
3949 * can ignore.
3950 */
3951 portp->rxignoremsk = 0;
3952 if (tiosp->c_iflag & IGNPAR)
3953 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3954 SR_RXOVERRUN);
3955 if (tiosp->c_iflag & IGNBRK)
3956 portp->rxignoremsk |= SR_RXBREAK;
3957
3958 portp->rxmarkmsk = SR_RXOVERRUN;
3959 if (tiosp->c_iflag & (INPCK | PARMRK))
3960 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3961 if (tiosp->c_iflag & BRKINT)
3962 portp->rxmarkmsk |= SR_RXBREAK;
3963
3964/*
3965 * Go through the char size, parity and stop bits and set all the
3966 * option register appropriately.
3967 */
3968 switch (tiosp->c_cflag & CSIZE) {
3969 case CS5:
3970 mr1 |= MR1_CS5;
3971 break;
3972 case CS6:
3973 mr1 |= MR1_CS6;
3974 break;
3975 case CS7:
3976 mr1 |= MR1_CS7;
3977 break;
3978 default:
3979 mr1 |= MR1_CS8;
3980 break;
3981 }
3982
3983 if (tiosp->c_cflag & CSTOPB)
3984 mr2 |= MR2_STOP2;
3985 else
3986 mr2 |= MR2_STOP1;
3987
3988 if (tiosp->c_cflag & PARENB) {
3989 if (tiosp->c_cflag & PARODD)
3990 mr1 |= (MR1_PARENB | MR1_PARODD);
3991 else
3992 mr1 |= (MR1_PARENB | MR1_PAREVEN);
3993 } else {
3994 mr1 |= MR1_PARNONE;
3995 }
3996
3997 mr1 |= MR1_ERRBLOCK;
3998
3999/*
4000 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
4001 * space for hardware flow control and the like. This should be set to
4002 * VMIN.
4003 */
4004 mr2 |= MR2_RXFIFOHALF;
4005
4006/*
4007 * Calculate the baud rate timers. For now we will just assume that
4008 * the input and output baud are the same. The sc26198 has a fixed
4009 * baud rate table, so only discrete baud rates possible.
4010 */
4011 baudrate = tiosp->c_cflag & CBAUD;
4012 if (baudrate & CBAUDEX) {
4013 baudrate &= ~CBAUDEX;
4014 if ((baudrate < 1) || (baudrate > 4))
4015 tiosp->c_cflag &= ~CBAUDEX;
4016 else
4017 baudrate += 15;
4018 }
4019 baudrate = stl_baudrates[baudrate];
4020 if ((tiosp->c_cflag & CBAUD) == B38400) {
4021 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
4022 baudrate = 57600;
4023 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
4024 baudrate = 115200;
4025 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
4026 baudrate = 230400;
4027 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
4028 baudrate = 460800;
4029 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
4030 baudrate = (portp->baud_base / portp->custom_divisor);
4031 }
4032 if (baudrate > STL_SC26198MAXBAUD)
4033 baudrate = STL_SC26198MAXBAUD;
4034
4035 if (baudrate > 0) {
4036 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
4037 if (baudrate <= sc26198_baudtable[clk])
4038 break;
4039 }
4040 }
4041
4042/*
4043 * Check what form of modem signaling is required and set it up.
4044 */
4045 if (tiosp->c_cflag & CLOCAL) {
4046 portp->flags &= ~ASYNC_CHECK_CD;
4047 } else {
4048 iopr |= IOPR_DCDCOS;
4049 imron |= IR_IOPORT;
4050 portp->flags |= ASYNC_CHECK_CD;
4051 }
4052
4053/*
4054 * Setup sc26198 enhanced modes if we can. In particular we want to
4055 * handle as much of the flow control as possible automatically. As
4056 * well as saving a few CPU cycles it will also greatly improve flow
4057 * control reliability.
4058 */
4059 if (tiosp->c_iflag & IXON) {
4060 mr0 |= MR0_SWFTX | MR0_SWFT;
4061 imron |= IR_XONXOFF;
4062 } else {
4063 imroff |= IR_XONXOFF;
4064 }
4065 if (tiosp->c_iflag & IXOFF)
4066 mr0 |= MR0_SWFRX;
4067
4068 if (tiosp->c_cflag & CRTSCTS) {
4069 mr2 |= MR2_AUTOCTS;
4070 mr1 |= MR1_AUTORTS;
4071 }
4072
4073/*
4074 * All sc26198 register values calculated so go through and set
4075 * them all up.
4076 */
4077
Jiri Slabya0564e12006-12-08 02:38:37 -08004078 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08004080 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
4081 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
4082 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4084 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085
Alan Coxb65b5b52006-06-27 02:54:05 -07004086 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 BRDENABLE(portp->brdnr, portp->pagenr);
4088 stl_sc26198setreg(portp, IMR, 0);
4089 stl_sc26198updatereg(portp, MR0, mr0);
4090 stl_sc26198updatereg(portp, MR1, mr1);
4091 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4092 stl_sc26198updatereg(portp, MR2, mr2);
4093 stl_sc26198updatereg(portp, IOPIOR,
4094 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4095
4096 if (baudrate > 0) {
4097 stl_sc26198setreg(portp, TXCSR, clk);
4098 stl_sc26198setreg(portp, RXCSR, clk);
4099 }
4100
4101 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4102 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4103
4104 ipr = stl_sc26198getreg(portp, IPR);
4105 if (ipr & IPR_DCD)
4106 portp->sigs &= ~TIOCM_CD;
4107 else
4108 portp->sigs |= TIOCM_CD;
4109
4110 portp->imr = (portp->imr & ~imroff) | imron;
4111 stl_sc26198setreg(portp, IMR, portp->imr);
4112 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004113 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114}
4115
4116/*****************************************************************************/
4117
4118/*
4119 * Set the state of the DTR and RTS signals.
4120 */
4121
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004122static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123{
4124 unsigned char iopioron, iopioroff;
4125 unsigned long flags;
4126
Jiri Slabya0564e12006-12-08 02:38:37 -08004127 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4128 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
4130 iopioron = 0;
4131 iopioroff = 0;
4132 if (dtr == 0)
4133 iopioroff |= IPR_DTR;
4134 else if (dtr > 0)
4135 iopioron |= IPR_DTR;
4136 if (rts == 0)
4137 iopioroff |= IPR_RTS;
4138 else if (rts > 0)
4139 iopioron |= IPR_RTS;
4140
Alan Coxb65b5b52006-06-27 02:54:05 -07004141 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 BRDENABLE(portp->brdnr, portp->pagenr);
4143 stl_sc26198setreg(portp, IOPIOR,
4144 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4145 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004146 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147}
4148
4149/*****************************************************************************/
4150
4151/*
4152 * Return the state of the signals.
4153 */
4154
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004155static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156{
4157 unsigned char ipr;
4158 unsigned long flags;
4159 int sigs;
4160
Jiri Slabya0564e12006-12-08 02:38:37 -08004161 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162
Alan Coxb65b5b52006-06-27 02:54:05 -07004163 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 BRDENABLE(portp->brdnr, portp->pagenr);
4165 ipr = stl_sc26198getreg(portp, IPR);
4166 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004167 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
4169 sigs = 0;
4170 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4171 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4172 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4173 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4174 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004175 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176}
4177
4178/*****************************************************************************/
4179
4180/*
4181 * Enable/Disable the Transmitter and/or Receiver.
4182 */
4183
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004184static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185{
4186 unsigned char ccr;
4187 unsigned long flags;
4188
Jiri Slabya0564e12006-12-08 02:38:37 -08004189 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190
4191 ccr = portp->crenable;
4192 if (tx == 0)
4193 ccr &= ~CR_TXENABLE;
4194 else if (tx > 0)
4195 ccr |= CR_TXENABLE;
4196 if (rx == 0)
4197 ccr &= ~CR_RXENABLE;
4198 else if (rx > 0)
4199 ccr |= CR_RXENABLE;
4200
Alan Coxb65b5b52006-06-27 02:54:05 -07004201 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 BRDENABLE(portp->brdnr, portp->pagenr);
4203 stl_sc26198setreg(portp, SCCR, ccr);
4204 BRDDISABLE(portp->brdnr);
4205 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004206 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207}
4208
4209/*****************************************************************************/
4210
4211/*
4212 * Start/stop the Transmitter and/or Receiver.
4213 */
4214
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004215static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216{
4217 unsigned char imr;
4218 unsigned long flags;
4219
Jiri Slabya0564e12006-12-08 02:38:37 -08004220 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221
4222 imr = portp->imr;
4223 if (tx == 0)
4224 imr &= ~IR_TXRDY;
4225 else if (tx == 1)
4226 imr |= IR_TXRDY;
4227 if (rx == 0)
4228 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4229 else if (rx > 0)
4230 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4231
Alan Coxb65b5b52006-06-27 02:54:05 -07004232 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233 BRDENABLE(portp->brdnr, portp->pagenr);
4234 stl_sc26198setreg(portp, IMR, imr);
4235 BRDDISABLE(portp->brdnr);
4236 portp->imr = imr;
4237 if (tx > 0)
4238 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004239 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240}
4241
4242/*****************************************************************************/
4243
4244/*
4245 * Disable all interrupts from this port.
4246 */
4247
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004248static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249{
4250 unsigned long flags;
4251
Jiri Slabya0564e12006-12-08 02:38:37 -08004252 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
Alan Coxb65b5b52006-06-27 02:54:05 -07004254 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255 BRDENABLE(portp->brdnr, portp->pagenr);
4256 portp->imr = 0;
4257 stl_sc26198setreg(portp, IMR, 0);
4258 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004259 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
4262/*****************************************************************************/
4263
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004264static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265{
4266 unsigned long flags;
4267
Jiri Slabya0564e12006-12-08 02:38:37 -08004268 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269
Alan Coxb65b5b52006-06-27 02:54:05 -07004270 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 BRDENABLE(portp->brdnr, portp->pagenr);
4272 if (len == 1) {
4273 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4274 portp->stats.txbreaks++;
4275 } else {
4276 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4277 }
4278 BRDDISABLE(portp->brdnr);
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 * Take flow control actions...
4286 */
4287
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004288static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289{
4290 struct tty_struct *tty;
4291 unsigned long flags;
4292 unsigned char mr0;
4293
Jiri Slabya0564e12006-12-08 02:38:37 -08004294 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Jiri Slaby615e4a72006-12-08 02:38:38 -08004296 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 return;
4298 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004299 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 return;
4301
Alan Coxb65b5b52006-06-27 02:54:05 -07004302 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 BRDENABLE(portp->brdnr, portp->pagenr);
4304
4305 if (state) {
4306 if (tty->termios->c_iflag & IXOFF) {
4307 mr0 = stl_sc26198getreg(portp, MR0);
4308 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4309 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4310 mr0 |= MR0_SWFRX;
4311 portp->stats.rxxon++;
4312 stl_sc26198wait(portp);
4313 stl_sc26198setreg(portp, MR0, mr0);
4314 }
4315/*
4316 * Question: should we return RTS to what it was before? It may
4317 * have been set by an ioctl... Suppose not, since if you have
4318 * hardware flow control set then it is pretty silly to go and
4319 * set the RTS line by hand.
4320 */
4321 if (tty->termios->c_cflag & CRTSCTS) {
4322 stl_sc26198setreg(portp, MR1,
4323 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4324 stl_sc26198setreg(portp, IOPIOR,
4325 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4326 portp->stats.rxrtson++;
4327 }
4328 } else {
4329 if (tty->termios->c_iflag & IXOFF) {
4330 mr0 = stl_sc26198getreg(portp, MR0);
4331 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4332 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4333 mr0 &= ~MR0_SWFRX;
4334 portp->stats.rxxoff++;
4335 stl_sc26198wait(portp);
4336 stl_sc26198setreg(portp, MR0, mr0);
4337 }
4338 if (tty->termios->c_cflag & CRTSCTS) {
4339 stl_sc26198setreg(portp, MR1,
4340 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4341 stl_sc26198setreg(portp, IOPIOR,
4342 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4343 portp->stats.rxrtsoff++;
4344 }
4345 }
4346
4347 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004348 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349}
4350
4351/*****************************************************************************/
4352
4353/*
4354 * Send a flow control character.
4355 */
4356
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004357static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358{
4359 struct tty_struct *tty;
4360 unsigned long flags;
4361 unsigned char mr0;
4362
Jiri Slabya0564e12006-12-08 02:38:37 -08004363 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364
Jiri Slaby615e4a72006-12-08 02:38:38 -08004365 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366 return;
4367 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004368 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 return;
4370
Alan Coxb65b5b52006-06-27 02:54:05 -07004371 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372 BRDENABLE(portp->brdnr, portp->pagenr);
4373 if (state) {
4374 mr0 = stl_sc26198getreg(portp, MR0);
4375 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4376 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4377 mr0 |= MR0_SWFRX;
4378 portp->stats.rxxon++;
4379 stl_sc26198wait(portp);
4380 stl_sc26198setreg(portp, MR0, mr0);
4381 } else {
4382 mr0 = stl_sc26198getreg(portp, MR0);
4383 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4384 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4385 mr0 &= ~MR0_SWFRX;
4386 portp->stats.rxxoff++;
4387 stl_sc26198wait(portp);
4388 stl_sc26198setreg(portp, MR0, mr0);
4389 }
4390 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004391 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392}
4393
4394/*****************************************************************************/
4395
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004396static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397{
4398 unsigned long flags;
4399
Jiri Slabya0564e12006-12-08 02:38:37 -08004400 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Jiri Slaby615e4a72006-12-08 02:38:38 -08004402 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 return;
4404
Alan Coxb65b5b52006-06-27 02:54:05 -07004405 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 BRDENABLE(portp->brdnr, portp->pagenr);
4407 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4408 stl_sc26198setreg(portp, SCCR, portp->crenable);
4409 BRDDISABLE(portp->brdnr);
4410 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004411 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412}
4413
4414/*****************************************************************************/
4415
4416/*
4417 * Return the current state of data flow on this port. This is only
4418 * really interresting when determining if data has fully completed
4419 * transmission or not... The sc26198 interrupt scheme cannot
4420 * determine when all data has actually drained, so we need to
4421 * check the port statusy register to be sure.
4422 */
4423
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004424static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425{
4426 unsigned long flags;
4427 unsigned char sr;
4428
Jiri Slabya0564e12006-12-08 02:38:37 -08004429 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430
Jiri Slaby615e4a72006-12-08 02:38:38 -08004431 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004432 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004434 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
Alan Coxb65b5b52006-06-27 02:54:05 -07004436 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437 BRDENABLE(portp->brdnr, portp->pagenr);
4438 sr = stl_sc26198getreg(portp, SR);
4439 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004440 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
Jesper Juhl014c2542006-01-15 02:37:08 +01004442 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443}
4444
4445/*****************************************************************************/
4446
4447/*
4448 * Delay for a small amount of time, to give the sc26198 a chance
4449 * to process a command...
4450 */
4451
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004452static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453{
4454 int i;
4455
Jiri Slabya0564e12006-12-08 02:38:37 -08004456 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
Jiri Slaby615e4a72006-12-08 02:38:38 -08004458 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459 return;
4460
4461 for (i = 0; (i < 20); i++)
4462 stl_sc26198getglobreg(portp, TSTR);
4463}
4464
4465/*****************************************************************************/
4466
4467/*
4468 * If we are TX flow controlled and in IXANY mode then we may
4469 * need to unflow control here. We gotta do this because of the
4470 * automatic flow control modes of the sc26198.
4471 */
4472
Jiri Slaby60be4812006-12-08 02:38:40 -08004473static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474{
4475 unsigned char mr0;
4476
4477 mr0 = stl_sc26198getreg(portp, MR0);
4478 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4479 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4480 stl_sc26198wait(portp);
4481 stl_sc26198setreg(portp, MR0, mr0);
4482 clear_bit(ASYI_TXFLOWED, &portp->istate);
4483}
4484
4485/*****************************************************************************/
4486
4487/*
4488 * Interrupt service routine for sc26198 panels.
4489 */
4490
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004491static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004493 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 unsigned int iack;
4495
Alan Coxb65b5b52006-06-27 02:54:05 -07004496 spin_lock(&brd_lock);
4497
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498/*
4499 * Work around bug in sc26198 chip... Cannot have A6 address
4500 * line of UART high, else iack will be returned as 0.
4501 */
4502 outb(0, (iobase + 1));
4503
4504 iack = inb(iobase + XP_IACK);
4505 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4506
4507 if (iack & IVR_RXDATA)
4508 stl_sc26198rxisr(portp, iack);
4509 else if (iack & IVR_TXDATA)
4510 stl_sc26198txisr(portp);
4511 else
4512 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004513
4514 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515}
4516
4517/*****************************************************************************/
4518
4519/*
4520 * Transmit interrupt handler. This has gotta be fast! Handling TX
4521 * chars is pretty simple, stuff as many as possible from the TX buffer
4522 * into the sc26198 FIFO.
4523 * In practice it is possible that interrupts are enabled but that the
4524 * port has been hung up. Need to handle not having any TX buffer here,
4525 * this is done by using the side effect that head and tail will also
4526 * be NULL if the buffer has been freed.
4527 */
4528
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004529static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530{
4531 unsigned int ioaddr;
4532 unsigned char mr0;
4533 int len, stlen;
4534 char *head, *tail;
4535
Jiri Slabya0564e12006-12-08 02:38:37 -08004536 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537
4538 ioaddr = portp->ioaddr;
4539 head = portp->tx.head;
4540 tail = portp->tx.tail;
4541 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4542 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4543 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4544 set_bit(ASYI_TXLOW, &portp->istate);
4545 schedule_work(&portp->tqueue);
4546 }
4547
4548 if (len == 0) {
4549 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4550 mr0 = inb(ioaddr + XP_DATA);
4551 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4552 portp->imr &= ~IR_TXRDY;
4553 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4554 outb(portp->imr, (ioaddr + XP_DATA));
4555 clear_bit(ASYI_TXBUSY, &portp->istate);
4556 } else {
4557 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4558 outb(mr0, (ioaddr + XP_DATA));
4559 }
4560 } else {
4561 len = MIN(len, SC26198_TXFIFOSIZE);
4562 portp->stats.txtotal += len;
4563 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
4564 outb(GTXFIFO, (ioaddr + XP_ADDR));
4565 outsb((ioaddr + XP_DATA), tail, stlen);
4566 len -= stlen;
4567 tail += stlen;
4568 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4569 tail = portp->tx.buf;
4570 if (len > 0) {
4571 outsb((ioaddr + XP_DATA), tail, len);
4572 tail += len;
4573 }
4574 portp->tx.tail = tail;
4575 }
4576}
4577
4578/*****************************************************************************/
4579
4580/*
4581 * Receive character interrupt handler. Determine if we have good chars
4582 * or bad chars and then process appropriately. Good chars are easy
4583 * just shove the lot into the RX buffer and set all status byte to 0.
4584 * If a bad RX char then process as required. This routine needs to be
4585 * fast! In practice it is possible that we get an interrupt on a port
4586 * that is closed. This can happen on hangups - since they completely
4587 * shutdown a port not in user context. Need to handle this case.
4588 */
4589
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004590static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591{
4592 struct tty_struct *tty;
4593 unsigned int len, buflen, ioaddr;
4594
Jiri Slabya0564e12006-12-08 02:38:37 -08004595 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596
4597 tty = portp->tty;
4598 ioaddr = portp->ioaddr;
4599 outb(GIBCR, (ioaddr + XP_ADDR));
4600 len = inb(ioaddr + XP_DATA) + 1;
4601
4602 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004603 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604 len = MIN(len, sizeof(stl_unwanted));
4605 outb(GRXFIFO, (ioaddr + XP_ADDR));
4606 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4607 portp->stats.rxlost += len;
4608 portp->stats.rxtotal += len;
4609 } else {
4610 len = MIN(len, buflen);
4611 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004612 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004614 tty_prepare_flip_string(tty, &ptr, len);
4615 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 tty_schedule_flip(tty);
4617 portp->stats.rxtotal += len;
4618 }
4619 }
4620 } else {
4621 stl_sc26198rxbadchars(portp);
4622 }
4623
4624/*
4625 * If we are TX flow controlled and in IXANY mode then we may need
4626 * to unflow control here. We gotta do this because of the automatic
4627 * flow control modes of the sc26198.
4628 */
4629 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004630 if ((tty != NULL) &&
4631 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632 (tty->termios->c_iflag & IXANY)) {
4633 stl_sc26198txunflow(portp, tty);
4634 }
4635 }
4636}
4637
4638/*****************************************************************************/
4639
4640/*
4641 * Process an RX bad character.
4642 */
4643
Jiri Slaby60be4812006-12-08 02:38:40 -08004644static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645{
4646 struct tty_struct *tty;
4647 unsigned int ioaddr;
4648
4649 tty = portp->tty;
4650 ioaddr = portp->ioaddr;
4651
4652 if (status & SR_RXPARITY)
4653 portp->stats.rxparity++;
4654 if (status & SR_RXFRAMING)
4655 portp->stats.rxframing++;
4656 if (status & SR_RXOVERRUN)
4657 portp->stats.rxoverrun++;
4658 if (status & SR_RXBREAK)
4659 portp->stats.rxbreaks++;
4660
Jiri Slaby615e4a72006-12-08 02:38:38 -08004661 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662 ((portp->rxignoremsk & status) == 0)) {
4663 if (portp->rxmarkmsk & status) {
4664 if (status & SR_RXBREAK) {
4665 status = TTY_BREAK;
4666 if (portp->flags & ASYNC_SAK) {
4667 do_SAK(tty);
4668 BRDENABLE(portp->brdnr, portp->pagenr);
4669 }
4670 } else if (status & SR_RXPARITY) {
4671 status = TTY_PARITY;
4672 } else if (status & SR_RXFRAMING) {
4673 status = TTY_FRAME;
4674 } else if(status & SR_RXOVERRUN) {
4675 status = TTY_OVERRUN;
4676 } else {
4677 status = 0;
4678 }
4679 } else {
4680 status = 0;
4681 }
4682
Alan Cox33f0f882006-01-09 20:54:13 -08004683 tty_insert_flip_char(tty, ch, status);
4684 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685
4686 if (status == 0)
4687 portp->stats.rxtotal++;
4688 }
4689}
4690
4691/*****************************************************************************/
4692
4693/*
4694 * Process all characters in the RX FIFO of the UART. Check all char
4695 * status bytes as well, and process as required. We need to check
4696 * all bytes in the FIFO, in case some more enter the FIFO while we
4697 * are here. To get the exact character error type we need to switch
4698 * into CHAR error mode (that is why we need to make sure we empty
4699 * the FIFO).
4700 */
4701
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004702static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703{
4704 unsigned char status, mr1;
4705 char ch;
4706
4707/*
4708 * To get the precise error type for each character we must switch
4709 * back into CHAR error mode.
4710 */
4711 mr1 = stl_sc26198getreg(portp, MR1);
4712 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4713
4714 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4715 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4716 ch = stl_sc26198getreg(portp, RXFIFO);
4717 stl_sc26198rxbadch(portp, status, ch);
4718 }
4719
4720/*
4721 * To get correct interrupt class we must switch back into BLOCK
4722 * error mode.
4723 */
4724 stl_sc26198setreg(portp, MR1, mr1);
4725}
4726
4727/*****************************************************************************/
4728
4729/*
4730 * Other interrupt handler. This includes modem signals, flow
4731 * control actions, etc. Most stuff is left to off-level interrupt
4732 * processing time.
4733 */
4734
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004735static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736{
4737 unsigned char cir, ipr, xisr;
4738
Jiri Slabya0564e12006-12-08 02:38:37 -08004739 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740
4741 cir = stl_sc26198getglobreg(portp, CIR);
4742
4743 switch (cir & CIR_SUBTYPEMASK) {
4744 case CIR_SUBCOS:
4745 ipr = stl_sc26198getreg(portp, IPR);
4746 if (ipr & IPR_DCDCHANGE) {
4747 set_bit(ASYI_DCDCHANGE, &portp->istate);
4748 schedule_work(&portp->tqueue);
4749 portp->stats.modem++;
4750 }
4751 break;
4752 case CIR_SUBXONXOFF:
4753 xisr = stl_sc26198getreg(portp, XISR);
4754 if (xisr & XISR_RXXONGOT) {
4755 set_bit(ASYI_TXFLOWED, &portp->istate);
4756 portp->stats.txxoff++;
4757 }
4758 if (xisr & XISR_RXXOFFGOT) {
4759 clear_bit(ASYI_TXFLOWED, &portp->istate);
4760 portp->stats.txxon++;
4761 }
4762 break;
4763 case CIR_SUBBREAK:
4764 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4765 stl_sc26198rxbadchars(portp);
4766 break;
4767 default:
4768 break;
4769 }
4770}
4771
Jiri Slaby23b85a12006-12-08 02:38:40 -08004772/*
4773 * Loadable module initialization stuff.
4774 */
4775static int __init stallion_module_init(void)
4776{
4777 unsigned int i;
4778
4779 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4780
4781 spin_lock_init(&stallion_lock);
4782 spin_lock_init(&brd_lock);
4783
4784 stl_initbrds();
4785
4786 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4787 if (!stl_serial)
4788 return -1;
4789
4790/*
4791 * Set up a character driver for per board stuff. This is mainly used
4792 * to do stats ioctls on the ports.
4793 */
4794 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4795 printk("STALLION: failed to register serial board device\n");
4796
4797 stallion_class = class_create(THIS_MODULE, "staliomem");
4798 for (i = 0; i < 4; i++)
4799 class_device_create(stallion_class, NULL,
4800 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4801 "staliomem%d", i);
4802
4803 stl_serial->owner = THIS_MODULE;
4804 stl_serial->driver_name = stl_drvname;
4805 stl_serial->name = "ttyE";
4806 stl_serial->major = STL_SERIALMAJOR;
4807 stl_serial->minor_start = 0;
4808 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4809 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4810 stl_serial->init_termios = stl_deftermios;
4811 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4812 tty_set_operations(stl_serial, &stl_ops);
4813
4814 if (tty_register_driver(stl_serial)) {
4815 put_tty_driver(stl_serial);
4816 printk("STALLION: failed to register serial driver\n");
4817 return -1;
4818 }
4819
4820 return 0;
4821}
4822
4823static void __exit stallion_module_exit(void)
4824{
4825 struct stlbrd *brdp;
4826 struct stlpanel *panelp;
4827 struct stlport *portp;
4828 int i, j, k;
4829
4830 pr_debug("cleanup_module()\n");
4831
4832 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4833 stl_drvversion);
4834
4835/*
4836 * Free up all allocated resources used by the ports. This includes
4837 * memory and interrupts. As part of this process we will also do
4838 * a hangup on every open port - to try to flush out any processes
4839 * hanging onto ports.
4840 */
4841 i = tty_unregister_driver(stl_serial);
4842 put_tty_driver(stl_serial);
4843 if (i) {
4844 printk("STALLION: failed to un-register tty driver, "
4845 "errno=%d\n", -i);
4846 return;
4847 }
4848 for (i = 0; i < 4; i++)
4849 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4850 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4851 printk("STALLION: failed to un-register serial memory device, "
4852 "errno=%d\n", -i);
4853 class_destroy(stallion_class);
4854
4855 for (i = 0; (i < stl_nrbrds); i++) {
4856 if ((brdp = stl_brds[i]) == NULL)
4857 continue;
4858
4859 free_irq(brdp->irq, brdp);
4860
4861 for (j = 0; (j < STL_MAXPANELS); j++) {
4862 panelp = brdp->panels[j];
4863 if (panelp == NULL)
4864 continue;
4865 for (k = 0; (k < STL_PORTSPERPANEL); k++) {
4866 portp = panelp->ports[k];
4867 if (portp == NULL)
4868 continue;
4869 if (portp->tty != NULL)
4870 stl_hangup(portp->tty);
4871 kfree(portp->tx.buf);
4872 kfree(portp);
4873 }
4874 kfree(panelp);
4875 }
4876
4877 release_region(brdp->ioaddr1, brdp->iosize1);
4878 if (brdp->iosize2 > 0)
4879 release_region(brdp->ioaddr2, brdp->iosize2);
4880
4881 kfree(brdp);
4882 stl_brds[i] = NULL;
4883 }
4884}
4885
4886module_init(stallion_module_init);
4887module_exit(stallion_module_exit);
4888
4889MODULE_AUTHOR("Greg Ungerer");
4890MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4891MODULE_LICENSE("GPL");