blob: 71bfdccfb42e71601627d429929799122dfa7f0c [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 */
Alan Cox606d0992006-12-08 02:38:45 -0800144static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
146 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800147 .c_ispeed = 9600,
148 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149};
150
151/*
152 * Define global stats structures. Not used often, and can be
153 * re-used for each stats call.
154 */
155static comstats_t stl_comstats;
156static combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800157static struct stlbrd stl_dummybrd;
158static struct stlport stl_dummyport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160/*
161 * Define global place to put buffer overflow characters.
162 */
163static char stl_unwanted[SC26198_RXFIFOSIZE];
164
165/*****************************************************************************/
166
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800167static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
169/*
170 * Per board state flags. Used with the state field of the board struct.
171 * Not really much here!
172 */
173#define BRD_FOUND 0x1
174
175/*
176 * Define the port structure istate flags. These set of flags are
177 * modified at interrupt time - so setting and reseting them needs
178 * to be atomic. Use the bit clear/setting routines for this.
179 */
180#define ASYI_TXBUSY 1
181#define ASYI_TXLOW 2
182#define ASYI_DCDCHANGE 3
183#define ASYI_TXFLOWED 4
184
185/*
186 * Define an array of board names as printable strings. Handy for
187 * referencing boards when printing trace and stuff.
188 */
189static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800190 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,
208 NULL,
209 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 "EasyIO",
211 "EC8/32-AT",
212 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800213 NULL,
214 NULL,
215 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 "EC8/32-PCI",
217 "EC8/64-PCI",
218 "EasyIO-PCI",
219};
220
221/*****************************************************************************/
222
223/*
224 * Define some string labels for arguments passed from the module
225 * load line. These allow for easy board definitions, and easy
226 * modification of the io, memory and irq resoucres.
227 */
228static int stl_nargs = 0;
229static char *board0[4];
230static char *board1[4];
231static char *board2[4];
232static char *board3[4];
233
234static char **stl_brdsp[] = {
235 (char **) &board0,
236 (char **) &board1,
237 (char **) &board2,
238 (char **) &board3
239};
240
241/*
242 * Define a set of common board names, and types. This is used to
243 * parse any module arguments.
244 */
245
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800246static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 char *name;
248 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800249} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 { "easyio", BRD_EASYIO },
251 { "eio", BRD_EASYIO },
252 { "20", BRD_EASYIO },
253 { "ec8/32", BRD_ECH },
254 { "ec8/32-at", BRD_ECH },
255 { "ec8/32-isa", BRD_ECH },
256 { "ech", BRD_ECH },
257 { "echat", BRD_ECH },
258 { "21", BRD_ECH },
259 { "ec8/32-mc", BRD_ECHMC },
260 { "ec8/32-mca", BRD_ECHMC },
261 { "echmc", BRD_ECHMC },
262 { "echmca", BRD_ECHMC },
263 { "22", BRD_ECHMC },
264 { "ec8/32-pc", BRD_ECHPCI },
265 { "ec8/32-pci", BRD_ECHPCI },
266 { "26", BRD_ECHPCI },
267 { "ec8/64-pc", BRD_ECH64PCI },
268 { "ec8/64-pci", BRD_ECH64PCI },
269 { "ech-pci", BRD_ECH64PCI },
270 { "echpci", BRD_ECH64PCI },
271 { "echpc", BRD_ECH64PCI },
272 { "27", BRD_ECH64PCI },
273 { "easyio-pc", BRD_EASYIOPCI },
274 { "easyio-pci", BRD_EASYIOPCI },
275 { "eio-pci", BRD_EASYIOPCI },
276 { "eiopci", BRD_EASYIOPCI },
277 { "28", BRD_EASYIOPCI },
278};
279
280/*
281 * Define the module agruments.
282 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284module_param_array(board0, charp, &stl_nargs, 0);
285MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
286module_param_array(board1, charp, &stl_nargs, 0);
287MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
288module_param_array(board2, charp, &stl_nargs, 0);
289MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
290module_param_array(board3, charp, &stl_nargs, 0);
291MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
292
293/*****************************************************************************/
294
295/*
296 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
297 * to the directly accessible io ports of these boards (not the uarts -
298 * they are in cd1400.h and sc26198.h).
299 */
300#define EIO_8PORTRS 0x04
301#define EIO_4PORTRS 0x05
302#define EIO_8PORTDI 0x00
303#define EIO_8PORTM 0x06
304#define EIO_MK3 0x03
305#define EIO_IDBITMASK 0x07
306
307#define EIO_BRDMASK 0xf0
308#define ID_BRD4 0x10
309#define ID_BRD8 0x20
310#define ID_BRD16 0x30
311
312#define EIO_INTRPEND 0x08
313#define EIO_INTEDGE 0x00
314#define EIO_INTLEVEL 0x08
315#define EIO_0WS 0x10
316
317#define ECH_ID 0xa0
318#define ECH_IDBITMASK 0xe0
319#define ECH_BRDENABLE 0x08
320#define ECH_BRDDISABLE 0x00
321#define ECH_INTENABLE 0x01
322#define ECH_INTDISABLE 0x00
323#define ECH_INTLEVEL 0x02
324#define ECH_INTEDGE 0x00
325#define ECH_INTRPEND 0x01
326#define ECH_BRDRESET 0x01
327
328#define ECHMC_INTENABLE 0x01
329#define ECHMC_BRDRESET 0x02
330
331#define ECH_PNLSTATUS 2
332#define ECH_PNL16PORT 0x20
333#define ECH_PNLIDMASK 0x07
334#define ECH_PNLXPID 0x40
335#define ECH_PNLINTRPEND 0x80
336
337#define ECH_ADDR2MASK 0x1e0
338
339/*
340 * Define the vector mapping bits for the programmable interrupt board
341 * hardware. These bits encode the interrupt for the board to use - it
342 * is software selectable (except the EIO-8M).
343 */
344static unsigned char stl_vecmap[] = {
345 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
346 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
347};
348
349/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700350 * Lock ordering is that you may not take stallion_lock holding
351 * brd_lock.
352 */
353
354static spinlock_t brd_lock; /* Guard the board mapping */
355static spinlock_t stallion_lock; /* Guard the tty driver */
356
357/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 * Set up enable and disable macros for the ECH boards. They require
359 * the secondary io address space to be activated and deactivated.
360 * This way all ECH boards can share their secondary io region.
361 * If this is an ECH-PCI board then also need to set the page pointer
362 * to point to the correct page.
363 */
364#define BRDENABLE(brdnr,pagenr) \
365 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
366 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
367 stl_brds[(brdnr)]->ioctrl); \
368 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
369 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
370
371#define BRDDISABLE(brdnr) \
372 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
373 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
374 stl_brds[(brdnr)]->ioctrl);
375
376#define STL_CD1400MAXBAUD 230400
377#define STL_SC26198MAXBAUD 460800
378
379#define STL_BAUDBASE 115200
380#define STL_CLOSEDELAY (5 * HZ / 10)
381
382/*****************************************************************************/
383
384#ifdef CONFIG_PCI
385
386/*
387 * Define the Stallion PCI vendor and device IDs.
388 */
389#ifndef PCI_VENDOR_ID_STALLION
390#define PCI_VENDOR_ID_STALLION 0x124d
391#endif
392#ifndef PCI_DEVICE_ID_ECHPCI832
393#define PCI_DEVICE_ID_ECHPCI832 0x0000
394#endif
395#ifndef PCI_DEVICE_ID_ECHPCI864
396#define PCI_DEVICE_ID_ECHPCI864 0x0002
397#endif
398#ifndef PCI_DEVICE_ID_EIOPCI
399#define PCI_DEVICE_ID_EIOPCI 0x0003
400#endif
401
402/*
403 * Define structure to hold all Stallion PCI boards.
404 */
405typedef struct stlpcibrd {
406 unsigned short vendid;
407 unsigned short devid;
408 int brdtype;
409} stlpcibrd_t;
410
411static stlpcibrd_t stl_pcibrds[] = {
412 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI },
413 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI },
414 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI },
415 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
416};
417
Tobias Klauserfe971072006-01-09 20:54:02 -0800418static int stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
420#endif
421
422/*****************************************************************************/
423
424/*
425 * Define macros to extract a brd/port number from a minor number.
426 */
427#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
428#define MINOR2PORT(min) ((min) & 0x3f)
429
430/*
431 * Define a baud rate table that converts termios baud rate selector
432 * into the actual baud rate value. All baud rate calculations are
433 * based on the actual baud rate required.
434 */
435static unsigned int stl_baudrates[] = {
436 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
437 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
438};
439
440/*
441 * Define some handy local macros...
442 */
443#undef MIN
444#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
445
446#undef TOLOWER
447#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
448
449/*****************************************************************************/
450
451/*
452 * Declare all those functions in this driver!
453 */
454
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800456static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800457static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
458static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800459static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461/*
462 * CD1400 uart specific handling functions.
463 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800464static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
465static int stl_cd1400getreg(struct stlport *portp, int regnr);
466static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
467static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
468static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800469static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800470static int stl_cd1400getsignals(struct stlport *portp);
471static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
472static void stl_cd1400ccrwait(struct stlport *portp);
473static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
474static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
475static void stl_cd1400disableintrs(struct stlport *portp);
476static void stl_cd1400sendbreak(struct stlport *portp, int len);
477static void stl_cd1400flowctrl(struct stlport *portp, int state);
478static void stl_cd1400sendflow(struct stlport *portp, int state);
479static void stl_cd1400flush(struct stlport *portp);
480static int stl_cd1400datastate(struct stlport *portp);
481static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
482static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
483static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
484static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
485static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800487static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
489/*
490 * SC26198 uart specific handling functions.
491 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800492static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
493static int stl_sc26198getreg(struct stlport *portp, int regnr);
494static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
495static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
496static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
497static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800498static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800499static int stl_sc26198getsignals(struct stlport *portp);
500static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
501static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
502static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
503static void stl_sc26198disableintrs(struct stlport *portp);
504static void stl_sc26198sendbreak(struct stlport *portp, int len);
505static void stl_sc26198flowctrl(struct stlport *portp, int state);
506static void stl_sc26198sendflow(struct stlport *portp, int state);
507static void stl_sc26198flush(struct stlport *portp);
508static int stl_sc26198datastate(struct stlport *portp);
509static void stl_sc26198wait(struct stlport *portp);
510static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
511static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
512static void stl_sc26198txisr(struct stlport *port);
513static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
514static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
515static void stl_sc26198rxbadchars(struct stlport *portp);
516static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
518/*****************************************************************************/
519
520/*
521 * Generic UART support structure.
522 */
523typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800524 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
525 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800526 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800527 int (*getsignals)(struct stlport *portp);
528 void (*setsignals)(struct stlport *portp, int dtr, int rts);
529 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
530 void (*startrxtx)(struct stlport *portp, int rx, int tx);
531 void (*disableintrs)(struct stlport *portp);
532 void (*sendbreak)(struct stlport *portp, int len);
533 void (*flowctrl)(struct stlport *portp, int state);
534 void (*sendflow)(struct stlport *portp, int state);
535 void (*flush)(struct stlport *portp);
536 int (*datastate)(struct stlport *portp);
537 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538} uart_t;
539
540/*
541 * Define some macros to make calling these functions nice and clean.
542 */
543#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
544#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
545#define stl_setport (* ((uart_t *) portp->uartp)->setport)
546#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
547#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
548#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
549#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
550#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
551#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
552#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
553#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
554#define stl_flush (* ((uart_t *) portp->uartp)->flush)
555#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
556
557/*****************************************************************************/
558
559/*
560 * CD1400 UART specific data initialization.
561 */
562static uart_t stl_cd1400uart = {
563 stl_cd1400panelinit,
564 stl_cd1400portinit,
565 stl_cd1400setport,
566 stl_cd1400getsignals,
567 stl_cd1400setsignals,
568 stl_cd1400enablerxtx,
569 stl_cd1400startrxtx,
570 stl_cd1400disableintrs,
571 stl_cd1400sendbreak,
572 stl_cd1400flowctrl,
573 stl_cd1400sendflow,
574 stl_cd1400flush,
575 stl_cd1400datastate,
576 stl_cd1400eiointr
577};
578
579/*
580 * Define the offsets within the register bank of a cd1400 based panel.
581 * These io address offsets are common to the EasyIO board as well.
582 */
583#define EREG_ADDR 0
584#define EREG_DATA 4
585#define EREG_RXACK 5
586#define EREG_TXACK 6
587#define EREG_MDACK 7
588
589#define EREG_BANKSIZE 8
590
591#define CD1400_CLK 25000000
592#define CD1400_CLK8M 20000000
593
594/*
595 * Define the cd1400 baud rate clocks. These are used when calculating
596 * what clock and divisor to use for the required baud rate. Also
597 * define the maximum baud rate allowed, and the default base baud.
598 */
599static int stl_cd1400clkdivs[] = {
600 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
601};
602
603/*****************************************************************************/
604
605/*
606 * SC26198 UART specific data initization.
607 */
608static uart_t stl_sc26198uart = {
609 stl_sc26198panelinit,
610 stl_sc26198portinit,
611 stl_sc26198setport,
612 stl_sc26198getsignals,
613 stl_sc26198setsignals,
614 stl_sc26198enablerxtx,
615 stl_sc26198startrxtx,
616 stl_sc26198disableintrs,
617 stl_sc26198sendbreak,
618 stl_sc26198flowctrl,
619 stl_sc26198sendflow,
620 stl_sc26198flush,
621 stl_sc26198datastate,
622 stl_sc26198intr
623};
624
625/*
626 * Define the offsets within the register bank of a sc26198 based panel.
627 */
628#define XP_DATA 0
629#define XP_ADDR 1
630#define XP_MODID 2
631#define XP_STATUS 2
632#define XP_IACK 3
633
634#define XP_BANKSIZE 4
635
636/*
637 * Define the sc26198 baud rate table. Offsets within the table
638 * represent the actual baud rate selector of sc26198 registers.
639 */
640static unsigned int sc26198_baudtable[] = {
641 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
642 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
643 230400, 460800, 921600
644};
645
Tobias Klauserfe971072006-01-09 20:54:02 -0800646#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
648/*****************************************************************************/
649
650/*
651 * Define the driver info for a user level control device. Used mainly
652 * to get at port stats - only not using the port device itself.
653 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700654static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 .owner = THIS_MODULE,
656 .ioctl = stl_memioctl,
657};
658
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800659static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
661/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 * Check for any arguments passed in on the module load command line.
663 */
664
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665/*****************************************************************************/
666
667/*
668 * Convert an ascii string number into an unsigned long.
669 */
670
671static unsigned long stl_atol(char *str)
672{
673 unsigned long val;
674 int base, c;
675 char *sp;
676
677 val = 0;
678 sp = str;
679 if ((*sp == '0') && (*(sp+1) == 'x')) {
680 base = 16;
681 sp += 2;
682 } else if (*sp == '0') {
683 base = 8;
684 sp++;
685 } else {
686 base = 10;
687 }
688
689 for (; (*sp != 0); sp++) {
690 c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
691 if ((c < 0) || (c >= base)) {
692 printk("STALLION: invalid argument %s\n", str);
693 val = 0;
694 break;
695 }
696 val = (val * base) + c;
697 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100698 return val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699}
700
701/*****************************************************************************/
702
703/*
704 * Parse the supplied argument string, into the board conf struct.
705 */
706
Jiri Slaby40e82652006-12-08 02:38:41 -0800707static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708{
709 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800710 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Jiri Slabya0564e12006-12-08 02:38:37 -0800712 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Jiri Slaby615e4a72006-12-08 02:38:38 -0800714 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100715 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
718 *sp = TOLOWER(*sp);
719
Tobias Klauserfe971072006-01-09 20:54:02 -0800720 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
722 break;
723 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800724 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800726 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 }
728
729 confp->brdtype = stl_brdstr[i].type;
730
731 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800732 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 confp->ioaddr1 = stl_atol(argp[i]);
734 i++;
735 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800736 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 confp->ioaddr2 = stl_atol(argp[i]);
738 i++;
739 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800740 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 confp->irq = stl_atol(argp[i]);
Jesper Juhl014c2542006-01-15 02:37:08 +0100742 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743}
744
745/*****************************************************************************/
746
747/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 * Allocate a new board structure. Fill out the basic info in it.
749 */
750
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800751static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800753 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800755 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800756 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700757 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800758 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800759 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 }
761
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100763 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764}
765
Jiri Slaby96b066b2006-12-08 02:38:42 -0800766static void __init stl_argbrds(void)
767{
768 struct stlconf conf;
769 struct stlbrd *brdp;
770 int i;
771
772 pr_debug("stl_argbrds()\n");
773
774 for (i = stl_nrbrds; (i < stl_nargs); i++) {
775 memset(&conf, 0, sizeof(conf));
776 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
777 continue;
778 if ((brdp = stl_allocbrd()) == NULL)
779 continue;
780 stl_nrbrds = i + 1;
781 brdp->brdnr = i;
782 brdp->brdtype = conf.brdtype;
783 brdp->ioaddr1 = conf.ioaddr1;
784 brdp->ioaddr2 = conf.ioaddr2;
785 brdp->irq = conf.irq;
786 brdp->irqtype = conf.irqtype;
787 stl_brdinit(brdp);
788 }
789}
790
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791/*****************************************************************************/
792
793static int stl_open(struct tty_struct *tty, struct file *filp)
794{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800795 struct stlport *portp;
796 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 unsigned int minordev;
798 int brdnr, panelnr, portnr, rc;
799
Jiri Slabya0564e12006-12-08 02:38:37 -0800800 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
802 minordev = tty->index;
803 brdnr = MINOR2BRD(minordev);
804 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100805 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800807 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100808 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 minordev = MINOR2PORT(minordev);
810 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800811 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 break;
813 if (minordev < brdp->panels[panelnr]->nrports) {
814 portnr = minordev;
815 break;
816 }
817 minordev -= brdp->panels[panelnr]->nrports;
818 }
819 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100820 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800823 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100824 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
826/*
827 * On the first open of the device setup the port hardware, and
828 * initialize the per port data structure.
829 */
830 portp->tty = tty;
831 tty->driver_data = portp;
832 portp->refcount++;
833
834 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800835 if (!portp->tx.buf) {
836 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
837 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100838 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 portp->tx.head = portp->tx.buf;
840 portp->tx.tail = portp->tx.buf;
841 }
842 stl_setport(portp, tty->termios);
843 portp->sigs = stl_getsignals(portp);
844 stl_setsignals(portp, 1, 1);
845 stl_enablerxtx(portp, 1, 1);
846 stl_startrxtx(portp, 1, 0);
847 clear_bit(TTY_IO_ERROR, &tty->flags);
848 portp->flags |= ASYNC_INITIALIZED;
849 }
850
851/*
852 * Check if this port is in the middle of closing. If so then wait
853 * until it is closed then return error status, based on flag settings.
854 * The sleep here does not need interrupt protection since the wakeup
855 * for it is done with the same context.
856 */
857 if (portp->flags & ASYNC_CLOSING) {
858 interruptible_sleep_on(&portp->close_wait);
859 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100860 return -EAGAIN;
861 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 }
863
864/*
865 * Based on type of open being done check if it can overlap with any
866 * previous opens still in effect. If we are a normal serial device
867 * then also we might have to wait for carrier.
868 */
869 if (!(filp->f_flags & O_NONBLOCK)) {
870 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100871 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 }
873 portp->flags |= ASYNC_NORMAL_ACTIVE;
874
Jesper Juhl014c2542006-01-15 02:37:08 +0100875 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876}
877
878/*****************************************************************************/
879
880/*
881 * Possibly need to wait for carrier (DCD signal) to come high. Say
882 * maybe because if we are clocal then we don't need to wait...
883 */
884
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800885static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886{
887 unsigned long flags;
888 int rc, doclocal;
889
Jiri Slabya0564e12006-12-08 02:38:37 -0800890 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
892 rc = 0;
893 doclocal = 0;
894
Alan Coxb65b5b52006-06-27 02:54:05 -0700895 spin_lock_irqsave(&stallion_lock, flags);
896
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 if (portp->tty->termios->c_cflag & CLOCAL)
898 doclocal++;
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 portp->openwaitcnt++;
901 if (! tty_hung_up_p(filp))
902 portp->refcount--;
903
904 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700905 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 stl_setsignals(portp, 1, 1);
907 if (tty_hung_up_p(filp) ||
908 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
909 if (portp->flags & ASYNC_HUP_NOTIFY)
910 rc = -EBUSY;
911 else
912 rc = -ERESTARTSYS;
913 break;
914 }
915 if (((portp->flags & ASYNC_CLOSING) == 0) &&
916 (doclocal || (portp->sigs & TIOCM_CD))) {
917 break;
918 }
919 if (signal_pending(current)) {
920 rc = -ERESTARTSYS;
921 break;
922 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700923 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 interruptible_sleep_on(&portp->open_wait);
925 }
926
927 if (! tty_hung_up_p(filp))
928 portp->refcount++;
929 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700930 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931
Jesper Juhl014c2542006-01-15 02:37:08 +0100932 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933}
934
935/*****************************************************************************/
936
Jiri Slaby96b066b2006-12-08 02:38:42 -0800937static void stl_flushbuffer(struct tty_struct *tty)
938{
939 struct stlport *portp;
940
941 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
942
943 if (tty == NULL)
944 return;
945 portp = tty->driver_data;
946 if (portp == NULL)
947 return;
948
949 stl_flush(portp);
950 tty_wakeup(tty);
951}
952
953/*****************************************************************************/
954
955static void stl_waituntilsent(struct tty_struct *tty, int timeout)
956{
957 struct stlport *portp;
958 unsigned long tend;
959
960 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
961
962 if (tty == NULL)
963 return;
964 portp = tty->driver_data;
965 if (portp == NULL)
966 return;
967
968 if (timeout == 0)
969 timeout = HZ;
970 tend = jiffies + timeout;
971
972 while (stl_datastate(portp)) {
973 if (signal_pending(current))
974 break;
975 msleep_interruptible(20);
976 if (time_after_eq(jiffies, tend))
977 break;
978 }
979}
980
981/*****************************************************************************/
982
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983static void stl_close(struct tty_struct *tty, struct file *filp)
984{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800985 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 unsigned long flags;
987
Jiri Slabya0564e12006-12-08 02:38:37 -0800988 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
990 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800991 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 return;
993
Alan Coxb65b5b52006-06-27 02:54:05 -0700994 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700996 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 return;
998 }
999 if ((tty->count == 1) && (portp->refcount != 1))
1000 portp->refcount = 1;
1001 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -07001002 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 return;
1004 }
1005
1006 portp->refcount = 0;
1007 portp->flags |= ASYNC_CLOSING;
1008
1009/*
1010 * May want to wait for any data to drain before closing. The BUSY
1011 * flag keeps track of whether we are still sending or not - it is
1012 * very accurate for the cd1400, not quite so for the sc26198.
1013 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
1014 */
1015 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -07001016
1017 spin_unlock_irqrestore(&stallion_lock, flags);
1018
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1020 tty_wait_until_sent(tty, portp->closing_wait);
1021 stl_waituntilsent(tty, (HZ / 2));
1022
Alan Coxb65b5b52006-06-27 02:54:05 -07001023
1024 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -07001026 spin_unlock_irqrestore(&stallion_lock, flags);
1027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 stl_disableintrs(portp);
1029 if (tty->termios->c_cflag & HUPCL)
1030 stl_setsignals(portp, 0, 0);
1031 stl_enablerxtx(portp, 0, 0);
1032 stl_flushbuffer(tty);
1033 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001034 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001036 portp->tx.buf = NULL;
1037 portp->tx.head = NULL;
1038 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040 set_bit(TTY_IO_ERROR, &tty->flags);
1041 tty_ldisc_flush(tty);
1042
1043 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001044 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
1046 if (portp->openwaitcnt) {
1047 if (portp->close_delay)
1048 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
1049 wake_up_interruptible(&portp->open_wait);
1050 }
1051
1052 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1053 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054}
1055
1056/*****************************************************************************/
1057
1058/*
1059 * Write routine. Take data and stuff it in to the TX ring queue.
1060 * If transmit interrupts are not running then start them.
1061 */
1062
1063static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
1064{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001065 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 unsigned int len, stlen;
1067 unsigned char *chbuf;
1068 char *head, *tail;
1069
Jiri Slabya0564e12006-12-08 02:38:37 -08001070 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001073 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001074 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001075 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001076 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
1078/*
1079 * If copying direct from user space we must cater for page faults,
1080 * causing us to "sleep" here for a while. To handle this copy in all
1081 * the data we need now, into a local buffer. Then when we got it all
1082 * copy it into the TX buffer.
1083 */
1084 chbuf = (unsigned char *) buf;
1085
1086 head = portp->tx.head;
1087 tail = portp->tx.tail;
1088 if (head >= tail) {
1089 len = STL_TXBUFSIZE - (head - tail) - 1;
1090 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1091 } else {
1092 len = tail - head - 1;
1093 stlen = len;
1094 }
1095
1096 len = MIN(len, count);
1097 count = 0;
1098 while (len > 0) {
1099 stlen = MIN(len, stlen);
1100 memcpy(head, chbuf, stlen);
1101 len -= stlen;
1102 chbuf += stlen;
1103 count += stlen;
1104 head += stlen;
1105 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1106 head = portp->tx.buf;
1107 stlen = tail - head;
1108 }
1109 }
1110 portp->tx.head = head;
1111
1112 clear_bit(ASYI_TXLOW, &portp->istate);
1113 stl_startrxtx(portp, -1, 1);
1114
Jesper Juhl014c2542006-01-15 02:37:08 +01001115 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116}
1117
1118/*****************************************************************************/
1119
1120static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1121{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001122 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 unsigned int len;
1124 char *head, *tail;
1125
Jiri Slabya0564e12006-12-08 02:38:37 -08001126 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
Jiri Slaby615e4a72006-12-08 02:38:38 -08001128 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 return;
1130 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001131 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001133 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return;
1135
1136 head = portp->tx.head;
1137 tail = portp->tx.tail;
1138
1139 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1140 len--;
1141
1142 if (len > 0) {
1143 *head++ = ch;
1144 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1145 head = portp->tx.buf;
1146 }
1147 portp->tx.head = head;
1148}
1149
1150/*****************************************************************************/
1151
1152/*
1153 * If there are any characters in the buffer then make sure that TX
1154 * interrupts are on and get'em out. Normally used after the putchar
1155 * routine has been called.
1156 */
1157
1158static void stl_flushchars(struct tty_struct *tty)
1159{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001160 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Jiri Slabya0564e12006-12-08 02:38:37 -08001162 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Jiri Slaby615e4a72006-12-08 02:38:38 -08001164 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 return;
1166 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001167 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001169 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 return;
1171
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 stl_startrxtx(portp, -1, 1);
1173}
1174
1175/*****************************************************************************/
1176
1177static int stl_writeroom(struct tty_struct *tty)
1178{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001179 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 char *head, *tail;
1181
Jiri Slabya0564e12006-12-08 02:38:37 -08001182 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Jiri Slaby615e4a72006-12-08 02:38:38 -08001184 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001185 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001187 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001188 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001189 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001190 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191
1192 head = portp->tx.head;
1193 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001194 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195}
1196
1197/*****************************************************************************/
1198
1199/*
1200 * Return number of chars in the TX buffer. Normally we would just
1201 * calculate the number of chars in the buffer and return that, but if
1202 * the buffer is empty and TX interrupts are still on then we return
1203 * that the buffer still has 1 char in it. This way whoever called us
1204 * will not think that ALL chars have drained - since the UART still
1205 * must have some chars in it (we are busy after all).
1206 */
1207
1208static int stl_charsinbuffer(struct tty_struct *tty)
1209{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001210 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 unsigned int size;
1212 char *head, *tail;
1213
Jiri Slabya0564e12006-12-08 02:38:37 -08001214 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Jiri Slaby615e4a72006-12-08 02:38:38 -08001216 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001217 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001219 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001220 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001221 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001222 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
1224 head = portp->tx.head;
1225 tail = portp->tx.tail;
1226 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1227 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1228 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001229 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230}
1231
1232/*****************************************************************************/
1233
1234/*
1235 * Generate the serial struct info.
1236 */
1237
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001238static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239{
1240 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001241 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Jiri Slabya0564e12006-12-08 02:38:37 -08001243 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
1245 memset(&sio, 0, sizeof(struct serial_struct));
1246 sio.line = portp->portnr;
1247 sio.port = portp->ioaddr;
1248 sio.flags = portp->flags;
1249 sio.baud_base = portp->baud_base;
1250 sio.close_delay = portp->close_delay;
1251 sio.closing_wait = portp->closing_wait;
1252 sio.custom_divisor = portp->custom_divisor;
1253 sio.hub6 = 0;
1254 if (portp->uartp == &stl_cd1400uart) {
1255 sio.type = PORT_CIRRUS;
1256 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1257 } else {
1258 sio.type = PORT_UNKNOWN;
1259 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1260 }
1261
1262 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001263 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 sio.irq = brdp->irq;
1265
1266 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1267}
1268
1269/*****************************************************************************/
1270
1271/*
1272 * Set port according to the serial struct info.
1273 * At this point we do not do any auto-configure stuff, so we will
1274 * just quietly ignore any requests to change irq, etc.
1275 */
1276
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001277static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278{
1279 struct serial_struct sio;
1280
Jiri Slabya0564e12006-12-08 02:38:37 -08001281 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
1283 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1284 return -EFAULT;
1285 if (!capable(CAP_SYS_ADMIN)) {
1286 if ((sio.baud_base != portp->baud_base) ||
1287 (sio.close_delay != portp->close_delay) ||
1288 ((sio.flags & ~ASYNC_USR_MASK) !=
1289 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001290 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 }
1292
1293 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1294 (sio.flags & ASYNC_USR_MASK);
1295 portp->baud_base = sio.baud_base;
1296 portp->close_delay = sio.close_delay;
1297 portp->closing_wait = sio.closing_wait;
1298 portp->custom_divisor = sio.custom_divisor;
1299 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001300 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301}
1302
1303/*****************************************************************************/
1304
1305static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1306{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001307 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Jiri Slaby615e4a72006-12-08 02:38:38 -08001309 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001310 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001312 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001313 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001315 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
1317 return stl_getsignals(portp);
1318}
1319
1320static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1321 unsigned int set, unsigned int clear)
1322{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001323 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 int rts = -1, dtr = -1;
1325
Jiri Slaby615e4a72006-12-08 02:38:38 -08001326 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001327 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001329 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001330 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001332 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333
1334 if (set & TIOCM_RTS)
1335 rts = 1;
1336 if (set & TIOCM_DTR)
1337 dtr = 1;
1338 if (clear & TIOCM_RTS)
1339 rts = 0;
1340 if (clear & TIOCM_DTR)
1341 dtr = 0;
1342
1343 stl_setsignals(portp, dtr, rts);
1344 return 0;
1345}
1346
1347static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1348{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001349 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 unsigned int ival;
1351 int rc;
1352 void __user *argp = (void __user *)arg;
1353
Jiri Slabya0564e12006-12-08 02:38:37 -08001354 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1355 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Jiri Slaby615e4a72006-12-08 02:38:38 -08001357 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001358 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001360 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001361 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1364 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1365 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001366 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 }
1368
1369 rc = 0;
1370
1371 switch (cmd) {
1372 case TIOCGSOFTCAR:
1373 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1374 (unsigned __user *) argp);
1375 break;
1376 case TIOCSSOFTCAR:
1377 if (get_user(ival, (unsigned int __user *) arg))
1378 return -EFAULT;
1379 tty->termios->c_cflag =
1380 (tty->termios->c_cflag & ~CLOCAL) |
1381 (ival ? CLOCAL : 0);
1382 break;
1383 case TIOCGSERIAL:
1384 rc = stl_getserial(portp, argp);
1385 break;
1386 case TIOCSSERIAL:
1387 rc = stl_setserial(portp, argp);
1388 break;
1389 case COM_GETPORTSTATS:
1390 rc = stl_getportstats(portp, argp);
1391 break;
1392 case COM_CLRPORTSTATS:
1393 rc = stl_clrportstats(portp, argp);
1394 break;
1395 case TIOCSERCONFIG:
1396 case TIOCSERGWILD:
1397 case TIOCSERSWILD:
1398 case TIOCSERGETLSR:
1399 case TIOCSERGSTRUCT:
1400 case TIOCSERGETMULTI:
1401 case TIOCSERSETMULTI:
1402 default:
1403 rc = -ENOIOCTLCMD;
1404 break;
1405 }
1406
Jesper Juhl014c2542006-01-15 02:37:08 +01001407 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408}
1409
1410/*****************************************************************************/
1411
Jiri Slaby96b066b2006-12-08 02:38:42 -08001412/*
1413 * Start the transmitter again. Just turn TX interrupts back on.
1414 */
1415
1416static void stl_start(struct tty_struct *tty)
1417{
1418 struct stlport *portp;
1419
1420 pr_debug("stl_start(tty=%p)\n", tty);
1421
1422 if (tty == NULL)
1423 return;
1424 portp = tty->driver_data;
1425 if (portp == NULL)
1426 return;
1427 stl_startrxtx(portp, -1, 1);
1428}
1429
1430/*****************************************************************************/
1431
Alan Cox606d0992006-12-08 02:38:45 -08001432static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001434 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001435 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Jiri Slabya0564e12006-12-08 02:38:37 -08001437 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
Jiri Slaby615e4a72006-12-08 02:38:38 -08001439 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 return;
1441 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001442 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 return;
1444
1445 tiosp = tty->termios;
1446 if ((tiosp->c_cflag == old->c_cflag) &&
1447 (tiosp->c_iflag == old->c_iflag))
1448 return;
1449
1450 stl_setport(portp, tiosp);
1451 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1452 -1);
1453 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1454 tty->hw_stopped = 0;
1455 stl_start(tty);
1456 }
1457 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1458 wake_up_interruptible(&portp->open_wait);
1459}
1460
1461/*****************************************************************************/
1462
1463/*
1464 * Attempt to flow control who ever is sending us data. Based on termios
1465 * settings use software or/and hardware flow control.
1466 */
1467
1468static void stl_throttle(struct tty_struct *tty)
1469{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001470 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
Jiri Slabya0564e12006-12-08 02:38:37 -08001472 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
Jiri Slaby615e4a72006-12-08 02:38:38 -08001474 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 return;
1476 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001477 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 return;
1479 stl_flowctrl(portp, 0);
1480}
1481
1482/*****************************************************************************/
1483
1484/*
1485 * Unflow control the device sending us data...
1486 */
1487
1488static void stl_unthrottle(struct tty_struct *tty)
1489{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001490 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Jiri Slabya0564e12006-12-08 02:38:37 -08001492 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
Jiri Slaby615e4a72006-12-08 02:38:38 -08001494 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 return;
1496 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001497 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 return;
1499 stl_flowctrl(portp, 1);
1500}
1501
1502/*****************************************************************************/
1503
1504/*
1505 * Stop the transmitter. Basically to do this we will just turn TX
1506 * interrupts off.
1507 */
1508
1509static void stl_stop(struct tty_struct *tty)
1510{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001511 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
Jiri Slabya0564e12006-12-08 02:38:37 -08001513 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
Jiri Slaby615e4a72006-12-08 02:38:38 -08001515 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 return;
1517 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001518 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 return;
1520 stl_startrxtx(portp, -1, 0);
1521}
1522
1523/*****************************************************************************/
1524
1525/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 * Hangup this port. This is pretty much like closing the port, only
1527 * a little more brutal. No waiting for data to drain. Shutdown the
1528 * port and maybe drop signals.
1529 */
1530
1531static void stl_hangup(struct tty_struct *tty)
1532{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001533 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Jiri Slabya0564e12006-12-08 02:38:37 -08001535 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Jiri Slaby615e4a72006-12-08 02:38:38 -08001537 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 return;
1539 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001540 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 return;
1542
1543 portp->flags &= ~ASYNC_INITIALIZED;
1544 stl_disableintrs(portp);
1545 if (tty->termios->c_cflag & HUPCL)
1546 stl_setsignals(portp, 0, 0);
1547 stl_enablerxtx(portp, 0, 0);
1548 stl_flushbuffer(tty);
1549 portp->istate = 0;
1550 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001551 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001553 portp->tx.buf = NULL;
1554 portp->tx.head = NULL;
1555 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001557 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1559 portp->refcount = 0;
1560 wake_up_interruptible(&portp->open_wait);
1561}
1562
1563/*****************************************************************************/
1564
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565static void stl_breakctl(struct tty_struct *tty, int state)
1566{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001567 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
Jiri Slabya0564e12006-12-08 02:38:37 -08001569 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
Jiri Slaby615e4a72006-12-08 02:38:38 -08001571 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 return;
1573 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001574 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 return;
1576
1577 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1578}
1579
1580/*****************************************************************************/
1581
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582static void stl_sendxchar(struct tty_struct *tty, char ch)
1583{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001584 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
Jiri Slabya0564e12006-12-08 02:38:37 -08001586 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
Jiri Slaby615e4a72006-12-08 02:38:38 -08001588 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 return;
1590 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001591 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 return;
1593
1594 if (ch == STOP_CHAR(tty))
1595 stl_sendflow(portp, 0);
1596 else if (ch == START_CHAR(tty))
1597 stl_sendflow(portp, 1);
1598 else
1599 stl_putchar(tty, ch);
1600}
1601
1602/*****************************************************************************/
1603
1604#define MAXLINE 80
1605
1606/*
1607 * Format info for a specified port. The line is deliberately limited
1608 * to 80 characters. (If it is too long it will be truncated, if too
1609 * short then padded with spaces).
1610 */
1611
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001612static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613{
1614 char *sp;
1615 int sigs, cnt;
1616
1617 sp = pos;
1618 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1619 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1620 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1621
1622 if (portp->stats.rxframing)
1623 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1624 if (portp->stats.rxparity)
1625 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1626 if (portp->stats.rxbreaks)
1627 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1628 if (portp->stats.rxoverrun)
1629 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1630
1631 sigs = stl_getsignals(portp);
1632 cnt = sprintf(sp, "%s%s%s%s%s ",
1633 (sigs & TIOCM_RTS) ? "|RTS" : "",
1634 (sigs & TIOCM_CTS) ? "|CTS" : "",
1635 (sigs & TIOCM_DTR) ? "|DTR" : "",
1636 (sigs & TIOCM_CD) ? "|DCD" : "",
1637 (sigs & TIOCM_DSR) ? "|DSR" : "");
1638 *sp = ' ';
1639 sp += cnt;
1640
1641 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1642 *sp++ = ' ';
1643 if (cnt >= MAXLINE)
1644 pos[(MAXLINE - 2)] = '+';
1645 pos[(MAXLINE - 1)] = '\n';
1646
Jesper Juhl014c2542006-01-15 02:37:08 +01001647 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648}
1649
1650/*****************************************************************************/
1651
1652/*
1653 * Port info, read from the /proc file system.
1654 */
1655
1656static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1657{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001658 struct stlbrd *brdp;
1659 struct stlpanel *panelp;
1660 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 int brdnr, panelnr, portnr, totalport;
1662 int curoff, maxoff;
1663 char *pos;
1664
Jiri Slabya0564e12006-12-08 02:38:37 -08001665 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1666 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
1668 pos = page;
1669 totalport = 0;
1670 curoff = 0;
1671
1672 if (off == 0) {
1673 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1674 stl_drvversion);
1675 while (pos < (page + MAXLINE - 1))
1676 *pos++ = ' ';
1677 *pos++ = '\n';
1678 }
1679 curoff = MAXLINE;
1680
1681/*
1682 * We scan through for each board, panel and port. The offset is
1683 * calculated on the fly, and irrelevant ports are skipped.
1684 */
1685 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1686 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001687 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 continue;
1689 if (brdp->state == 0)
1690 continue;
1691
1692 maxoff = curoff + (brdp->nrports * MAXLINE);
1693 if (off >= maxoff) {
1694 curoff = maxoff;
1695 continue;
1696 }
1697
1698 totalport = brdnr * STL_MAXPORTS;
1699 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1700 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001701 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 continue;
1703
1704 maxoff = curoff + (panelp->nrports * MAXLINE);
1705 if (off >= maxoff) {
1706 curoff = maxoff;
1707 totalport += panelp->nrports;
1708 continue;
1709 }
1710
1711 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1712 totalport++) {
1713 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001714 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 continue;
1716 if (off >= (curoff += MAXLINE))
1717 continue;
1718 if ((pos - page + MAXLINE) > count)
1719 goto stl_readdone;
1720 pos += stl_portinfo(portp, totalport, pos);
1721 }
1722 }
1723 }
1724
1725 *eof = 1;
1726
1727stl_readdone:
1728 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001729 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730}
1731
1732/*****************************************************************************/
1733
1734/*
1735 * All board interrupts are vectored through here first. This code then
1736 * calls off to the approrpriate board interrupt handlers.
1737 */
1738
David Howells7d12e782006-10-05 14:55:46 +01001739static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001741 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
Jiri Slabya0564e12006-12-08 02:38:37 -08001743 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744
1745 return IRQ_RETVAL((* brdp->isr)(brdp));
1746}
1747
1748/*****************************************************************************/
1749
1750/*
1751 * Interrupt service routine for EasyIO board types.
1752 */
1753
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001754static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001756 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 unsigned int iobase;
1758 int handled = 0;
1759
Alan Coxb65b5b52006-06-27 02:54:05 -07001760 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 panelp = brdp->panels[0];
1762 iobase = panelp->iobase;
1763 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1764 handled = 1;
1765 (* panelp->isr)(panelp, iobase);
1766 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001767 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 return handled;
1769}
1770
1771/*****************************************************************************/
1772
1773/*
1774 * Interrupt service routine for ECH-AT board types.
1775 */
1776
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001777static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001779 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 unsigned int ioaddr;
1781 int bnknr;
1782 int handled = 0;
1783
1784 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1785
1786 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1787 handled = 1;
1788 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1789 ioaddr = brdp->bnkstataddr[bnknr];
1790 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1791 panelp = brdp->bnk2panel[bnknr];
1792 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1793 }
1794 }
1795 }
1796
1797 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1798
1799 return handled;
1800}
1801
1802/*****************************************************************************/
1803
1804/*
1805 * Interrupt service routine for ECH-MCA board types.
1806 */
1807
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001808static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001810 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 unsigned int ioaddr;
1812 int bnknr;
1813 int handled = 0;
1814
1815 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1816 handled = 1;
1817 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1818 ioaddr = brdp->bnkstataddr[bnknr];
1819 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1820 panelp = brdp->bnk2panel[bnknr];
1821 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1822 }
1823 }
1824 }
1825 return handled;
1826}
1827
1828/*****************************************************************************/
1829
1830/*
1831 * Interrupt service routine for ECH-PCI board types.
1832 */
1833
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001834static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001836 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 unsigned int ioaddr;
1838 int bnknr, recheck;
1839 int handled = 0;
1840
1841 while (1) {
1842 recheck = 0;
1843 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1844 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1845 ioaddr = brdp->bnkstataddr[bnknr];
1846 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1847 panelp = brdp->bnk2panel[bnknr];
1848 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1849 recheck++;
1850 handled = 1;
1851 }
1852 }
1853 if (! recheck)
1854 break;
1855 }
1856 return handled;
1857}
1858
1859/*****************************************************************************/
1860
1861/*
1862 * Interrupt service routine for ECH-8/64-PCI board types.
1863 */
1864
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001865static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001867 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 unsigned int ioaddr;
1869 int bnknr;
1870 int handled = 0;
1871
1872 while (inb(brdp->ioctrl) & 0x1) {
1873 handled = 1;
1874 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1875 ioaddr = brdp->bnkstataddr[bnknr];
1876 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1877 panelp = brdp->bnk2panel[bnknr];
1878 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1879 }
1880 }
1881 }
1882
1883 return handled;
1884}
1885
1886/*****************************************************************************/
1887
1888/*
1889 * Service an off-level request for some channel.
1890 */
Al Viro3e577a82006-12-06 18:41:45 +00001891static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001893 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 struct tty_struct *tty;
1895 unsigned int oldsigs;
1896
Jiri Slabya0564e12006-12-08 02:38:37 -08001897 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898
Jiri Slaby615e4a72006-12-08 02:38:38 -08001899 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 return;
1901
1902 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001903 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 return;
1905
1906 lock_kernel();
1907 if (test_bit(ASYI_TXLOW, &portp->istate)) {
1908 tty_wakeup(tty);
1909 }
1910 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
1911 clear_bit(ASYI_DCDCHANGE, &portp->istate);
1912 oldsigs = portp->sigs;
1913 portp->sigs = stl_getsignals(portp);
1914 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
1915 wake_up_interruptible(&portp->open_wait);
1916 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
1917 if (portp->flags & ASYNC_CHECK_CD)
1918 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
1919 }
1920 }
1921 unlock_kernel();
1922}
1923
1924/*****************************************************************************/
1925
1926/*
1927 * Initialize all the ports on a panel.
1928 */
1929
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001930static int __init stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001932 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 int chipmask, i;
1934
Jiri Slabya0564e12006-12-08 02:38:37 -08001935 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
1937 chipmask = stl_panelinit(brdp, panelp);
1938
1939/*
1940 * All UART's are initialized (if found!). Now go through and setup
1941 * each ports data structures.
1942 */
1943 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001944 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001945 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001947 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 break;
1949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
1951 portp->magic = STL_PORTMAGIC;
1952 portp->portnr = i;
1953 portp->brdnr = panelp->brdnr;
1954 portp->panelnr = panelp->panelnr;
1955 portp->uartp = panelp->uartp;
1956 portp->clk = brdp->clk;
1957 portp->baud_base = STL_BAUDBASE;
1958 portp->close_delay = STL_CLOSEDELAY;
1959 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00001960 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 init_waitqueue_head(&portp->open_wait);
1962 init_waitqueue_head(&portp->close_wait);
1963 portp->stats.brd = portp->brdnr;
1964 portp->stats.panel = portp->panelnr;
1965 portp->stats.port = portp->portnr;
1966 panelp->ports[i] = portp;
1967 stl_portinit(brdp, panelp, portp);
1968 }
1969
1970 return(0);
1971}
1972
1973/*****************************************************************************/
1974
1975/*
1976 * Try to find and initialize an EasyIO board.
1977 */
1978
Jiri Slaby40e82652006-12-08 02:38:41 -08001979static int __init stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001981 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 unsigned int status;
1983 char *name;
1984 int rc;
1985
Jiri Slabya0564e12006-12-08 02:38:37 -08001986 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
1988 brdp->ioctrl = brdp->ioaddr1 + 1;
1989 brdp->iostatus = brdp->ioaddr1 + 2;
1990
1991 status = inb(brdp->iostatus);
1992 if ((status & EIO_IDBITMASK) == EIO_MK3)
1993 brdp->ioctrl++;
1994
1995/*
1996 * Handle board specific stuff now. The real difference is PCI
1997 * or not PCI.
1998 */
1999 if (brdp->brdtype == BRD_EASYIOPCI) {
2000 brdp->iosize1 = 0x80;
2001 brdp->iosize2 = 0x80;
2002 name = "serial(EIO-PCI)";
2003 outb(0x41, (brdp->ioaddr2 + 0x4c));
2004 } else {
2005 brdp->iosize1 = 8;
2006 name = "serial(EIO)";
2007 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2008 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2009 printk("STALLION: invalid irq=%d for brd=%d\n",
2010 brdp->irq, brdp->brdnr);
2011 return(-EINVAL);
2012 }
2013 outb((stl_vecmap[brdp->irq] | EIO_0WS |
2014 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
2015 brdp->ioctrl);
2016 }
2017
2018 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2019 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2020 "%x conflicts with another device\n", brdp->brdnr,
2021 brdp->ioaddr1);
2022 return(-EBUSY);
2023 }
2024
2025 if (brdp->iosize2 > 0)
2026 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2027 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2028 "address %x conflicts with another device\n",
2029 brdp->brdnr, brdp->ioaddr2);
2030 printk(KERN_WARNING "STALLION: Warning, also "
2031 "releasing board %d I/O address %x \n",
2032 brdp->brdnr, brdp->ioaddr1);
2033 release_region(brdp->ioaddr1, brdp->iosize1);
2034 return(-EBUSY);
2035 }
2036
2037/*
2038 * Everything looks OK, so let's go ahead and probe for the hardware.
2039 */
2040 brdp->clk = CD1400_CLK;
2041 brdp->isr = stl_eiointr;
2042
2043 switch (status & EIO_IDBITMASK) {
2044 case EIO_8PORTM:
2045 brdp->clk = CD1400_CLK8M;
2046 /* fall thru */
2047 case EIO_8PORTRS:
2048 case EIO_8PORTDI:
2049 brdp->nrports = 8;
2050 break;
2051 case EIO_4PORTRS:
2052 brdp->nrports = 4;
2053 break;
2054 case EIO_MK3:
2055 switch (status & EIO_BRDMASK) {
2056 case ID_BRD4:
2057 brdp->nrports = 4;
2058 break;
2059 case ID_BRD8:
2060 brdp->nrports = 8;
2061 break;
2062 case ID_BRD16:
2063 brdp->nrports = 16;
2064 break;
2065 default:
2066 return(-ENODEV);
2067 }
2068 break;
2069 default:
2070 return(-ENODEV);
2071 }
2072
2073/*
2074 * We have verified that the board is actually present, so now we
2075 * can complete the setup.
2076 */
2077
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002078 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002079 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002081 "(size=%Zd)\n", sizeof(struct stlpanel));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002082 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
2085 panelp->magic = STL_PANELMAGIC;
2086 panelp->brdnr = brdp->brdnr;
2087 panelp->panelnr = 0;
2088 panelp->nrports = brdp->nrports;
2089 panelp->iobase = brdp->ioaddr1;
2090 panelp->hwid = status;
2091 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002092 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 panelp->isr = stl_sc26198intr;
2094 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002095 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 panelp->isr = stl_cd1400eiointr;
2097 }
2098
2099 brdp->panels[0] = panelp;
2100 brdp->nrpanels = 1;
2101 brdp->state |= BRD_FOUND;
2102 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002103 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 printk("STALLION: failed to register interrupt "
2105 "routine for %s irq=%d\n", name, brdp->irq);
2106 rc = -ENODEV;
2107 } else {
2108 rc = 0;
2109 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002110 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111}
2112
2113/*****************************************************************************/
2114
2115/*
2116 * Try to find an ECH board and initialize it. This code is capable of
2117 * dealing with all types of ECH board.
2118 */
2119
Jiri Slaby40e82652006-12-08 02:38:41 -08002120static int __init stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002122 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 unsigned int status, nxtid, ioaddr, conflict;
2124 int panelnr, banknr, i;
2125 char *name;
2126
Jiri Slabya0564e12006-12-08 02:38:37 -08002127 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
2129 status = 0;
2130 conflict = 0;
2131
2132/*
2133 * Set up the initial board register contents for boards. This varies a
2134 * bit between the different board types. So we need to handle each
2135 * separately. Also do a check that the supplied IRQ is good.
2136 */
2137 switch (brdp->brdtype) {
2138
2139 case BRD_ECH:
2140 brdp->isr = stl_echatintr;
2141 brdp->ioctrl = brdp->ioaddr1 + 1;
2142 brdp->iostatus = brdp->ioaddr1 + 1;
2143 status = inb(brdp->iostatus);
2144 if ((status & ECH_IDBITMASK) != ECH_ID)
2145 return(-ENODEV);
2146 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2147 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2148 printk("STALLION: invalid irq=%d for brd=%d\n",
2149 brdp->irq, brdp->brdnr);
2150 return(-EINVAL);
2151 }
2152 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2153 status |= (stl_vecmap[brdp->irq] << 1);
2154 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2155 brdp->ioctrlval = ECH_INTENABLE |
2156 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2157 for (i = 0; (i < 10); i++)
2158 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2159 brdp->iosize1 = 2;
2160 brdp->iosize2 = 32;
2161 name = "serial(EC8/32)";
2162 outb(status, brdp->ioaddr1);
2163 break;
2164
2165 case BRD_ECHMC:
2166 brdp->isr = stl_echmcaintr;
2167 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2168 brdp->iostatus = brdp->ioctrl;
2169 status = inb(brdp->iostatus);
2170 if ((status & ECH_IDBITMASK) != ECH_ID)
2171 return(-ENODEV);
2172 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2173 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2174 printk("STALLION: invalid irq=%d for brd=%d\n",
2175 brdp->irq, brdp->brdnr);
2176 return(-EINVAL);
2177 }
2178 outb(ECHMC_BRDRESET, brdp->ioctrl);
2179 outb(ECHMC_INTENABLE, brdp->ioctrl);
2180 brdp->iosize1 = 64;
2181 name = "serial(EC8/32-MC)";
2182 break;
2183
2184 case BRD_ECHPCI:
2185 brdp->isr = stl_echpciintr;
2186 brdp->ioctrl = brdp->ioaddr1 + 2;
2187 brdp->iosize1 = 4;
2188 brdp->iosize2 = 8;
2189 name = "serial(EC8/32-PCI)";
2190 break;
2191
2192 case BRD_ECH64PCI:
2193 brdp->isr = stl_echpci64intr;
2194 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2195 outb(0x43, (brdp->ioaddr1 + 0x4c));
2196 brdp->iosize1 = 0x80;
2197 brdp->iosize2 = 0x80;
2198 name = "serial(EC8/64-PCI)";
2199 break;
2200
2201 default:
2202 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
2203 return(-EINVAL);
2204 break;
2205 }
2206
2207/*
2208 * Check boards for possible IO address conflicts and return fail status
2209 * if an IO conflict found.
2210 */
2211 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2212 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2213 "%x conflicts with another device\n", brdp->brdnr,
2214 brdp->ioaddr1);
2215 return(-EBUSY);
2216 }
2217
2218 if (brdp->iosize2 > 0)
2219 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2220 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2221 "address %x conflicts with another device\n",
2222 brdp->brdnr, brdp->ioaddr2);
2223 printk(KERN_WARNING "STALLION: Warning, also "
2224 "releasing board %d I/O address %x \n",
2225 brdp->brdnr, brdp->ioaddr1);
2226 release_region(brdp->ioaddr1, brdp->iosize1);
2227 return(-EBUSY);
2228 }
2229
2230/*
2231 * Scan through the secondary io address space looking for panels.
2232 * As we find'em allocate and initialize panel structures for each.
2233 */
2234 brdp->clk = CD1400_CLK;
2235 brdp->hwid = status;
2236
2237 ioaddr = brdp->ioaddr2;
2238 banknr = 0;
2239 panelnr = 0;
2240 nxtid = 0;
2241
2242 for (i = 0; (i < STL_MAXPANELS); i++) {
2243 if (brdp->brdtype == BRD_ECHPCI) {
2244 outb(nxtid, brdp->ioctrl);
2245 ioaddr = brdp->ioaddr2;
2246 }
2247 status = inb(ioaddr + ECH_PNLSTATUS);
2248 if ((status & ECH_PNLIDMASK) != nxtid)
2249 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002250 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002251 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002253 "(size=%Zd)\n", sizeof(struct stlpanel));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 break;
2255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 panelp->magic = STL_PANELMAGIC;
2257 panelp->brdnr = brdp->brdnr;
2258 panelp->panelnr = panelnr;
2259 panelp->iobase = ioaddr;
2260 panelp->pagenr = nxtid;
2261 panelp->hwid = status;
2262 brdp->bnk2panel[banknr] = panelp;
2263 brdp->bnkpageaddr[banknr] = nxtid;
2264 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2265
2266 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002267 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 panelp->isr = stl_sc26198intr;
2269 if (status & ECH_PNL16PORT) {
2270 panelp->nrports = 16;
2271 brdp->bnk2panel[banknr] = panelp;
2272 brdp->bnkpageaddr[banknr] = nxtid;
2273 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2274 ECH_PNLSTATUS;
2275 } else {
2276 panelp->nrports = 8;
2277 }
2278 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002279 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 panelp->isr = stl_cd1400echintr;
2281 if (status & ECH_PNL16PORT) {
2282 panelp->nrports = 16;
2283 panelp->ackmask = 0x80;
2284 if (brdp->brdtype != BRD_ECHPCI)
2285 ioaddr += EREG_BANKSIZE;
2286 brdp->bnk2panel[banknr] = panelp;
2287 brdp->bnkpageaddr[banknr] = ++nxtid;
2288 brdp->bnkstataddr[banknr++] = ioaddr +
2289 ECH_PNLSTATUS;
2290 } else {
2291 panelp->nrports = 8;
2292 panelp->ackmask = 0xc0;
2293 }
2294 }
2295
2296 nxtid++;
2297 ioaddr += EREG_BANKSIZE;
2298 brdp->nrports += panelp->nrports;
2299 brdp->panels[panelnr++] = panelp;
2300 if ((brdp->brdtype != BRD_ECHPCI) &&
2301 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
2302 break;
2303 }
2304
2305 brdp->nrpanels = panelnr;
2306 brdp->nrbnks = banknr;
2307 if (brdp->brdtype == BRD_ECH)
2308 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2309
2310 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002311 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 printk("STALLION: failed to register interrupt "
2313 "routine for %s irq=%d\n", name, brdp->irq);
2314 i = -ENODEV;
2315 } else {
2316 i = 0;
2317 }
2318
2319 return(i);
2320}
2321
2322/*****************************************************************************/
2323
2324/*
2325 * Initialize and configure the specified board.
2326 * Scan through all the boards in the configuration and see what we
2327 * can find. Handle EIO and the ECH boards a little differently here
2328 * since the initial search and setup is very different.
2329 */
2330
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002331static int __init stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332{
2333 int i;
2334
Jiri Slabya0564e12006-12-08 02:38:37 -08002335 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
2337 switch (brdp->brdtype) {
2338 case BRD_EASYIO:
2339 case BRD_EASYIOPCI:
2340 stl_initeio(brdp);
2341 break;
2342 case BRD_ECH:
2343 case BRD_ECHMC:
2344 case BRD_ECHPCI:
2345 case BRD_ECH64PCI:
2346 stl_initech(brdp);
2347 break;
2348 default:
2349 printk("STALLION: board=%d is unknown board type=%d\n",
2350 brdp->brdnr, brdp->brdtype);
2351 return(ENODEV);
2352 }
2353
2354 stl_brds[brdp->brdnr] = brdp;
2355 if ((brdp->state & BRD_FOUND) == 0) {
2356 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2357 stl_brdnames[brdp->brdtype], brdp->brdnr,
2358 brdp->ioaddr1, brdp->irq);
2359 return(ENODEV);
2360 }
2361
2362 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002363 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 stl_initports(brdp, brdp->panels[i]);
2365
2366 printk("STALLION: %s found, board=%d io=%x irq=%d "
2367 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2368 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2369 brdp->nrports);
2370 return(0);
2371}
2372
2373/*****************************************************************************/
2374
2375/*
2376 * Find the next available board number that is free.
2377 */
2378
Jiri Slaby40e82652006-12-08 02:38:41 -08002379static int __init stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380{
2381 int i;
2382
2383 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002384 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 if (i >= stl_nrbrds)
2386 stl_nrbrds = i + 1;
2387 return(i);
2388 }
2389 }
2390 return(-1);
2391}
2392
2393/*****************************************************************************/
2394
2395#ifdef CONFIG_PCI
2396
2397/*
2398 * We have a Stallion board. Allocate a board structure and
2399 * initialize it. Read its IO and IRQ resources from PCI
2400 * configuration space.
2401 */
2402
Jiri Slaby40e82652006-12-08 02:38:41 -08002403static int __init stl_initpcibrd(int brdtype, struct pci_dev *devp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002405 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406
Jiri Slabya0564e12006-12-08 02:38:37 -08002407 pr_debug("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 devp->bus->number, devp->devfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
2410 if (pci_enable_device(devp))
2411 return(-EIO);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002412 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 return(-ENOMEM);
2414 if ((brdp->brdnr = stl_getbrdnr()) < 0) {
2415 printk("STALLION: too many boards found, "
2416 "maximum supported %d\n", STL_MAXBRDS);
2417 return(0);
2418 }
2419 brdp->brdtype = brdtype;
2420
2421/*
2422 * Different Stallion boards use the BAR registers in different ways,
2423 * so set up io addresses based on board type.
2424 */
Jiri Slabya0564e12006-12-08 02:38:37 -08002425 pr_debug("%s(%d): BAR[]=%Lx,%Lx,%Lx,%Lx IRQ=%x\n", __FILE__, __LINE__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 pci_resource_start(devp, 0), pci_resource_start(devp, 1),
2427 pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
2429/*
2430 * We have all resources from the board, so let's setup the actual
2431 * board structure now.
2432 */
2433 switch (brdtype) {
2434 case BRD_ECHPCI:
2435 brdp->ioaddr2 = pci_resource_start(devp, 0);
2436 brdp->ioaddr1 = pci_resource_start(devp, 1);
2437 break;
2438 case BRD_ECH64PCI:
2439 brdp->ioaddr2 = pci_resource_start(devp, 2);
2440 brdp->ioaddr1 = pci_resource_start(devp, 1);
2441 break;
2442 case BRD_EASYIOPCI:
2443 brdp->ioaddr1 = pci_resource_start(devp, 2);
2444 brdp->ioaddr2 = pci_resource_start(devp, 1);
2445 break;
2446 default:
2447 printk("STALLION: unknown PCI board type=%d\n", brdtype);
2448 break;
2449 }
2450
2451 brdp->irq = devp->irq;
2452 stl_brdinit(brdp);
2453
2454 return(0);
2455}
2456
2457/*****************************************************************************/
2458
2459/*
2460 * Find all Stallion PCI boards that might be installed. Initialize each
2461 * one as it is found.
2462 */
2463
2464
Jiri Slaby40e82652006-12-08 02:38:41 -08002465static int __init stl_findpcibrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466{
2467 struct pci_dev *dev = NULL;
2468 int i, rc;
2469
Jiri Slabya0564e12006-12-08 02:38:37 -08002470 pr_debug("stl_findpcibrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471
2472 for (i = 0; (i < stl_nrpcibrds); i++)
Alan Cox606d0992006-12-08 02:38:45 -08002473 while ((dev = pci_get_device(stl_pcibrds[i].vendid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 stl_pcibrds[i].devid, dev))) {
2475
2476/*
2477 * Found a device on the PCI bus that has our vendor and
2478 * device ID. Need to check now that it is really us.
2479 */
2480 if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
2481 continue;
2482
2483 rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
2484 if (rc)
2485 return(rc);
2486 }
2487
2488 return(0);
2489}
2490
2491#endif
2492
2493/*****************************************************************************/
2494
2495/*
2496 * Scan through all the boards in the configuration and see what we
2497 * can find. Handle EIO and the ECH boards a little differently here
2498 * since the initial search and setup is too different.
2499 */
2500
Jiri Slaby40e82652006-12-08 02:38:41 -08002501static int __init stl_initbrds(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002503 struct stlbrd *brdp;
2504 struct stlconf *confp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 int i;
2506
Jiri Slabya0564e12006-12-08 02:38:37 -08002507 pr_debug("stl_initbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
2509 if (stl_nrbrds > STL_MAXBRDS) {
2510 printk("STALLION: too many boards in configuration table, "
2511 "truncating to %d\n", STL_MAXBRDS);
2512 stl_nrbrds = STL_MAXBRDS;
2513 }
2514
2515/*
2516 * Firstly scan the list of static boards configured. Allocate
2517 * resources and initialize the boards as found.
2518 */
2519 for (i = 0; (i < stl_nrbrds); i++) {
2520 confp = &stl_brdconf[i];
2521 stl_parsebrd(confp, stl_brdsp[i]);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002522 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 return(-ENOMEM);
2524 brdp->brdnr = i;
2525 brdp->brdtype = confp->brdtype;
2526 brdp->ioaddr1 = confp->ioaddr1;
2527 brdp->ioaddr2 = confp->ioaddr2;
2528 brdp->irq = confp->irq;
2529 brdp->irqtype = confp->irqtype;
2530 stl_brdinit(brdp);
2531 }
2532
2533/*
2534 * Find any dynamically supported boards. That is via module load
2535 * line options or auto-detected on the PCI bus.
2536 */
2537 stl_argbrds();
2538#ifdef CONFIG_PCI
2539 stl_findpcibrds();
2540#endif
2541
2542 return(0);
2543}
2544
2545/*****************************************************************************/
2546
2547/*
2548 * Return the board stats structure to user app.
2549 */
2550
2551static int stl_getbrdstats(combrd_t __user *bp)
2552{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002553 struct stlbrd *brdp;
2554 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 int i;
2556
2557 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2558 return -EFAULT;
2559 if (stl_brdstats.brd >= STL_MAXBRDS)
2560 return(-ENODEV);
2561 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002562 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 return(-ENODEV);
2564
2565 memset(&stl_brdstats, 0, sizeof(combrd_t));
2566 stl_brdstats.brd = brdp->brdnr;
2567 stl_brdstats.type = brdp->brdtype;
2568 stl_brdstats.hwid = brdp->hwid;
2569 stl_brdstats.state = brdp->state;
2570 stl_brdstats.ioaddr = brdp->ioaddr1;
2571 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2572 stl_brdstats.irq = brdp->irq;
2573 stl_brdstats.nrpanels = brdp->nrpanels;
2574 stl_brdstats.nrports = brdp->nrports;
2575 for (i = 0; (i < brdp->nrpanels); i++) {
2576 panelp = brdp->panels[i];
2577 stl_brdstats.panels[i].panel = i;
2578 stl_brdstats.panels[i].hwid = panelp->hwid;
2579 stl_brdstats.panels[i].nrports = panelp->nrports;
2580 }
2581
2582 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2583}
2584
2585/*****************************************************************************/
2586
2587/*
2588 * Resolve the referenced port number into a port struct pointer.
2589 */
2590
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002591static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002593 struct stlbrd *brdp;
2594 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595
2596 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002597 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002599 if (brdp == NULL)
2600 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002602 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002604 if (panelp == NULL)
2605 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002607 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 return(panelp->ports[portnr]);
2609}
2610
2611/*****************************************************************************/
2612
2613/*
2614 * Return the port stats structure to user app. A NULL port struct
2615 * pointer passed in means that we need to find out from the app
2616 * what port to get stats for (used through board control device).
2617 */
2618
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002619static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620{
2621 unsigned char *head, *tail;
2622 unsigned long flags;
2623
2624 if (!portp) {
2625 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2626 return -EFAULT;
2627 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2628 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002629 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 return(-ENODEV);
2631 }
2632
2633 portp->stats.state = portp->istate;
2634 portp->stats.flags = portp->flags;
2635 portp->stats.hwid = portp->hwid;
2636
2637 portp->stats.ttystate = 0;
2638 portp->stats.cflags = 0;
2639 portp->stats.iflags = 0;
2640 portp->stats.oflags = 0;
2641 portp->stats.lflags = 0;
2642 portp->stats.rxbuffered = 0;
2643
Alan Coxb65b5b52006-06-27 02:54:05 -07002644 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002645 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 if (portp->tty->driver_data == portp) {
2647 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002648 /* No longer available as a statistic */
2649 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002650 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 portp->stats.cflags = portp->tty->termios->c_cflag;
2652 portp->stats.iflags = portp->tty->termios->c_iflag;
2653 portp->stats.oflags = portp->tty->termios->c_oflag;
2654 portp->stats.lflags = portp->tty->termios->c_lflag;
2655 }
2656 }
2657 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002658 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
2660 head = portp->tx.head;
2661 tail = portp->tx.tail;
2662 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2663 (STL_TXBUFSIZE - (tail - head)));
2664
2665 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2666
2667 return copy_to_user(cp, &portp->stats,
2668 sizeof(comstats_t)) ? -EFAULT : 0;
2669}
2670
2671/*****************************************************************************/
2672
2673/*
2674 * Clear the port stats structure. We also return it zeroed out...
2675 */
2676
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002677static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678{
2679 if (!portp) {
2680 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2681 return -EFAULT;
2682 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2683 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002684 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 return(-ENODEV);
2686 }
2687
2688 memset(&portp->stats, 0, sizeof(comstats_t));
2689 portp->stats.brd = portp->brdnr;
2690 portp->stats.panel = portp->panelnr;
2691 portp->stats.port = portp->portnr;
2692 return copy_to_user(cp, &portp->stats,
2693 sizeof(comstats_t)) ? -EFAULT : 0;
2694}
2695
2696/*****************************************************************************/
2697
2698/*
2699 * Return the entire driver ports structure to a user app.
2700 */
2701
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002702static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002704 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002706 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 return -EFAULT;
2708 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2709 stl_dummyport.portnr);
2710 if (!portp)
2711 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002712 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713}
2714
2715/*****************************************************************************/
2716
2717/*
2718 * Return the entire driver board structure to a user app.
2719 */
2720
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002721static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002723 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002725 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 return -EFAULT;
2727 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2728 return -ENODEV;
2729 brdp = stl_brds[stl_dummybrd.brdnr];
2730 if (!brdp)
2731 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002732 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733}
2734
2735/*****************************************************************************/
2736
2737/*
2738 * The "staliomem" device is also required to do some special operations
2739 * on the board and/or ports. In this driver it is mostly used for stats
2740 * collection.
2741 */
2742
2743static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2744{
2745 int brdnr, rc;
2746 void __user *argp = (void __user *)arg;
2747
Jiri Slabya0564e12006-12-08 02:38:37 -08002748 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749
2750 brdnr = iminor(ip);
2751 if (brdnr >= STL_MAXBRDS)
2752 return(-ENODEV);
2753 rc = 0;
2754
2755 switch (cmd) {
2756 case COM_GETPORTSTATS:
2757 rc = stl_getportstats(NULL, argp);
2758 break;
2759 case COM_CLRPORTSTATS:
2760 rc = stl_clrportstats(NULL, argp);
2761 break;
2762 case COM_GETBRDSTATS:
2763 rc = stl_getbrdstats(argp);
2764 break;
2765 case COM_READPORT:
2766 rc = stl_getportstruct(argp);
2767 break;
2768 case COM_READBOARD:
2769 rc = stl_getbrdstruct(argp);
2770 break;
2771 default:
2772 rc = -ENOIOCTLCMD;
2773 break;
2774 }
2775
2776 return(rc);
2777}
2778
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002779static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 .open = stl_open,
2781 .close = stl_close,
2782 .write = stl_write,
2783 .put_char = stl_putchar,
2784 .flush_chars = stl_flushchars,
2785 .write_room = stl_writeroom,
2786 .chars_in_buffer = stl_charsinbuffer,
2787 .ioctl = stl_ioctl,
2788 .set_termios = stl_settermios,
2789 .throttle = stl_throttle,
2790 .unthrottle = stl_unthrottle,
2791 .stop = stl_stop,
2792 .start = stl_start,
2793 .hangup = stl_hangup,
2794 .flush_buffer = stl_flushbuffer,
2795 .break_ctl = stl_breakctl,
2796 .wait_until_sent = stl_waituntilsent,
2797 .send_xchar = stl_sendxchar,
2798 .read_proc = stl_readproc,
2799 .tiocmget = stl_tiocmget,
2800 .tiocmset = stl_tiocmset,
2801};
2802
2803/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804/* CD1400 HARDWARE FUNCTIONS */
2805/*****************************************************************************/
2806
2807/*
2808 * These functions get/set/update the registers of the cd1400 UARTs.
2809 * Access to the cd1400 registers is via an address/data io port pair.
2810 * (Maybe should make this inline...)
2811 */
2812
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002813static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814{
2815 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002816 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817}
2818
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002819static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820{
2821 outb((regnr + portp->uartaddr), portp->ioaddr);
2822 outb(value, portp->ioaddr + EREG_DATA);
2823}
2824
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002825static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826{
2827 outb((regnr + portp->uartaddr), portp->ioaddr);
2828 if (inb(portp->ioaddr + EREG_DATA) != value) {
2829 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002830 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002832 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833}
2834
2835/*****************************************************************************/
2836
2837/*
2838 * Inbitialize the UARTs in a panel. We don't care what sort of board
2839 * these ports are on - since the port io registers are almost
2840 * identical when dealing with ports.
2841 */
2842
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002843static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844{
2845 unsigned int gfrcr;
2846 int chipmask, i, j;
2847 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002848 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849
Jiri Slabya0564e12006-12-08 02:38:37 -08002850 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851
Alan Coxb65b5b52006-06-27 02:54:05 -07002852 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 BRDENABLE(panelp->brdnr, panelp->pagenr);
2854
2855/*
2856 * Check that each chip is present and started up OK.
2857 */
2858 chipmask = 0;
2859 nrchips = panelp->nrports / CD1400_PORTS;
2860 for (i = 0; (i < nrchips); i++) {
2861 if (brdp->brdtype == BRD_ECHPCI) {
2862 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2863 ioaddr = panelp->iobase;
2864 } else {
2865 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
2866 }
2867 uartaddr = (i & 0x01) ? 0x080 : 0;
2868 outb((GFRCR + uartaddr), ioaddr);
2869 outb(0, (ioaddr + EREG_DATA));
2870 outb((CCR + uartaddr), ioaddr);
2871 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2872 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2873 outb((GFRCR + uartaddr), ioaddr);
2874 for (j = 0; (j < CCR_MAXWAIT); j++) {
2875 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2876 break;
2877 }
2878 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2879 printk("STALLION: cd1400 not responding, "
2880 "brd=%d panel=%d chip=%d\n",
2881 panelp->brdnr, panelp->panelnr, i);
2882 continue;
2883 }
2884 chipmask |= (0x1 << i);
2885 outb((PPR + uartaddr), ioaddr);
2886 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2887 }
2888
2889 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002890 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002891 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892}
2893
2894/*****************************************************************************/
2895
2896/*
2897 * Initialize hardware specific port registers.
2898 */
2899
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002900static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901{
Alan Coxb65b5b52006-06-27 02:54:05 -07002902 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002903 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2904 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905
Jiri Slaby615e4a72006-12-08 02:38:38 -08002906 if ((brdp == NULL) || (panelp == NULL) ||
2907 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 return;
2909
Alan Coxb65b5b52006-06-27 02:54:05 -07002910 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2912 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2913 portp->uartaddr = (portp->portnr & 0x04) << 5;
2914 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2915
2916 BRDENABLE(portp->brdnr, portp->pagenr);
2917 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2918 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2919 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2920 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002921 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922}
2923
2924/*****************************************************************************/
2925
2926/*
2927 * Wait for the command register to be ready. We will poll this,
2928 * since it won't usually take too long to be ready.
2929 */
2930
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002931static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932{
2933 int i;
2934
2935 for (i = 0; (i < CCR_MAXWAIT); i++) {
2936 if (stl_cd1400getreg(portp, CCR) == 0) {
2937 return;
2938 }
2939 }
2940
2941 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2942 portp->portnr, portp->panelnr, portp->brdnr);
2943}
2944
2945/*****************************************************************************/
2946
2947/*
2948 * Set up the cd1400 registers for a port based on the termios port
2949 * settings.
2950 */
2951
Alan Cox606d0992006-12-08 02:38:45 -08002952static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002954 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 unsigned long flags;
2956 unsigned int clkdiv, baudrate;
2957 unsigned char cor1, cor2, cor3;
2958 unsigned char cor4, cor5, ccr;
2959 unsigned char srer, sreron, sreroff;
2960 unsigned char mcor1, mcor2, rtpr;
2961 unsigned char clk, div;
2962
2963 cor1 = 0;
2964 cor2 = 0;
2965 cor3 = 0;
2966 cor4 = 0;
2967 cor5 = 0;
2968 ccr = 0;
2969 rtpr = 0;
2970 clk = 0;
2971 div = 0;
2972 mcor1 = 0;
2973 mcor2 = 0;
2974 sreron = 0;
2975 sreroff = 0;
2976
2977 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002978 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 return;
2980
2981/*
2982 * Set up the RX char ignore mask with those RX error types we
2983 * can ignore. We can get the cd1400 to help us out a little here,
2984 * it will ignore parity errors and breaks for us.
2985 */
2986 portp->rxignoremsk = 0;
2987 if (tiosp->c_iflag & IGNPAR) {
2988 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2989 cor1 |= COR1_PARIGNORE;
2990 }
2991 if (tiosp->c_iflag & IGNBRK) {
2992 portp->rxignoremsk |= ST_BREAK;
2993 cor4 |= COR4_IGNBRK;
2994 }
2995
2996 portp->rxmarkmsk = ST_OVERRUN;
2997 if (tiosp->c_iflag & (INPCK | PARMRK))
2998 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2999 if (tiosp->c_iflag & BRKINT)
3000 portp->rxmarkmsk |= ST_BREAK;
3001
3002/*
3003 * Go through the char size, parity and stop bits and set all the
3004 * option register appropriately.
3005 */
3006 switch (tiosp->c_cflag & CSIZE) {
3007 case CS5:
3008 cor1 |= COR1_CHL5;
3009 break;
3010 case CS6:
3011 cor1 |= COR1_CHL6;
3012 break;
3013 case CS7:
3014 cor1 |= COR1_CHL7;
3015 break;
3016 default:
3017 cor1 |= COR1_CHL8;
3018 break;
3019 }
3020
3021 if (tiosp->c_cflag & CSTOPB)
3022 cor1 |= COR1_STOP2;
3023 else
3024 cor1 |= COR1_STOP1;
3025
3026 if (tiosp->c_cflag & PARENB) {
3027 if (tiosp->c_cflag & PARODD)
3028 cor1 |= (COR1_PARENB | COR1_PARODD);
3029 else
3030 cor1 |= (COR1_PARENB | COR1_PAREVEN);
3031 } else {
3032 cor1 |= COR1_PARNONE;
3033 }
3034
3035/*
3036 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
3037 * space for hardware flow control and the like. This should be set to
3038 * VMIN. Also here we will set the RX data timeout to 10ms - this should
3039 * really be based on VTIME.
3040 */
3041 cor3 |= FIFO_RXTHRESHOLD;
3042 rtpr = 2;
3043
3044/*
3045 * Calculate the baud rate timers. For now we will just assume that
3046 * the input and output baud are the same. Could have used a baud
3047 * table here, but this way we can generate virtually any baud rate
3048 * we like!
3049 */
3050 baudrate = tiosp->c_cflag & CBAUD;
3051 if (baudrate & CBAUDEX) {
3052 baudrate &= ~CBAUDEX;
3053 if ((baudrate < 1) || (baudrate > 4))
3054 tiosp->c_cflag &= ~CBAUDEX;
3055 else
3056 baudrate += 15;
3057 }
3058 baudrate = stl_baudrates[baudrate];
3059 if ((tiosp->c_cflag & CBAUD) == B38400) {
3060 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3061 baudrate = 57600;
3062 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3063 baudrate = 115200;
3064 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3065 baudrate = 230400;
3066 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3067 baudrate = 460800;
3068 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3069 baudrate = (portp->baud_base / portp->custom_divisor);
3070 }
3071 if (baudrate > STL_CD1400MAXBAUD)
3072 baudrate = STL_CD1400MAXBAUD;
3073
3074 if (baudrate > 0) {
3075 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
3076 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
3077 if (clkdiv < 0x100)
3078 break;
3079 }
3080 div = (unsigned char) clkdiv;
3081 }
3082
3083/*
3084 * Check what form of modem signaling is required and set it up.
3085 */
3086 if ((tiosp->c_cflag & CLOCAL) == 0) {
3087 mcor1 |= MCOR1_DCD;
3088 mcor2 |= MCOR2_DCD;
3089 sreron |= SRER_MODEM;
3090 portp->flags |= ASYNC_CHECK_CD;
3091 } else {
3092 portp->flags &= ~ASYNC_CHECK_CD;
3093 }
3094
3095/*
3096 * Setup cd1400 enhanced modes if we can. In particular we want to
3097 * handle as much of the flow control as possible automatically. As
3098 * well as saving a few CPU cycles it will also greatly improve flow
3099 * control reliability.
3100 */
3101 if (tiosp->c_iflag & IXON) {
3102 cor2 |= COR2_TXIBE;
3103 cor3 |= COR3_SCD12;
3104 if (tiosp->c_iflag & IXANY)
3105 cor2 |= COR2_IXM;
3106 }
3107
3108 if (tiosp->c_cflag & CRTSCTS) {
3109 cor2 |= COR2_CTSAE;
3110 mcor1 |= FIFO_RTSTHRESHOLD;
3111 }
3112
3113/*
3114 * All cd1400 register values calculated so go through and set
3115 * them all up.
3116 */
3117
Jiri Slabya0564e12006-12-08 02:38:37 -08003118 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003120 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003122 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003124 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3125 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3127 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Alan Coxb65b5b52006-06-27 02:54:05 -07003129 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 BRDENABLE(portp->brdnr, portp->pagenr);
3131 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3132 srer = stl_cd1400getreg(portp, SRER);
3133 stl_cd1400setreg(portp, SRER, 0);
3134 if (stl_cd1400updatereg(portp, COR1, cor1))
3135 ccr = 1;
3136 if (stl_cd1400updatereg(portp, COR2, cor2))
3137 ccr = 1;
3138 if (stl_cd1400updatereg(portp, COR3, cor3))
3139 ccr = 1;
3140 if (ccr) {
3141 stl_cd1400ccrwait(portp);
3142 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3143 }
3144 stl_cd1400setreg(portp, COR4, cor4);
3145 stl_cd1400setreg(portp, COR5, cor5);
3146 stl_cd1400setreg(portp, MCOR1, mcor1);
3147 stl_cd1400setreg(portp, MCOR2, mcor2);
3148 if (baudrate > 0) {
3149 stl_cd1400setreg(portp, TCOR, clk);
3150 stl_cd1400setreg(portp, TBPR, div);
3151 stl_cd1400setreg(portp, RCOR, clk);
3152 stl_cd1400setreg(portp, RBPR, div);
3153 }
3154 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3155 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3156 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3157 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3158 stl_cd1400setreg(portp, RTPR, rtpr);
3159 mcor1 = stl_cd1400getreg(portp, MSVR1);
3160 if (mcor1 & MSVR1_DCD)
3161 portp->sigs |= TIOCM_CD;
3162 else
3163 portp->sigs &= ~TIOCM_CD;
3164 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3165 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003166 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167}
3168
3169/*****************************************************************************/
3170
3171/*
3172 * Set the state of the DTR and RTS signals.
3173 */
3174
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003175static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176{
3177 unsigned char msvr1, msvr2;
3178 unsigned long flags;
3179
Jiri Slabya0564e12006-12-08 02:38:37 -08003180 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3181 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
3183 msvr1 = 0;
3184 msvr2 = 0;
3185 if (dtr > 0)
3186 msvr1 = MSVR1_DTR;
3187 if (rts > 0)
3188 msvr2 = MSVR2_RTS;
3189
Alan Coxb65b5b52006-06-27 02:54:05 -07003190 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 BRDENABLE(portp->brdnr, portp->pagenr);
3192 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3193 if (rts >= 0)
3194 stl_cd1400setreg(portp, MSVR2, msvr2);
3195 if (dtr >= 0)
3196 stl_cd1400setreg(portp, MSVR1, msvr1);
3197 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003198 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199}
3200
3201/*****************************************************************************/
3202
3203/*
3204 * Return the state of the signals.
3205 */
3206
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003207static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208{
3209 unsigned char msvr1, msvr2;
3210 unsigned long flags;
3211 int sigs;
3212
Jiri Slabya0564e12006-12-08 02:38:37 -08003213 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214
Alan Coxb65b5b52006-06-27 02:54:05 -07003215 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 BRDENABLE(portp->brdnr, portp->pagenr);
3217 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3218 msvr1 = stl_cd1400getreg(portp, MSVR1);
3219 msvr2 = stl_cd1400getreg(portp, MSVR2);
3220 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003221 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222
3223 sigs = 0;
3224 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3225 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3226 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3227 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3228#if 0
3229 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3230 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3231#else
3232 sigs |= TIOCM_DSR;
3233#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003234 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235}
3236
3237/*****************************************************************************/
3238
3239/*
3240 * Enable/Disable the Transmitter and/or Receiver.
3241 */
3242
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003243static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244{
3245 unsigned char ccr;
3246 unsigned long flags;
3247
Jiri Slabya0564e12006-12-08 02:38:37 -08003248 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3249
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250 ccr = 0;
3251
3252 if (tx == 0)
3253 ccr |= CCR_TXDISABLE;
3254 else if (tx > 0)
3255 ccr |= CCR_TXENABLE;
3256 if (rx == 0)
3257 ccr |= CCR_RXDISABLE;
3258 else if (rx > 0)
3259 ccr |= CCR_RXENABLE;
3260
Alan Coxb65b5b52006-06-27 02:54:05 -07003261 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 BRDENABLE(portp->brdnr, portp->pagenr);
3263 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3264 stl_cd1400ccrwait(portp);
3265 stl_cd1400setreg(portp, CCR, ccr);
3266 stl_cd1400ccrwait(portp);
3267 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003268 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269}
3270
3271/*****************************************************************************/
3272
3273/*
3274 * Start/stop the Transmitter and/or Receiver.
3275 */
3276
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003277static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278{
3279 unsigned char sreron, sreroff;
3280 unsigned long flags;
3281
Jiri Slabya0564e12006-12-08 02:38:37 -08003282 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
3284 sreron = 0;
3285 sreroff = 0;
3286 if (tx == 0)
3287 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3288 else if (tx == 1)
3289 sreron |= SRER_TXDATA;
3290 else if (tx >= 2)
3291 sreron |= SRER_TXEMPTY;
3292 if (rx == 0)
3293 sreroff |= SRER_RXDATA;
3294 else if (rx > 0)
3295 sreron |= SRER_RXDATA;
3296
Alan Coxb65b5b52006-06-27 02:54:05 -07003297 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 BRDENABLE(portp->brdnr, portp->pagenr);
3299 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3300 stl_cd1400setreg(portp, SRER,
3301 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3302 BRDDISABLE(portp->brdnr);
3303 if (tx > 0)
3304 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003305 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306}
3307
3308/*****************************************************************************/
3309
3310/*
3311 * Disable all interrupts from this port.
3312 */
3313
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003314static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315{
3316 unsigned long flags;
3317
Jiri Slabya0564e12006-12-08 02:38:37 -08003318 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3319
Alan Coxb65b5b52006-06-27 02:54:05 -07003320 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 BRDENABLE(portp->brdnr, portp->pagenr);
3322 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3323 stl_cd1400setreg(portp, SRER, 0);
3324 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003325 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326}
3327
3328/*****************************************************************************/
3329
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003330static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331{
3332 unsigned long flags;
3333
Jiri Slabya0564e12006-12-08 02:38:37 -08003334 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335
Alan Coxb65b5b52006-06-27 02:54:05 -07003336 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 BRDENABLE(portp->brdnr, portp->pagenr);
3338 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3339 stl_cd1400setreg(portp, SRER,
3340 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3341 SRER_TXEMPTY));
3342 BRDDISABLE(portp->brdnr);
3343 portp->brklen = len;
3344 if (len == 1)
3345 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003346 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347}
3348
3349/*****************************************************************************/
3350
3351/*
3352 * Take flow control actions...
3353 */
3354
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003355static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356{
3357 struct tty_struct *tty;
3358 unsigned long flags;
3359
Jiri Slabya0564e12006-12-08 02:38:37 -08003360 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361
Jiri Slaby615e4a72006-12-08 02:38:38 -08003362 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363 return;
3364 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003365 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 return;
3367
Alan Coxb65b5b52006-06-27 02:54:05 -07003368 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369 BRDENABLE(portp->brdnr, portp->pagenr);
3370 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3371
3372 if (state) {
3373 if (tty->termios->c_iflag & IXOFF) {
3374 stl_cd1400ccrwait(portp);
3375 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3376 portp->stats.rxxon++;
3377 stl_cd1400ccrwait(portp);
3378 }
3379/*
3380 * Question: should we return RTS to what it was before? It may
3381 * have been set by an ioctl... Suppose not, since if you have
3382 * hardware flow control set then it is pretty silly to go and
3383 * set the RTS line by hand.
3384 */
3385 if (tty->termios->c_cflag & CRTSCTS) {
3386 stl_cd1400setreg(portp, MCOR1,
3387 (stl_cd1400getreg(portp, MCOR1) |
3388 FIFO_RTSTHRESHOLD));
3389 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3390 portp->stats.rxrtson++;
3391 }
3392 } else {
3393 if (tty->termios->c_iflag & IXOFF) {
3394 stl_cd1400ccrwait(portp);
3395 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3396 portp->stats.rxxoff++;
3397 stl_cd1400ccrwait(portp);
3398 }
3399 if (tty->termios->c_cflag & CRTSCTS) {
3400 stl_cd1400setreg(portp, MCOR1,
3401 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3402 stl_cd1400setreg(portp, MSVR2, 0);
3403 portp->stats.rxrtsoff++;
3404 }
3405 }
3406
3407 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003408 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409}
3410
3411/*****************************************************************************/
3412
3413/*
3414 * Send a flow control character...
3415 */
3416
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003417static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418{
3419 struct tty_struct *tty;
3420 unsigned long flags;
3421
Jiri Slabya0564e12006-12-08 02:38:37 -08003422 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423
Jiri Slaby615e4a72006-12-08 02:38:38 -08003424 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425 return;
3426 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003427 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 return;
3429
Alan Coxb65b5b52006-06-27 02:54:05 -07003430 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 BRDENABLE(portp->brdnr, portp->pagenr);
3432 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3433 if (state) {
3434 stl_cd1400ccrwait(portp);
3435 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3436 portp->stats.rxxon++;
3437 stl_cd1400ccrwait(portp);
3438 } else {
3439 stl_cd1400ccrwait(portp);
3440 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3441 portp->stats.rxxoff++;
3442 stl_cd1400ccrwait(portp);
3443 }
3444 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003445 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446}
3447
3448/*****************************************************************************/
3449
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003450static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451{
3452 unsigned long flags;
3453
Jiri Slabya0564e12006-12-08 02:38:37 -08003454 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455
Jiri Slaby615e4a72006-12-08 02:38:38 -08003456 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 return;
3458
Alan Coxb65b5b52006-06-27 02:54:05 -07003459 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 BRDENABLE(portp->brdnr, portp->pagenr);
3461 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3462 stl_cd1400ccrwait(portp);
3463 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3464 stl_cd1400ccrwait(portp);
3465 portp->tx.tail = portp->tx.head;
3466 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003467 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468}
3469
3470/*****************************************************************************/
3471
3472/*
3473 * Return the current state of data flow on this port. This is only
3474 * really interresting when determining if data has fully completed
3475 * transmission or not... This is easy for the cd1400, it accurately
3476 * maintains the busy port flag.
3477 */
3478
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003479static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480{
Jiri Slabya0564e12006-12-08 02:38:37 -08003481 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482
Jiri Slaby615e4a72006-12-08 02:38:38 -08003483 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003484 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485
Jesper Juhl014c2542006-01-15 02:37:08 +01003486 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487}
3488
3489/*****************************************************************************/
3490
3491/*
3492 * Interrupt service routine for cd1400 EasyIO boards.
3493 */
3494
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003495static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496{
3497 unsigned char svrtype;
3498
Jiri Slabya0564e12006-12-08 02:38:37 -08003499 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500
Alan Coxb65b5b52006-06-27 02:54:05 -07003501 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 outb(SVRR, iobase);
3503 svrtype = inb(iobase + EREG_DATA);
3504 if (panelp->nrports > 4) {
3505 outb((SVRR + 0x80), iobase);
3506 svrtype |= inb(iobase + EREG_DATA);
3507 }
3508
3509 if (svrtype & SVRR_RX)
3510 stl_cd1400rxisr(panelp, iobase);
3511 else if (svrtype & SVRR_TX)
3512 stl_cd1400txisr(panelp, iobase);
3513 else if (svrtype & SVRR_MDM)
3514 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003515
3516 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517}
3518
3519/*****************************************************************************/
3520
3521/*
3522 * Interrupt service routine for cd1400 panels.
3523 */
3524
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003525static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526{
3527 unsigned char svrtype;
3528
Jiri Slabya0564e12006-12-08 02:38:37 -08003529 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530
3531 outb(SVRR, iobase);
3532 svrtype = inb(iobase + EREG_DATA);
3533 outb((SVRR + 0x80), iobase);
3534 svrtype |= inb(iobase + EREG_DATA);
3535 if (svrtype & SVRR_RX)
3536 stl_cd1400rxisr(panelp, iobase);
3537 else if (svrtype & SVRR_TX)
3538 stl_cd1400txisr(panelp, iobase);
3539 else if (svrtype & SVRR_MDM)
3540 stl_cd1400mdmisr(panelp, iobase);
3541}
3542
3543
3544/*****************************************************************************/
3545
3546/*
3547 * Unfortunately we need to handle breaks in the TX data stream, since
3548 * this is the only way to generate them on the cd1400.
3549 */
3550
Jiri Slaby60be4812006-12-08 02:38:40 -08003551static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552{
3553 if (portp->brklen == 1) {
3554 outb((COR2 + portp->uartaddr), ioaddr);
3555 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3556 (ioaddr + EREG_DATA));
3557 outb((TDR + portp->uartaddr), ioaddr);
3558 outb(ETC_CMD, (ioaddr + EREG_DATA));
3559 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3560 outb((SRER + portp->uartaddr), ioaddr);
3561 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3562 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003563 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 } else if (portp->brklen > 1) {
3565 outb((TDR + portp->uartaddr), ioaddr);
3566 outb(ETC_CMD, (ioaddr + EREG_DATA));
3567 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3568 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003569 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570 } else {
3571 outb((COR2 + portp->uartaddr), ioaddr);
3572 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3573 (ioaddr + EREG_DATA));
3574 portp->brklen = 0;
3575 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003576 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577}
3578
3579/*****************************************************************************/
3580
3581/*
3582 * Transmit interrupt handler. This has gotta be fast! Handling TX
3583 * chars is pretty simple, stuff as many as possible from the TX buffer
3584 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3585 * are embedded as commands in the data stream. Oh no, had to use a goto!
3586 * This could be optimized more, will do when I get time...
3587 * In practice it is possible that interrupts are enabled but that the
3588 * port has been hung up. Need to handle not having any TX buffer here,
3589 * this is done by using the side effect that head and tail will also
3590 * be NULL if the buffer has been freed.
3591 */
3592
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003593static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003595 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596 int len, stlen;
3597 char *head, *tail;
3598 unsigned char ioack, srer;
3599
Jiri Slabya0564e12006-12-08 02:38:37 -08003600 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601
3602 ioack = inb(ioaddr + EREG_TXACK);
3603 if (((ioack & panelp->ackmask) != 0) ||
3604 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3605 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3606 return;
3607 }
3608 portp = panelp->ports[(ioack >> 3)];
3609
3610/*
3611 * Unfortunately we need to handle breaks in the data stream, since
3612 * this is the only way to generate them on the cd1400. Do it now if
3613 * a break is to be sent.
3614 */
3615 if (portp->brklen != 0)
3616 if (stl_cd1400breakisr(portp, ioaddr))
3617 goto stl_txalldone;
3618
3619 head = portp->tx.head;
3620 tail = portp->tx.tail;
3621 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3622 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3623 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3624 set_bit(ASYI_TXLOW, &portp->istate);
3625 schedule_work(&portp->tqueue);
3626 }
3627
3628 if (len == 0) {
3629 outb((SRER + portp->uartaddr), ioaddr);
3630 srer = inb(ioaddr + EREG_DATA);
3631 if (srer & SRER_TXDATA) {
3632 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3633 } else {
3634 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3635 clear_bit(ASYI_TXBUSY, &portp->istate);
3636 }
3637 outb(srer, (ioaddr + EREG_DATA));
3638 } else {
3639 len = MIN(len, CD1400_TXFIFOSIZE);
3640 portp->stats.txtotal += len;
3641 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
3642 outb((TDR + portp->uartaddr), ioaddr);
3643 outsb((ioaddr + EREG_DATA), tail, stlen);
3644 len -= stlen;
3645 tail += stlen;
3646 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3647 tail = portp->tx.buf;
3648 if (len > 0) {
3649 outsb((ioaddr + EREG_DATA), tail, len);
3650 tail += len;
3651 }
3652 portp->tx.tail = tail;
3653 }
3654
3655stl_txalldone:
3656 outb((EOSRR + portp->uartaddr), ioaddr);
3657 outb(0, (ioaddr + EREG_DATA));
3658}
3659
3660/*****************************************************************************/
3661
3662/*
3663 * Receive character interrupt handler. Determine if we have good chars
3664 * or bad chars and then process appropriately. Good chars are easy
3665 * just shove the lot into the RX buffer and set all status byte to 0.
3666 * If a bad RX char then process as required. This routine needs to be
3667 * fast! In practice it is possible that we get an interrupt on a port
3668 * that is closed. This can happen on hangups - since they completely
3669 * shutdown a port not in user context. Need to handle this case.
3670 */
3671
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003672static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003674 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 struct tty_struct *tty;
3676 unsigned int ioack, len, buflen;
3677 unsigned char status;
3678 char ch;
3679
Jiri Slabya0564e12006-12-08 02:38:37 -08003680 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681
3682 ioack = inb(ioaddr + EREG_RXACK);
3683 if ((ioack & panelp->ackmask) != 0) {
3684 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3685 return;
3686 }
3687 portp = panelp->ports[(ioack >> 3)];
3688 tty = portp->tty;
3689
3690 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3691 outb((RDCR + portp->uartaddr), ioaddr);
3692 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003693 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 len = MIN(len, sizeof(stl_unwanted));
3695 outb((RDSR + portp->uartaddr), ioaddr);
3696 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3697 portp->stats.rxlost += len;
3698 portp->stats.rxtotal += len;
3699 } else {
3700 len = MIN(len, buflen);
3701 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003702 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003704 tty_prepare_flip_string(tty, &ptr, len);
3705 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 tty_schedule_flip(tty);
3707 portp->stats.rxtotal += len;
3708 }
3709 }
3710 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3711 outb((RDSR + portp->uartaddr), ioaddr);
3712 status = inb(ioaddr + EREG_DATA);
3713 ch = inb(ioaddr + EREG_DATA);
3714 if (status & ST_PARITY)
3715 portp->stats.rxparity++;
3716 if (status & ST_FRAMING)
3717 portp->stats.rxframing++;
3718 if (status & ST_OVERRUN)
3719 portp->stats.rxoverrun++;
3720 if (status & ST_BREAK)
3721 portp->stats.rxbreaks++;
3722 if (status & ST_SCHARMASK) {
3723 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3724 portp->stats.txxon++;
3725 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3726 portp->stats.txxoff++;
3727 goto stl_rxalldone;
3728 }
Alan Cox33f0f882006-01-09 20:54:13 -08003729 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 if (portp->rxmarkmsk & status) {
3731 if (status & ST_BREAK) {
3732 status = TTY_BREAK;
3733 if (portp->flags & ASYNC_SAK) {
3734 do_SAK(tty);
3735 BRDENABLE(portp->brdnr, portp->pagenr);
3736 }
3737 } else if (status & ST_PARITY) {
3738 status = TTY_PARITY;
3739 } else if (status & ST_FRAMING) {
3740 status = TTY_FRAME;
3741 } else if(status & ST_OVERRUN) {
3742 status = TTY_OVERRUN;
3743 } else {
3744 status = 0;
3745 }
3746 } else {
3747 status = 0;
3748 }
Alan Cox33f0f882006-01-09 20:54:13 -08003749 tty_insert_flip_char(tty, ch, status);
3750 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 }
3752 } else {
3753 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3754 return;
3755 }
3756
3757stl_rxalldone:
3758 outb((EOSRR + portp->uartaddr), ioaddr);
3759 outb(0, (ioaddr + EREG_DATA));
3760}
3761
3762/*****************************************************************************/
3763
3764/*
3765 * Modem interrupt handler. The is called when the modem signal line
3766 * (DCD) has changed state. Leave most of the work to the off-level
3767 * processing routine.
3768 */
3769
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003770static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003772 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 unsigned int ioack;
3774 unsigned char misr;
3775
Jiri Slabya0564e12006-12-08 02:38:37 -08003776 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777
3778 ioack = inb(ioaddr + EREG_MDACK);
3779 if (((ioack & panelp->ackmask) != 0) ||
3780 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3781 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3782 return;
3783 }
3784 portp = panelp->ports[(ioack >> 3)];
3785
3786 outb((MISR + portp->uartaddr), ioaddr);
3787 misr = inb(ioaddr + EREG_DATA);
3788 if (misr & MISR_DCD) {
3789 set_bit(ASYI_DCDCHANGE, &portp->istate);
3790 schedule_work(&portp->tqueue);
3791 portp->stats.modem++;
3792 }
3793
3794 outb((EOSRR + portp->uartaddr), ioaddr);
3795 outb(0, (ioaddr + EREG_DATA));
3796}
3797
3798/*****************************************************************************/
3799/* SC26198 HARDWARE FUNCTIONS */
3800/*****************************************************************************/
3801
3802/*
3803 * These functions get/set/update the registers of the sc26198 UARTs.
3804 * Access to the sc26198 registers is via an address/data io port pair.
3805 * (Maybe should make this inline...)
3806 */
3807
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003808static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809{
3810 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003811 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812}
3813
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003814static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815{
3816 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3817 outb(value, (portp->ioaddr + XP_DATA));
3818}
3819
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003820static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821{
3822 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3823 if (inb(portp->ioaddr + XP_DATA) != value) {
3824 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003825 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003827 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828}
3829
3830/*****************************************************************************/
3831
3832/*
3833 * Functions to get and set the sc26198 global registers.
3834 */
3835
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003836static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837{
3838 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003839 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840}
3841
3842#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003843static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844{
3845 outb(regnr, (portp->ioaddr + XP_ADDR));
3846 outb(value, (portp->ioaddr + XP_DATA));
3847}
3848#endif
3849
3850/*****************************************************************************/
3851
3852/*
3853 * Inbitialize the UARTs in a panel. We don't care what sort of board
3854 * these ports are on - since the port io registers are almost
3855 * identical when dealing with ports.
3856 */
3857
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003858static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859{
3860 int chipmask, i;
3861 int nrchips, ioaddr;
3862
Jiri Slabya0564e12006-12-08 02:38:37 -08003863 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864
3865 BRDENABLE(panelp->brdnr, panelp->pagenr);
3866
3867/*
3868 * Check that each chip is present and started up OK.
3869 */
3870 chipmask = 0;
3871 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3872 if (brdp->brdtype == BRD_ECHPCI)
3873 outb(panelp->pagenr, brdp->ioctrl);
3874
3875 for (i = 0; (i < nrchips); i++) {
3876 ioaddr = panelp->iobase + (i * 4);
3877 outb(SCCR, (ioaddr + XP_ADDR));
3878 outb(CR_RESETALL, (ioaddr + XP_DATA));
3879 outb(TSTR, (ioaddr + XP_ADDR));
3880 if (inb(ioaddr + XP_DATA) != 0) {
3881 printk("STALLION: sc26198 not responding, "
3882 "brd=%d panel=%d chip=%d\n",
3883 panelp->brdnr, panelp->panelnr, i);
3884 continue;
3885 }
3886 chipmask |= (0x1 << i);
3887 outb(GCCR, (ioaddr + XP_ADDR));
3888 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3889 outb(WDTRCR, (ioaddr + XP_ADDR));
3890 outb(0xff, (ioaddr + XP_DATA));
3891 }
3892
3893 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003894 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895}
3896
3897/*****************************************************************************/
3898
3899/*
3900 * Initialize hardware specific port registers.
3901 */
3902
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003903static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904{
Jiri Slabya0564e12006-12-08 02:38:37 -08003905 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3906 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
Jiri Slaby615e4a72006-12-08 02:38:38 -08003908 if ((brdp == NULL) || (panelp == NULL) ||
3909 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 return;
3911
3912 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3913 portp->uartaddr = (portp->portnr & 0x07) << 4;
3914 portp->pagenr = panelp->pagenr;
3915 portp->hwid = 0x1;
3916
3917 BRDENABLE(portp->brdnr, portp->pagenr);
3918 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3919 BRDDISABLE(portp->brdnr);
3920}
3921
3922/*****************************************************************************/
3923
3924/*
3925 * Set up the sc26198 registers for a port based on the termios port
3926 * settings.
3927 */
3928
Alan Cox606d0992006-12-08 02:38:45 -08003929static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003931 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 unsigned long flags;
3933 unsigned int baudrate;
3934 unsigned char mr0, mr1, mr2, clk;
3935 unsigned char imron, imroff, iopr, ipr;
3936
3937 mr0 = 0;
3938 mr1 = 0;
3939 mr2 = 0;
3940 clk = 0;
3941 iopr = 0;
3942 imron = 0;
3943 imroff = 0;
3944
3945 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003946 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 return;
3948
3949/*
3950 * Set up the RX char ignore mask with those RX error types we
3951 * can ignore.
3952 */
3953 portp->rxignoremsk = 0;
3954 if (tiosp->c_iflag & IGNPAR)
3955 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3956 SR_RXOVERRUN);
3957 if (tiosp->c_iflag & IGNBRK)
3958 portp->rxignoremsk |= SR_RXBREAK;
3959
3960 portp->rxmarkmsk = SR_RXOVERRUN;
3961 if (tiosp->c_iflag & (INPCK | PARMRK))
3962 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3963 if (tiosp->c_iflag & BRKINT)
3964 portp->rxmarkmsk |= SR_RXBREAK;
3965
3966/*
3967 * Go through the char size, parity and stop bits and set all the
3968 * option register appropriately.
3969 */
3970 switch (tiosp->c_cflag & CSIZE) {
3971 case CS5:
3972 mr1 |= MR1_CS5;
3973 break;
3974 case CS6:
3975 mr1 |= MR1_CS6;
3976 break;
3977 case CS7:
3978 mr1 |= MR1_CS7;
3979 break;
3980 default:
3981 mr1 |= MR1_CS8;
3982 break;
3983 }
3984
3985 if (tiosp->c_cflag & CSTOPB)
3986 mr2 |= MR2_STOP2;
3987 else
3988 mr2 |= MR2_STOP1;
3989
3990 if (tiosp->c_cflag & PARENB) {
3991 if (tiosp->c_cflag & PARODD)
3992 mr1 |= (MR1_PARENB | MR1_PARODD);
3993 else
3994 mr1 |= (MR1_PARENB | MR1_PAREVEN);
3995 } else {
3996 mr1 |= MR1_PARNONE;
3997 }
3998
3999 mr1 |= MR1_ERRBLOCK;
4000
4001/*
4002 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
4003 * space for hardware flow control and the like. This should be set to
4004 * VMIN.
4005 */
4006 mr2 |= MR2_RXFIFOHALF;
4007
4008/*
4009 * Calculate the baud rate timers. For now we will just assume that
4010 * the input and output baud are the same. The sc26198 has a fixed
4011 * baud rate table, so only discrete baud rates possible.
4012 */
4013 baudrate = tiosp->c_cflag & CBAUD;
4014 if (baudrate & CBAUDEX) {
4015 baudrate &= ~CBAUDEX;
4016 if ((baudrate < 1) || (baudrate > 4))
4017 tiosp->c_cflag &= ~CBAUDEX;
4018 else
4019 baudrate += 15;
4020 }
4021 baudrate = stl_baudrates[baudrate];
4022 if ((tiosp->c_cflag & CBAUD) == B38400) {
4023 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
4024 baudrate = 57600;
4025 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
4026 baudrate = 115200;
4027 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
4028 baudrate = 230400;
4029 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
4030 baudrate = 460800;
4031 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
4032 baudrate = (portp->baud_base / portp->custom_divisor);
4033 }
4034 if (baudrate > STL_SC26198MAXBAUD)
4035 baudrate = STL_SC26198MAXBAUD;
4036
4037 if (baudrate > 0) {
4038 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
4039 if (baudrate <= sc26198_baudtable[clk])
4040 break;
4041 }
4042 }
4043
4044/*
4045 * Check what form of modem signaling is required and set it up.
4046 */
4047 if (tiosp->c_cflag & CLOCAL) {
4048 portp->flags &= ~ASYNC_CHECK_CD;
4049 } else {
4050 iopr |= IOPR_DCDCOS;
4051 imron |= IR_IOPORT;
4052 portp->flags |= ASYNC_CHECK_CD;
4053 }
4054
4055/*
4056 * Setup sc26198 enhanced modes if we can. In particular we want to
4057 * handle as much of the flow control as possible automatically. As
4058 * well as saving a few CPU cycles it will also greatly improve flow
4059 * control reliability.
4060 */
4061 if (tiosp->c_iflag & IXON) {
4062 mr0 |= MR0_SWFTX | MR0_SWFT;
4063 imron |= IR_XONXOFF;
4064 } else {
4065 imroff |= IR_XONXOFF;
4066 }
4067 if (tiosp->c_iflag & IXOFF)
4068 mr0 |= MR0_SWFRX;
4069
4070 if (tiosp->c_cflag & CRTSCTS) {
4071 mr2 |= MR2_AUTOCTS;
4072 mr1 |= MR1_AUTORTS;
4073 }
4074
4075/*
4076 * All sc26198 register values calculated so go through and set
4077 * them all up.
4078 */
4079
Jiri Slabya0564e12006-12-08 02:38:37 -08004080 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08004082 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
4083 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
4084 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4086 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087
Alan Coxb65b5b52006-06-27 02:54:05 -07004088 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089 BRDENABLE(portp->brdnr, portp->pagenr);
4090 stl_sc26198setreg(portp, IMR, 0);
4091 stl_sc26198updatereg(portp, MR0, mr0);
4092 stl_sc26198updatereg(portp, MR1, mr1);
4093 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4094 stl_sc26198updatereg(portp, MR2, mr2);
4095 stl_sc26198updatereg(portp, IOPIOR,
4096 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4097
4098 if (baudrate > 0) {
4099 stl_sc26198setreg(portp, TXCSR, clk);
4100 stl_sc26198setreg(portp, RXCSR, clk);
4101 }
4102
4103 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4104 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4105
4106 ipr = stl_sc26198getreg(portp, IPR);
4107 if (ipr & IPR_DCD)
4108 portp->sigs &= ~TIOCM_CD;
4109 else
4110 portp->sigs |= TIOCM_CD;
4111
4112 portp->imr = (portp->imr & ~imroff) | imron;
4113 stl_sc26198setreg(portp, IMR, portp->imr);
4114 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004115 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116}
4117
4118/*****************************************************************************/
4119
4120/*
4121 * Set the state of the DTR and RTS signals.
4122 */
4123
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004124static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125{
4126 unsigned char iopioron, iopioroff;
4127 unsigned long flags;
4128
Jiri Slabya0564e12006-12-08 02:38:37 -08004129 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4130 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131
4132 iopioron = 0;
4133 iopioroff = 0;
4134 if (dtr == 0)
4135 iopioroff |= IPR_DTR;
4136 else if (dtr > 0)
4137 iopioron |= IPR_DTR;
4138 if (rts == 0)
4139 iopioroff |= IPR_RTS;
4140 else if (rts > 0)
4141 iopioron |= IPR_RTS;
4142
Alan Coxb65b5b52006-06-27 02:54:05 -07004143 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 BRDENABLE(portp->brdnr, portp->pagenr);
4145 stl_sc26198setreg(portp, IOPIOR,
4146 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4147 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004148 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149}
4150
4151/*****************************************************************************/
4152
4153/*
4154 * Return the state of the signals.
4155 */
4156
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004157static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158{
4159 unsigned char ipr;
4160 unsigned long flags;
4161 int sigs;
4162
Jiri Slabya0564e12006-12-08 02:38:37 -08004163 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164
Alan Coxb65b5b52006-06-27 02:54:05 -07004165 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 BRDENABLE(portp->brdnr, portp->pagenr);
4167 ipr = stl_sc26198getreg(portp, IPR);
4168 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004169 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170
4171 sigs = 0;
4172 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4173 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4174 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4175 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4176 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004177 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178}
4179
4180/*****************************************************************************/
4181
4182/*
4183 * Enable/Disable the Transmitter and/or Receiver.
4184 */
4185
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004186static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187{
4188 unsigned char ccr;
4189 unsigned long flags;
4190
Jiri Slabya0564e12006-12-08 02:38:37 -08004191 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
4193 ccr = portp->crenable;
4194 if (tx == 0)
4195 ccr &= ~CR_TXENABLE;
4196 else if (tx > 0)
4197 ccr |= CR_TXENABLE;
4198 if (rx == 0)
4199 ccr &= ~CR_RXENABLE;
4200 else if (rx > 0)
4201 ccr |= CR_RXENABLE;
4202
Alan Coxb65b5b52006-06-27 02:54:05 -07004203 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 BRDENABLE(portp->brdnr, portp->pagenr);
4205 stl_sc26198setreg(portp, SCCR, ccr);
4206 BRDDISABLE(portp->brdnr);
4207 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004208 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209}
4210
4211/*****************************************************************************/
4212
4213/*
4214 * Start/stop the Transmitter and/or Receiver.
4215 */
4216
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004217static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218{
4219 unsigned char imr;
4220 unsigned long flags;
4221
Jiri Slabya0564e12006-12-08 02:38:37 -08004222 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223
4224 imr = portp->imr;
4225 if (tx == 0)
4226 imr &= ~IR_TXRDY;
4227 else if (tx == 1)
4228 imr |= IR_TXRDY;
4229 if (rx == 0)
4230 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4231 else if (rx > 0)
4232 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4233
Alan Coxb65b5b52006-06-27 02:54:05 -07004234 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 BRDENABLE(portp->brdnr, portp->pagenr);
4236 stl_sc26198setreg(portp, IMR, imr);
4237 BRDDISABLE(portp->brdnr);
4238 portp->imr = imr;
4239 if (tx > 0)
4240 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004241 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242}
4243
4244/*****************************************************************************/
4245
4246/*
4247 * Disable all interrupts from this port.
4248 */
4249
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004250static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251{
4252 unsigned long flags;
4253
Jiri Slabya0564e12006-12-08 02:38:37 -08004254 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255
Alan Coxb65b5b52006-06-27 02:54:05 -07004256 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 BRDENABLE(portp->brdnr, portp->pagenr);
4258 portp->imr = 0;
4259 stl_sc26198setreg(portp, IMR, 0);
4260 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004261 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262}
4263
4264/*****************************************************************************/
4265
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004266static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267{
4268 unsigned long flags;
4269
Jiri Slabya0564e12006-12-08 02:38:37 -08004270 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271
Alan Coxb65b5b52006-06-27 02:54:05 -07004272 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 BRDENABLE(portp->brdnr, portp->pagenr);
4274 if (len == 1) {
4275 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4276 portp->stats.txbreaks++;
4277 } else {
4278 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4279 }
4280 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004281 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282}
4283
4284/*****************************************************************************/
4285
4286/*
4287 * Take flow control actions...
4288 */
4289
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004290static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291{
4292 struct tty_struct *tty;
4293 unsigned long flags;
4294 unsigned char mr0;
4295
Jiri Slabya0564e12006-12-08 02:38:37 -08004296 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
Jiri Slaby615e4a72006-12-08 02:38:38 -08004298 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 return;
4300 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004301 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 return;
4303
Alan Coxb65b5b52006-06-27 02:54:05 -07004304 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 BRDENABLE(portp->brdnr, portp->pagenr);
4306
4307 if (state) {
4308 if (tty->termios->c_iflag & IXOFF) {
4309 mr0 = stl_sc26198getreg(portp, MR0);
4310 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4311 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4312 mr0 |= MR0_SWFRX;
4313 portp->stats.rxxon++;
4314 stl_sc26198wait(portp);
4315 stl_sc26198setreg(portp, MR0, mr0);
4316 }
4317/*
4318 * Question: should we return RTS to what it was before? It may
4319 * have been set by an ioctl... Suppose not, since if you have
4320 * hardware flow control set then it is pretty silly to go and
4321 * set the RTS line by hand.
4322 */
4323 if (tty->termios->c_cflag & CRTSCTS) {
4324 stl_sc26198setreg(portp, MR1,
4325 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4326 stl_sc26198setreg(portp, IOPIOR,
4327 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4328 portp->stats.rxrtson++;
4329 }
4330 } else {
4331 if (tty->termios->c_iflag & IXOFF) {
4332 mr0 = stl_sc26198getreg(portp, MR0);
4333 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4334 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4335 mr0 &= ~MR0_SWFRX;
4336 portp->stats.rxxoff++;
4337 stl_sc26198wait(portp);
4338 stl_sc26198setreg(portp, MR0, mr0);
4339 }
4340 if (tty->termios->c_cflag & CRTSCTS) {
4341 stl_sc26198setreg(portp, MR1,
4342 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4343 stl_sc26198setreg(portp, IOPIOR,
4344 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4345 portp->stats.rxrtsoff++;
4346 }
4347 }
4348
4349 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004350 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351}
4352
4353/*****************************************************************************/
4354
4355/*
4356 * Send a flow control character.
4357 */
4358
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004359static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360{
4361 struct tty_struct *tty;
4362 unsigned long flags;
4363 unsigned char mr0;
4364
Jiri Slabya0564e12006-12-08 02:38:37 -08004365 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366
Jiri Slaby615e4a72006-12-08 02:38:38 -08004367 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368 return;
4369 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004370 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371 return;
4372
Alan Coxb65b5b52006-06-27 02:54:05 -07004373 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 BRDENABLE(portp->brdnr, portp->pagenr);
4375 if (state) {
4376 mr0 = stl_sc26198getreg(portp, MR0);
4377 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4378 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4379 mr0 |= MR0_SWFRX;
4380 portp->stats.rxxon++;
4381 stl_sc26198wait(portp);
4382 stl_sc26198setreg(portp, MR0, mr0);
4383 } else {
4384 mr0 = stl_sc26198getreg(portp, MR0);
4385 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4386 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4387 mr0 &= ~MR0_SWFRX;
4388 portp->stats.rxxoff++;
4389 stl_sc26198wait(portp);
4390 stl_sc26198setreg(portp, MR0, mr0);
4391 }
4392 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004393 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394}
4395
4396/*****************************************************************************/
4397
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004398static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399{
4400 unsigned long flags;
4401
Jiri Slabya0564e12006-12-08 02:38:37 -08004402 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403
Jiri Slaby615e4a72006-12-08 02:38:38 -08004404 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 return;
4406
Alan Coxb65b5b52006-06-27 02:54:05 -07004407 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408 BRDENABLE(portp->brdnr, portp->pagenr);
4409 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4410 stl_sc26198setreg(portp, SCCR, portp->crenable);
4411 BRDDISABLE(portp->brdnr);
4412 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004413 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414}
4415
4416/*****************************************************************************/
4417
4418/*
4419 * Return the current state of data flow on this port. This is only
4420 * really interresting when determining if data has fully completed
4421 * transmission or not... The sc26198 interrupt scheme cannot
4422 * determine when all data has actually drained, so we need to
4423 * check the port statusy register to be sure.
4424 */
4425
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004426static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427{
4428 unsigned long flags;
4429 unsigned char sr;
4430
Jiri Slabya0564e12006-12-08 02:38:37 -08004431 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432
Jiri Slaby615e4a72006-12-08 02:38:38 -08004433 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004434 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004436 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
Alan Coxb65b5b52006-06-27 02:54:05 -07004438 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439 BRDENABLE(portp->brdnr, portp->pagenr);
4440 sr = stl_sc26198getreg(portp, SR);
4441 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004442 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443
Jesper Juhl014c2542006-01-15 02:37:08 +01004444 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445}
4446
4447/*****************************************************************************/
4448
4449/*
4450 * Delay for a small amount of time, to give the sc26198 a chance
4451 * to process a command...
4452 */
4453
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004454static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455{
4456 int i;
4457
Jiri Slabya0564e12006-12-08 02:38:37 -08004458 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459
Jiri Slaby615e4a72006-12-08 02:38:38 -08004460 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461 return;
4462
4463 for (i = 0; (i < 20); i++)
4464 stl_sc26198getglobreg(portp, TSTR);
4465}
4466
4467/*****************************************************************************/
4468
4469/*
4470 * If we are TX flow controlled and in IXANY mode then we may
4471 * need to unflow control here. We gotta do this because of the
4472 * automatic flow control modes of the sc26198.
4473 */
4474
Jiri Slaby60be4812006-12-08 02:38:40 -08004475static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476{
4477 unsigned char mr0;
4478
4479 mr0 = stl_sc26198getreg(portp, MR0);
4480 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4481 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4482 stl_sc26198wait(portp);
4483 stl_sc26198setreg(portp, MR0, mr0);
4484 clear_bit(ASYI_TXFLOWED, &portp->istate);
4485}
4486
4487/*****************************************************************************/
4488
4489/*
4490 * Interrupt service routine for sc26198 panels.
4491 */
4492
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004493static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004495 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496 unsigned int iack;
4497
Alan Coxb65b5b52006-06-27 02:54:05 -07004498 spin_lock(&brd_lock);
4499
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500/*
4501 * Work around bug in sc26198 chip... Cannot have A6 address
4502 * line of UART high, else iack will be returned as 0.
4503 */
4504 outb(0, (iobase + 1));
4505
4506 iack = inb(iobase + XP_IACK);
4507 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4508
4509 if (iack & IVR_RXDATA)
4510 stl_sc26198rxisr(portp, iack);
4511 else if (iack & IVR_TXDATA)
4512 stl_sc26198txisr(portp);
4513 else
4514 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004515
4516 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004517}
4518
4519/*****************************************************************************/
4520
4521/*
4522 * Transmit interrupt handler. This has gotta be fast! Handling TX
4523 * chars is pretty simple, stuff as many as possible from the TX buffer
4524 * into the sc26198 FIFO.
4525 * In practice it is possible that interrupts are enabled but that the
4526 * port has been hung up. Need to handle not having any TX buffer here,
4527 * this is done by using the side effect that head and tail will also
4528 * be NULL if the buffer has been freed.
4529 */
4530
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004531static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532{
4533 unsigned int ioaddr;
4534 unsigned char mr0;
4535 int len, stlen;
4536 char *head, *tail;
4537
Jiri Slabya0564e12006-12-08 02:38:37 -08004538 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539
4540 ioaddr = portp->ioaddr;
4541 head = portp->tx.head;
4542 tail = portp->tx.tail;
4543 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4544 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4545 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4546 set_bit(ASYI_TXLOW, &portp->istate);
4547 schedule_work(&portp->tqueue);
4548 }
4549
4550 if (len == 0) {
4551 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4552 mr0 = inb(ioaddr + XP_DATA);
4553 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4554 portp->imr &= ~IR_TXRDY;
4555 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4556 outb(portp->imr, (ioaddr + XP_DATA));
4557 clear_bit(ASYI_TXBUSY, &portp->istate);
4558 } else {
4559 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4560 outb(mr0, (ioaddr + XP_DATA));
4561 }
4562 } else {
4563 len = MIN(len, SC26198_TXFIFOSIZE);
4564 portp->stats.txtotal += len;
4565 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
4566 outb(GTXFIFO, (ioaddr + XP_ADDR));
4567 outsb((ioaddr + XP_DATA), tail, stlen);
4568 len -= stlen;
4569 tail += stlen;
4570 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4571 tail = portp->tx.buf;
4572 if (len > 0) {
4573 outsb((ioaddr + XP_DATA), tail, len);
4574 tail += len;
4575 }
4576 portp->tx.tail = tail;
4577 }
4578}
4579
4580/*****************************************************************************/
4581
4582/*
4583 * Receive character interrupt handler. Determine if we have good chars
4584 * or bad chars and then process appropriately. Good chars are easy
4585 * just shove the lot into the RX buffer and set all status byte to 0.
4586 * If a bad RX char then process as required. This routine needs to be
4587 * fast! In practice it is possible that we get an interrupt on a port
4588 * that is closed. This can happen on hangups - since they completely
4589 * shutdown a port not in user context. Need to handle this case.
4590 */
4591
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004592static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593{
4594 struct tty_struct *tty;
4595 unsigned int len, buflen, ioaddr;
4596
Jiri Slabya0564e12006-12-08 02:38:37 -08004597 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598
4599 tty = portp->tty;
4600 ioaddr = portp->ioaddr;
4601 outb(GIBCR, (ioaddr + XP_ADDR));
4602 len = inb(ioaddr + XP_DATA) + 1;
4603
4604 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004605 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 len = MIN(len, sizeof(stl_unwanted));
4607 outb(GRXFIFO, (ioaddr + XP_ADDR));
4608 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4609 portp->stats.rxlost += len;
4610 portp->stats.rxtotal += len;
4611 } else {
4612 len = MIN(len, buflen);
4613 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004614 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004616 tty_prepare_flip_string(tty, &ptr, len);
4617 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618 tty_schedule_flip(tty);
4619 portp->stats.rxtotal += len;
4620 }
4621 }
4622 } else {
4623 stl_sc26198rxbadchars(portp);
4624 }
4625
4626/*
4627 * If we are TX flow controlled and in IXANY mode then we may need
4628 * to unflow control here. We gotta do this because of the automatic
4629 * flow control modes of the sc26198.
4630 */
4631 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004632 if ((tty != NULL) &&
4633 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634 (tty->termios->c_iflag & IXANY)) {
4635 stl_sc26198txunflow(portp, tty);
4636 }
4637 }
4638}
4639
4640/*****************************************************************************/
4641
4642/*
4643 * Process an RX bad character.
4644 */
4645
Jiri Slaby60be4812006-12-08 02:38:40 -08004646static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647{
4648 struct tty_struct *tty;
4649 unsigned int ioaddr;
4650
4651 tty = portp->tty;
4652 ioaddr = portp->ioaddr;
4653
4654 if (status & SR_RXPARITY)
4655 portp->stats.rxparity++;
4656 if (status & SR_RXFRAMING)
4657 portp->stats.rxframing++;
4658 if (status & SR_RXOVERRUN)
4659 portp->stats.rxoverrun++;
4660 if (status & SR_RXBREAK)
4661 portp->stats.rxbreaks++;
4662
Jiri Slaby615e4a72006-12-08 02:38:38 -08004663 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004664 ((portp->rxignoremsk & status) == 0)) {
4665 if (portp->rxmarkmsk & status) {
4666 if (status & SR_RXBREAK) {
4667 status = TTY_BREAK;
4668 if (portp->flags & ASYNC_SAK) {
4669 do_SAK(tty);
4670 BRDENABLE(portp->brdnr, portp->pagenr);
4671 }
4672 } else if (status & SR_RXPARITY) {
4673 status = TTY_PARITY;
4674 } else if (status & SR_RXFRAMING) {
4675 status = TTY_FRAME;
4676 } else if(status & SR_RXOVERRUN) {
4677 status = TTY_OVERRUN;
4678 } else {
4679 status = 0;
4680 }
4681 } else {
4682 status = 0;
4683 }
4684
Alan Cox33f0f882006-01-09 20:54:13 -08004685 tty_insert_flip_char(tty, ch, status);
4686 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687
4688 if (status == 0)
4689 portp->stats.rxtotal++;
4690 }
4691}
4692
4693/*****************************************************************************/
4694
4695/*
4696 * Process all characters in the RX FIFO of the UART. Check all char
4697 * status bytes as well, and process as required. We need to check
4698 * all bytes in the FIFO, in case some more enter the FIFO while we
4699 * are here. To get the exact character error type we need to switch
4700 * into CHAR error mode (that is why we need to make sure we empty
4701 * the FIFO).
4702 */
4703
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004704static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004705{
4706 unsigned char status, mr1;
4707 char ch;
4708
4709/*
4710 * To get the precise error type for each character we must switch
4711 * back into CHAR error mode.
4712 */
4713 mr1 = stl_sc26198getreg(portp, MR1);
4714 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4715
4716 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4717 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4718 ch = stl_sc26198getreg(portp, RXFIFO);
4719 stl_sc26198rxbadch(portp, status, ch);
4720 }
4721
4722/*
4723 * To get correct interrupt class we must switch back into BLOCK
4724 * error mode.
4725 */
4726 stl_sc26198setreg(portp, MR1, mr1);
4727}
4728
4729/*****************************************************************************/
4730
4731/*
4732 * Other interrupt handler. This includes modem signals, flow
4733 * control actions, etc. Most stuff is left to off-level interrupt
4734 * processing time.
4735 */
4736
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004737static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004738{
4739 unsigned char cir, ipr, xisr;
4740
Jiri Slabya0564e12006-12-08 02:38:37 -08004741 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742
4743 cir = stl_sc26198getglobreg(portp, CIR);
4744
4745 switch (cir & CIR_SUBTYPEMASK) {
4746 case CIR_SUBCOS:
4747 ipr = stl_sc26198getreg(portp, IPR);
4748 if (ipr & IPR_DCDCHANGE) {
4749 set_bit(ASYI_DCDCHANGE, &portp->istate);
4750 schedule_work(&portp->tqueue);
4751 portp->stats.modem++;
4752 }
4753 break;
4754 case CIR_SUBXONXOFF:
4755 xisr = stl_sc26198getreg(portp, XISR);
4756 if (xisr & XISR_RXXONGOT) {
4757 set_bit(ASYI_TXFLOWED, &portp->istate);
4758 portp->stats.txxoff++;
4759 }
4760 if (xisr & XISR_RXXOFFGOT) {
4761 clear_bit(ASYI_TXFLOWED, &portp->istate);
4762 portp->stats.txxon++;
4763 }
4764 break;
4765 case CIR_SUBBREAK:
4766 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4767 stl_sc26198rxbadchars(portp);
4768 break;
4769 default:
4770 break;
4771 }
4772}
4773
Jiri Slaby23b85a12006-12-08 02:38:40 -08004774/*
4775 * Loadable module initialization stuff.
4776 */
4777static int __init stallion_module_init(void)
4778{
4779 unsigned int i;
4780
4781 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4782
4783 spin_lock_init(&stallion_lock);
4784 spin_lock_init(&brd_lock);
4785
4786 stl_initbrds();
4787
4788 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4789 if (!stl_serial)
4790 return -1;
4791
4792/*
4793 * Set up a character driver for per board stuff. This is mainly used
4794 * to do stats ioctls on the ports.
4795 */
4796 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4797 printk("STALLION: failed to register serial board device\n");
4798
4799 stallion_class = class_create(THIS_MODULE, "staliomem");
4800 for (i = 0; i < 4; i++)
4801 class_device_create(stallion_class, NULL,
4802 MKDEV(STL_SIOMEMMAJOR, i), NULL,
4803 "staliomem%d", i);
4804
4805 stl_serial->owner = THIS_MODULE;
4806 stl_serial->driver_name = stl_drvname;
4807 stl_serial->name = "ttyE";
4808 stl_serial->major = STL_SERIALMAJOR;
4809 stl_serial->minor_start = 0;
4810 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4811 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4812 stl_serial->init_termios = stl_deftermios;
4813 stl_serial->flags = TTY_DRIVER_REAL_RAW;
4814 tty_set_operations(stl_serial, &stl_ops);
4815
4816 if (tty_register_driver(stl_serial)) {
4817 put_tty_driver(stl_serial);
4818 printk("STALLION: failed to register serial driver\n");
4819 return -1;
4820 }
4821
4822 return 0;
4823}
4824
4825static void __exit stallion_module_exit(void)
4826{
4827 struct stlbrd *brdp;
4828 struct stlpanel *panelp;
4829 struct stlport *portp;
4830 int i, j, k;
4831
4832 pr_debug("cleanup_module()\n");
4833
4834 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4835 stl_drvversion);
4836
4837/*
4838 * Free up all allocated resources used by the ports. This includes
4839 * memory and interrupts. As part of this process we will also do
4840 * a hangup on every open port - to try to flush out any processes
4841 * hanging onto ports.
4842 */
4843 i = tty_unregister_driver(stl_serial);
4844 put_tty_driver(stl_serial);
4845 if (i) {
4846 printk("STALLION: failed to un-register tty driver, "
4847 "errno=%d\n", -i);
4848 return;
4849 }
4850 for (i = 0; i < 4; i++)
4851 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
4852 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
4853 printk("STALLION: failed to un-register serial memory device, "
4854 "errno=%d\n", -i);
4855 class_destroy(stallion_class);
4856
4857 for (i = 0; (i < stl_nrbrds); i++) {
4858 if ((brdp = stl_brds[i]) == NULL)
4859 continue;
4860
4861 free_irq(brdp->irq, brdp);
4862
4863 for (j = 0; (j < STL_MAXPANELS); j++) {
4864 panelp = brdp->panels[j];
4865 if (panelp == NULL)
4866 continue;
4867 for (k = 0; (k < STL_PORTSPERPANEL); k++) {
4868 portp = panelp->ports[k];
4869 if (portp == NULL)
4870 continue;
4871 if (portp->tty != NULL)
4872 stl_hangup(portp->tty);
4873 kfree(portp->tx.buf);
4874 kfree(portp);
4875 }
4876 kfree(panelp);
4877 }
4878
4879 release_region(brdp->ioaddr1, brdp->iosize1);
4880 if (brdp->iosize2 > 0)
4881 release_region(brdp->ioaddr2, brdp->iosize2);
4882
4883 kfree(brdp);
4884 stl_brds[i] = NULL;
4885 }
4886}
4887
4888module_init(stallion_module_init);
4889module_exit(stallion_module_exit);
4890
4891MODULE_AUTHOR("Greg Ungerer");
4892MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4893MODULE_LICENSE("GPL");