blob: 40c256d787fc8e27a1bef0adab13385b34eb4029 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*****************************************************************************/
2
3/*
4 * istallion.c -- stallion intelligent 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 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 */
18
19/*****************************************************************************/
20
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/interrupt.h>
24#include <linux/tty.h>
25#include <linux/tty_flip.h>
26#include <linux/serial.h>
27#include <linux/cdk.h>
28#include <linux/comstats.h>
29#include <linux/istallion.h>
30#include <linux/ioport.h>
31#include <linux/delay.h>
32#include <linux/init.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/device.h>
34#include <linux/wait.h>
Alan Cox4ac43602006-06-28 04:26:52 -070035#include <linux/eisa.h>
Jiri Slabya3f8d9d2006-12-08 02:39:18 -080036#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
38#include <asm/io.h>
39#include <asm/uaccess.h>
40
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43/*****************************************************************************/
44
45/*
46 * Define different board types. Not all of the following board types
47 * are supported by this driver. But I will use the standard "assigned"
48 * board numbers. Currently supported boards are abbreviated as:
49 * ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and
50 * STAL = Stallion.
51 */
52#define BRD_UNKNOWN 0
53#define BRD_STALLION 1
54#define BRD_BRUMBY4 2
55#define BRD_ONBOARD2 3
56#define BRD_ONBOARD 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#define BRD_ONBOARDE 7
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#define BRD_ECP 23
59#define BRD_ECPE 24
60#define BRD_ECPMC 25
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#define BRD_ECPPCI 29
62
63#define BRD_BRUMBY BRD_BRUMBY4
64
65/*
66 * Define a configuration structure to hold the board configuration.
67 * Need to set this up in the code (for now) with the boards that are
68 * to be configured into the system. This is what needs to be modified
69 * when adding/removing/modifying boards. Each line entry in the
70 * stli_brdconf[] array is a board. Each line contains io/irq/memory
71 * ranges for that board (as well as what type of board it is).
72 * Some examples:
73 * { BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },
74 * This line will configure an EasyConnection 8/64 at io address 2a0,
75 * and shared memory address of cc000. Multiple EasyConnection 8/64
76 * boards can share the same shared memory address space. No interrupt
77 * is required for this board type.
78 * Another example:
79 * { BRD_ECPE, 0x5000, 0, 0x80000000, 0, 0 },
80 * This line will configure an EasyConnection 8/64 EISA in slot 5 and
81 * shared memory address of 0x80000000 (2 GByte). Multiple
82 * EasyConnection 8/64 EISA boards can share the same shared memory
83 * address space. No interrupt is required for this board type.
84 * Another example:
85 * { BRD_ONBOARD, 0x240, 0, 0xd0000, 0, 0 },
86 * This line will configure an ONboard (ISA type) at io address 240,
87 * and shared memory address of d0000. Multiple ONboards can share
88 * the same shared memory address space. No interrupt required.
89 * Another example:
90 * { BRD_BRUMBY4, 0x360, 0, 0xc8000, 0, 0 },
91 * This line will configure a Brumby board (any number of ports!) at
92 * io address 360 and shared memory address of c8000. All Brumby boards
93 * configured into a system must have their own separate io and memory
94 * addresses. No interrupt is required.
95 * Another example:
96 * { BRD_STALLION, 0x330, 0, 0xd0000, 0, 0 },
97 * This line will configure an original Stallion board at io address 330
98 * and shared memory address d0000 (this would only be valid for a "V4.0"
99 * or Rev.O Stallion board). All Stallion boards configured into the
100 * system must have their own separate io and memory addresses. No
101 * interrupt is required.
102 */
103
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800104struct stlconf {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 int brdtype;
106 int ioaddr1;
107 int ioaddr2;
108 unsigned long memaddr;
109 int irq;
110 int irqtype;
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800111};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
Jiri Slaby1328d732006-12-08 02:39:19 -0800113static unsigned int stli_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
Alan Cox4ac43602006-06-28 04:26:52 -0700115/* stli_lock must NOT be taken holding brd_lock */
116static spinlock_t stli_lock; /* TTY logic lock */
117static spinlock_t brd_lock; /* Board logic lock */
118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119/*
120 * There is some experimental EISA board detection code in this driver.
121 * By default it is disabled, but for those that want to try it out,
122 * then set the define below to be 1.
123 */
124#define STLI_EISAPROBE 0
125
126/*****************************************************************************/
127
128/*
129 * Define some important driver characteristics. Device major numbers
130 * allocated as per Linux Device Registry.
131 */
132#ifndef STL_SIOMEMMAJOR
133#define STL_SIOMEMMAJOR 28
134#endif
135#ifndef STL_SERIALMAJOR
136#define STL_SERIALMAJOR 24
137#endif
138#ifndef STL_CALLOUTMAJOR
139#define STL_CALLOUTMAJOR 25
140#endif
141
142/*****************************************************************************/
143
144/*
145 * Define our local driver identity first. Set up stuff to deal with
146 * all the local structures required by a serial tty driver.
147 */
148static char *stli_drvtitle = "Stallion Intelligent Multiport Serial Driver";
149static char *stli_drvname = "istallion";
150static char *stli_drvversion = "5.6.0";
151static char *stli_serialname = "ttyE";
152
153static struct tty_driver *stli_serial;
154
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
156#define STLI_TXBUFSIZE 4096
157
158/*
159 * Use a fast local buffer for cooked characters. Typically a whole
160 * bunch of cooked characters come in for a port, 1 at a time. So we
161 * save those up into a local buffer, then write out the whole lot
162 * with a large memcpy. Just use 1 buffer for all ports, since its
163 * use it is only need for short periods of time by each port.
164 */
165static char *stli_txcookbuf;
166static int stli_txcooksize;
167static int stli_txcookrealsize;
168static struct tty_struct *stli_txcooktty;
169
170/*
171 * Define a local default termios struct. All ports will be created
172 * with this termios initially. Basically all it defines is a raw port
173 * at 9600 baud, 8 data bits, no parity, 1 stop bit.
174 */
Alan Cox606d0992006-12-08 02:38:45 -0800175static struct ktermios stli_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
177 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800178 .c_ispeed = 9600,
179 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180};
181
182/*
183 * Define global stats structures. Not used often, and can be
184 * re-used for each stats call.
185 */
186static comstats_t stli_comstats;
187static combrd_t stli_brdstats;
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800188static struct asystats stli_cdkstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190/*****************************************************************************/
191
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800192static struct stlibrd *stli_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194static int stli_shared;
195
196/*
197 * Per board state flags. Used with the state field of the board struct.
198 * Not really much here... All we need to do is keep track of whether
199 * the board has been detected, and whether it is actually running a slave
200 * or not.
201 */
202#define BST_FOUND 0x1
203#define BST_STARTED 0x2
204
205/*
206 * Define the set of port state flags. These are marked for internal
207 * state purposes only, usually to do with the state of communications
208 * with the slave. Most of them need to be updated atomically, so always
209 * use the bit setting operations (unless protected by cli/sti).
210 */
211#define ST_INITIALIZING 1
212#define ST_OPENING 2
213#define ST_CLOSING 3
214#define ST_CMDING 4
215#define ST_TXBUSY 5
216#define ST_RXING 6
217#define ST_DOFLUSHRX 7
218#define ST_DOFLUSHTX 8
219#define ST_DOSIGS 9
220#define ST_RXSTOP 10
221#define ST_GETSIGS 11
222
223/*
224 * Define an array of board names as printable strings. Handy for
225 * referencing boards when printing trace and stuff.
226 */
227static char *stli_brdnames[] = {
228 "Unknown",
229 "Stallion",
230 "Brumby",
231 "ONboard-MC",
232 "ONboard",
233 "Brumby",
234 "Brumby",
235 "ONboard-EI",
Jiri Slabya3f8d9d2006-12-08 02:39:18 -0800236 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 "ONboard",
238 "ONboard-MC",
239 "ONboard-MC",
Jiri Slabya3f8d9d2006-12-08 02:39:18 -0800240 NULL,
241 NULL,
242 NULL,
243 NULL,
244 NULL,
245 NULL,
246 NULL,
247 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 "EasyIO",
249 "EC8/32-AT",
250 "EC8/32-MC",
251 "EC8/64-AT",
252 "EC8/64-EI",
253 "EC8/64-MC",
254 "EC8/32-PCI",
255 "EC8/64-PCI",
256 "EasyIO-PCI",
257 "EC/RA-PCI",
258};
259
260/*****************************************************************************/
261
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262/*
263 * Define some string labels for arguments passed from the module
264 * load line. These allow for easy board definitions, and easy
265 * modification of the io, memory and irq resoucres.
266 */
267
268static char *board0[8];
269static char *board1[8];
270static char *board2[8];
271static char *board3[8];
272
273static char **stli_brdsp[] = {
274 (char **) &board0,
275 (char **) &board1,
276 (char **) &board2,
277 (char **) &board3
278};
279
280/*
281 * Define a set of common board names, and types. This is used to
282 * parse any module arguments.
283 */
284
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800285static struct stlibrdtype {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 char *name;
287 int type;
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800288} stli_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 { "stallion", BRD_STALLION },
290 { "1", BRD_STALLION },
291 { "brumby", BRD_BRUMBY },
292 { "brumby4", BRD_BRUMBY },
293 { "brumby/4", BRD_BRUMBY },
294 { "brumby-4", BRD_BRUMBY },
295 { "brumby8", BRD_BRUMBY },
296 { "brumby/8", BRD_BRUMBY },
297 { "brumby-8", BRD_BRUMBY },
298 { "brumby16", BRD_BRUMBY },
299 { "brumby/16", BRD_BRUMBY },
300 { "brumby-16", BRD_BRUMBY },
301 { "2", BRD_BRUMBY },
302 { "onboard2", BRD_ONBOARD2 },
303 { "onboard-2", BRD_ONBOARD2 },
304 { "onboard/2", BRD_ONBOARD2 },
305 { "onboard-mc", BRD_ONBOARD2 },
306 { "onboard/mc", BRD_ONBOARD2 },
307 { "onboard-mca", BRD_ONBOARD2 },
308 { "onboard/mca", BRD_ONBOARD2 },
309 { "3", BRD_ONBOARD2 },
310 { "onboard", BRD_ONBOARD },
311 { "onboardat", BRD_ONBOARD },
312 { "4", BRD_ONBOARD },
313 { "onboarde", BRD_ONBOARDE },
314 { "onboard-e", BRD_ONBOARDE },
315 { "onboard/e", BRD_ONBOARDE },
316 { "onboard-ei", BRD_ONBOARDE },
317 { "onboard/ei", BRD_ONBOARDE },
318 { "7", BRD_ONBOARDE },
319 { "ecp", BRD_ECP },
320 { "ecpat", BRD_ECP },
321 { "ec8/64", BRD_ECP },
322 { "ec8/64-at", BRD_ECP },
323 { "ec8/64-isa", BRD_ECP },
324 { "23", BRD_ECP },
325 { "ecpe", BRD_ECPE },
326 { "ecpei", BRD_ECPE },
327 { "ec8/64-e", BRD_ECPE },
328 { "ec8/64-ei", BRD_ECPE },
329 { "24", BRD_ECPE },
330 { "ecpmc", BRD_ECPMC },
331 { "ec8/64-mc", BRD_ECPMC },
332 { "ec8/64-mca", BRD_ECPMC },
333 { "25", BRD_ECPMC },
334 { "ecppci", BRD_ECPPCI },
335 { "ec/ra", BRD_ECPPCI },
336 { "ec/ra-pc", BRD_ECPPCI },
337 { "ec/ra-pci", BRD_ECPPCI },
338 { "29", BRD_ECPPCI },
339};
340
341/*
342 * Define the module agruments.
343 */
344MODULE_AUTHOR("Greg Ungerer");
345MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
346MODULE_LICENSE("GPL");
347
348
Rusty Russell8d3b33f2006-03-25 03:07:05 -0800349module_param_array(board0, charp, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
Rusty Russell8d3b33f2006-03-25 03:07:05 -0800351module_param_array(board1, charp, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
Rusty Russell8d3b33f2006-03-25 03:07:05 -0800353module_param_array(board2, charp, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
Rusty Russell8d3b33f2006-03-25 03:07:05 -0800355module_param_array(board3, charp, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
357
Jiri Slabya00f33f2006-12-08 02:39:20 -0800358#if STLI_EISAPROBE != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359/*
360 * Set up a default memory address table for EISA board probing.
361 * The default addresses are all bellow 1Mbyte, which has to be the
362 * case anyway. They should be safe, since we only read values from
363 * them, and interrupts are disabled while we do it. If the higher
364 * memory support is compiled in then we also try probing around
365 * the 1Gb, 2Gb and 3Gb areas as well...
366 */
367static unsigned long stli_eisamemprobeaddrs[] = {
368 0xc0000, 0xd0000, 0xe0000, 0xf0000,
369 0x80000000, 0x80010000, 0x80020000, 0x80030000,
370 0x40000000, 0x40010000, 0x40020000, 0x40030000,
371 0xc0000000, 0xc0010000, 0xc0020000, 0xc0030000,
372 0xff000000, 0xff010000, 0xff020000, 0xff030000,
373};
374
Tobias Klauserfe971072006-01-09 20:54:02 -0800375static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
Jiri Slabya00f33f2006-12-08 02:39:20 -0800376#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
378/*
379 * Define the Stallion PCI vendor and device IDs.
380 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381#ifndef PCI_DEVICE_ID_ECRA
382#define PCI_DEVICE_ID_ECRA 0x0004
383#endif
384
385static struct pci_device_id istallion_pci_tbl[] = {
Alan Cox4ac43602006-06-28 04:26:52 -0700386 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 { 0 }
388};
389MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
390
Jiri Slaby845bead2006-12-08 02:39:17 -0800391static struct pci_driver stli_pcidriver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393/*****************************************************************************/
394
395/*
396 * Hardware configuration info for ECP boards. These defines apply
397 * to the directly accessible io ports of the ECP. There is a set of
398 * defines for each ECP board type, ISA, EISA, MCA and PCI.
399 */
400#define ECP_IOSIZE 4
401
402#define ECP_MEMSIZE (128 * 1024)
403#define ECP_PCIMEMSIZE (256 * 1024)
404
405#define ECP_ATPAGESIZE (4 * 1024)
406#define ECP_MCPAGESIZE (4 * 1024)
407#define ECP_EIPAGESIZE (64 * 1024)
408#define ECP_PCIPAGESIZE (64 * 1024)
409
410#define STL_EISAID 0x8c4e
411
412/*
413 * Important defines for the ISA class of ECP board.
414 */
415#define ECP_ATIREG 0
416#define ECP_ATCONFR 1
417#define ECP_ATMEMAR 2
418#define ECP_ATMEMPR 3
419#define ECP_ATSTOP 0x1
420#define ECP_ATINTENAB 0x10
421#define ECP_ATENABLE 0x20
422#define ECP_ATDISABLE 0x00
423#define ECP_ATADDRMASK 0x3f000
424#define ECP_ATADDRSHFT 12
425
426/*
427 * Important defines for the EISA class of ECP board.
428 */
429#define ECP_EIIREG 0
430#define ECP_EIMEMARL 1
431#define ECP_EICONFR 2
432#define ECP_EIMEMARH 3
433#define ECP_EIENABLE 0x1
434#define ECP_EIDISABLE 0x0
435#define ECP_EISTOP 0x4
436#define ECP_EIEDGE 0x00
437#define ECP_EILEVEL 0x80
438#define ECP_EIADDRMASKL 0x00ff0000
439#define ECP_EIADDRSHFTL 16
440#define ECP_EIADDRMASKH 0xff000000
441#define ECP_EIADDRSHFTH 24
442#define ECP_EIBRDENAB 0xc84
443
444#define ECP_EISAID 0x4
445
446/*
447 * Important defines for the Micro-channel class of ECP board.
448 * (It has a lot in common with the ISA boards.)
449 */
450#define ECP_MCIREG 0
451#define ECP_MCCONFR 1
452#define ECP_MCSTOP 0x20
453#define ECP_MCENABLE 0x80
454#define ECP_MCDISABLE 0x00
455
456/*
457 * Important defines for the PCI class of ECP board.
458 * (It has a lot in common with the other ECP boards.)
459 */
460#define ECP_PCIIREG 0
461#define ECP_PCICONFR 1
462#define ECP_PCISTOP 0x01
463
464/*
465 * Hardware configuration info for ONboard and Brumby boards. These
466 * defines apply to the directly accessible io ports of these boards.
467 */
468#define ONB_IOSIZE 16
469#define ONB_MEMSIZE (64 * 1024)
470#define ONB_ATPAGESIZE (64 * 1024)
471#define ONB_MCPAGESIZE (64 * 1024)
472#define ONB_EIMEMSIZE (128 * 1024)
473#define ONB_EIPAGESIZE (64 * 1024)
474
475/*
476 * Important defines for the ISA class of ONboard board.
477 */
478#define ONB_ATIREG 0
479#define ONB_ATMEMAR 1
480#define ONB_ATCONFR 2
481#define ONB_ATSTOP 0x4
482#define ONB_ATENABLE 0x01
483#define ONB_ATDISABLE 0x00
484#define ONB_ATADDRMASK 0xff0000
485#define ONB_ATADDRSHFT 16
486
487#define ONB_MEMENABLO 0
488#define ONB_MEMENABHI 0x02
489
490/*
491 * Important defines for the EISA class of ONboard board.
492 */
493#define ONB_EIIREG 0
494#define ONB_EIMEMARL 1
495#define ONB_EICONFR 2
496#define ONB_EIMEMARH 3
497#define ONB_EIENABLE 0x1
498#define ONB_EIDISABLE 0x0
499#define ONB_EISTOP 0x4
500#define ONB_EIEDGE 0x00
501#define ONB_EILEVEL 0x80
502#define ONB_EIADDRMASKL 0x00ff0000
503#define ONB_EIADDRSHFTL 16
504#define ONB_EIADDRMASKH 0xff000000
505#define ONB_EIADDRSHFTH 24
506#define ONB_EIBRDENAB 0xc84
507
508#define ONB_EISAID 0x1
509
510/*
511 * Important defines for the Brumby boards. They are pretty simple,
512 * there is not much that is programmably configurable.
513 */
514#define BBY_IOSIZE 16
515#define BBY_MEMSIZE (64 * 1024)
516#define BBY_PAGESIZE (16 * 1024)
517
518#define BBY_ATIREG 0
519#define BBY_ATCONFR 1
520#define BBY_ATSTOP 0x4
521
522/*
523 * Important defines for the Stallion boards. They are pretty simple,
524 * there is not much that is programmably configurable.
525 */
526#define STAL_IOSIZE 16
527#define STAL_MEMSIZE (64 * 1024)
528#define STAL_PAGESIZE (64 * 1024)
529
530/*
531 * Define the set of status register values for EasyConnection panels.
532 * The signature will return with the status value for each panel. From
533 * this we can determine what is attached to the board - before we have
534 * actually down loaded any code to it.
535 */
536#define ECH_PNLSTATUS 2
537#define ECH_PNL16PORT 0x20
538#define ECH_PNLIDMASK 0x07
539#define ECH_PNLXPID 0x40
540#define ECH_PNLINTRPEND 0x80
541
542/*
543 * Define some macros to do things to the board. Even those these boards
544 * are somewhat related there is often significantly different ways of
545 * doing some operation on it (like enable, paging, reset, etc). So each
546 * board class has a set of functions which do the commonly required
547 * operations. The macros below basically just call these functions,
548 * generally checking for a NULL function - which means that the board
549 * needs nothing done to it to achieve this operation!
550 */
551#define EBRDINIT(brdp) \
552 if (brdp->init != NULL) \
553 (* brdp->init)(brdp)
554
555#define EBRDENABLE(brdp) \
556 if (brdp->enable != NULL) \
557 (* brdp->enable)(brdp);
558
559#define EBRDDISABLE(brdp) \
560 if (brdp->disable != NULL) \
561 (* brdp->disable)(brdp);
562
563#define EBRDINTR(brdp) \
564 if (brdp->intr != NULL) \
565 (* brdp->intr)(brdp);
566
567#define EBRDRESET(brdp) \
568 if (brdp->reset != NULL) \
569 (* brdp->reset)(brdp);
570
571#define EBRDGETMEMPTR(brdp,offset) \
572 (* brdp->getmemptr)(brdp, offset, __LINE__)
573
574/*
575 * Define the maximal baud rate, and the default baud base for ports.
576 */
577#define STL_MAXBAUD 460800
578#define STL_BAUDBASE 115200
579#define STL_CLOSEDELAY (5 * HZ / 10)
580
581/*****************************************************************************/
582
583/*
584 * Define macros to extract a brd or port number from a minor number.
585 */
586#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
587#define MINOR2PORT(min) ((min) & 0x3f)
588
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589/*****************************************************************************/
590
591/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 * Prototype all functions in this driver!
593 */
594
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800595static int stli_parsebrd(struct stlconf *confp, char **argp);
Adrian Bunk672b2712006-06-30 01:55:30 -0700596static int stli_init(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597static int stli_open(struct tty_struct *tty, struct file *filp);
598static void stli_close(struct tty_struct *tty, struct file *filp);
599static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count);
600static void stli_putchar(struct tty_struct *tty, unsigned char ch);
601static void stli_flushchars(struct tty_struct *tty);
602static int stli_writeroom(struct tty_struct *tty);
603static int stli_charsinbuffer(struct tty_struct *tty);
604static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
Alan Cox606d0992006-12-08 02:38:45 -0800605static void stli_settermios(struct tty_struct *tty, struct ktermios *old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606static void stli_throttle(struct tty_struct *tty);
607static void stli_unthrottle(struct tty_struct *tty);
608static void stli_stop(struct tty_struct *tty);
609static void stli_start(struct tty_struct *tty);
610static void stli_flushbuffer(struct tty_struct *tty);
611static void stli_breakctl(struct tty_struct *tty, int state);
612static void stli_waituntilsent(struct tty_struct *tty, int timeout);
613static void stli_sendxchar(struct tty_struct *tty, char ch);
614static void stli_hangup(struct tty_struct *tty);
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800615static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800617static int stli_brdinit(struct stlibrd *brdp);
618static int stli_startbrd(struct stlibrd *brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
620static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
621static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800622static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623static void stli_poll(unsigned long arg);
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800624static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
625static int stli_initopen(struct stlibrd *brdp, struct stliport *portp);
626static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
627static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
628static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp);
Al Viro3e577a82006-12-06 18:41:45 +0000629static void stli_dohangup(struct work_struct *);
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800630static int stli_setport(struct stliport *portp);
631static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
632static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
633static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
634static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
635static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
637static long stli_mktiocm(unsigned long sigvalue);
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800638static void stli_read(struct stlibrd *brdp, struct stliport *portp);
639static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
640static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641static int stli_getbrdstats(combrd_t __user *bp);
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800642static int stli_getportstats(struct stliport *portp, comstats_t __user *cp);
643static int stli_portcmdstats(struct stliport *portp);
644static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
645static int stli_getportstruct(struct stliport __user *arg);
646static int stli_getbrdstruct(struct stlibrd __user *arg);
647static struct stlibrd *stli_allocbrd(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800649static void stli_ecpinit(struct stlibrd *brdp);
650static void stli_ecpenable(struct stlibrd *brdp);
651static void stli_ecpdisable(struct stlibrd *brdp);
652static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
653static void stli_ecpreset(struct stlibrd *brdp);
654static void stli_ecpintr(struct stlibrd *brdp);
655static void stli_ecpeiinit(struct stlibrd *brdp);
656static void stli_ecpeienable(struct stlibrd *brdp);
657static void stli_ecpeidisable(struct stlibrd *brdp);
658static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
659static void stli_ecpeireset(struct stlibrd *brdp);
660static void stli_ecpmcenable(struct stlibrd *brdp);
661static void stli_ecpmcdisable(struct stlibrd *brdp);
662static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
663static void stli_ecpmcreset(struct stlibrd *brdp);
664static void stli_ecppciinit(struct stlibrd *brdp);
665static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
666static void stli_ecppcireset(struct stlibrd *brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800668static void stli_onbinit(struct stlibrd *brdp);
669static void stli_onbenable(struct stlibrd *brdp);
670static void stli_onbdisable(struct stlibrd *brdp);
671static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
672static void stli_onbreset(struct stlibrd *brdp);
673static void stli_onbeinit(struct stlibrd *brdp);
674static void stli_onbeenable(struct stlibrd *brdp);
675static void stli_onbedisable(struct stlibrd *brdp);
676static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
677static void stli_onbereset(struct stlibrd *brdp);
678static void stli_bbyinit(struct stlibrd *brdp);
679static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
680static void stli_bbyreset(struct stlibrd *brdp);
681static void stli_stalinit(struct stlibrd *brdp);
682static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
683static void stli_stalreset(struct stlibrd *brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Jiri Slaby1328d732006-12-08 02:39:19 -0800685static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800687static int stli_initecp(struct stlibrd *brdp);
688static int stli_initonb(struct stlibrd *brdp);
Jiri Slabya00f33f2006-12-08 02:39:20 -0800689#if STLI_EISAPROBE != 0
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800690static int stli_eisamemprobe(struct stlibrd *brdp);
Jiri Slabya00f33f2006-12-08 02:39:20 -0800691#endif
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800692static int stli_initports(struct stlibrd *brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694/*****************************************************************************/
695
696/*
697 * Define the driver info for a user level shared memory device. This
698 * device will work sort of like the /dev/kmem device - except that it
699 * will give access to the shared memory on the Stallion intelligent
700 * board. This is also a very useful debugging tool.
701 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700702static const struct file_operations stli_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 .owner = THIS_MODULE,
704 .read = stli_memread,
705 .write = stli_memwrite,
706 .ioctl = stli_memioctl,
707};
708
709/*****************************************************************************/
710
711/*
712 * Define a timer_list entry for our poll routine. The slave board
713 * is polled every so often to see if anything needs doing. This is
714 * much cheaper on host cpu than using interrupts. It turns out to
715 * not increase character latency by much either...
716 */
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700717static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
719static int stli_timeron;
720
721/*
722 * Define the calculation for the timeout routine.
723 */
724#define STLI_TIMEOUT (jiffies + 1)
725
726/*****************************************************************************/
727
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800728static struct class *istallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800730static void stli_cleanup_ports(struct stlibrd *brdp)
Jiri Slaby845bead2006-12-08 02:39:17 -0800731{
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800732 struct stliport *portp;
Jiri Slaby845bead2006-12-08 02:39:17 -0800733 unsigned int j;
734
735 for (j = 0; j < STL_MAXPORTS; j++) {
736 portp = brdp->ports[j];
737 if (portp != NULL) {
738 if (portp->tty != NULL)
739 tty_hangup(portp->tty);
740 kfree(portp);
741 }
742 }
743}
744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745/*
746 * Loadable module initialization stuff.
747 */
748
749static int __init istallion_module_init(void)
750{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 stli_init();
Alan Cox4ac43602006-06-28 04:26:52 -0700752 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753}
754
755/*****************************************************************************/
756
757static void __exit istallion_module_exit(void)
758{
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800759 struct stlibrd *brdp;
Jiri Slaby1328d732006-12-08 02:39:19 -0800760 unsigned int j;
Jiri Slaby845bead2006-12-08 02:39:17 -0800761 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
764 stli_drvversion);
765
Jiri Slaby845bead2006-12-08 02:39:17 -0800766 pci_unregister_driver(&stli_pcidriver);
Alan Cox4ac43602006-06-28 04:26:52 -0700767 /*
768 * Free up all allocated resources used by the ports. This includes
769 * memory and interrupts.
770 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 if (stli_timeron) {
772 stli_timeron = 0;
Alan Cox4ac43602006-06-28 04:26:52 -0700773 del_timer_sync(&stli_timerlist);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 }
775
776 i = tty_unregister_driver(stli_serial);
777 if (i) {
778 printk("STALLION: failed to un-register tty driver, "
779 "errno=%d\n", -i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 return;
781 }
782 put_tty_driver(stli_serial);
Jiri Slaby1328d732006-12-08 02:39:19 -0800783 for (j = 0; j < 4; j++)
784 class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j));
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800785 class_destroy(istallion_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
787 printk("STALLION: failed to un-register serial memory device, "
788 "errno=%d\n", -i);
Jesper Juhl735d5662005-11-07 01:01:29 -0800789
Jesper Juhl735d5662005-11-07 01:01:29 -0800790 kfree(stli_txcookbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Jiri Slaby1328d732006-12-08 02:39:19 -0800792 for (j = 0; (j < stli_nrbrds); j++) {
793 if ((brdp = stli_brds[j]) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 continue;
Jiri Slaby845bead2006-12-08 02:39:17 -0800795
796 stli_cleanup_ports(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
798 iounmap(brdp->membase);
799 if (brdp->iosize > 0)
800 release_region(brdp->iobase, brdp->iosize);
801 kfree(brdp);
Jiri Slaby1328d732006-12-08 02:39:19 -0800802 stli_brds[j] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804}
805
806module_init(istallion_module_init);
807module_exit(istallion_module_exit);
808
809/*****************************************************************************/
810
811/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 * Parse the supplied argument string, into the board conf struct.
813 */
814
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800815static int stli_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816{
Jiri Slaby1328d732006-12-08 02:39:19 -0800817 unsigned int i;
Alan Cox4ac43602006-06-28 04:26:52 -0700818 char *sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Alan Cox4ac43602006-06-28 04:26:52 -0700820 if (argp[0] == NULL || *argp[0] == 0)
821 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
823 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
Jiri Slabya3f8d9d2006-12-08 02:39:18 -0800824 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Tobias Klauserfe971072006-01-09 20:54:02 -0800826 for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
828 break;
829 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800830 if (i == ARRAY_SIZE(stli_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800832 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 }
834
835 confp->brdtype = stli_brdstr[i].type;
Alan Cox4ac43602006-06-28 04:26:52 -0700836 if (argp[1] != NULL && *argp[1] != 0)
Jiri Slabya3f8d9d2006-12-08 02:39:18 -0800837 confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0);
Alan Cox4ac43602006-06-28 04:26:52 -0700838 if (argp[2] != NULL && *argp[2] != 0)
Jiri Slabya3f8d9d2006-12-08 02:39:18 -0800839 confp->memaddr = simple_strtoul(argp[2], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 return(1);
841}
842
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843/*****************************************************************************/
844
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845static int stli_open(struct tty_struct *tty, struct file *filp)
846{
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800847 struct stlibrd *brdp;
848 struct stliport *portp;
Jiri Slaby1328d732006-12-08 02:39:19 -0800849 unsigned int minordev, brdnr, portnr;
850 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
852 minordev = tty->index;
853 brdnr = MINOR2BRD(minordev);
854 if (brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -0700855 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 brdp = stli_brds[brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -0700857 if (brdp == NULL)
858 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 if ((brdp->state & BST_STARTED) == 0)
Alan Cox4ac43602006-06-28 04:26:52 -0700860 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 portnr = MINOR2PORT(minordev);
Jiri Slaby1328d732006-12-08 02:39:19 -0800862 if (portnr > brdp->nrports)
Alan Cox4ac43602006-06-28 04:26:52 -0700863 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864
865 portp = brdp->ports[portnr];
Alan Cox4ac43602006-06-28 04:26:52 -0700866 if (portp == NULL)
867 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 if (portp->devnr < 1)
Alan Cox4ac43602006-06-28 04:26:52 -0700869 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
871
872/*
873 * Check if this port is in the middle of closing. If so then wait
874 * until it is closed then return error status based on flag settings.
875 * The sleep here does not need interrupt protection since the wakeup
876 * for it is done with the same context.
877 */
878 if (portp->flags & ASYNC_CLOSING) {
879 interruptible_sleep_on(&portp->close_wait);
880 if (portp->flags & ASYNC_HUP_NOTIFY)
Alan Cox4ac43602006-06-28 04:26:52 -0700881 return -EAGAIN;
882 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 }
884
885/*
886 * On the first open of the device setup the port hardware, and
887 * initialize the per port data structure. Since initializing the port
888 * requires several commands to the board we will need to wait for any
889 * other open that is already initializing the port.
890 */
891 portp->tty = tty;
892 tty->driver_data = portp;
893 portp->refcount++;
894
895 wait_event_interruptible(portp->raw_wait,
896 !test_bit(ST_INITIALIZING, &portp->state));
897 if (signal_pending(current))
Alan Cox4ac43602006-06-28 04:26:52 -0700898 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
900 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
901 set_bit(ST_INITIALIZING, &portp->state);
902 if ((rc = stli_initopen(brdp, portp)) >= 0) {
903 portp->flags |= ASYNC_INITIALIZED;
904 clear_bit(TTY_IO_ERROR, &tty->flags);
905 }
906 clear_bit(ST_INITIALIZING, &portp->state);
907 wake_up_interruptible(&portp->raw_wait);
908 if (rc < 0)
Alan Cox4ac43602006-06-28 04:26:52 -0700909 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
911
912/*
913 * Check if this port is in the middle of closing. If so then wait
914 * until it is closed then return error status, based on flag settings.
915 * The sleep here does not need interrupt protection since the wakeup
916 * for it is done with the same context.
917 */
918 if (portp->flags & ASYNC_CLOSING) {
919 interruptible_sleep_on(&portp->close_wait);
920 if (portp->flags & ASYNC_HUP_NOTIFY)
Alan Cox4ac43602006-06-28 04:26:52 -0700921 return -EAGAIN;
922 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 }
924
925/*
926 * Based on type of open being done check if it can overlap with any
927 * previous opens still in effect. If we are a normal serial device
928 * then also we might have to wait for carrier.
929 */
930 if (!(filp->f_flags & O_NONBLOCK)) {
931 if ((rc = stli_waitcarrier(brdp, portp, filp)) != 0)
Alan Cox4ac43602006-06-28 04:26:52 -0700932 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 }
934 portp->flags |= ASYNC_NORMAL_ACTIVE;
Alan Cox4ac43602006-06-28 04:26:52 -0700935 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936}
937
938/*****************************************************************************/
939
940static void stli_close(struct tty_struct *tty, struct file *filp)
941{
Jiri Slaby1f8ec432006-12-08 02:39:18 -0800942 struct stlibrd *brdp;
943 struct stliport *portp;
Alan Cox4ac43602006-06-28 04:26:52 -0700944 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
946 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -0700947 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 return;
949
Alan Cox4ac43602006-06-28 04:26:52 -0700950 spin_lock_irqsave(&stli_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (tty_hung_up_p(filp)) {
Alan Cox4ac43602006-06-28 04:26:52 -0700952 spin_unlock_irqrestore(&stli_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return;
954 }
955 if ((tty->count == 1) && (portp->refcount != 1))
956 portp->refcount = 1;
957 if (portp->refcount-- > 1) {
Alan Cox4ac43602006-06-28 04:26:52 -0700958 spin_unlock_irqrestore(&stli_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 return;
960 }
961
962 portp->flags |= ASYNC_CLOSING;
963
964/*
965 * May want to wait for data to drain before closing. The BUSY flag
966 * keeps track of whether we are still transmitting or not. It is
967 * updated by messages from the slave - indicating when all chars
968 * really have drained.
969 */
970 if (tty == stli_txcooktty)
971 stli_flushchars(tty);
972 tty->closing = 1;
Alan Cox4ac43602006-06-28 04:26:52 -0700973 spin_unlock_irqrestore(&stli_lock, flags);
974
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
976 tty_wait_until_sent(tty, portp->closing_wait);
977
978 portp->flags &= ~ASYNC_INITIALIZED;
979 brdp = stli_brds[portp->brdnr];
980 stli_rawclose(brdp, portp, 0, 0);
981 if (tty->termios->c_cflag & HUPCL) {
982 stli_mkasysigs(&portp->asig, 0, 0);
983 if (test_bit(ST_CMDING, &portp->state))
984 set_bit(ST_DOSIGS, &portp->state);
985 else
986 stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig,
987 sizeof(asysigs_t), 0);
988 }
989 clear_bit(ST_TXBUSY, &portp->state);
990 clear_bit(ST_RXSTOP, &portp->state);
991 set_bit(TTY_IO_ERROR, &tty->flags);
992 if (tty->ldisc.flush_buffer)
993 (tty->ldisc.flush_buffer)(tty);
994 set_bit(ST_DOFLUSHRX, &portp->state);
995 stli_flushbuffer(tty);
996
997 tty->closing = 0;
Alan Cox4ac43602006-06-28 04:26:52 -0700998 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
1000 if (portp->openwaitcnt) {
1001 if (portp->close_delay)
1002 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
1003 wake_up_interruptible(&portp->open_wait);
1004 }
1005
1006 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1007 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008}
1009
1010/*****************************************************************************/
1011
1012/*
1013 * Carry out first open operations on a port. This involves a number of
1014 * commands to be sent to the slave. We need to open the port, set the
1015 * notification events, set the initial port settings, get and set the
1016 * initial signal values. We sleep and wait in between each one. But
1017 * this still all happens pretty quickly.
1018 */
1019
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001020static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021{
Alan Cox4ac43602006-06-28 04:26:52 -07001022 struct tty_struct *tty;
1023 asynotify_t nt;
1024 asyport_t aport;
1025 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
1027 if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07001028 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 memset(&nt, 0, sizeof(asynotify_t));
1031 nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
1032 nt.signal = SG_DCD;
1033 if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
1034 sizeof(asynotify_t), 0)) < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07001035 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
1037 tty = portp->tty;
Alan Cox4ac43602006-06-28 04:26:52 -07001038 if (tty == NULL)
1039 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 stli_mkasyport(portp, &aport, tty->termios);
1041 if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
1042 sizeof(asyport_t), 0)) < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07001043 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045 set_bit(ST_GETSIGS, &portp->state);
1046 if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
1047 sizeof(asysigs_t), 1)) < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07001048 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 if (test_and_clear_bit(ST_GETSIGS, &portp->state))
1050 portp->sigs = stli_mktiocm(portp->asig.sigvalue);
1051 stli_mkasysigs(&portp->asig, 1, 1);
1052 if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
1053 sizeof(asysigs_t), 0)) < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07001054 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Alan Cox4ac43602006-06-28 04:26:52 -07001056 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057}
1058
1059/*****************************************************************************/
1060
1061/*
1062 * Send an open message to the slave. This will sleep waiting for the
1063 * acknowledgement, so must have user context. We need to co-ordinate
1064 * with close events here, since we don't want open and close events
1065 * to overlap.
1066 */
1067
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001068static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069{
Alan Cox4ac43602006-06-28 04:26:52 -07001070 cdkhdr_t __iomem *hdrp;
1071 cdkctrl_t __iomem *cp;
1072 unsigned char __iomem *bits;
1073 unsigned long flags;
1074 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
1076/*
1077 * Send a message to the slave to open this port.
1078 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
1080/*
1081 * Slave is already closing this port. This can happen if a hangup
1082 * occurs on this port. So we must wait until it is complete. The
1083 * order of opens and closes may not be preserved across shared
1084 * memory, so we must wait until it is complete.
1085 */
1086 wait_event_interruptible(portp->raw_wait,
1087 !test_bit(ST_CLOSING, &portp->state));
1088 if (signal_pending(current)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 return -ERESTARTSYS;
1090 }
1091
1092/*
1093 * Everything is ready now, so write the open message into shared
1094 * memory. Once the message is in set the service bits to say that
1095 * this port wants service.
1096 */
Alan Cox4ac43602006-06-28 04:26:52 -07001097 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001099 cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
1100 writel(arg, &cp->openarg);
1101 writeb(1, &cp->open);
1102 hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
1103 bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 portp->portidx;
Alan Cox4ac43602006-06-28 04:26:52 -07001105 writeb(readb(bits) | portp->portbit, bits);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 EBRDDISABLE(brdp);
1107
1108 if (wait == 0) {
Alan Cox4ac43602006-06-28 04:26:52 -07001109 spin_unlock_irqrestore(&brd_lock, flags);
1110 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 }
1112
1113/*
1114 * Slave is in action, so now we must wait for the open acknowledgment
1115 * to come back.
1116 */
1117 rc = 0;
1118 set_bit(ST_OPENING, &portp->state);
Alan Cox4ac43602006-06-28 04:26:52 -07001119 spin_unlock_irqrestore(&brd_lock, flags);
1120
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 wait_event_interruptible(portp->raw_wait,
1122 !test_bit(ST_OPENING, &portp->state));
1123 if (signal_pending(current))
1124 rc = -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 if ((rc == 0) && (portp->rc != 0))
1127 rc = -EIO;
Alan Cox4ac43602006-06-28 04:26:52 -07001128 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129}
1130
1131/*****************************************************************************/
1132
1133/*
1134 * Send a close message to the slave. Normally this will sleep waiting
1135 * for the acknowledgement, but if wait parameter is 0 it will not. If
1136 * wait is true then must have user context (to sleep).
1137 */
1138
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001139static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140{
Alan Cox4ac43602006-06-28 04:26:52 -07001141 cdkhdr_t __iomem *hdrp;
1142 cdkctrl_t __iomem *cp;
1143 unsigned char __iomem *bits;
1144 unsigned long flags;
1145 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147/*
1148 * Slave is already closing this port. This can happen if a hangup
1149 * occurs on this port.
1150 */
1151 if (wait) {
1152 wait_event_interruptible(portp->raw_wait,
1153 !test_bit(ST_CLOSING, &portp->state));
1154 if (signal_pending(current)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 return -ERESTARTSYS;
1156 }
1157 }
1158
1159/*
1160 * Write the close command into shared memory.
1161 */
Alan Cox4ac43602006-06-28 04:26:52 -07001162 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001164 cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
1165 writel(arg, &cp->closearg);
1166 writeb(1, &cp->close);
1167 hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
1168 bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 portp->portidx;
Alan Cox4ac43602006-06-28 04:26:52 -07001170 writeb(readb(bits) |portp->portbit, bits);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 EBRDDISABLE(brdp);
1172
1173 set_bit(ST_CLOSING, &portp->state);
Alan Cox4ac43602006-06-28 04:26:52 -07001174 spin_unlock_irqrestore(&brd_lock, flags);
1175
1176 if (wait == 0)
1177 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
1179/*
1180 * Slave is in action, so now we must wait for the open acknowledgment
1181 * to come back.
1182 */
1183 rc = 0;
1184 wait_event_interruptible(portp->raw_wait,
1185 !test_bit(ST_CLOSING, &portp->state));
1186 if (signal_pending(current))
1187 rc = -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
1189 if ((rc == 0) && (portp->rc != 0))
1190 rc = -EIO;
Alan Cox4ac43602006-06-28 04:26:52 -07001191 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192}
1193
1194/*****************************************************************************/
1195
1196/*
1197 * Send a command to the slave and wait for the response. This must
1198 * have user context (it sleeps). This routine is generic in that it
1199 * can send any type of command. Its purpose is to wait for that command
1200 * to complete (as opposed to initiating the command then returning).
1201 */
1202
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001203static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 wait_event_interruptible(portp->raw_wait,
1206 !test_bit(ST_CMDING, &portp->state));
Alan Cox4ac43602006-06-28 04:26:52 -07001207 if (signal_pending(current))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
1210 stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
1211
1212 wait_event_interruptible(portp->raw_wait,
1213 !test_bit(ST_CMDING, &portp->state));
Alan Cox4ac43602006-06-28 04:26:52 -07001214 if (signal_pending(current))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
1217 if (portp->rc != 0)
Alan Cox4ac43602006-06-28 04:26:52 -07001218 return -EIO;
1219 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220}
1221
1222/*****************************************************************************/
1223
1224/*
1225 * Send the termios settings for this port to the slave. This sleeps
1226 * waiting for the command to complete - so must have user context.
1227 */
1228
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001229static int stli_setport(struct stliport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001231 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07001232 asyport_t aport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Alan Cox4ac43602006-06-28 04:26:52 -07001234 if (portp == NULL)
1235 return -ENODEV;
1236 if (portp->tty == NULL)
1237 return -ENODEV;
Jiri Slaby1328d732006-12-08 02:39:19 -08001238 if (portp->brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07001239 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001241 if (brdp == NULL)
1242 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
1244 stli_mkasyport(portp, &aport, portp->tty->termios);
1245 return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
1246}
1247
1248/*****************************************************************************/
1249
1250/*
1251 * Possibly need to wait for carrier (DCD signal) to come high. Say
1252 * maybe because if we are clocal then we don't need to wait...
1253 */
1254
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001255static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256{
Alan Cox4ac43602006-06-28 04:26:52 -07001257 unsigned long flags;
1258 int rc, doclocal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
1260 rc = 0;
1261 doclocal = 0;
1262
1263 if (portp->tty->termios->c_cflag & CLOCAL)
1264 doclocal++;
1265
Alan Cox4ac43602006-06-28 04:26:52 -07001266 spin_lock_irqsave(&stli_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 portp->openwaitcnt++;
1268 if (! tty_hung_up_p(filp))
1269 portp->refcount--;
Alan Cox4ac43602006-06-28 04:26:52 -07001270 spin_unlock_irqrestore(&stli_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
1272 for (;;) {
1273 stli_mkasysigs(&portp->asig, 1, 1);
1274 if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
1275 &portp->asig, sizeof(asysigs_t), 0)) < 0)
1276 break;
1277 if (tty_hung_up_p(filp) ||
1278 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
1279 if (portp->flags & ASYNC_HUP_NOTIFY)
1280 rc = -EBUSY;
1281 else
1282 rc = -ERESTARTSYS;
1283 break;
1284 }
1285 if (((portp->flags & ASYNC_CLOSING) == 0) &&
1286 (doclocal || (portp->sigs & TIOCM_CD))) {
1287 break;
1288 }
1289 if (signal_pending(current)) {
1290 rc = -ERESTARTSYS;
1291 break;
1292 }
1293 interruptible_sleep_on(&portp->open_wait);
1294 }
1295
Alan Cox4ac43602006-06-28 04:26:52 -07001296 spin_lock_irqsave(&stli_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 if (! tty_hung_up_p(filp))
1298 portp->refcount++;
1299 portp->openwaitcnt--;
Alan Cox4ac43602006-06-28 04:26:52 -07001300 spin_unlock_irqrestore(&stli_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
Alan Cox4ac43602006-06-28 04:26:52 -07001302 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303}
1304
1305/*****************************************************************************/
1306
1307/*
1308 * Write routine. Take the data and put it in the shared memory ring
1309 * queue. If port is not already sending chars then need to mark the
1310 * service bits for this port.
1311 */
1312
1313static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count)
1314{
Alan Cox4ac43602006-06-28 04:26:52 -07001315 cdkasy_t __iomem *ap;
1316 cdkhdr_t __iomem *hdrp;
1317 unsigned char __iomem *bits;
1318 unsigned char __iomem *shbuf;
1319 unsigned char *chbuf;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001320 struct stliport *portp;
1321 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07001322 unsigned int len, stlen, head, tail, size;
1323 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 if (tty == stli_txcooktty)
1326 stli_flushchars(tty);
1327 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001328 if (portp == NULL)
1329 return 0;
Jiri Slaby1328d732006-12-08 02:39:19 -08001330 if (portp->brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07001331 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001333 if (brdp == NULL)
1334 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 chbuf = (unsigned char *) buf;
1336
1337/*
1338 * All data is now local, shove as much as possible into shared memory.
1339 */
Alan Cox4ac43602006-06-28 04:26:52 -07001340 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001342 ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
1343 head = (unsigned int) readw(&ap->txq.head);
1344 tail = (unsigned int) readw(&ap->txq.tail);
1345 if (tail != ((unsigned int) readw(&ap->txq.tail)))
1346 tail = (unsigned int) readw(&ap->txq.tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 size = portp->txsize;
1348 if (head >= tail) {
1349 len = size - (head - tail) - 1;
1350 stlen = size - head;
1351 } else {
1352 len = tail - head - 1;
1353 stlen = len;
1354 }
1355
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08001356 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 count = 0;
Alan Cox4ac43602006-06-28 04:26:52 -07001358 shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
1360 while (len > 0) {
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08001361 stlen = min(len, stlen);
Alan Cox4ac43602006-06-28 04:26:52 -07001362 memcpy_toio(shbuf + head, chbuf, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 chbuf += stlen;
1364 len -= stlen;
1365 count += stlen;
1366 head += stlen;
1367 if (head >= size) {
1368 head = 0;
1369 stlen = tail;
1370 }
1371 }
1372
Alan Cox4ac43602006-06-28 04:26:52 -07001373 ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
1374 writew(head, &ap->txq.head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 if (test_bit(ST_TXBUSY, &portp->state)) {
Alan Cox4ac43602006-06-28 04:26:52 -07001376 if (readl(&ap->changed.data) & DT_TXEMPTY)
1377 writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 }
Alan Cox4ac43602006-06-28 04:26:52 -07001379 hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
1380 bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 portp->portidx;
Alan Cox4ac43602006-06-28 04:26:52 -07001382 writeb(readb(bits) | portp->portbit, bits);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 set_bit(ST_TXBUSY, &portp->state);
1384 EBRDDISABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001385 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 return(count);
1388}
1389
1390/*****************************************************************************/
1391
1392/*
1393 * Output a single character. We put it into a temporary local buffer
1394 * (for speed) then write out that buffer when the flushchars routine
1395 * is called. There is a safety catch here so that if some other port
1396 * writes chars before the current buffer has been, then we write them
1397 * first them do the new ports.
1398 */
1399
1400static void stli_putchar(struct tty_struct *tty, unsigned char ch)
1401{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 if (tty != stli_txcooktty) {
Alan Cox4ac43602006-06-28 04:26:52 -07001403 if (stli_txcooktty != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 stli_flushchars(stli_txcooktty);
1405 stli_txcooktty = tty;
1406 }
1407
1408 stli_txcookbuf[stli_txcooksize++] = ch;
1409}
1410
1411/*****************************************************************************/
1412
1413/*
1414 * Transfer characters from the local TX cooking buffer to the board.
1415 * We sort of ignore the tty that gets passed in here. We rely on the
1416 * info stored with the TX cook buffer to tell us which port to flush
1417 * the data on. In any case we clean out the TX cook buffer, for re-use
1418 * by someone else.
1419 */
1420
1421static void stli_flushchars(struct tty_struct *tty)
1422{
Alan Cox4ac43602006-06-28 04:26:52 -07001423 cdkhdr_t __iomem *hdrp;
1424 unsigned char __iomem *bits;
1425 cdkasy_t __iomem *ap;
1426 struct tty_struct *cooktty;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001427 struct stliport *portp;
1428 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07001429 unsigned int len, stlen, head, tail, size, count, cooksize;
1430 unsigned char *buf;
1431 unsigned char __iomem *shbuf;
1432 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
1434 cooksize = stli_txcooksize;
1435 cooktty = stli_txcooktty;
1436 stli_txcooksize = 0;
1437 stli_txcookrealsize = 0;
Alan Cox4ac43602006-06-28 04:26:52 -07001438 stli_txcooktty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
Alan Cox4ac43602006-06-28 04:26:52 -07001440 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 return;
Alan Cox4ac43602006-06-28 04:26:52 -07001442 if (cooktty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 return;
1444 if (tty != cooktty)
1445 tty = cooktty;
1446 if (cooksize == 0)
1447 return;
1448
1449 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001450 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 return;
Jiri Slaby1328d732006-12-08 02:39:19 -08001452 if (portp->brdnr >= stli_nrbrds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 return;
1454 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001455 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 return;
1457
Alan Cox4ac43602006-06-28 04:26:52 -07001458 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 EBRDENABLE(brdp);
1460
Alan Cox4ac43602006-06-28 04:26:52 -07001461 ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
1462 head = (unsigned int) readw(&ap->txq.head);
1463 tail = (unsigned int) readw(&ap->txq.tail);
1464 if (tail != ((unsigned int) readw(&ap->txq.tail)))
1465 tail = (unsigned int) readw(&ap->txq.tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 size = portp->txsize;
1467 if (head >= tail) {
1468 len = size - (head - tail) - 1;
1469 stlen = size - head;
1470 } else {
1471 len = tail - head - 1;
1472 stlen = len;
1473 }
1474
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08001475 len = min(len, cooksize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 count = 0;
Al Viro29756fa2006-10-10 22:47:27 +01001477 shbuf = EBRDGETMEMPTR(brdp, portp->txoffset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 buf = stli_txcookbuf;
1479
1480 while (len > 0) {
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08001481 stlen = min(len, stlen);
Alan Cox4ac43602006-06-28 04:26:52 -07001482 memcpy_toio(shbuf + head, buf, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 buf += stlen;
1484 len -= stlen;
1485 count += stlen;
1486 head += stlen;
1487 if (head >= size) {
1488 head = 0;
1489 stlen = tail;
1490 }
1491 }
1492
Alan Cox4ac43602006-06-28 04:26:52 -07001493 ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
1494 writew(head, &ap->txq.head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
1496 if (test_bit(ST_TXBUSY, &portp->state)) {
Alan Cox4ac43602006-06-28 04:26:52 -07001497 if (readl(&ap->changed.data) & DT_TXEMPTY)
1498 writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 }
Alan Cox4ac43602006-06-28 04:26:52 -07001500 hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
1501 bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 portp->portidx;
Alan Cox4ac43602006-06-28 04:26:52 -07001503 writeb(readb(bits) | portp->portbit, bits);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 set_bit(ST_TXBUSY, &portp->state);
1505
1506 EBRDDISABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001507 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508}
1509
1510/*****************************************************************************/
1511
1512static int stli_writeroom(struct tty_struct *tty)
1513{
Alan Cox4ac43602006-06-28 04:26:52 -07001514 cdkasyrq_t __iomem *rp;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001515 struct stliport *portp;
1516 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07001517 unsigned int head, tail, len;
1518 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 if (tty == stli_txcooktty) {
1521 if (stli_txcookrealsize != 0) {
1522 len = stli_txcookrealsize - stli_txcooksize;
Alan Cox4ac43602006-06-28 04:26:52 -07001523 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 }
1525 }
1526
1527 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001528 if (portp == NULL)
1529 return 0;
Jiri Slaby1328d732006-12-08 02:39:19 -08001530 if (portp->brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07001531 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001533 if (brdp == NULL)
1534 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
Alan Cox4ac43602006-06-28 04:26:52 -07001536 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001538 rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
1539 head = (unsigned int) readw(&rp->head);
1540 tail = (unsigned int) readw(&rp->tail);
1541 if (tail != ((unsigned int) readw(&rp->tail)))
1542 tail = (unsigned int) readw(&rp->tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head);
1544 len--;
1545 EBRDDISABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001546 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
1548 if (tty == stli_txcooktty) {
1549 stli_txcookrealsize = len;
1550 len -= stli_txcooksize;
1551 }
Alan Cox4ac43602006-06-28 04:26:52 -07001552 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553}
1554
1555/*****************************************************************************/
1556
1557/*
1558 * Return the number of characters in the transmit buffer. Normally we
1559 * will return the number of chars in the shared memory ring queue.
1560 * We need to kludge around the case where the shared memory buffer is
1561 * empty but not all characters have drained yet, for this case just
1562 * return that there is 1 character in the buffer!
1563 */
1564
1565static int stli_charsinbuffer(struct tty_struct *tty)
1566{
Alan Cox4ac43602006-06-28 04:26:52 -07001567 cdkasyrq_t __iomem *rp;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001568 struct stliport *portp;
1569 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07001570 unsigned int head, tail, len;
1571 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 if (tty == stli_txcooktty)
1574 stli_flushchars(tty);
1575 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001576 if (portp == NULL)
1577 return 0;
Jiri Slaby1328d732006-12-08 02:39:19 -08001578 if (portp->brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07001579 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001581 if (brdp == NULL)
1582 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Alan Cox4ac43602006-06-28 04:26:52 -07001584 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001586 rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
1587 head = (unsigned int) readw(&rp->head);
1588 tail = (unsigned int) readw(&rp->tail);
1589 if (tail != ((unsigned int) readw(&rp->tail)))
1590 tail = (unsigned int) readw(&rp->tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head));
1592 if ((len == 0) && test_bit(ST_TXBUSY, &portp->state))
1593 len = 1;
1594 EBRDDISABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07001595 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
Alan Cox4ac43602006-06-28 04:26:52 -07001597 return len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598}
1599
1600/*****************************************************************************/
1601
1602/*
1603 * Generate the serial struct info.
1604 */
1605
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001606static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607{
Alan Cox4ac43602006-06-28 04:26:52 -07001608 struct serial_struct sio;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001609 struct stlibrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
1611 memset(&sio, 0, sizeof(struct serial_struct));
1612 sio.type = PORT_UNKNOWN;
1613 sio.line = portp->portnr;
1614 sio.irq = 0;
1615 sio.flags = portp->flags;
1616 sio.baud_base = portp->baud_base;
1617 sio.close_delay = portp->close_delay;
1618 sio.closing_wait = portp->closing_wait;
1619 sio.custom_divisor = portp->custom_divisor;
1620 sio.xmit_fifo_size = 0;
1621 sio.hub6 = 0;
1622
1623 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001624 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 sio.port = brdp->iobase;
1626
1627 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ?
1628 -EFAULT : 0;
1629}
1630
1631/*****************************************************************************/
1632
1633/*
1634 * Set port according to the serial struct info.
1635 * At this point we do not do any auto-configure stuff, so we will
1636 * just quietly ignore any requests to change irq, etc.
1637 */
1638
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001639static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640{
Alan Cox4ac43602006-06-28 04:26:52 -07001641 struct serial_struct sio;
1642 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
1644 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1645 return -EFAULT;
1646 if (!capable(CAP_SYS_ADMIN)) {
1647 if ((sio.baud_base != portp->baud_base) ||
1648 (sio.close_delay != portp->close_delay) ||
1649 ((sio.flags & ~ASYNC_USR_MASK) !=
1650 (portp->flags & ~ASYNC_USR_MASK)))
Alan Cox4ac43602006-06-28 04:26:52 -07001651 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 }
1653
1654 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1655 (sio.flags & ASYNC_USR_MASK);
1656 portp->baud_base = sio.baud_base;
1657 portp->close_delay = sio.close_delay;
1658 portp->closing_wait = sio.closing_wait;
1659 portp->custom_divisor = sio.custom_divisor;
1660
1661 if ((rc = stli_setport(portp)) < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07001662 return rc;
1663 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664}
1665
1666/*****************************************************************************/
1667
1668static int stli_tiocmget(struct tty_struct *tty, struct file *file)
1669{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001670 struct stliport *portp = tty->driver_data;
1671 struct stlibrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 int rc;
1673
Alan Cox4ac43602006-06-28 04:26:52 -07001674 if (portp == NULL)
1675 return -ENODEV;
Jiri Slaby1328d732006-12-08 02:39:19 -08001676 if (portp->brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07001677 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001679 if (brdp == NULL)
1680 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 if (tty->flags & (1 << TTY_IO_ERROR))
Alan Cox4ac43602006-06-28 04:26:52 -07001682 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
1684 if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
1685 &portp->asig, sizeof(asysigs_t), 1)) < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07001686 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
1688 return stli_mktiocm(portp->asig.sigvalue);
1689}
1690
1691static int stli_tiocmset(struct tty_struct *tty, struct file *file,
1692 unsigned int set, unsigned int clear)
1693{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001694 struct stliport *portp = tty->driver_data;
1695 struct stlibrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 int rts = -1, dtr = -1;
1697
Alan Cox4ac43602006-06-28 04:26:52 -07001698 if (portp == NULL)
1699 return -ENODEV;
Jiri Slaby1328d732006-12-08 02:39:19 -08001700 if (portp->brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07001701 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001703 if (brdp == NULL)
1704 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 if (tty->flags & (1 << TTY_IO_ERROR))
Alan Cox4ac43602006-06-28 04:26:52 -07001706 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
1708 if (set & TIOCM_RTS)
1709 rts = 1;
1710 if (set & TIOCM_DTR)
1711 dtr = 1;
1712 if (clear & TIOCM_RTS)
1713 rts = 0;
1714 if (clear & TIOCM_DTR)
1715 dtr = 0;
1716
1717 stli_mkasysigs(&portp->asig, dtr, rts);
1718
1719 return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
1720 sizeof(asysigs_t), 0);
1721}
1722
1723static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1724{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001725 struct stliport *portp;
1726 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07001727 unsigned int ival;
1728 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 void __user *argp = (void __user *)arg;
1730
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001732 if (portp == NULL)
1733 return -ENODEV;
Jiri Slaby1328d732006-12-08 02:39:19 -08001734 if (portp->brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07001735 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001737 if (brdp == NULL)
1738 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
1740 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1741 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1742 if (tty->flags & (1 << TTY_IO_ERROR))
Alan Cox4ac43602006-06-28 04:26:52 -07001743 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 }
1745
1746 rc = 0;
1747
1748 switch (cmd) {
1749 case TIOCGSOFTCAR:
1750 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1751 (unsigned __user *) arg);
1752 break;
1753 case TIOCSSOFTCAR:
1754 if ((rc = get_user(ival, (unsigned __user *) arg)) == 0)
1755 tty->termios->c_cflag =
1756 (tty->termios->c_cflag & ~CLOCAL) |
1757 (ival ? CLOCAL : 0);
1758 break;
1759 case TIOCGSERIAL:
1760 rc = stli_getserial(portp, argp);
1761 break;
1762 case TIOCSSERIAL:
1763 rc = stli_setserial(portp, argp);
1764 break;
1765 case STL_GETPFLAG:
1766 rc = put_user(portp->pflag, (unsigned __user *)argp);
1767 break;
1768 case STL_SETPFLAG:
1769 if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0)
1770 stli_setport(portp);
1771 break;
1772 case COM_GETPORTSTATS:
1773 rc = stli_getportstats(portp, argp);
1774 break;
1775 case COM_CLRPORTSTATS:
1776 rc = stli_clrportstats(portp, argp);
1777 break;
1778 case TIOCSERCONFIG:
1779 case TIOCSERGWILD:
1780 case TIOCSERSWILD:
1781 case TIOCSERGETLSR:
1782 case TIOCSERGSTRUCT:
1783 case TIOCSERGETMULTI:
1784 case TIOCSERSETMULTI:
1785 default:
1786 rc = -ENOIOCTLCMD;
1787 break;
1788 }
1789
Alan Cox4ac43602006-06-28 04:26:52 -07001790 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791}
1792
1793/*****************************************************************************/
1794
1795/*
1796 * This routine assumes that we have user context and can sleep.
1797 * Looks like it is true for the current ttys implementation..!!
1798 */
1799
Alan Cox606d0992006-12-08 02:38:45 -08001800static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001802 struct stliport *portp;
1803 struct stlibrd *brdp;
Alan Cox606d0992006-12-08 02:38:45 -08001804 struct ktermios *tiosp;
Alan Cox4ac43602006-06-28 04:26:52 -07001805 asyport_t aport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806
Alan Cox4ac43602006-06-28 04:26:52 -07001807 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 return;
1809 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001810 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 return;
Jiri Slaby1328d732006-12-08 02:39:19 -08001812 if (portp->brdnr >= stli_nrbrds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 return;
1814 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001815 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 return;
1817
1818 tiosp = tty->termios;
1819 if ((tiosp->c_cflag == old->c_cflag) &&
1820 (tiosp->c_iflag == old->c_iflag))
1821 return;
1822
1823 stli_mkasyport(portp, &aport, tiosp);
1824 stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
1825 stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1);
1826 stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
1827 sizeof(asysigs_t), 0);
1828 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0))
1829 tty->hw_stopped = 0;
1830 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1831 wake_up_interruptible(&portp->open_wait);
1832}
1833
1834/*****************************************************************************/
1835
1836/*
1837 * Attempt to flow control who ever is sending us data. We won't really
1838 * do any flow control action here. We can't directly, and even if we
1839 * wanted to we would have to send a command to the slave. The slave
1840 * knows how to flow control, and will do so when its buffers reach its
1841 * internal high water marks. So what we will do is set a local state
1842 * bit that will stop us sending any RX data up from the poll routine
1843 * (which is the place where RX data from the slave is handled).
1844 */
1845
1846static void stli_throttle(struct tty_struct *tty)
1847{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001848 struct stliport *portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001849 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 set_bit(ST_RXSTOP, &portp->state);
1852}
1853
1854/*****************************************************************************/
1855
1856/*
1857 * Unflow control the device sending us data... That means that all
1858 * we have to do is clear the RXSTOP state bit. The next poll call
1859 * will then be able to pass the RX data back up.
1860 */
1861
1862static void stli_unthrottle(struct tty_struct *tty)
1863{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001864 struct stliport *portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001865 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 clear_bit(ST_RXSTOP, &portp->state);
1868}
1869
1870/*****************************************************************************/
1871
1872/*
Alan Cox4ac43602006-06-28 04:26:52 -07001873 * Stop the transmitter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 */
1875
1876static void stli_stop(struct tty_struct *tty)
1877{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878}
1879
1880/*****************************************************************************/
1881
1882/*
Alan Cox4ac43602006-06-28 04:26:52 -07001883 * Start the transmitter again.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 */
1885
1886static void stli_start(struct tty_struct *tty)
1887{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888}
1889
1890/*****************************************************************************/
1891
1892/*
1893 * Scheduler called hang up routine. This is called from the scheduler,
1894 * not direct from the driver "poll" routine. We can't call it there
1895 * since the real local hangup code will enable/disable the board and
1896 * other things that we can't do while handling the poll. Much easier
1897 * to deal with it some time later (don't really care when, hangups
1898 * aren't that time critical).
1899 */
1900
Al Viro3e577a82006-12-06 18:41:45 +00001901static void stli_dohangup(struct work_struct *ugly_api)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001903 struct stliport *portp = container_of(ugly_api, struct stliport, tqhangup);
Alan Cox4ac43602006-06-28 04:26:52 -07001904 if (portp->tty != NULL) {
1905 tty_hangup(portp->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 }
1907}
1908
1909/*****************************************************************************/
1910
1911/*
1912 * Hangup this port. This is pretty much like closing the port, only
1913 * a little more brutal. No waiting for data to drain. Shutdown the
1914 * port and maybe drop signals. This is rather tricky really. We want
1915 * to close the port as well.
1916 */
1917
1918static void stli_hangup(struct tty_struct *tty)
1919{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001920 struct stliport *portp;
1921 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07001922 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001925 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 return;
Jiri Slaby1328d732006-12-08 02:39:19 -08001927 if (portp->brdnr >= stli_nrbrds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 return;
1929 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001930 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 return;
1932
1933 portp->flags &= ~ASYNC_INITIALIZED;
1934
Alan Cox4ac43602006-06-28 04:26:52 -07001935 if (!test_bit(ST_CLOSING, &portp->state))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 stli_rawclose(brdp, portp, 0, 0);
Alan Cox4ac43602006-06-28 04:26:52 -07001937
1938 spin_lock_irqsave(&stli_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 if (tty->termios->c_cflag & HUPCL) {
1940 stli_mkasysigs(&portp->asig, 0, 0);
1941 if (test_bit(ST_CMDING, &portp->state)) {
1942 set_bit(ST_DOSIGS, &portp->state);
1943 set_bit(ST_DOFLUSHTX, &portp->state);
1944 set_bit(ST_DOFLUSHRX, &portp->state);
1945 } else {
1946 stli_sendcmd(brdp, portp, A_SETSIGNALSF,
1947 &portp->asig, sizeof(asysigs_t), 0);
1948 }
1949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
1951 clear_bit(ST_TXBUSY, &portp->state);
1952 clear_bit(ST_RXSTOP, &portp->state);
1953 set_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox4ac43602006-06-28 04:26:52 -07001954 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1956 portp->refcount = 0;
Alan Cox4ac43602006-06-28 04:26:52 -07001957 spin_unlock_irqrestore(&stli_lock, flags);
1958
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 wake_up_interruptible(&portp->open_wait);
1960}
1961
1962/*****************************************************************************/
1963
1964/*
1965 * Flush characters from the lower buffer. We may not have user context
1966 * so we cannot sleep waiting for it to complete. Also we need to check
1967 * if there is chars for this port in the TX cook buffer, and flush them
1968 * as well.
1969 */
1970
1971static void stli_flushbuffer(struct tty_struct *tty)
1972{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08001973 struct stliport *portp;
1974 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07001975 unsigned long ftype, flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07001978 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 return;
Jiri Slaby1328d732006-12-08 02:39:19 -08001980 if (portp->brdnr >= stli_nrbrds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 return;
1982 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07001983 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 return;
1985
Alan Cox4ac43602006-06-28 04:26:52 -07001986 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 if (tty == stli_txcooktty) {
Alan Cox4ac43602006-06-28 04:26:52 -07001988 stli_txcooktty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 stli_txcooksize = 0;
1990 stli_txcookrealsize = 0;
1991 }
1992 if (test_bit(ST_CMDING, &portp->state)) {
1993 set_bit(ST_DOFLUSHTX, &portp->state);
1994 } else {
1995 ftype = FLUSHTX;
1996 if (test_bit(ST_DOFLUSHRX, &portp->state)) {
1997 ftype |= FLUSHRX;
1998 clear_bit(ST_DOFLUSHRX, &portp->state);
1999 }
Alan Cox4ac43602006-06-28 04:26:52 -07002000 __stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 }
Alan Cox4ac43602006-06-28 04:26:52 -07002002 spin_unlock_irqrestore(&brd_lock, flags);
2003 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004}
2005
2006/*****************************************************************************/
2007
2008static void stli_breakctl(struct tty_struct *tty, int state)
2009{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002010 struct stlibrd *brdp;
2011 struct stliport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 long arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07002015 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 return;
Jiri Slaby1328d732006-12-08 02:39:19 -08002017 if (portp->brdnr >= stli_nrbrds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 return;
2019 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07002020 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 return;
2022
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 arg = (state == -1) ? BREAKON : BREAKOFF;
2024 stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025}
2026
2027/*****************************************************************************/
2028
2029static void stli_waituntilsent(struct tty_struct *tty, int timeout)
2030{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002031 struct stliport *portp;
Alan Cox4ac43602006-06-28 04:26:52 -07002032 unsigned long tend;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
Alan Cox4ac43602006-06-28 04:26:52 -07002034 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 return;
2036 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07002037 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 return;
2039
2040 if (timeout == 0)
2041 timeout = HZ;
2042 tend = jiffies + timeout;
2043
2044 while (test_bit(ST_TXBUSY, &portp->state)) {
2045 if (signal_pending(current))
2046 break;
2047 msleep_interruptible(20);
2048 if (time_after_eq(jiffies, tend))
2049 break;
2050 }
2051}
2052
2053/*****************************************************************************/
2054
2055static void stli_sendxchar(struct tty_struct *tty, char ch)
2056{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002057 struct stlibrd *brdp;
2058 struct stliport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 asyctrl_t actrl;
2060
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 portp = tty->driver_data;
Alan Cox4ac43602006-06-28 04:26:52 -07002062 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 return;
Jiri Slaby1328d732006-12-08 02:39:19 -08002064 if (portp->brdnr >= stli_nrbrds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 return;
2066 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07002067 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 return;
2069
2070 memset(&actrl, 0, sizeof(asyctrl_t));
2071 if (ch == STOP_CHAR(tty)) {
2072 actrl.rxctrl = CT_STOPFLOW;
2073 } else if (ch == START_CHAR(tty)) {
2074 actrl.rxctrl = CT_STARTFLOW;
2075 } else {
2076 actrl.txctrl = CT_SENDCHR;
2077 actrl.tximdch = ch;
2078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);
2080}
2081
2082/*****************************************************************************/
2083
2084#define MAXLINE 80
2085
2086/*
2087 * Format info for a specified port. The line is deliberately limited
2088 * to 80 characters. (If it is too long it will be truncated, if too
2089 * short then padded with spaces).
2090 */
2091
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002092static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093{
Alan Cox4ac43602006-06-28 04:26:52 -07002094 char *sp, *uart;
2095 int rc, cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096
2097 rc = stli_portcmdstats(portp);
2098
2099 uart = "UNKNOWN";
2100 if (brdp->state & BST_STARTED) {
2101 switch (stli_comstats.hwid) {
Alan Cox4ac43602006-06-28 04:26:52 -07002102 case 0: uart = "2681"; break;
2103 case 1: uart = "SC26198"; break;
2104 default:uart = "CD1400"; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 }
2106 }
2107
2108 sp = pos;
2109 sp += sprintf(sp, "%d: uart:%s ", portnr, uart);
2110
2111 if ((brdp->state & BST_STARTED) && (rc >= 0)) {
2112 sp += sprintf(sp, "tx:%d rx:%d", (int) stli_comstats.txtotal,
2113 (int) stli_comstats.rxtotal);
2114
2115 if (stli_comstats.rxframing)
2116 sp += sprintf(sp, " fe:%d",
2117 (int) stli_comstats.rxframing);
2118 if (stli_comstats.rxparity)
2119 sp += sprintf(sp, " pe:%d",
2120 (int) stli_comstats.rxparity);
2121 if (stli_comstats.rxbreaks)
2122 sp += sprintf(sp, " brk:%d",
2123 (int) stli_comstats.rxbreaks);
2124 if (stli_comstats.rxoverrun)
2125 sp += sprintf(sp, " oe:%d",
2126 (int) stli_comstats.rxoverrun);
2127
2128 cnt = sprintf(sp, "%s%s%s%s%s ",
2129 (stli_comstats.signals & TIOCM_RTS) ? "|RTS" : "",
2130 (stli_comstats.signals & TIOCM_CTS) ? "|CTS" : "",
2131 (stli_comstats.signals & TIOCM_DTR) ? "|DTR" : "",
2132 (stli_comstats.signals & TIOCM_CD) ? "|DCD" : "",
2133 (stli_comstats.signals & TIOCM_DSR) ? "|DSR" : "");
2134 *sp = ' ';
2135 sp += cnt;
2136 }
2137
2138 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
2139 *sp++ = ' ';
2140 if (cnt >= MAXLINE)
2141 pos[(MAXLINE - 2)] = '+';
2142 pos[(MAXLINE - 1)] = '\n';
2143
2144 return(MAXLINE);
2145}
2146
2147/*****************************************************************************/
2148
2149/*
2150 * Port info, read from the /proc file system.
2151 */
2152
2153static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
2154{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002155 struct stlibrd *brdp;
2156 struct stliport *portp;
Jiri Slaby1328d732006-12-08 02:39:19 -08002157 unsigned int brdnr, portnr, totalport;
Alan Cox4ac43602006-06-28 04:26:52 -07002158 int curoff, maxoff;
2159 char *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
2161 pos = page;
2162 totalport = 0;
2163 curoff = 0;
2164
2165 if (off == 0) {
2166 pos += sprintf(pos, "%s: version %s", stli_drvtitle,
2167 stli_drvversion);
2168 while (pos < (page + MAXLINE - 1))
2169 *pos++ = ' ';
2170 *pos++ = '\n';
2171 }
2172 curoff = MAXLINE;
2173
2174/*
2175 * We scan through for each board, panel and port. The offset is
2176 * calculated on the fly, and irrelevant ports are skipped.
2177 */
2178 for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
2179 brdp = stli_brds[brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07002180 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 continue;
2182 if (brdp->state == 0)
2183 continue;
2184
2185 maxoff = curoff + (brdp->nrports * MAXLINE);
2186 if (off >= maxoff) {
2187 curoff = maxoff;
2188 continue;
2189 }
2190
2191 totalport = brdnr * STL_MAXPORTS;
2192 for (portnr = 0; (portnr < brdp->nrports); portnr++,
2193 totalport++) {
2194 portp = brdp->ports[portnr];
Alan Cox4ac43602006-06-28 04:26:52 -07002195 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 continue;
2197 if (off >= (curoff += MAXLINE))
2198 continue;
2199 if ((pos - page + MAXLINE) > count)
2200 goto stli_readdone;
2201 pos += stli_portinfo(brdp, portp, totalport, pos);
2202 }
2203 }
2204
2205 *eof = 1;
2206
2207stli_readdone:
2208 *start = page;
2209 return(pos - page);
2210}
2211
2212/*****************************************************************************/
2213
2214/*
2215 * Generic send command routine. This will send a message to the slave,
2216 * of the specified type with the specified argument. Must be very
2217 * careful of data that will be copied out from shared memory -
2218 * containing command results. The command completion is all done from
2219 * a poll routine that does not have user context. Therefore you cannot
2220 * copy back directly into user space, or to the kernel stack of a
2221 * process. This routine does not sleep, so can be called from anywhere.
Alan Cox4ac43602006-06-28 04:26:52 -07002222 *
2223 * The caller must hold the brd_lock (see also stli_sendcmd the usual
2224 * entry point)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 */
2226
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002227static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228{
Alan Cox4ac43602006-06-28 04:26:52 -07002229 cdkhdr_t __iomem *hdrp;
2230 cdkctrl_t __iomem *cp;
2231 unsigned char __iomem *bits;
2232 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233
Alan Cox4ac43602006-06-28 04:26:52 -07002234 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235
2236 if (test_bit(ST_CMDING, &portp->state)) {
2237 printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n",
2238 (int) cmd);
Alan Cox4ac43602006-06-28 04:26:52 -07002239 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 return;
2241 }
2242
2243 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07002244 cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 if (size > 0) {
Alan Cox4ac43602006-06-28 04:26:52 -07002246 memcpy_toio((void __iomem *) &(cp->args[0]), arg, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 if (copyback) {
2248 portp->argp = arg;
2249 portp->argsize = size;
2250 }
2251 }
Alan Cox4ac43602006-06-28 04:26:52 -07002252 writel(0, &cp->status);
2253 writel(cmd, &cp->cmd);
2254 hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
2255 bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 portp->portidx;
Alan Cox4ac43602006-06-28 04:26:52 -07002257 writeb(readb(bits) | portp->portbit, bits);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 set_bit(ST_CMDING, &portp->state);
2259 EBRDDISABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07002260 spin_unlock_irqrestore(&brd_lock, flags);
2261}
2262
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002263static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
Alan Cox4ac43602006-06-28 04:26:52 -07002264{
2265 unsigned long flags;
2266
2267 spin_lock_irqsave(&brd_lock, flags);
2268 __stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
2269 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270}
2271
2272/*****************************************************************************/
2273
2274/*
2275 * Read data from shared memory. This assumes that the shared memory
2276 * is enabled and that interrupts are off. Basically we just empty out
2277 * the shared memory buffer into the tty buffer. Must be careful to
2278 * handle the case where we fill up the tty buffer, but still have
2279 * more chars to unload.
2280 */
2281
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002282static void stli_read(struct stlibrd *brdp, struct stliport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283{
Alan Cox4ac43602006-06-28 04:26:52 -07002284 cdkasyrq_t __iomem *rp;
2285 char __iomem *shbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 struct tty_struct *tty;
Alan Cox4ac43602006-06-28 04:26:52 -07002287 unsigned int head, tail, size;
2288 unsigned int len, stlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
2290 if (test_bit(ST_RXSTOP, &portp->state))
2291 return;
2292 tty = portp->tty;
Alan Cox4ac43602006-06-28 04:26:52 -07002293 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 return;
2295
Alan Cox4ac43602006-06-28 04:26:52 -07002296 rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
2297 head = (unsigned int) readw(&rp->head);
2298 if (head != ((unsigned int) readw(&rp->head)))
2299 head = (unsigned int) readw(&rp->head);
2300 tail = (unsigned int) readw(&rp->tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 size = portp->rxsize;
2302 if (head >= tail) {
2303 len = head - tail;
2304 stlen = len;
2305 } else {
2306 len = size - (tail - head);
2307 stlen = size - tail;
2308 }
2309
Alan Cox33f0f882006-01-09 20:54:13 -08002310 len = tty_buffer_request_room(tty, len);
Alan Cox4ac43602006-06-28 04:26:52 -07002311
2312 shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313
2314 while (len > 0) {
Alan Cox4ac43602006-06-28 04:26:52 -07002315 unsigned char *cptr;
2316
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08002317 stlen = min(len, stlen);
Alan Cox4ac43602006-06-28 04:26:52 -07002318 tty_prepare_flip_string(tty, &cptr, stlen);
2319 memcpy_fromio(cptr, shbuf + tail, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 len -= stlen;
2321 tail += stlen;
2322 if (tail >= size) {
2323 tail = 0;
2324 stlen = head;
2325 }
2326 }
Alan Cox4ac43602006-06-28 04:26:52 -07002327 rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
2328 writew(tail, &rp->tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
2330 if (head != tail)
2331 set_bit(ST_RXING, &portp->state);
2332
2333 tty_schedule_flip(tty);
2334}
2335
2336/*****************************************************************************/
2337
2338/*
2339 * Set up and carry out any delayed commands. There is only a small set
2340 * of slave commands that can be done "off-level". So it is not too
2341 * difficult to deal with them here.
2342 */
2343
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002344static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345{
Alan Cox4ac43602006-06-28 04:26:52 -07002346 int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
2348 if (test_bit(ST_DOSIGS, &portp->state)) {
2349 if (test_bit(ST_DOFLUSHTX, &portp->state) &&
2350 test_bit(ST_DOFLUSHRX, &portp->state))
2351 cmd = A_SETSIGNALSF;
2352 else if (test_bit(ST_DOFLUSHTX, &portp->state))
2353 cmd = A_SETSIGNALSFTX;
2354 else if (test_bit(ST_DOFLUSHRX, &portp->state))
2355 cmd = A_SETSIGNALSFRX;
2356 else
2357 cmd = A_SETSIGNALS;
2358 clear_bit(ST_DOFLUSHTX, &portp->state);
2359 clear_bit(ST_DOFLUSHRX, &portp->state);
2360 clear_bit(ST_DOSIGS, &portp->state);
Alan Cox4ac43602006-06-28 04:26:52 -07002361 memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 sizeof(asysigs_t));
Alan Cox4ac43602006-06-28 04:26:52 -07002363 writel(0, &cp->status);
2364 writel(cmd, &cp->cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 set_bit(ST_CMDING, &portp->state);
2366 } else if (test_bit(ST_DOFLUSHTX, &portp->state) ||
2367 test_bit(ST_DOFLUSHRX, &portp->state)) {
2368 cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0);
2369 cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0);
2370 clear_bit(ST_DOFLUSHTX, &portp->state);
2371 clear_bit(ST_DOFLUSHRX, &portp->state);
Alan Cox4ac43602006-06-28 04:26:52 -07002372 memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int));
2373 writel(0, &cp->status);
2374 writel(A_FLUSH, &cp->cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 set_bit(ST_CMDING, &portp->state);
2376 }
2377}
2378
2379/*****************************************************************************/
2380
2381/*
2382 * Host command service checking. This handles commands or messages
2383 * coming from the slave to the host. Must have board shared memory
2384 * enabled and interrupts off when called. Notice that by servicing the
2385 * read data last we don't need to change the shared memory pointer
2386 * during processing (which is a slow IO operation).
2387 * Return value indicates if this port is still awaiting actions from
2388 * the slave (like open, command, or even TX data being sent). If 0
2389 * then port is still busy, otherwise no longer busy.
2390 */
2391
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002392static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393{
Alan Cox4ac43602006-06-28 04:26:52 -07002394 cdkasy_t __iomem *ap;
2395 cdkctrl_t __iomem *cp;
2396 struct tty_struct *tty;
2397 asynotify_t nt;
2398 unsigned long oldsigs;
2399 int rc, donerx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400
Alan Cox4ac43602006-06-28 04:26:52 -07002401 ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 cp = &ap->ctrl;
2403
2404/*
2405 * Check if we are waiting for an open completion message.
2406 */
2407 if (test_bit(ST_OPENING, &portp->state)) {
Alan Cox4ac43602006-06-28 04:26:52 -07002408 rc = readl(&cp->openarg);
2409 if (readb(&cp->open) == 0 && rc != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 if (rc > 0)
2411 rc--;
Alan Cox4ac43602006-06-28 04:26:52 -07002412 writel(0, &cp->openarg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 portp->rc = rc;
2414 clear_bit(ST_OPENING, &portp->state);
2415 wake_up_interruptible(&portp->raw_wait);
2416 }
2417 }
2418
2419/*
2420 * Check if we are waiting for a close completion message.
2421 */
2422 if (test_bit(ST_CLOSING, &portp->state)) {
Alan Cox4ac43602006-06-28 04:26:52 -07002423 rc = (int) readl(&cp->closearg);
2424 if (readb(&cp->close) == 0 && rc != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 if (rc > 0)
2426 rc--;
Alan Cox4ac43602006-06-28 04:26:52 -07002427 writel(0, &cp->closearg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 portp->rc = rc;
2429 clear_bit(ST_CLOSING, &portp->state);
2430 wake_up_interruptible(&portp->raw_wait);
2431 }
2432 }
2433
2434/*
2435 * Check if we are waiting for a command completion message. We may
2436 * need to copy out the command results associated with this command.
2437 */
2438 if (test_bit(ST_CMDING, &portp->state)) {
Alan Cox4ac43602006-06-28 04:26:52 -07002439 rc = readl(&cp->status);
2440 if (readl(&cp->cmd) == 0 && rc != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 if (rc > 0)
2442 rc--;
Alan Cox4ac43602006-06-28 04:26:52 -07002443 if (portp->argp != NULL) {
2444 memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 portp->argsize);
Alan Cox4ac43602006-06-28 04:26:52 -07002446 portp->argp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 }
Alan Cox4ac43602006-06-28 04:26:52 -07002448 writel(0, &cp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 portp->rc = rc;
2450 clear_bit(ST_CMDING, &portp->state);
2451 stli_dodelaycmd(portp, cp);
2452 wake_up_interruptible(&portp->raw_wait);
2453 }
2454 }
2455
2456/*
2457 * Check for any notification messages ready. This includes lots of
2458 * different types of events - RX chars ready, RX break received,
2459 * TX data low or empty in the slave, modem signals changed state.
2460 */
2461 donerx = 0;
2462
2463 if (ap->notify) {
2464 nt = ap->changed;
2465 ap->notify = 0;
2466 tty = portp->tty;
2467
2468 if (nt.signal & SG_DCD) {
2469 oldsigs = portp->sigs;
2470 portp->sigs = stli_mktiocm(nt.sigvalue);
2471 clear_bit(ST_GETSIGS, &portp->state);
2472 if ((portp->sigs & TIOCM_CD) &&
2473 ((oldsigs & TIOCM_CD) == 0))
2474 wake_up_interruptible(&portp->open_wait);
2475 if ((oldsigs & TIOCM_CD) &&
2476 ((portp->sigs & TIOCM_CD) == 0)) {
2477 if (portp->flags & ASYNC_CHECK_CD) {
2478 if (tty)
2479 schedule_work(&portp->tqhangup);
2480 }
2481 }
2482 }
2483
2484 if (nt.data & DT_TXEMPTY)
2485 clear_bit(ST_TXBUSY, &portp->state);
2486 if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
Alan Cox4ac43602006-06-28 04:26:52 -07002487 if (tty != NULL) {
2488 tty_wakeup(tty);
2489 EBRDENABLE(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 wake_up_interruptible(&tty->write_wait);
2491 }
2492 }
2493
2494 if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
Alan Cox4ac43602006-06-28 04:26:52 -07002495 if (tty != NULL) {
Alan Cox33f0f882006-01-09 20:54:13 -08002496 tty_insert_flip_char(tty, 0, TTY_BREAK);
2497 if (portp->flags & ASYNC_SAK) {
2498 do_SAK(tty);
2499 EBRDENABLE(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 }
Alan Cox33f0f882006-01-09 20:54:13 -08002501 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 }
2503 }
2504
2505 if (nt.data & DT_RXBUSY) {
2506 donerx++;
2507 stli_read(brdp, portp);
2508 }
2509 }
2510
2511/*
2512 * It might seem odd that we are checking for more RX chars here.
2513 * But, we need to handle the case where the tty buffer was previously
2514 * filled, but we had more characters to pass up. The slave will not
2515 * send any more RX notify messages until the RX buffer has been emptied.
2516 * But it will leave the service bits on (since the buffer is not empty).
2517 * So from here we can try to process more RX chars.
2518 */
2519 if ((!donerx) && test_bit(ST_RXING, &portp->state)) {
2520 clear_bit(ST_RXING, &portp->state);
2521 stli_read(brdp, portp);
2522 }
2523
2524 return((test_bit(ST_OPENING, &portp->state) ||
2525 test_bit(ST_CLOSING, &portp->state) ||
2526 test_bit(ST_CMDING, &portp->state) ||
2527 test_bit(ST_TXBUSY, &portp->state) ||
2528 test_bit(ST_RXING, &portp->state)) ? 0 : 1);
2529}
2530
2531/*****************************************************************************/
2532
2533/*
2534 * Service all ports on a particular board. Assumes that the boards
2535 * shared memory is enabled, and that the page pointer is pointed
2536 * at the cdk header structure.
2537 */
2538
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002539static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002541 struct stliport *portp;
Alan Cox4ac43602006-06-28 04:26:52 -07002542 unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
2543 unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
2544 unsigned char __iomem *slavep;
2545 int bitpos, bitat, bitsize;
2546 int channr, nrdevs, slavebitchange;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
2548 bitsize = brdp->bitsize;
2549 nrdevs = brdp->nrdevs;
2550
2551/*
2552 * Check if slave wants any service. Basically we try to do as
2553 * little work as possible here. There are 2 levels of service
2554 * bits. So if there is nothing to do we bail early. We check
2555 * 8 service bits at a time in the inner loop, so we can bypass
2556 * the lot if none of them want service.
2557 */
Alan Cox4ac43602006-06-28 04:26:52 -07002558 memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 bitsize);
2560
2561 memset(&slavebits[0], 0, bitsize);
2562 slavebitchange = 0;
2563
2564 for (bitpos = 0; (bitpos < bitsize); bitpos++) {
2565 if (hostbits[bitpos] == 0)
2566 continue;
2567 channr = bitpos * 8;
2568 for (bitat = 0x1; (channr < nrdevs); channr++, bitat <<= 1) {
2569 if (hostbits[bitpos] & bitat) {
2570 portp = brdp->ports[(channr - 1)];
2571 if (stli_hostcmd(brdp, portp)) {
2572 slavebitchange++;
2573 slavebits[bitpos] |= bitat;
2574 }
2575 }
2576 }
2577 }
2578
2579/*
2580 * If any of the ports are no longer busy then update them in the
2581 * slave request bits. We need to do this after, since a host port
2582 * service may initiate more slave requests.
2583 */
2584 if (slavebitchange) {
Alan Cox4ac43602006-06-28 04:26:52 -07002585 hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
2586 slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 for (bitpos = 0; (bitpos < bitsize); bitpos++) {
Alan Cox4ac43602006-06-28 04:26:52 -07002588 if (readb(slavebits + bitpos))
2589 writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 }
2591 }
2592}
2593
2594/*****************************************************************************/
2595
2596/*
2597 * Driver poll routine. This routine polls the boards in use and passes
2598 * messages back up to host when necessary. This is actually very
2599 * CPU efficient, since we will always have the kernel poll clock, it
2600 * adds only a few cycles when idle (since board service can be
2601 * determined very easily), but when loaded generates no interrupts
2602 * (with their expensive associated context change).
2603 */
2604
2605static void stli_poll(unsigned long arg)
2606{
Alan Cox4ac43602006-06-28 04:26:52 -07002607 cdkhdr_t __iomem *hdrp;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002608 struct stlibrd *brdp;
Jiri Slaby1328d732006-12-08 02:39:19 -08002609 unsigned int brdnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
2611 stli_timerlist.expires = STLI_TIMEOUT;
2612 add_timer(&stli_timerlist);
2613
2614/*
2615 * Check each board and do any servicing required.
2616 */
2617 for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
2618 brdp = stli_brds[brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07002619 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 continue;
2621 if ((brdp->state & BST_STARTED) == 0)
2622 continue;
2623
Alan Cox4ac43602006-06-28 04:26:52 -07002624 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07002626 hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
2627 if (readb(&hdrp->hostreq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 stli_brdpoll(brdp, hdrp);
2629 EBRDDISABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07002630 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 }
2632}
2633
2634/*****************************************************************************/
2635
2636/*
2637 * Translate the termios settings into the port setting structure of
2638 * the slave.
2639 */
2640
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002641static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 memset(pp, 0, sizeof(asyport_t));
2644
2645/*
2646 * Start of by setting the baud, char size, parity and stop bit info.
2647 */
Alan Cox1db27c12006-09-29 02:01:38 -07002648 pp->baudout = tty_get_baud_rate(portp->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 if ((tiosp->c_cflag & CBAUD) == B38400) {
2650 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2651 pp->baudout = 57600;
2652 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2653 pp->baudout = 115200;
2654 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2655 pp->baudout = 230400;
2656 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2657 pp->baudout = 460800;
2658 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
2659 pp->baudout = (portp->baud_base / portp->custom_divisor);
2660 }
2661 if (pp->baudout > STL_MAXBAUD)
2662 pp->baudout = STL_MAXBAUD;
2663 pp->baudin = pp->baudout;
2664
2665 switch (tiosp->c_cflag & CSIZE) {
2666 case CS5:
2667 pp->csize = 5;
2668 break;
2669 case CS6:
2670 pp->csize = 6;
2671 break;
2672 case CS7:
2673 pp->csize = 7;
2674 break;
2675 default:
2676 pp->csize = 8;
2677 break;
2678 }
2679
2680 if (tiosp->c_cflag & CSTOPB)
2681 pp->stopbs = PT_STOP2;
2682 else
2683 pp->stopbs = PT_STOP1;
2684
2685 if (tiosp->c_cflag & PARENB) {
2686 if (tiosp->c_cflag & PARODD)
2687 pp->parity = PT_ODDPARITY;
2688 else
2689 pp->parity = PT_EVENPARITY;
2690 } else {
2691 pp->parity = PT_NOPARITY;
2692 }
2693
2694/*
2695 * Set up any flow control options enabled.
2696 */
2697 if (tiosp->c_iflag & IXON) {
2698 pp->flow |= F_IXON;
2699 if (tiosp->c_iflag & IXANY)
2700 pp->flow |= F_IXANY;
2701 }
2702 if (tiosp->c_cflag & CRTSCTS)
2703 pp->flow |= (F_RTSFLOW | F_CTSFLOW);
2704
2705 pp->startin = tiosp->c_cc[VSTART];
2706 pp->stopin = tiosp->c_cc[VSTOP];
2707 pp->startout = tiosp->c_cc[VSTART];
2708 pp->stopout = tiosp->c_cc[VSTOP];
2709
2710/*
2711 * Set up the RX char marking mask with those RX error types we must
2712 * catch. We can get the slave to help us out a little here, it will
2713 * ignore parity errors and breaks for us, and mark parity errors in
2714 * the data stream.
2715 */
2716 if (tiosp->c_iflag & IGNPAR)
2717 pp->iflag |= FI_IGNRXERRS;
2718 if (tiosp->c_iflag & IGNBRK)
2719 pp->iflag |= FI_IGNBREAK;
2720
2721 portp->rxmarkmsk = 0;
2722 if (tiosp->c_iflag & (INPCK | PARMRK))
2723 pp->iflag |= FI_1MARKRXERRS;
2724 if (tiosp->c_iflag & BRKINT)
2725 portp->rxmarkmsk |= BRKINT;
2726
2727/*
2728 * Set up clocal processing as required.
2729 */
2730 if (tiosp->c_cflag & CLOCAL)
2731 portp->flags &= ~ASYNC_CHECK_CD;
2732 else
2733 portp->flags |= ASYNC_CHECK_CD;
2734
2735/*
2736 * Transfer any persistent flags into the asyport structure.
2737 */
2738 pp->pflag = (portp->pflag & 0xffff);
2739 pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0;
2740 pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0;
2741 pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0;
2742}
2743
2744/*****************************************************************************/
2745
2746/*
2747 * Construct a slave signals structure for setting the DTR and RTS
2748 * signals as specified.
2749 */
2750
2751static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
2752{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 memset(sp, 0, sizeof(asysigs_t));
2754 if (dtr >= 0) {
2755 sp->signal |= SG_DTR;
2756 sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0);
2757 }
2758 if (rts >= 0) {
2759 sp->signal |= SG_RTS;
2760 sp->sigvalue |= ((rts > 0) ? SG_RTS : 0);
2761 }
2762}
2763
2764/*****************************************************************************/
2765
2766/*
2767 * Convert the signals returned from the slave into a local TIOCM type
2768 * signals value. We keep them locally in TIOCM format.
2769 */
2770
2771static long stli_mktiocm(unsigned long sigvalue)
2772{
Alan Cox4ac43602006-06-28 04:26:52 -07002773 long tiocm = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
2775 tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
2776 tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
2777 tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0);
2778 tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0);
2779 tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0);
2780 return(tiocm);
2781}
2782
2783/*****************************************************************************/
2784
2785/*
2786 * All panels and ports actually attached have been worked out. All
2787 * we need to do here is set up the appropriate per port data structures.
2788 */
2789
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002790static int stli_initports(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002792 struct stliport *portp;
Jiri Slaby1328d732006-12-08 02:39:19 -08002793 unsigned int i, panelnr, panelport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002796 portp = kzalloc(sizeof(struct stliport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002797 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 printk("STALLION: failed to allocate port structure\n");
2799 continue;
2800 }
2801
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 portp->magic = STLI_PORTMAGIC;
2803 portp->portnr = i;
2804 portp->brdnr = brdp->brdnr;
2805 portp->panelnr = panelnr;
2806 portp->baud_base = STL_BAUDBASE;
2807 portp->close_delay = STL_CLOSEDELAY;
2808 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00002809 INIT_WORK(&portp->tqhangup, stli_dohangup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 init_waitqueue_head(&portp->open_wait);
2811 init_waitqueue_head(&portp->close_wait);
2812 init_waitqueue_head(&portp->raw_wait);
2813 panelport++;
2814 if (panelport >= brdp->panels[panelnr]) {
2815 panelport = 0;
2816 panelnr++;
2817 }
2818 brdp->ports[i] = portp;
2819 }
2820
Alan Cox4ac43602006-06-28 04:26:52 -07002821 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822}
2823
2824/*****************************************************************************/
2825
2826/*
2827 * All the following routines are board specific hardware operations.
2828 */
2829
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002830static void stli_ecpinit(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831{
2832 unsigned long memconf;
2833
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
2835 udelay(10);
2836 outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
2837 udelay(100);
2838
2839 memconf = (brdp->memaddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT;
2840 outb(memconf, (brdp->iobase + ECP_ATMEMAR));
2841}
2842
2843/*****************************************************************************/
2844
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002845static void stli_ecpenable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
2848}
2849
2850/*****************************************************************************/
2851
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002852static void stli_ecpdisable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
2855}
2856
2857/*****************************************************************************/
2858
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002859static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860{
Al Viro29756fa2006-10-10 22:47:27 +01002861 void __iomem *ptr;
Alan Cox4ac43602006-06-28 04:26:52 -07002862 unsigned char val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863
2864 if (offset > brdp->memsize) {
2865 printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
2866 "range at line=%d(%d), brd=%d\n",
2867 (int) offset, line, __LINE__, brdp->brdnr);
2868 ptr = NULL;
2869 val = 0;
2870 } else {
2871 ptr = brdp->membase + (offset % ECP_ATPAGESIZE);
2872 val = (unsigned char) (offset / ECP_ATPAGESIZE);
2873 }
2874 outb(val, (brdp->iobase + ECP_ATMEMPR));
2875 return(ptr);
2876}
2877
2878/*****************************************************************************/
2879
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002880static void stli_ecpreset(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882 outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
2883 udelay(10);
2884 outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
2885 udelay(500);
2886}
2887
2888/*****************************************************************************/
2889
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002890static void stli_ecpintr(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 outb(0x1, brdp->iobase);
2893}
2894
2895/*****************************************************************************/
2896
2897/*
2898 * The following set of functions act on ECP EISA boards.
2899 */
2900
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002901static void stli_ecpeiinit(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902{
2903 unsigned long memconf;
2904
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
2906 outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
2907 udelay(10);
2908 outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
2909 udelay(500);
2910
2911 memconf = (brdp->memaddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL;
2912 outb(memconf, (brdp->iobase + ECP_EIMEMARL));
2913 memconf = (brdp->memaddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH;
2914 outb(memconf, (brdp->iobase + ECP_EIMEMARH));
2915}
2916
2917/*****************************************************************************/
2918
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002919static void stli_ecpeienable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920{
2921 outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR));
2922}
2923
2924/*****************************************************************************/
2925
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002926static void stli_ecpeidisable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927{
2928 outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
2929}
2930
2931/*****************************************************************************/
2932
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002933static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934{
Al Viro29756fa2006-10-10 22:47:27 +01002935 void __iomem *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 unsigned char val;
2937
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 if (offset > brdp->memsize) {
2939 printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
2940 "range at line=%d(%d), brd=%d\n",
2941 (int) offset, line, __LINE__, brdp->brdnr);
2942 ptr = NULL;
2943 val = 0;
2944 } else {
2945 ptr = brdp->membase + (offset % ECP_EIPAGESIZE);
2946 if (offset < ECP_EIPAGESIZE)
2947 val = ECP_EIENABLE;
2948 else
2949 val = ECP_EIENABLE | 0x40;
2950 }
2951 outb(val, (brdp->iobase + ECP_EICONFR));
2952 return(ptr);
2953}
2954
2955/*****************************************************************************/
2956
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002957static void stli_ecpeireset(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958{
2959 outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
2960 udelay(10);
2961 outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
2962 udelay(500);
2963}
2964
2965/*****************************************************************************/
2966
2967/*
2968 * The following set of functions act on ECP MCA boards.
2969 */
2970
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002971static void stli_ecpmcenable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972{
2973 outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR));
2974}
2975
2976/*****************************************************************************/
2977
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002978static void stli_ecpmcdisable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979{
2980 outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
2981}
2982
2983/*****************************************************************************/
2984
Jiri Slaby1f8ec432006-12-08 02:39:18 -08002985static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986{
Al Viro29756fa2006-10-10 22:47:27 +01002987 void __iomem *ptr;
Alan Cox4ac43602006-06-28 04:26:52 -07002988 unsigned char val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
2990 if (offset > brdp->memsize) {
2991 printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
2992 "range at line=%d(%d), brd=%d\n",
2993 (int) offset, line, __LINE__, brdp->brdnr);
2994 ptr = NULL;
2995 val = 0;
2996 } else {
2997 ptr = brdp->membase + (offset % ECP_MCPAGESIZE);
2998 val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE;
2999 }
3000 outb(val, (brdp->iobase + ECP_MCCONFR));
3001 return(ptr);
3002}
3003
3004/*****************************************************************************/
3005
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003006static void stli_ecpmcreset(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007{
3008 outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR));
3009 udelay(10);
3010 outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
3011 udelay(500);
3012}
3013
3014/*****************************************************************************/
3015
3016/*
3017 * The following set of functions act on ECP PCI boards.
3018 */
3019
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003020static void stli_ecppciinit(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
3023 udelay(10);
3024 outb(0, (brdp->iobase + ECP_PCICONFR));
3025 udelay(500);
3026}
3027
3028/*****************************************************************************/
3029
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003030static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031{
Al Viro29756fa2006-10-10 22:47:27 +01003032 void __iomem *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 unsigned char val;
3034
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 if (offset > brdp->memsize) {
3036 printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
3037 "range at line=%d(%d), board=%d\n",
3038 (int) offset, line, __LINE__, brdp->brdnr);
3039 ptr = NULL;
3040 val = 0;
3041 } else {
3042 ptr = brdp->membase + (offset % ECP_PCIPAGESIZE);
3043 val = (offset / ECP_PCIPAGESIZE) << 1;
3044 }
3045 outb(val, (brdp->iobase + ECP_PCICONFR));
3046 return(ptr);
3047}
3048
3049/*****************************************************************************/
3050
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003051static void stli_ecppcireset(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052{
3053 outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
3054 udelay(10);
3055 outb(0, (brdp->iobase + ECP_PCICONFR));
3056 udelay(500);
3057}
3058
3059/*****************************************************************************/
3060
3061/*
3062 * The following routines act on ONboards.
3063 */
3064
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003065static void stli_onbinit(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066{
3067 unsigned long memconf;
3068
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
3070 udelay(10);
3071 outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
3072 mdelay(1000);
3073
3074 memconf = (brdp->memaddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT;
3075 outb(memconf, (brdp->iobase + ONB_ATMEMAR));
3076 outb(0x1, brdp->iobase);
3077 mdelay(1);
3078}
3079
3080/*****************************************************************************/
3081
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003082static void stli_onbenable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084 outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
3085}
3086
3087/*****************************************************************************/
3088
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003089static void stli_onbdisable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
3092}
3093
3094/*****************************************************************************/
3095
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003096static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097{
Al Viro29756fa2006-10-10 22:47:27 +01003098 void __iomem *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 if (offset > brdp->memsize) {
3101 printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
3102 "range at line=%d(%d), brd=%d\n",
3103 (int) offset, line, __LINE__, brdp->brdnr);
3104 ptr = NULL;
3105 } else {
3106 ptr = brdp->membase + (offset % ONB_ATPAGESIZE);
3107 }
3108 return(ptr);
3109}
3110
3111/*****************************************************************************/
3112
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003113static void stli_onbreset(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115 outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
3116 udelay(10);
3117 outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
3118 mdelay(1000);
3119}
3120
3121/*****************************************************************************/
3122
3123/*
3124 * The following routines act on ONboard EISA.
3125 */
3126
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003127static void stli_onbeinit(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128{
3129 unsigned long memconf;
3130
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
3132 outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
3133 udelay(10);
3134 outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
3135 mdelay(1000);
3136
3137 memconf = (brdp->memaddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL;
3138 outb(memconf, (brdp->iobase + ONB_EIMEMARL));
3139 memconf = (brdp->memaddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH;
3140 outb(memconf, (brdp->iobase + ONB_EIMEMARH));
3141 outb(0x1, brdp->iobase);
3142 mdelay(1);
3143}
3144
3145/*****************************************************************************/
3146
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003147static void stli_onbeenable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
3150}
3151
3152/*****************************************************************************/
3153
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003154static void stli_onbedisable(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
3157}
3158
3159/*****************************************************************************/
3160
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003161static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162{
Al Viro29756fa2006-10-10 22:47:27 +01003163 void __iomem *ptr;
Alan Cox4ac43602006-06-28 04:26:52 -07003164 unsigned char val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165
3166 if (offset > brdp->memsize) {
3167 printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
3168 "range at line=%d(%d), brd=%d\n",
3169 (int) offset, line, __LINE__, brdp->brdnr);
3170 ptr = NULL;
3171 val = 0;
3172 } else {
3173 ptr = brdp->membase + (offset % ONB_EIPAGESIZE);
3174 if (offset < ONB_EIPAGESIZE)
3175 val = ONB_EIENABLE;
3176 else
3177 val = ONB_EIENABLE | 0x40;
3178 }
3179 outb(val, (brdp->iobase + ONB_EICONFR));
3180 return(ptr);
3181}
3182
3183/*****************************************************************************/
3184
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003185static void stli_onbereset(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
3188 udelay(10);
3189 outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
3190 mdelay(1000);
3191}
3192
3193/*****************************************************************************/
3194
3195/*
3196 * The following routines act on Brumby boards.
3197 */
3198
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003199static void stli_bbyinit(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
3202 udelay(10);
3203 outb(0, (brdp->iobase + BBY_ATCONFR));
3204 mdelay(1000);
3205 outb(0x1, brdp->iobase);
3206 mdelay(1);
3207}
3208
3209/*****************************************************************************/
3210
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003211static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212{
Al Viro29756fa2006-10-10 22:47:27 +01003213 void __iomem *ptr;
Alan Cox4ac43602006-06-28 04:26:52 -07003214 unsigned char val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215
Alan Cox4ac43602006-06-28 04:26:52 -07003216 BUG_ON(offset > brdp->memsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217
Alan Cox4ac43602006-06-28 04:26:52 -07003218 ptr = brdp->membase + (offset % BBY_PAGESIZE);
3219 val = (unsigned char) (offset / BBY_PAGESIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 outb(val, (brdp->iobase + BBY_ATCONFR));
3221 return(ptr);
3222}
3223
3224/*****************************************************************************/
3225
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003226static void stli_bbyreset(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
3229 udelay(10);
3230 outb(0, (brdp->iobase + BBY_ATCONFR));
3231 mdelay(1000);
3232}
3233
3234/*****************************************************************************/
3235
3236/*
3237 * The following routines act on original old Stallion boards.
3238 */
3239
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003240static void stli_stalinit(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242 outb(0x1, brdp->iobase);
3243 mdelay(1000);
3244}
3245
3246/*****************************************************************************/
3247
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003248static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249{
Alan Cox4ac43602006-06-28 04:26:52 -07003250 BUG_ON(offset > brdp->memsize);
3251 return brdp->membase + (offset % STAL_PAGESIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252}
3253
3254/*****************************************************************************/
3255
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003256static void stli_stalreset(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257{
Alan Cox4ac43602006-06-28 04:26:52 -07003258 u32 __iomem *vecp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
Alan Cox4ac43602006-06-28 04:26:52 -07003260 vecp = (u32 __iomem *) (brdp->membase + 0x30);
3261 writel(0xffff0000, vecp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 outb(0, brdp->iobase);
3263 mdelay(1000);
3264}
3265
3266/*****************************************************************************/
3267
3268/*
3269 * Try to find an ECP board and initialize it. This handles only ECP
3270 * board types.
3271 */
3272
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003273static int stli_initecp(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274{
Alan Cox4ac43602006-06-28 04:26:52 -07003275 cdkecpsig_t sig;
3276 cdkecpsig_t __iomem *sigsp;
3277 unsigned int status, nxtid;
3278 char *name;
3279 int panelnr, nrports;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280
3281 if (!request_region(brdp->iobase, brdp->iosize, "istallion"))
3282 return -EIO;
3283
3284 if ((brdp->iobase == 0) || (brdp->memaddr == 0))
3285 {
3286 release_region(brdp->iobase, brdp->iosize);
Alan Cox4ac43602006-06-28 04:26:52 -07003287 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288 }
3289
3290 brdp->iosize = ECP_IOSIZE;
3291
3292/*
3293 * Based on the specific board type setup the common vars to access
3294 * and enable shared memory. Set all board specific information now
3295 * as well.
3296 */
3297 switch (brdp->brdtype) {
3298 case BRD_ECP:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 brdp->memsize = ECP_MEMSIZE;
3300 brdp->pagesize = ECP_ATPAGESIZE;
3301 brdp->init = stli_ecpinit;
3302 brdp->enable = stli_ecpenable;
3303 brdp->reenable = stli_ecpenable;
3304 brdp->disable = stli_ecpdisable;
3305 brdp->getmemptr = stli_ecpgetmemptr;
3306 brdp->intr = stli_ecpintr;
3307 brdp->reset = stli_ecpreset;
3308 name = "serial(EC8/64)";
3309 break;
3310
3311 case BRD_ECPE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312 brdp->memsize = ECP_MEMSIZE;
3313 brdp->pagesize = ECP_EIPAGESIZE;
3314 brdp->init = stli_ecpeiinit;
3315 brdp->enable = stli_ecpeienable;
3316 brdp->reenable = stli_ecpeienable;
3317 brdp->disable = stli_ecpeidisable;
3318 brdp->getmemptr = stli_ecpeigetmemptr;
3319 brdp->intr = stli_ecpintr;
3320 brdp->reset = stli_ecpeireset;
3321 name = "serial(EC8/64-EI)";
3322 break;
3323
3324 case BRD_ECPMC:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325 brdp->memsize = ECP_MEMSIZE;
3326 brdp->pagesize = ECP_MCPAGESIZE;
3327 brdp->init = NULL;
3328 brdp->enable = stli_ecpmcenable;
3329 brdp->reenable = stli_ecpmcenable;
3330 brdp->disable = stli_ecpmcdisable;
3331 brdp->getmemptr = stli_ecpmcgetmemptr;
3332 brdp->intr = stli_ecpintr;
3333 brdp->reset = stli_ecpmcreset;
3334 name = "serial(EC8/64-MCA)";
3335 break;
3336
3337 case BRD_ECPPCI:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 brdp->memsize = ECP_PCIMEMSIZE;
3339 brdp->pagesize = ECP_PCIPAGESIZE;
3340 brdp->init = stli_ecppciinit;
3341 brdp->enable = NULL;
3342 brdp->reenable = NULL;
3343 brdp->disable = NULL;
3344 brdp->getmemptr = stli_ecppcigetmemptr;
3345 brdp->intr = stli_ecpintr;
3346 brdp->reset = stli_ecppcireset;
3347 name = "serial(EC/RA-PCI)";
3348 break;
3349
3350 default:
3351 release_region(brdp->iobase, brdp->iosize);
Alan Cox4ac43602006-06-28 04:26:52 -07003352 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 }
3354
3355/*
3356 * The per-board operations structure is all set up, so now let's go
3357 * and get the board operational. Firstly initialize board configuration
3358 * registers. Set the memory mapping info so we can get at the boards
3359 * shared memory.
3360 */
3361 EBRDINIT(brdp);
3362
3363 brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
Alan Cox4ac43602006-06-28 04:26:52 -07003364 if (brdp->membase == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 {
3366 release_region(brdp->iobase, brdp->iosize);
Alan Cox4ac43602006-06-28 04:26:52 -07003367 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 }
3369
3370/*
3371 * Now that all specific code is set up, enable the shared memory and
3372 * look for the a signature area that will tell us exactly what board
3373 * this is, and what it is connected to it.
3374 */
3375 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07003376 sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
Al Viro634965f2006-09-23 01:20:31 +01003377 memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 EBRDDISABLE(brdp);
3379
Alan Cox4ac43602006-06-28 04:26:52 -07003380 if (sig.magic != cpu_to_le32(ECP_MAGIC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 {
3382 release_region(brdp->iobase, brdp->iosize);
Amol Ladaa8a8d62006-12-06 20:35:22 -08003383 iounmap(brdp->membase);
3384 brdp->membase = NULL;
Alan Cox4ac43602006-06-28 04:26:52 -07003385 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 }
3387
3388/*
3389 * Scan through the signature looking at the panels connected to the
3390 * board. Calculate the total number of ports as we go.
3391 */
3392 for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) {
3393 status = sig.panelid[nxtid];
3394 if ((status & ECH_PNLIDMASK) != nxtid)
3395 break;
3396
3397 brdp->panelids[panelnr] = status;
3398 nrports = (status & ECH_PNL16PORT) ? 16 : 8;
3399 if ((nrports == 16) && ((status & ECH_PNLXPID) == 0))
3400 nxtid++;
3401 brdp->panels[panelnr] = nrports;
3402 brdp->nrports += nrports;
3403 nxtid++;
3404 brdp->nrpanels++;
3405 }
3406
3407
3408 brdp->state |= BST_FOUND;
Alan Cox4ac43602006-06-28 04:26:52 -07003409 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410}
3411
3412/*****************************************************************************/
3413
3414/*
3415 * Try to find an ONboard, Brumby or Stallion board and initialize it.
3416 * This handles only these board types.
3417 */
3418
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003419static int stli_initonb(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420{
Alan Cox4ac43602006-06-28 04:26:52 -07003421 cdkonbsig_t sig;
3422 cdkonbsig_t __iomem *sigsp;
3423 char *name;
3424 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425
3426/*
3427 * Do a basic sanity check on the IO and memory addresses.
3428 */
Alan Cox4ac43602006-06-28 04:26:52 -07003429 if (brdp->iobase == 0 || brdp->memaddr == 0)
3430 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431
3432 brdp->iosize = ONB_IOSIZE;
3433
3434 if (!request_region(brdp->iobase, brdp->iosize, "istallion"))
3435 return -EIO;
3436
3437/*
3438 * Based on the specific board type setup the common vars to access
3439 * and enable shared memory. Set all board specific information now
3440 * as well.
3441 */
3442 switch (brdp->brdtype) {
3443 case BRD_ONBOARD:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 case BRD_ONBOARD2:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 brdp->memsize = ONB_MEMSIZE;
3446 brdp->pagesize = ONB_ATPAGESIZE;
3447 brdp->init = stli_onbinit;
3448 brdp->enable = stli_onbenable;
3449 brdp->reenable = stli_onbenable;
3450 brdp->disable = stli_onbdisable;
3451 brdp->getmemptr = stli_onbgetmemptr;
3452 brdp->intr = stli_ecpintr;
3453 brdp->reset = stli_onbreset;
3454 if (brdp->memaddr > 0x100000)
3455 brdp->enabval = ONB_MEMENABHI;
3456 else
3457 brdp->enabval = ONB_MEMENABLO;
3458 name = "serial(ONBoard)";
3459 break;
3460
3461 case BRD_ONBOARDE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 brdp->memsize = ONB_EIMEMSIZE;
3463 brdp->pagesize = ONB_EIPAGESIZE;
3464 brdp->init = stli_onbeinit;
3465 brdp->enable = stli_onbeenable;
3466 brdp->reenable = stli_onbeenable;
3467 brdp->disable = stli_onbedisable;
3468 brdp->getmemptr = stli_onbegetmemptr;
3469 brdp->intr = stli_ecpintr;
3470 brdp->reset = stli_onbereset;
3471 name = "serial(ONBoard/E)";
3472 break;
3473
3474 case BRD_BRUMBY4:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475 brdp->memsize = BBY_MEMSIZE;
3476 brdp->pagesize = BBY_PAGESIZE;
3477 brdp->init = stli_bbyinit;
3478 brdp->enable = NULL;
3479 brdp->reenable = NULL;
3480 brdp->disable = NULL;
3481 brdp->getmemptr = stli_bbygetmemptr;
3482 brdp->intr = stli_ecpintr;
3483 brdp->reset = stli_bbyreset;
3484 name = "serial(Brumby)";
3485 break;
3486
3487 case BRD_STALLION:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 brdp->memsize = STAL_MEMSIZE;
3489 brdp->pagesize = STAL_PAGESIZE;
3490 brdp->init = stli_stalinit;
3491 brdp->enable = NULL;
3492 brdp->reenable = NULL;
3493 brdp->disable = NULL;
3494 brdp->getmemptr = stli_stalgetmemptr;
3495 brdp->intr = stli_ecpintr;
3496 brdp->reset = stli_stalreset;
3497 name = "serial(Stallion)";
3498 break;
3499
3500 default:
3501 release_region(brdp->iobase, brdp->iosize);
Alan Cox4ac43602006-06-28 04:26:52 -07003502 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 }
3504
3505/*
3506 * The per-board operations structure is all set up, so now let's go
3507 * and get the board operational. Firstly initialize board configuration
3508 * registers. Set the memory mapping info so we can get at the boards
3509 * shared memory.
3510 */
3511 EBRDINIT(brdp);
3512
3513 brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
Alan Cox4ac43602006-06-28 04:26:52 -07003514 if (brdp->membase == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 {
3516 release_region(brdp->iobase, brdp->iosize);
Alan Cox4ac43602006-06-28 04:26:52 -07003517 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518 }
3519
3520/*
3521 * Now that all specific code is set up, enable the shared memory and
3522 * look for the a signature area that will tell us exactly what board
3523 * this is, and how many ports.
3524 */
3525 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07003526 sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
3527 memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528 EBRDDISABLE(brdp);
3529
Alan Cox4ac43602006-06-28 04:26:52 -07003530 if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) ||
3531 sig.magic1 != cpu_to_le16(ONB_MAGIC1) ||
3532 sig.magic2 != cpu_to_le16(ONB_MAGIC2) ||
3533 sig.magic3 != cpu_to_le16(ONB_MAGIC3))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534 {
3535 release_region(brdp->iobase, brdp->iosize);
Amol Ladaa8a8d62006-12-06 20:35:22 -08003536 iounmap(brdp->membase);
3537 brdp->membase = NULL;
Alan Cox4ac43602006-06-28 04:26:52 -07003538 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 }
3540
3541/*
3542 * Scan through the signature alive mask and calculate how many ports
3543 * there are on this board.
3544 */
3545 brdp->nrpanels = 1;
3546 if (sig.amask1) {
3547 brdp->nrports = 32;
3548 } else {
3549 for (i = 0; (i < 16); i++) {
3550 if (((sig.amask0 << i) & 0x8000) == 0)
3551 break;
3552 }
3553 brdp->nrports = i;
3554 }
3555 brdp->panels[0] = brdp->nrports;
3556
3557
3558 brdp->state |= BST_FOUND;
Alan Cox4ac43602006-06-28 04:26:52 -07003559 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560}
3561
3562/*****************************************************************************/
3563
3564/*
3565 * Start up a running board. This routine is only called after the
3566 * code has been down loaded to the board and is operational. It will
3567 * read in the memory map, and get the show on the road...
3568 */
3569
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003570static int stli_startbrd(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571{
Alan Cox4ac43602006-06-28 04:26:52 -07003572 cdkhdr_t __iomem *hdrp;
3573 cdkmem_t __iomem *memp;
3574 cdkasy_t __iomem *ap;
3575 unsigned long flags;
Jiri Slaby1328d732006-12-08 02:39:19 -08003576 unsigned int portnr, nrdevs, i;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003577 struct stliport *portp;
Jiri Slaby1328d732006-12-08 02:39:19 -08003578 int rc = 0;
Alan Cox4ac43602006-06-28 04:26:52 -07003579 u32 memoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580
Alan Cox4ac43602006-06-28 04:26:52 -07003581 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582 EBRDENABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07003583 hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 nrdevs = hdrp->nrdevs;
3585
3586#if 0
3587 printk("%s(%d): CDK version %d.%d.%d --> "
3588 "nrdevs=%d memp=%x hostp=%x slavep=%x\n",
Alan Cox4ac43602006-06-28 04:26:52 -07003589 __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification),
3590 readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp),
3591 readl(&hdrp->slavep));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592#endif
3593
3594 if (nrdevs < (brdp->nrports + 1)) {
3595 printk(KERN_ERR "STALLION: slave failed to allocate memory for "
3596 "all devices, devices=%d\n", nrdevs);
3597 brdp->nrports = nrdevs - 1;
3598 }
3599 brdp->nrdevs = nrdevs;
3600 brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
3601 brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
3602 brdp->bitsize = (nrdevs + 7) / 8;
Alan Cox4ac43602006-06-28 04:26:52 -07003603 memoff = readl(&hdrp->memp);
3604 if (memoff > brdp->memsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 printk(KERN_ERR "STALLION: corrupted shared memory region?\n");
3606 rc = -EIO;
3607 goto stli_donestartup;
3608 }
Alan Cox4ac43602006-06-28 04:26:52 -07003609 memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff);
3610 if (readw(&memp->dtype) != TYP_ASYNCTRL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 printk(KERN_ERR "STALLION: no slave control device found\n");
3612 goto stli_donestartup;
3613 }
3614 memp++;
3615
3616/*
3617 * Cycle through memory allocation of each port. We are guaranteed to
3618 * have all ports inside the first page of slave window, so no need to
3619 * change pages while reading memory map.
3620 */
3621 for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
Alan Cox4ac43602006-06-28 04:26:52 -07003622 if (readw(&memp->dtype) != TYP_ASYNC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 break;
3624 portp = brdp->ports[portnr];
Alan Cox4ac43602006-06-28 04:26:52 -07003625 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 break;
3627 portp->devnr = i;
Alan Cox4ac43602006-06-28 04:26:52 -07003628 portp->addr = readl(&memp->offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs));
3630 portp->portidx = (unsigned char) (i / 8);
3631 portp->portbit = (unsigned char) (0x1 << (i % 8));
3632 }
3633
Alan Cox4ac43602006-06-28 04:26:52 -07003634 writeb(0xff, &hdrp->slavereq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
3636/*
3637 * For each port setup a local copy of the RX and TX buffer offsets
3638 * and sizes. We do this separate from the above, because we need to
3639 * move the shared memory page...
3640 */
3641 for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
3642 portp = brdp->ports[portnr];
Alan Cox4ac43602006-06-28 04:26:52 -07003643 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 break;
3645 if (portp->addr == 0)
3646 break;
Alan Cox4ac43602006-06-28 04:26:52 -07003647 ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
3648 if (ap != NULL) {
3649 portp->rxsize = readw(&ap->rxq.size);
3650 portp->txsize = readw(&ap->txq.size);
3651 portp->rxoffset = readl(&ap->rxq.offset);
3652 portp->txoffset = readl(&ap->txq.offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 }
3654 }
3655
3656stli_donestartup:
3657 EBRDDISABLE(brdp);
Alan Cox4ac43602006-06-28 04:26:52 -07003658 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
3660 if (rc == 0)
3661 brdp->state |= BST_STARTED;
3662
3663 if (! stli_timeron) {
3664 stli_timeron++;
3665 stli_timerlist.expires = STLI_TIMEOUT;
3666 add_timer(&stli_timerlist);
3667 }
3668
Alan Cox4ac43602006-06-28 04:26:52 -07003669 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670}
3671
3672/*****************************************************************************/
3673
3674/*
3675 * Probe and initialize the specified board.
3676 */
3677
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003678static int __devinit stli_brdinit(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 stli_brds[brdp->brdnr] = brdp;
3681
3682 switch (brdp->brdtype) {
3683 case BRD_ECP:
3684 case BRD_ECPE:
3685 case BRD_ECPMC:
3686 case BRD_ECPPCI:
3687 stli_initecp(brdp);
3688 break;
3689 case BRD_ONBOARD:
3690 case BRD_ONBOARDE:
3691 case BRD_ONBOARD2:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 case BRD_BRUMBY4:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 case BRD_STALLION:
3694 stli_initonb(brdp);
3695 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 default:
3697 printk(KERN_ERR "STALLION: board=%d is unknown board "
3698 "type=%d\n", brdp->brdnr, brdp->brdtype);
Alan Cox4ac43602006-06-28 04:26:52 -07003699 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 }
3701
3702 if ((brdp->state & BST_FOUND) == 0) {
3703 printk(KERN_ERR "STALLION: %s board not found, board=%d "
3704 "io=%x mem=%x\n",
3705 stli_brdnames[brdp->brdtype], brdp->brdnr,
3706 brdp->iobase, (int) brdp->memaddr);
Alan Cox4ac43602006-06-28 04:26:52 -07003707 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 }
3709
3710 stli_initports(brdp);
3711 printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x "
3712 "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
3713 brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
3714 brdp->nrpanels, brdp->nrports);
Alan Cox4ac43602006-06-28 04:26:52 -07003715 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716}
3717
Jiri Slabya00f33f2006-12-08 02:39:20 -08003718#if STLI_EISAPROBE != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719/*****************************************************************************/
3720
3721/*
3722 * Probe around trying to find where the EISA boards shared memory
3723 * might be. This is a bit if hack, but it is the best we can do.
3724 */
3725
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003726static int stli_eisamemprobe(struct stlibrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727{
Alan Cox4ac43602006-06-28 04:26:52 -07003728 cdkecpsig_t ecpsig, __iomem *ecpsigp;
3729 cdkonbsig_t onbsig, __iomem *onbsigp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 int i, foundit;
3731
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732/*
3733 * First up we reset the board, to get it into a known state. There
3734 * is only 2 board types here we need to worry about. Don;t use the
3735 * standard board init routine here, it programs up the shared
3736 * memory address, and we don't know it yet...
3737 */
3738 if (brdp->brdtype == BRD_ECPE) {
3739 outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
3740 outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
3741 udelay(10);
3742 outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
3743 udelay(500);
3744 stli_ecpeienable(brdp);
3745 } else if (brdp->brdtype == BRD_ONBOARDE) {
3746 outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
3747 outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
3748 udelay(10);
3749 outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
3750 mdelay(100);
3751 outb(0x1, brdp->iobase);
3752 mdelay(1);
3753 stli_onbeenable(brdp);
3754 } else {
Alan Cox4ac43602006-06-28 04:26:52 -07003755 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 }
3757
3758 foundit = 0;
3759 brdp->memsize = ECP_MEMSIZE;
3760
3761/*
3762 * Board shared memory is enabled, so now we have a poke around and
3763 * see if we can find it.
3764 */
3765 for (i = 0; (i < stli_eisamempsize); i++) {
3766 brdp->memaddr = stli_eisamemprobeaddrs[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767 brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
Alan Cox4ac43602006-06-28 04:26:52 -07003768 if (brdp->membase == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 continue;
3770
3771 if (brdp->brdtype == BRD_ECPE) {
Al Viro29756fa2006-10-10 22:47:27 +01003772 ecpsigp = stli_ecpeigetmemptr(brdp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 CDK_SIGADDR, __LINE__);
Alan Cox4ac43602006-06-28 04:26:52 -07003774 memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t));
3775 if (ecpsig.magic == cpu_to_le32(ECP_MAGIC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 foundit = 1;
3777 } else {
Alan Cox4ac43602006-06-28 04:26:52 -07003778 onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 CDK_SIGADDR, __LINE__);
Alan Cox4ac43602006-06-28 04:26:52 -07003780 memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t));
3781 if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) &&
3782 (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) &&
3783 (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) &&
3784 (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 foundit = 1;
3786 }
3787
3788 iounmap(brdp->membase);
3789 if (foundit)
3790 break;
3791 }
3792
3793/*
3794 * Regardless of whether we found the shared memory or not we must
3795 * disable the region. After that return success or failure.
3796 */
3797 if (brdp->brdtype == BRD_ECPE)
3798 stli_ecpeidisable(brdp);
3799 else
3800 stli_onbedisable(brdp);
3801
3802 if (! foundit) {
3803 brdp->memaddr = 0;
3804 brdp->membase = NULL;
3805 printk(KERN_ERR "STALLION: failed to probe shared memory "
3806 "region for %s in EISA slot=%d\n",
3807 stli_brdnames[brdp->brdtype], (brdp->iobase >> 12));
Alan Cox4ac43602006-06-28 04:26:52 -07003808 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809 }
Alan Cox4ac43602006-06-28 04:26:52 -07003810 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811}
Jiri Slabya00f33f2006-12-08 02:39:20 -08003812#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813
3814static int stli_getbrdnr(void)
3815{
Jiri Slaby1328d732006-12-08 02:39:19 -08003816 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817
3818 for (i = 0; i < STL_MAXBRDS; i++) {
3819 if (!stli_brds[i]) {
3820 if (i >= stli_nrbrds)
3821 stli_nrbrds = i + 1;
3822 return i;
3823 }
3824 }
3825 return -1;
3826}
3827
Jiri Slabya00f33f2006-12-08 02:39:20 -08003828#if STLI_EISAPROBE != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829/*****************************************************************************/
3830
3831/*
3832 * Probe around and try to find any EISA boards in system. The biggest
3833 * problem here is finding out what memory address is associated with
3834 * an EISA board after it is found. The registers of the ECPE and
3835 * ONboardE are not readable - so we can't read them from there. We
3836 * don't have access to the EISA CMOS (or EISA BIOS) so we don't
3837 * actually have any way to find out the real value. The best we can
3838 * do is go probing around in the usual places hoping we can find it.
3839 */
3840
3841static int stli_findeisabrds(void)
3842{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003843 struct stlibrd *brdp;
Jiri Slaby1328d732006-12-08 02:39:19 -08003844 unsigned int iobase, eid, i;
3845 int brdnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
3847/*
Alan Cox4ac43602006-06-28 04:26:52 -07003848 * Firstly check if this is an EISA system. If this is not an EISA system then
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 * don't bother going any further!
3850 */
Alan Cox4ac43602006-06-28 04:26:52 -07003851 if (EISA_bus)
3852 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853
3854/*
3855 * Looks like an EISA system, so go searching for EISA boards.
3856 */
3857 for (iobase = 0x1000; (iobase <= 0xc000); iobase += 0x1000) {
3858 outb(0xff, (iobase + 0xc80));
3859 eid = inb(iobase + 0xc80);
3860 eid |= inb(iobase + 0xc81) << 8;
3861 if (eid != STL_EISAID)
3862 continue;
3863
3864/*
3865 * We have found a board. Need to check if this board was
3866 * statically configured already (just in case!).
3867 */
3868 for (i = 0; (i < STL_MAXBRDS); i++) {
3869 brdp = stli_brds[i];
Alan Cox4ac43602006-06-28 04:26:52 -07003870 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 continue;
3872 if (brdp->iobase == iobase)
3873 break;
3874 }
3875 if (i < STL_MAXBRDS)
3876 continue;
3877
3878/*
3879 * We have found a Stallion board and it is not configured already.
3880 * Allocate a board structure and initialize it.
3881 */
Alan Cox4ac43602006-06-28 04:26:52 -07003882 if ((brdp = stli_allocbrd()) == NULL)
3883 return -ENOMEM;
Jiri Slaby1328d732006-12-08 02:39:19 -08003884 brdnr = stli_getbrdnr();
3885 if (brdnr < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07003886 return -ENOMEM;
Jiri Slaby1328d732006-12-08 02:39:19 -08003887 brdp->brdnr = (unsigned int)brdnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888 eid = inb(iobase + 0xc82);
3889 if (eid == ECP_EISAID)
3890 brdp->brdtype = BRD_ECPE;
3891 else if (eid == ONB_EISAID)
3892 brdp->brdtype = BRD_ONBOARDE;
3893 else
3894 brdp->brdtype = BRD_UNKNOWN;
3895 brdp->iobase = iobase;
3896 outb(0x1, (iobase + 0xc84));
3897 if (stli_eisamemprobe(brdp))
3898 outb(0, (iobase + 0xc84));
3899 stli_brdinit(brdp);
3900 }
3901
Alan Cox4ac43602006-06-28 04:26:52 -07003902 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903}
Jiri Slabya00f33f2006-12-08 02:39:20 -08003904#else
3905static inline int stli_findeisabrds(void) { return 0; }
3906#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
3908/*****************************************************************************/
3909
3910/*
3911 * Find the next available board number that is free.
3912 */
3913
3914/*****************************************************************************/
3915
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916/*
3917 * We have a Stallion board. Allocate a board structure and
3918 * initialize it. Read its IO and MEMORY resources from PCI
3919 * configuration space.
3920 */
3921
Jiri Slaby845bead2006-12-08 02:39:17 -08003922static int __devinit stli_pciprobe(struct pci_dev *pdev,
3923 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003925 struct stlibrd *brdp;
Jiri Slaby1328d732006-12-08 02:39:19 -08003926 int brdnr, retval = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927
Jiri Slaby845bead2006-12-08 02:39:17 -08003928 retval = pci_enable_device(pdev);
3929 if (retval)
3930 goto err;
3931 brdp = stli_allocbrd();
3932 if (brdp == NULL) {
3933 retval = -ENOMEM;
3934 goto err;
3935 }
Jiri Slaby1328d732006-12-08 02:39:19 -08003936 brdnr = stli_getbrdnr();
3937 if (brdnr < 0) { /* TODO: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 printk(KERN_INFO "STALLION: too many boards found, "
3939 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby845bead2006-12-08 02:39:17 -08003940 retval = -EIO;
3941 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 }
Jiri Slaby1328d732006-12-08 02:39:19 -08003943 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby845bead2006-12-08 02:39:17 -08003944 brdp->brdtype = BRD_ECPPCI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945/*
3946 * We have all resources from the board, so lets setup the actual
3947 * board structure now.
3948 */
Jiri Slaby845bead2006-12-08 02:39:17 -08003949 brdp->iobase = pci_resource_start(pdev, 3);
3950 brdp->memaddr = pci_resource_start(pdev, 2);
3951 retval = stli_brdinit(brdp);
3952 if (retval)
3953 goto err_fr;
3954
3955 pci_set_drvdata(pdev, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956
Alan Cox4ac43602006-06-28 04:26:52 -07003957 return 0;
Jiri Slaby845bead2006-12-08 02:39:17 -08003958err_fr:
3959 kfree(brdp);
3960err:
3961 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962}
3963
Jiri Slaby845bead2006-12-08 02:39:17 -08003964static void stli_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003966 struct stlibrd *brdp = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
Jiri Slaby845bead2006-12-08 02:39:17 -08003968 stli_cleanup_ports(brdp);
3969
3970 iounmap(brdp->membase);
3971 if (brdp->iosize > 0)
3972 release_region(brdp->iobase, brdp->iosize);
3973
3974 stli_brds[brdp->brdnr] = NULL;
3975 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976}
3977
Jiri Slaby845bead2006-12-08 02:39:17 -08003978static struct pci_driver stli_pcidriver = {
3979 .name = "istallion",
3980 .id_table = istallion_pci_tbl,
3981 .probe = stli_pciprobe,
3982 .remove = __devexit_p(stli_pciremove)
3983};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984/*****************************************************************************/
3985
3986/*
3987 * Allocate a new board structure. Fill out the basic info in it.
3988 */
3989
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003990static struct stlibrd *stli_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003992 struct stlibrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003994 brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08003995 if (!brdp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 printk(KERN_ERR "STALLION: failed to allocate memory "
Jiri Slaby1f8ec432006-12-08 02:39:18 -08003997 "(size=%Zd)\n", sizeof(struct stlibrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08003998 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000 brdp->magic = STLI_BOARDMAGIC;
Alan Cox4ac43602006-06-28 04:26:52 -07004001 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002}
4003
4004/*****************************************************************************/
4005
4006/*
4007 * Scan through all the boards in the configuration and see what we
4008 * can find.
4009 */
4010
4011static int stli_initbrds(void)
4012{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004013 struct stlibrd *brdp, *nxtbrdp;
4014 struct stlconf conf;
Jiri Slaby1328d732006-12-08 02:39:19 -08004015 unsigned int i, j;
4016 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08004018 for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp);
4019 stli_nrbrds++) {
4020 memset(&conf, 0, sizeof(conf));
4021 if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0)
4022 continue;
Alan Cox4ac43602006-06-28 04:26:52 -07004023 if ((brdp = stli_allocbrd()) == NULL)
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08004024 continue;
4025 brdp->brdnr = stli_nrbrds;
4026 brdp->brdtype = conf.brdtype;
4027 brdp->iobase = conf.ioaddr1;
4028 brdp->memaddr = conf.memaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 stli_brdinit(brdp);
4030 }
4031
Jiri Slabya00f33f2006-12-08 02:39:20 -08004032 stli_findeisabrds();
Jiri Slaby845bead2006-12-08 02:39:17 -08004033
4034 retval = pci_register_driver(&stli_pcidriver);
4035 /* TODO: check retval and do something */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036
4037/*
4038 * All found boards are initialized. Now for a little optimization, if
4039 * no boards are sharing the "shared memory" regions then we can just
4040 * leave them all enabled. This is in fact the usual case.
4041 */
4042 stli_shared = 0;
4043 if (stli_nrbrds > 1) {
4044 for (i = 0; (i < stli_nrbrds); i++) {
4045 brdp = stli_brds[i];
Alan Cox4ac43602006-06-28 04:26:52 -07004046 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047 continue;
4048 for (j = i + 1; (j < stli_nrbrds); j++) {
4049 nxtbrdp = stli_brds[j];
Alan Cox4ac43602006-06-28 04:26:52 -07004050 if (nxtbrdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 continue;
4052 if ((brdp->membase >= nxtbrdp->membase) &&
4053 (brdp->membase <= (nxtbrdp->membase +
4054 nxtbrdp->memsize - 1))) {
4055 stli_shared++;
4056 break;
4057 }
4058 }
4059 }
4060 }
4061
4062 if (stli_shared == 0) {
4063 for (i = 0; (i < stli_nrbrds); i++) {
4064 brdp = stli_brds[i];
Alan Cox4ac43602006-06-28 04:26:52 -07004065 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 continue;
4067 if (brdp->state & BST_FOUND) {
4068 EBRDENABLE(brdp);
4069 brdp->enable = NULL;
4070 brdp->disable = NULL;
4071 }
4072 }
4073 }
4074
Alan Cox4ac43602006-06-28 04:26:52 -07004075 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076}
4077
4078/*****************************************************************************/
4079
4080/*
4081 * Code to handle an "staliomem" read operation. This device is the
4082 * contents of the board shared memory. It is used for down loading
4083 * the slave image (and debugging :-)
4084 */
4085
4086static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp)
4087{
Alan Cox4ac43602006-06-28 04:26:52 -07004088 unsigned long flags;
Al Viro29756fa2006-10-10 22:47:27 +01004089 void __iomem *memptr;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004090 struct stlibrd *brdp;
Jiri Slaby1328d732006-12-08 02:39:19 -08004091 unsigned int brdnr;
4092 int size, n;
Alan Cox4ac43602006-06-28 04:26:52 -07004093 void *p;
4094 loff_t off = *offp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
Josef Sipeka7113a92006-12-08 02:36:55 -08004096 brdnr = iminor(fp->f_path.dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 if (brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07004098 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 brdp = stli_brds[brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07004100 if (brdp == NULL)
4101 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102 if (brdp->state == 0)
Alan Cox4ac43602006-06-28 04:26:52 -07004103 return -ENODEV;
4104 if (off >= brdp->memsize || off + count < off)
4105 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08004107 size = min(count, (size_t)(brdp->memsize - off));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108
Alan Cox4ac43602006-06-28 04:26:52 -07004109 /*
4110 * Copy the data a page at a time
4111 */
4112
4113 p = (void *)__get_free_page(GFP_KERNEL);
4114 if(p == NULL)
4115 return -ENOMEM;
4116
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 while (size > 0) {
Alan Cox4ac43602006-06-28 04:26:52 -07004118 spin_lock_irqsave(&brd_lock, flags);
4119 EBRDENABLE(brdp);
Al Viro29756fa2006-10-10 22:47:27 +01004120 memptr = EBRDGETMEMPTR(brdp, off);
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08004121 n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
4122 n = min(n, (int)PAGE_SIZE);
Alan Cox4ac43602006-06-28 04:26:52 -07004123 memcpy_fromio(p, memptr, n);
4124 EBRDDISABLE(brdp);
4125 spin_unlock_irqrestore(&brd_lock, flags);
4126 if (copy_to_user(buf, p, n)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 count = -EFAULT;
4128 goto out;
4129 }
Alan Cox4ac43602006-06-28 04:26:52 -07004130 off += n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 buf += n;
4132 size -= n;
4133 }
4134out:
Alan Cox4ac43602006-06-28 04:26:52 -07004135 *offp = off;
4136 free_page((unsigned long)p);
4137 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138}
4139
4140/*****************************************************************************/
4141
4142/*
4143 * Code to handle an "staliomem" write operation. This device is the
4144 * contents of the board shared memory. It is used for down loading
4145 * the slave image (and debugging :-)
Alan Cox4ac43602006-06-28 04:26:52 -07004146 *
4147 * FIXME: copy under lock
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 */
4149
4150static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp)
4151{
Alan Cox4ac43602006-06-28 04:26:52 -07004152 unsigned long flags;
Al Viro29756fa2006-10-10 22:47:27 +01004153 void __iomem *memptr;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004154 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07004155 char __user *chbuf;
Jiri Slaby1328d732006-12-08 02:39:19 -08004156 unsigned int brdnr;
4157 int size, n;
Alan Cox4ac43602006-06-28 04:26:52 -07004158 void *p;
4159 loff_t off = *offp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160
Josef Sipeka7113a92006-12-08 02:36:55 -08004161 brdnr = iminor(fp->f_path.dentry->d_inode);
Alan Cox4ac43602006-06-28 04:26:52 -07004162
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163 if (brdnr >= stli_nrbrds)
Alan Cox4ac43602006-06-28 04:26:52 -07004164 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165 brdp = stli_brds[brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07004166 if (brdp == NULL)
4167 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 if (brdp->state == 0)
Alan Cox4ac43602006-06-28 04:26:52 -07004169 return -ENODEV;
4170 if (off >= brdp->memsize || off + count < off)
4171 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
4173 chbuf = (char __user *) buf;
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08004174 size = min(count, (size_t)(brdp->memsize - off));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175
Alan Cox4ac43602006-06-28 04:26:52 -07004176 /*
4177 * Copy the data a page at a time
4178 */
4179
4180 p = (void *)__get_free_page(GFP_KERNEL);
4181 if(p == NULL)
4182 return -ENOMEM;
4183
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 while (size > 0) {
Jiri Slabya3f8d9d2006-12-08 02:39:18 -08004185 n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
4186 n = min(n, (int)PAGE_SIZE);
Alan Cox4ac43602006-06-28 04:26:52 -07004187 if (copy_from_user(p, chbuf, n)) {
4188 if (count == 0)
4189 count = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 goto out;
4191 }
Alan Cox4ac43602006-06-28 04:26:52 -07004192 spin_lock_irqsave(&brd_lock, flags);
4193 EBRDENABLE(brdp);
Al Viro29756fa2006-10-10 22:47:27 +01004194 memptr = EBRDGETMEMPTR(brdp, off);
Alan Cox4ac43602006-06-28 04:26:52 -07004195 memcpy_toio(memptr, p, n);
4196 EBRDDISABLE(brdp);
4197 spin_unlock_irqrestore(&brd_lock, flags);
4198 off += n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 chbuf += n;
4200 size -= n;
4201 }
4202out:
Alan Cox4ac43602006-06-28 04:26:52 -07004203 free_page((unsigned long) p);
4204 *offp = off;
4205 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206}
4207
4208/*****************************************************************************/
4209
4210/*
4211 * Return the board stats structure to user app.
4212 */
4213
4214static int stli_getbrdstats(combrd_t __user *bp)
4215{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004216 struct stlibrd *brdp;
Jiri Slaby1328d732006-12-08 02:39:19 -08004217 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
4219 if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
4220 return -EFAULT;
4221 if (stli_brdstats.brd >= STL_MAXBRDS)
Alan Cox4ac43602006-06-28 04:26:52 -07004222 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223 brdp = stli_brds[stli_brdstats.brd];
Alan Cox4ac43602006-06-28 04:26:52 -07004224 if (brdp == NULL)
4225 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226
4227 memset(&stli_brdstats, 0, sizeof(combrd_t));
4228 stli_brdstats.brd = brdp->brdnr;
4229 stli_brdstats.type = brdp->brdtype;
4230 stli_brdstats.hwid = 0;
4231 stli_brdstats.state = brdp->state;
4232 stli_brdstats.ioaddr = brdp->iobase;
4233 stli_brdstats.memaddr = brdp->memaddr;
4234 stli_brdstats.nrpanels = brdp->nrpanels;
4235 stli_brdstats.nrports = brdp->nrports;
4236 for (i = 0; (i < brdp->nrpanels); i++) {
4237 stli_brdstats.panels[i].panel = i;
4238 stli_brdstats.panels[i].hwid = brdp->panelids[i];
4239 stli_brdstats.panels[i].nrports = brdp->panels[i];
4240 }
4241
4242 if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t)))
4243 return -EFAULT;
Alan Cox4ac43602006-06-28 04:26:52 -07004244 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245}
4246
4247/*****************************************************************************/
4248
4249/*
4250 * Resolve the referenced port number into a port struct pointer.
4251 */
4252
Jiri Slaby1328d732006-12-08 02:39:19 -08004253static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
4254 unsigned int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004256 struct stlibrd *brdp;
Jiri Slaby1328d732006-12-08 02:39:19 -08004257 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258
Jiri Slaby1328d732006-12-08 02:39:19 -08004259 if (brdnr >= STL_MAXBRDS)
Alan Cox4ac43602006-06-28 04:26:52 -07004260 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 brdp = stli_brds[brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07004262 if (brdp == NULL)
4263 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 for (i = 0; (i < panelnr); i++)
4265 portnr += brdp->panels[i];
Jiri Slaby1328d732006-12-08 02:39:19 -08004266 if (portnr >= brdp->nrports)
Alan Cox4ac43602006-06-28 04:26:52 -07004267 return NULL;
4268 return brdp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269}
4270
4271/*****************************************************************************/
4272
4273/*
4274 * Return the port stats structure to user app. A NULL port struct
4275 * pointer passed in means that we need to find out from the app
4276 * what port to get stats for (used through board control device).
4277 */
4278
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004279static int stli_portcmdstats(struct stliport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280{
4281 unsigned long flags;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004282 struct stlibrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 int rc;
4284
4285 memset(&stli_comstats, 0, sizeof(comstats_t));
4286
Alan Cox4ac43602006-06-28 04:26:52 -07004287 if (portp == NULL)
4288 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 brdp = stli_brds[portp->brdnr];
Alan Cox4ac43602006-06-28 04:26:52 -07004290 if (brdp == NULL)
4291 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292
4293 if (brdp->state & BST_STARTED) {
4294 if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
4295 &stli_cdkstats, sizeof(asystats_t), 1)) < 0)
Alan Cox4ac43602006-06-28 04:26:52 -07004296 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 } else {
4298 memset(&stli_cdkstats, 0, sizeof(asystats_t));
4299 }
4300
4301 stli_comstats.brd = portp->brdnr;
4302 stli_comstats.panel = portp->panelnr;
4303 stli_comstats.port = portp->portnr;
4304 stli_comstats.state = portp->state;
4305 stli_comstats.flags = portp->flags;
4306
Alan Cox4ac43602006-06-28 04:26:52 -07004307 spin_lock_irqsave(&brd_lock, flags);
4308 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 if (portp->tty->driver_data == portp) {
4310 stli_comstats.ttystate = portp->tty->flags;
Alan Cox4ac43602006-06-28 04:26:52 -07004311 stli_comstats.rxbuffered = -1;
4312 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 stli_comstats.cflags = portp->tty->termios->c_cflag;
4314 stli_comstats.iflags = portp->tty->termios->c_iflag;
4315 stli_comstats.oflags = portp->tty->termios->c_oflag;
4316 stli_comstats.lflags = portp->tty->termios->c_lflag;
4317 }
4318 }
4319 }
Alan Cox4ac43602006-06-28 04:26:52 -07004320 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321
4322 stli_comstats.txtotal = stli_cdkstats.txchars;
4323 stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
4324 stli_comstats.txbuffered = stli_cdkstats.txringq;
4325 stli_comstats.rxbuffered += stli_cdkstats.rxringq;
4326 stli_comstats.rxoverrun = stli_cdkstats.overruns;
4327 stli_comstats.rxparity = stli_cdkstats.parity;
4328 stli_comstats.rxframing = stli_cdkstats.framing;
4329 stli_comstats.rxlost = stli_cdkstats.ringover;
4330 stli_comstats.rxbreaks = stli_cdkstats.rxbreaks;
4331 stli_comstats.txbreaks = stli_cdkstats.txbreaks;
4332 stli_comstats.txxon = stli_cdkstats.txstart;
4333 stli_comstats.txxoff = stli_cdkstats.txstop;
4334 stli_comstats.rxxon = stli_cdkstats.rxstart;
4335 stli_comstats.rxxoff = stli_cdkstats.rxstop;
4336 stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2;
4337 stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff;
4338 stli_comstats.modem = stli_cdkstats.dcdcnt;
4339 stli_comstats.hwid = stli_cdkstats.hwid;
4340 stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
4341
Alan Cox4ac43602006-06-28 04:26:52 -07004342 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343}
4344
4345/*****************************************************************************/
4346
4347/*
4348 * Return the port stats structure to user app. A NULL port struct
4349 * pointer passed in means that we need to find out from the app
4350 * what port to get stats for (used through board control device).
4351 */
4352
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004353static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004355 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07004356 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357
4358 if (!portp) {
4359 if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
4360 return -EFAULT;
4361 portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
4362 stli_comstats.port);
4363 if (!portp)
4364 return -ENODEV;
4365 }
4366
4367 brdp = stli_brds[portp->brdnr];
4368 if (!brdp)
4369 return -ENODEV;
4370
4371 if ((rc = stli_portcmdstats(portp)) < 0)
4372 return rc;
4373
4374 return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
4375 -EFAULT : 0;
4376}
4377
4378/*****************************************************************************/
4379
4380/*
4381 * Clear the port stats structure. We also return it zeroed out...
4382 */
4383
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004384static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004386 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07004387 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388
4389 if (!portp) {
4390 if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
4391 return -EFAULT;
4392 portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
4393 stli_comstats.port);
4394 if (!portp)
4395 return -ENODEV;
4396 }
4397
4398 brdp = stli_brds[portp->brdnr];
4399 if (!brdp)
4400 return -ENODEV;
4401
4402 if (brdp->state & BST_STARTED) {
4403 if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0)
4404 return rc;
4405 }
4406
4407 memset(&stli_comstats, 0, sizeof(comstats_t));
4408 stli_comstats.brd = portp->brdnr;
4409 stli_comstats.panel = portp->panelnr;
4410 stli_comstats.port = portp->portnr;
4411
4412 if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
4413 return -EFAULT;
4414 return 0;
4415}
4416
4417/*****************************************************************************/
4418
4419/*
4420 * Return the entire driver ports structure to a user app.
4421 */
4422
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004423static int stli_getportstruct(struct stliport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424{
Jiri Slaby1328d732006-12-08 02:39:19 -08004425 struct stliport stli_dummyport;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004426 struct stliport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004428 if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 return -EFAULT;
4430 portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
4431 stli_dummyport.portnr);
4432 if (!portp)
4433 return -ENODEV;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004434 if (copy_to_user(arg, portp, sizeof(struct stliport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 return -EFAULT;
4436 return 0;
4437}
4438
4439/*****************************************************************************/
4440
4441/*
4442 * Return the entire driver board structure to a user app.
4443 */
4444
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004445static int stli_getbrdstruct(struct stlibrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446{
Jiri Slaby1328d732006-12-08 02:39:19 -08004447 struct stlibrd stli_dummybrd;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004448 struct stlibrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004450 if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451 return -EFAULT;
Jiri Slaby1328d732006-12-08 02:39:19 -08004452 if (stli_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 return -ENODEV;
4454 brdp = stli_brds[stli_dummybrd.brdnr];
4455 if (!brdp)
4456 return -ENODEV;
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004457 if (copy_to_user(arg, brdp, sizeof(struct stlibrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 return -EFAULT;
4459 return 0;
4460}
4461
4462/*****************************************************************************/
4463
4464/*
4465 * The "staliomem" device is also required to do some special operations on
4466 * the board. We need to be able to send an interrupt to the board,
4467 * reset it, and start/stop it.
4468 */
4469
4470static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
4471{
Jiri Slaby1f8ec432006-12-08 02:39:18 -08004472 struct stlibrd *brdp;
Alan Cox4ac43602006-06-28 04:26:52 -07004473 int brdnr, rc, done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474 void __user *argp = (void __user *)arg;
4475
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476/*
4477 * First up handle the board independent ioctls.
4478 */
4479 done = 0;
4480 rc = 0;
4481
4482 switch (cmd) {
4483 case COM_GETPORTSTATS:
4484 rc = stli_getportstats(NULL, argp);
4485 done++;
4486 break;
4487 case COM_CLRPORTSTATS:
4488 rc = stli_clrportstats(NULL, argp);
4489 done++;
4490 break;
4491 case COM_GETBRDSTATS:
4492 rc = stli_getbrdstats(argp);
4493 done++;
4494 break;
4495 case COM_READPORT:
4496 rc = stli_getportstruct(argp);
4497 done++;
4498 break;
4499 case COM_READBOARD:
4500 rc = stli_getbrdstruct(argp);
4501 done++;
4502 break;
4503 }
4504
4505 if (done)
Alan Cox4ac43602006-06-28 04:26:52 -07004506 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507
4508/*
4509 * Now handle the board specific ioctls. These all depend on the
4510 * minor number of the device they were called from.
4511 */
4512 brdnr = iminor(ip);
4513 if (brdnr >= STL_MAXBRDS)
Alan Cox4ac43602006-06-28 04:26:52 -07004514 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 brdp = stli_brds[brdnr];
4516 if (!brdp)
Alan Cox4ac43602006-06-28 04:26:52 -07004517 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518 if (brdp->state == 0)
Alan Cox4ac43602006-06-28 04:26:52 -07004519 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520
4521 switch (cmd) {
4522 case STL_BINTR:
4523 EBRDINTR(brdp);
4524 break;
4525 case STL_BSTART:
4526 rc = stli_startbrd(brdp);
4527 break;
4528 case STL_BSTOP:
4529 brdp->state &= ~BST_STARTED;
4530 break;
4531 case STL_BRESET:
4532 brdp->state &= ~BST_STARTED;
4533 EBRDRESET(brdp);
4534 if (stli_shared == 0) {
4535 if (brdp->reenable != NULL)
4536 (* brdp->reenable)(brdp);
4537 }
4538 break;
4539 default:
4540 rc = -ENOIOCTLCMD;
4541 break;
4542 }
Alan Cox4ac43602006-06-28 04:26:52 -07004543 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544}
4545
Jeff Dikeb68e31d2006-10-02 02:17:18 -07004546static const struct tty_operations stli_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547 .open = stli_open,
4548 .close = stli_close,
4549 .write = stli_write,
4550 .put_char = stli_putchar,
4551 .flush_chars = stli_flushchars,
4552 .write_room = stli_writeroom,
4553 .chars_in_buffer = stli_charsinbuffer,
4554 .ioctl = stli_ioctl,
4555 .set_termios = stli_settermios,
4556 .throttle = stli_throttle,
4557 .unthrottle = stli_unthrottle,
4558 .stop = stli_stop,
4559 .start = stli_start,
4560 .hangup = stli_hangup,
4561 .flush_buffer = stli_flushbuffer,
4562 .break_ctl = stli_breakctl,
4563 .wait_until_sent = stli_waituntilsent,
4564 .send_xchar = stli_sendxchar,
4565 .read_proc = stli_readproc,
4566 .tiocmget = stli_tiocmget,
4567 .tiocmset = stli_tiocmset,
4568};
4569
4570/*****************************************************************************/
4571
Adrian Bunk672b2712006-06-30 01:55:30 -07004572static int __init stli_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573{
4574 int i;
4575 printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
4576
Alan Cox4ac43602006-06-28 04:26:52 -07004577 spin_lock_init(&stli_lock);
4578 spin_lock_init(&brd_lock);
4579
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 stli_initbrds();
4581
4582 stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4583 if (!stli_serial)
4584 return -ENOMEM;
4585
4586/*
4587 * Allocate a temporary write buffer.
4588 */
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08004589 stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
4590 if (!stli_txcookbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591 printk(KERN_ERR "STALLION: failed to allocate memory "
4592 "(size=%d)\n", STLI_TXBUFSIZE);
4593
4594/*
4595 * Set up a character driver for the shared memory region. We need this
4596 * to down load the slave code image. Also it is a useful debugging tool.
4597 */
4598 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem))
4599 printk(KERN_ERR "STALLION: failed to register serial memory "
4600 "device\n");
4601
gregkh@suse.deca8eca62005-03-23 09:53:09 -08004602 istallion_class = class_create(THIS_MODULE, "staliomem");
Greg Kroah-Hartman7c69ef72005-06-20 21:15:16 -07004603 for (i = 0; i < 4; i++)
Greg Kroah-Hartman53f46542005-10-27 22:25:43 -07004604 class_device_create(istallion_class, NULL,
4605 MKDEV(STL_SIOMEMMAJOR, i),
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 NULL, "staliomem%d", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607
4608/*
4609 * Set up the tty driver structure and register us as a driver.
4610 */
4611 stli_serial->owner = THIS_MODULE;
4612 stli_serial->driver_name = stli_drvname;
4613 stli_serial->name = stli_serialname;
4614 stli_serial->major = STL_SERIALMAJOR;
4615 stli_serial->minor_start = 0;
4616 stli_serial->type = TTY_DRIVER_TYPE_SERIAL;
4617 stli_serial->subtype = SERIAL_TYPE_NORMAL;
4618 stli_serial->init_termios = stli_deftermios;
4619 stli_serial->flags = TTY_DRIVER_REAL_RAW;
4620 tty_set_operations(stli_serial, &stli_ops);
4621
4622 if (tty_register_driver(stli_serial)) {
4623 put_tty_driver(stli_serial);
4624 printk(KERN_ERR "STALLION: failed to register serial driver\n");
4625 return -EBUSY;
4626 }
Alan Cox4ac43602006-06-28 04:26:52 -07004627 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628}
4629
4630/*****************************************************************************/