Fix common misspellings
[deliverable/linux.git] / drivers / staging / tty / ip2 / ip2main.c
CommitLineData
1da177e4
LT
1/*
2*
3* (c) 1999 by Computone Corporation
4*
5********************************************************************************
6*
7* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport
8* serial I/O controllers.
9*
10* DESCRIPTION: Mainline code for the device driver
11*
12*******************************************************************************/
13// ToDo:
14//
15// Fix the immediate DSS_NOW problem.
16// Work over the channel stats return logic in ip2_ipl_ioctl so they
17// make sense for all 256 possible channels and so the user space
18// utilities will compile and work properly.
19//
20// Done:
21//
22// 1.2.14 /\/\|=mhw=|\/\/
23// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts.
24// Changed the definition of ip2trace to be more consistent with kernel style
25// Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates
26//
27// 1.2.13 /\/\|=mhw=|\/\/
28// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform
29// to agreed devfs serial device naming convention.
30//
31// 1.2.12 /\/\|=mhw=|\/\/
32// Cleaned up some remove queue cut and paste errors
33//
34// 1.2.11 /\/\|=mhw=|\/\/
35// Clean up potential NULL pointer dereferences
36// Clean up devfs registration
37// Add kernel command line parsing for io and irq
9c4b562a 38// Compile defaults for io and irq are now set in ip2.c not ip2.h!
1da177e4
LT
39// Reworked poll_only hack for explicit parameter setting
40// You must now EXPLICITLY set poll_only = 1 or set all irqs to 0
41// Merged ip2_loadmain and old_ip2_init
42// Converted all instances of interruptible_sleep_on into queue calls
43// Most of these had no race conditions but better to clean up now
44//
45// 1.2.10 /\/\|=mhw=|\/\/
46// Fixed the bottom half interrupt handler and enabled USE_IQI
47// to split the interrupt handler into a formal top-half / bottom-half
48// Fixed timing window on high speed processors that queued messages to
49// the outbound mail fifo faster than the board could handle.
50//
51// 1.2.9
52// Four box EX was barfing on >128k kmalloc, made structure smaller by
53// reducing output buffer size
54//
55// 1.2.8
56// Device file system support (MHW)
57//
58// 1.2.7
59// Fixed
60// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
61//
62// 1.2.6
63//Fixes DCD problems
64// DCD was not reported when CLOCAL was set on call to TIOCMGET
65//
66//Enhancements:
67// TIOCMGET requests and waits for status return
68// No DSS interrupts enabled except for DCD when needed
69//
70// For internal use only
71//
72//#define IP2DEBUG_INIT
73//#define IP2DEBUG_OPEN
74//#define IP2DEBUG_WRITE
75//#define IP2DEBUG_READ
76//#define IP2DEBUG_IOCTL
77//#define IP2DEBUG_IPL
78
79//#define IP2DEBUG_TRACE
80//#define DEBUG_FIFO
81
82/************/
83/* Includes */
84/************/
1da177e4
LT
85
86#include <linux/ctype.h>
87#include <linux/string.h>
88#include <linux/fcntl.h>
89#include <linux/errno.h>
90#include <linux/module.h>
91#include <linux/signal.h>
92#include <linux/sched.h>
1da177e4
LT
93#include <linux/timer.h>
94#include <linux/interrupt.h>
95#include <linux/pci.h>
96#include <linux/mm.h>
97#include <linux/slab.h>
98#include <linux/major.h>
99#include <linux/wait.h>
100#include <linux/device.h>
613655fa 101#include <linux/mutex.h>
547d8bb7
DW
102#include <linux/firmware.h>
103#include <linux/platform_device.h>
1da177e4
LT
104
105#include <linux/tty.h>
106#include <linux/tty_flip.h>
107#include <linux/termios.h>
108#include <linux/tty_driver.h>
109#include <linux/serial.h>
110#include <linux/ptrace.h>
111#include <linux/ioport.h>
112
113#include <linux/cdk.h>
114#include <linux/comstats.h>
115#include <linux/delay.h>
116#include <linux/bitops.h>
117
118#include <asm/system.h>
119#include <asm/io.h>
120#include <asm/irq.h>
121
122#include <linux/vmalloc.h>
123#include <linux/init.h>
1da177e4
LT
124
125#include <asm/uaccess.h>
126
9c4b562a
AB
127#include "ip2types.h"
128#include "ip2trace.h"
129#include "ip2ioctl.h"
130#include "ip2.h"
131#include "i2ellis.h"
132#include "i2lib.h"
1da177e4
LT
133
134/*****************
135 * /proc/ip2mem *
136 *****************/
137
138#include <linux/proc_fs.h>
4a5cdb5b 139#include <linux/seq_file.h>
1da177e4 140
613655fa 141static DEFINE_MUTEX(ip2_mutex);
4a5cdb5b 142static const struct file_operations ip2mem_proc_fops;
cdda7cd9 143static const struct file_operations ip2_proc_fops;
1da177e4
LT
144
145/********************/
146/* Type Definitions */
147/********************/
148
149/*************/
150/* Constants */
151/*************/
152
153/* String constants to identify ourselves */
cf176bc3
JS
154static const char pcName[] = "Computone IntelliPort Plus multiport driver";
155static const char pcVersion[] = "1.2.14";
1da177e4
LT
156
157/* String constants for port names */
cf176bc3
JS
158static const char pcDriver_name[] = "ip2";
159static const char pcIpl[] = "ip2ipl";
1da177e4 160
1da177e4
LT
161/***********************/
162/* Function Prototypes */
163/***********************/
164
165/* Global module entry functions */
166
167/* Private (static) functions */
168static int ip2_open(PTTY, struct file *);
169static void ip2_close(PTTY, struct file *);
d9e39538 170static int ip2_write(PTTY, const unsigned char *, int);
f34d7a5b 171static int ip2_putchar(PTTY, unsigned char);
1da177e4
LT
172static void ip2_flush_chars(PTTY);
173static int ip2_write_room(PTTY);
174static int ip2_chars_in_buf(PTTY);
175static void ip2_flush_buffer(PTTY);
6caa76b7 176static int ip2_ioctl(PTTY, UINT, ULONG);
606d099c 177static void ip2_set_termios(PTTY, struct ktermios *);
1da177e4
LT
178static void ip2_set_line_discipline(PTTY);
179static void ip2_throttle(PTTY);
180static void ip2_unthrottle(PTTY);
181static void ip2_stop(PTTY);
182static void ip2_start(PTTY);
183static void ip2_hangup(PTTY);
60b33c13 184static int ip2_tiocmget(struct tty_struct *tty);
20b9d177 185static int ip2_tiocmset(struct tty_struct *tty,
1da177e4 186 unsigned int set, unsigned int clear);
0587102c
AC
187static int ip2_get_icount(struct tty_struct *tty,
188 struct serial_icounter_struct *icount);
1da177e4
LT
189
190static void set_irq(int, int);
c4028958 191static void ip2_interrupt_bh(struct work_struct *work);
7d12e780 192static irqreturn_t ip2_interrupt(int irq, void *dev_id);
1da177e4
LT
193static void ip2_poll(unsigned long arg);
194static inline void service_all_boards(void);
c4028958
DH
195static void do_input(struct work_struct *);
196static void do_status(struct work_struct *);
1da177e4
LT
197
198static void ip2_wait_until_sent(PTTY,int);
199
606d099c 200static void set_params (i2ChanStrPtr, struct ktermios *);
1da177e4
LT
201static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
202static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
203
204static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);
205static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);
47be36a2 206static long ip2_ipl_ioctl(struct file *, UINT, ULONG);
1da177e4
LT
207static int ip2_ipl_open(struct inode *, struct file *);
208
209static int DumpTraceBuffer(char __user *, int);
210static int DumpFifoBuffer( char __user *, int);
211
547d8bb7 212static void ip2_init_board(int, const struct firmware *);
1da177e4 213static unsigned short find_eisa_board(int);
02c95a62 214static int ip2_setup(char *str);
1da177e4
LT
215
216/***************/
217/* Static Data */
218/***************/
219
220static struct tty_driver *ip2_tty_driver;
221
222/* Here, then is a table of board pointers which the interrupt routine should
223 * scan through to determine who it must service.
224 */
225static unsigned short i2nBoards; // Number of boards here
226
227static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];
228
229static i2ChanStrPtr DevTable[IP2_MAX_PORTS];
230//DevTableMem just used to save addresses for kfree
231static void *DevTableMem[IP2_MAX_BOARDS];
232
233/* This is the driver descriptor for the ip2ipl device, which is used to
234 * download the loadware to the boards.
235 */
62322d25 236static const struct file_operations ip2_ipl = {
1da177e4
LT
237 .owner = THIS_MODULE,
238 .read = ip2_ipl_read,
239 .write = ip2_ipl_write,
47be36a2 240 .unlocked_ioctl = ip2_ipl_ioctl,
1da177e4 241 .open = ip2_ipl_open,
6038f373 242 .llseek = noop_llseek,
1da177e4
LT
243};
244
cf176bc3
JS
245static unsigned long irq_counter;
246static unsigned long bh_counter;
1da177e4
LT
247
248// Use immediate queue to service interrupts
249#define USE_IQI
250//#define USE_IQ // PCI&2.2 needs work
251
252/* The timer_list entry for our poll routine. If interrupt operation is not
253 * selected, the board is serviced periodically to see if anything needs doing.
254 */
255#define POLL_TIMEOUT (jiffies + 1)
8d06afab 256static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
1da177e4
LT
257
258#ifdef IP2DEBUG_TRACE
259/* Trace (debug) buffer data */
260#define TRACEMAX 1000
261static unsigned long tracebuf[TRACEMAX];
262static int tracestuff;
263static int tracestrip;
264static int tracewrap;
265#endif
266
267/**********/
268/* Macros */
269/**********/
270
795877cf 271#ifdef IP2DEBUG_OPEN
7d7b93c1
AC
272#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
273 tty->name,(pCh->flags), \
1da177e4
LT
274 tty->count,/*GET_USE_COUNT(module)*/0,s)
275#else
276#define DBG_CNT(s)
277#endif
278
279/********/
280/* Code */
281/********/
282
9c4b562a
AB
283#include "i2ellis.c" /* Extremely low-level interface services */
284#include "i2cmd.c" /* Standard loadware command definitions */
285#include "i2lib.c" /* High level interface services */
1da177e4
LT
286
287/* Configuration area for modprobe */
288
289MODULE_AUTHOR("Doug McNash");
290MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
47babd4c 291MODULE_LICENSE("GPL");
1da177e4 292
02c95a62
RM
293#define MAX_CMD_STR 50
294
cf176bc3 295static int poll_only;
02c95a62 296static char cmd[MAX_CMD_STR];
1da177e4
LT
297
298static int Eisa_irq;
299static int Eisa_slot;
300
301static int iindx;
302static char rirqs[IP2_MAX_BOARDS];
303static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
304
47babd4c
JS
305/* Note: Add compiled in defaults to these arrays, not to the structure
306 in ip2.h any longer. That structure WILL get overridden
307 by these values, or command line values, or insmod values!!! =mhw=
308*/
309static int io[IP2_MAX_BOARDS];
310static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
311
312MODULE_AUTHOR("Doug McNash");
313MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
314module_param_array(irq, int, NULL, 0);
315MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
316module_param_array(io, int, NULL, 0);
317MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
318module_param(poll_only, bool, 0);
319MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
02c95a62
RM
320module_param_string(ip2, cmd, MAX_CMD_STR, 0);
321MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='");
47babd4c 322
1da177e4 323/* for sysfs class support */
ca8eca68 324static struct class *ip2_class;
1da177e4 325
f1ddfd95 326/* Some functions to keep track of what irqs we have */
1da177e4 327
f1ddfd95 328static int __init is_valid_irq(int irq)
1da177e4
LT
329{
330 int *i = Valid_Irqs;
331
f1ddfd95 332 while (*i != 0 && *i != irq)
1da177e4 333 i++;
f1ddfd95
JS
334
335 return *i;
1da177e4
LT
336}
337
f1ddfd95 338static void __init mark_requested_irq(char irq)
1da177e4
LT
339{
340 rirqs[iindx++] = irq;
341}
342
f1ddfd95 343static int __exit clear_requested_irq(char irq)
1da177e4
LT
344{
345 int i;
f1ddfd95 346 for (i = 0; i < IP2_MAX_BOARDS; ++i) {
1da177e4
LT
347 if (rirqs[i] == irq) {
348 rirqs[i] = 0;
349 return 1;
350 }
351 }
352 return 0;
353}
1da177e4 354
f1ddfd95 355static int have_requested_irq(char irq)
1da177e4 356{
f1ddfd95
JS
357 /* array init to zeros so 0 irq will not be requested as a side
358 * effect */
1da177e4 359 int i;
f1ddfd95 360 for (i = 0; i < IP2_MAX_BOARDS; ++i)
1da177e4
LT
361 if (rirqs[i] == irq)
362 return 1;
1da177e4
LT
363 return 0;
364}
365
1da177e4
LT
366/******************************************************************************/
367/* Function: cleanup_module() */
368/* Parameters: None */
369/* Returns: Nothing */
370/* */
371/* Description: */
372/* This is a required entry point for an installable module. It has to return */
373/* the device and the driver to a passive state. It should not be necessary */
374/* to reset the board fully, especially as the loadware is downloaded */
375/* externally rather than in the driver. We just want to disable the board */
376/* and clear the loadware to a reset state. To allow this there has to be a */
377/* way to detect whether the board has the loadware running at init time to */
378/* handle subsequent installations of the driver. All memory allocated by the */
379/* driver should be returned since it may be unloaded from memory. */
380/******************************************************************************/
7ccd7020 381static void __exit ip2_cleanup_module(void)
1da177e4
LT
382{
383 int err;
384 int i;
385
9d020a2e 386 del_timer_sync(&PollTimer);
1da177e4
LT
387
388 /* Reset the boards we have. */
f1ddfd95
JS
389 for (i = 0; i < IP2_MAX_BOARDS; i++)
390 if (i2BoardPtrTable[i])
391 iiReset(i2BoardPtrTable[i]);
1da177e4
LT
392
393 /* The following is done at most once, if any boards were installed. */
f1ddfd95
JS
394 for (i = 0; i < IP2_MAX_BOARDS; i++) {
395 if (i2BoardPtrTable[i]) {
396 iiResetDelay(i2BoardPtrTable[i]);
1da177e4 397 /* free io addresses and Tibet */
f1ddfd95 398 release_region(ip2config.addr[i], 8);
07c015e7 399 device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
f1ddfd95
JS
400 device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
401 4 * i + 1));
1da177e4
LT
402 }
403 /* Disable and remove interrupt handler. */
f1ddfd95
JS
404 if (ip2config.irq[i] > 0 &&
405 have_requested_irq(ip2config.irq[i])) {
406 free_irq(ip2config.irq[i], (void *)&pcName);
407 clear_requested_irq(ip2config.irq[i]);
1da177e4
LT
408 }
409 }
ca8eca68 410 class_destroy(ip2_class);
f1ddfd95
JS
411 err = tty_unregister_driver(ip2_tty_driver);
412 if (err)
413 printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
414 err);
1da177e4 415 put_tty_driver(ip2_tty_driver);
68fc4fab 416 unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
c74c120a 417 remove_proc_entry("ip2mem", NULL);
1da177e4 418
f1ddfd95 419 /* free memory */
1da177e4
LT
420 for (i = 0; i < IP2_MAX_BOARDS; i++) {
421 void *pB;
422#ifdef CONFIG_PCI
423 if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
424 pci_disable_device(ip2config.pci_dev[i]);
1aff0eca 425 pci_dev_put(ip2config.pci_dev[i]);
1da177e4
LT
426 ip2config.pci_dev[i] = NULL;
427 }
428#endif
7ccd7020
JS
429 pB = i2BoardPtrTable[i];
430 if (pB != NULL) {
f1ddfd95 431 kfree(pB);
1da177e4
LT
432 i2BoardPtrTable[i] = NULL;
433 }
f1ddfd95
JS
434 if (DevTableMem[i] != NULL) {
435 kfree(DevTableMem[i]);
1da177e4
LT
436 DevTableMem[i] = NULL;
437 }
438 }
1da177e4 439}
83e422b7 440module_exit(ip2_cleanup_module);
1da177e4 441
b68e31d0 442static const struct tty_operations ip2_ops = {
1da177e4
LT
443 .open = ip2_open,
444 .close = ip2_close,
445 .write = ip2_write,
446 .put_char = ip2_putchar,
447 .flush_chars = ip2_flush_chars,
448 .write_room = ip2_write_room,
449 .chars_in_buffer = ip2_chars_in_buf,
450 .flush_buffer = ip2_flush_buffer,
451 .ioctl = ip2_ioctl,
452 .throttle = ip2_throttle,
453 .unthrottle = ip2_unthrottle,
454 .set_termios = ip2_set_termios,
455 .set_ldisc = ip2_set_line_discipline,
456 .stop = ip2_stop,
457 .start = ip2_start,
458 .hangup = ip2_hangup,
1da177e4
LT
459 .tiocmget = ip2_tiocmget,
460 .tiocmset = ip2_tiocmset,
0587102c 461 .get_icount = ip2_get_icount,
cdda7cd9 462 .proc_fops = &ip2_proc_fops,
1da177e4
LT
463};
464
465/******************************************************************************/
466/* Function: ip2_loadmain() */
467/* Parameters: irq, io from command line of insmod et. al. */
468/* pointer to fip firmware and firmware size for boards */
469/* Returns: Success (0) */
470/* */
471/* Description: */
472/* This was the required entry point for all drivers (now in ip2.c) */
473/* It performs all */
474/* initialisation of the devices and driver structures, and registers itself */
475/* with the relevant kernel modules. */
476/******************************************************************************/
0f2ed4c6
TG
477/* IRQF_DISABLED - if set blocks all interrupts else only this line */
478/* IRQF_SHARED - for shared irq PCI or maybe EISA only */
1da177e4
LT
479/* SA_RANDOM - can be source for cert. random number generators */
480#define IP2_SA_FLAGS 0
481
547d8bb7
DW
482
483static const struct firmware *ip2_request_firmware(void)
484{
485 struct platform_device *pdev;
486 const struct firmware *fw;
487
488 pdev = platform_device_register_simple("ip2", 0, NULL, 0);
489 if (IS_ERR(pdev)) {
490 printk(KERN_ERR "Failed to register platform device for ip2\n");
491 return NULL;
492 }
493 if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) {
494 printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n");
495 fw = NULL;
496 }
497 platform_device_unregister(pdev);
498 return fw;
499}
500
47babd4c
JS
501/******************************************************************************
502 * ip2_setup:
503 * str: kernel command line string
504 *
505 * Can't autoprobe the boards so user must specify configuration on
506 * kernel command line. Sane people build it modular but the others
507 * come here.
508 *
509 * Alternating pairs of io,irq for up to 4 boards.
510 * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
511 *
512 * io=0 => No board
513 * io=1 => PCI
514 * io=2 => EISA
515 * else => ISA I/O address
516 *
517 * irq=0 or invalid for ISA will revert to polling mode
518 *
519 * Any value = -1, do not overwrite compiled in value.
520 *
521 ******************************************************************************/
522static int __init ip2_setup(char *str)
523{
524 int j, ints[10]; /* 4 boards, 2 parameters + 2 */
525 unsigned int i;
526
527 str = get_options(str, ARRAY_SIZE(ints), ints);
528
529 for (i = 0, j = 1; i < 4; i++) {
530 if (j > ints[0])
531 break;
532 if (ints[j] >= 0)
533 io[i] = ints[j];
534 j++;
535 if (j > ints[0])
536 break;
537 if (ints[j] >= 0)
538 irq[i] = ints[j];
539 j++;
540 }
541 return 1;
542}
543__setup("ip2=", ip2_setup);
47babd4c 544
f1ddfd95 545static int __init ip2_loadmain(void)
1da177e4
LT
546{
547 int i, j, box;
548 int err = 0;
1da177e4
LT
549 i2eBordStrPtr pB = NULL;
550 int rc = -1;
547d8bb7 551 const struct firmware *fw = NULL;
02c95a62
RM
552 char *str;
553
554 str = cmd;
1da177e4 555
47babd4c
JS
556 if (poll_only) {
557 /* Hard lock the interrupts to zero */
558 irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
559 }
560
02c95a62
RM
561 /* Check module parameter with 'ip2=' has been passed or not */
562 if (!poll_only && (!strncmp(str, "ip2=", 4)))
563 ip2_setup(str);
564
f1ddfd95 565 ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
1da177e4
LT
566
567 /* process command line arguments to modprobe or
568 insmod i.e. iop & irqp */
569 /* irqp and iop should ALWAYS be specified now... But we check
570 them individually just to be sure, anyways... */
f1ddfd95 571 for (i = 0; i < IP2_MAX_BOARDS; ++i) {
47babd4c
JS
572 ip2config.addr[i] = io[i];
573 if (irq[i] >= 0)
574 ip2config.irq[i] = irq[i];
575 else
576 ip2config.irq[i] = 0;
f1ddfd95
JS
577 /* This is a little bit of a hack. If poll_only=1 on command
578 line back in ip2.c OR all IRQs on all specified boards are
579 explicitly set to 0, then drop to poll only mode and override
580 PCI or EISA interrupts. This superceeds the old hack of
581 triggering if all interrupts were zero (like da default).
582 Still a hack but less prone to random acts of terrorism.
583
584 What we really should do, now that the IRQ default is set
585 to -1, is to use 0 as a hard coded, do not probe.
586
587 /\/\|=mhw=|\/\/
588 */
47babd4c 589 poll_only |= irq[i];
1da177e4
LT
590 }
591 poll_only = !poll_only;
592
1da177e4 593 /* Announce our presence */
f1ddfd95 594 printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
1da177e4
LT
595
596 ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
597 if (!ip2_tty_driver)
598 return -ENOMEM;
599
1da177e4 600 /* Initialise all the boards we can find (up to the maximum). */
f1ddfd95
JS
601 for (i = 0; i < IP2_MAX_BOARDS; ++i) {
602 switch (ip2config.addr[i]) {
1da177e4
LT
603 case 0: /* skip this slot even if card is present */
604 break;
605 default: /* ISA */
606 /* ISA address must be specified */
f1ddfd95
JS
607 if (ip2config.addr[i] < 0x100 ||
608 ip2config.addr[i] > 0x3f8) {
609 printk(KERN_ERR "IP2: Bad ISA board %d "
610 "address %x\n", i,
611 ip2config.addr[i]);
1da177e4 612 ip2config.addr[i] = 0;
f1ddfd95
JS
613 break;
614 }
615 ip2config.type[i] = ISA;
616
617 /* Check for valid irq argument, set for polling if
618 * invalid */
619 if (ip2config.irq[i] &&
620 !is_valid_irq(ip2config.irq[i])) {
621 printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
622 ip2config.irq[i]);
623 /* 0 is polling and is valid in that sense */
624 ip2config.irq[i] = 0;
1da177e4
LT
625 }
626 break;
627 case PCI:
628#ifdef CONFIG_PCI
f1ddfd95 629 {
795877cf 630 struct pci_dev *pdev = NULL;
f1ddfd95
JS
631 u32 addr;
632 int status;
633
634 pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
635 PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
636 if (pdev == NULL) {
637 ip2config.addr[i] = 0;
638 printk(KERN_ERR "IP2: PCI board %d not "
639 "found\n", i);
640 break;
1da177e4 641 }
f1ddfd95
JS
642
643 if (pci_enable_device(pdev)) {
644 dev_err(&pdev->dev, "can't enable device\n");
795877cf 645 goto out;
f1ddfd95
JS
646 }
647 ip2config.type[i] = PCI;
648 ip2config.pci_dev[i] = pci_dev_get(pdev);
649 status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
650 &addr);
651 if (addr & 1)
652 ip2config.addr[i] = (USHORT)(addr & 0xfffe);
653 else
654 dev_err(&pdev->dev, "I/O address error\n");
655
656 ip2config.irq[i] = pdev->irq;
795877cf
RM
657out:
658 pci_dev_put(pdev);
f1ddfd95 659 }
1da177e4 660#else
f1ddfd95
JS
661 printk(KERN_ERR "IP2: PCI card specified but PCI "
662 "support not enabled.\n");
663 printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
664 "defined!\n");
1da177e4
LT
665#endif /* CONFIG_PCI */
666 break;
667 case EISA:
f1ddfd95
JS
668 ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
669 if (ip2config.addr[i] != 0) {
1da177e4
LT
670 /* Eisa_irq set as side effect, boo */
671 ip2config.type[i] = EISA;
672 }
673 ip2config.irq[i] = Eisa_irq;
674 break;
675 } /* switch */
676 } /* for */
1aff0eca 677
f1ddfd95
JS
678 for (i = 0; i < IP2_MAX_BOARDS; ++i) {
679 if (ip2config.addr[i]) {
978550b8
MK
680 pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
681 if (pB) {
1da177e4 682 i2BoardPtrTable[i] = pB;
f1ddfd95
JS
683 iiSetAddress(pB, ip2config.addr[i],
684 ii2DelayTimer);
685 iiReset(pB);
686 } else
687 printk(KERN_ERR "IP2: board memory allocation "
688 "error\n");
1da177e4
LT
689 }
690 }
f1ddfd95
JS
691 for (i = 0; i < IP2_MAX_BOARDS; ++i) {
692 pB = i2BoardPtrTable[i];
693 if (pB != NULL) {
694 iiResetDelay(pB);
1da177e4
LT
695 break;
696 }
697 }
f1ddfd95 698 for (i = 0; i < IP2_MAX_BOARDS; ++i) {
547d8bb7
DW
699 /* We don't want to request the firmware unless we have at
700 least one board */
f1ddfd95 701 if (i2BoardPtrTable[i] != NULL) {
547d8bb7
DW
702 if (!fw)
703 fw = ip2_request_firmware();
704 if (!fw)
705 break;
706 ip2_init_board(i, fw);
1da177e4
LT
707 }
708 }
547d8bb7
DW
709 if (fw)
710 release_firmware(fw);
1da177e4 711
f1ddfd95 712 ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
1da177e4
LT
713
714 ip2_tty_driver->owner = THIS_MODULE;
715 ip2_tty_driver->name = "ttyF";
1da177e4
LT
716 ip2_tty_driver->driver_name = pcDriver_name;
717 ip2_tty_driver->major = IP2_TTY_MAJOR;
718 ip2_tty_driver->minor_start = 0;
719 ip2_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
720 ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL;
721 ip2_tty_driver->init_termios = tty_std_termios;
722 ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
f1ddfd95
JS
723 ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW |
724 TTY_DRIVER_DYNAMIC_DEV;
1da177e4
LT
725 tty_set_operations(ip2_tty_driver, &ip2_ops);
726
f1ddfd95 727 ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
1da177e4 728
f1ddfd95
JS
729 err = tty_register_driver(ip2_tty_driver);
730 if (err) {
731 printk(KERN_ERR "IP2: failed to register tty driver\n");
1da177e4 732 put_tty_driver(ip2_tty_driver);
f1ddfd95
JS
733 return err; /* leaking resources */
734 }
735
736 err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
737 if (err) {
738 printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
739 err);
1da177e4
LT
740 } else {
741 /* create the sysfs class */
ca8eca68 742 ip2_class = class_create(THIS_MODULE, "ip2");
1da177e4
LT
743 if (IS_ERR(ip2_class)) {
744 err = PTR_ERR(ip2_class);
745 goto out_chrdev;
746 }
747 }
748 /* Register the read_procmem thing */
4a5cdb5b 749 if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
1da177e4 750 printk(KERN_ERR "IP2: failed to register read_procmem\n");
f1ddfd95
JS
751 return -EIO; /* leaking resources */
752 }
1da177e4 753
f1ddfd95
JS
754 ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
755 /* Register the interrupt handler or poll handler, depending upon the
756 * specified interrupt.
757 */
1da177e4 758
f1ddfd95
JS
759 for (i = 0; i < IP2_MAX_BOARDS; ++i) {
760 if (ip2config.addr[i] == 0)
761 continue;
1da177e4 762
f1ddfd95
JS
763 pB = i2BoardPtrTable[i];
764 if (pB != NULL) {
03457cd4
GKH
765 device_create(ip2_class, NULL,
766 MKDEV(IP2_IPL_MAJOR, 4 * i),
767 NULL, "ipl%d", i);
768 device_create(ip2_class, NULL,
769 MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
770 NULL, "stat%d", i);
f1ddfd95
JS
771
772 for (box = 0; box < ABS_MAX_BOXES; box++)
773 for (j = 0; j < ABS_BIGGEST_BOX; j++)
774 if (pB->i2eChannelMap[box] & (1 << j))
775 tty_register_device(
776 ip2_tty_driver,
777 j + ABS_BIGGEST_BOX *
778 (box+i*ABS_MAX_BOXES),
779 NULL);
780 }
1da177e4 781
f1ddfd95
JS
782 if (poll_only) {
783 /* Poll only forces driver to only use polling and
784 to ignore the probed PCI or EISA interrupts. */
785 ip2config.irq[i] = CIR_POLL;
786 }
787 if (ip2config.irq[i] == CIR_POLL) {
1da177e4 788retry:
9d020a2e
AM
789 if (!timer_pending(&PollTimer)) {
790 mod_timer(&PollTimer, POLL_TIMEOUT);
f1ddfd95 791 printk(KERN_INFO "IP2: polling\n");
1da177e4 792 }
f1ddfd95
JS
793 } else {
794 if (have_requested_irq(ip2config.irq[i]))
795 continue;
796 rc = request_irq(ip2config.irq[i], ip2_interrupt,
797 IP2_SA_FLAGS |
798 (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
799 pcName, i2BoardPtrTable[i]);
800 if (rc) {
801 printk(KERN_ERR "IP2: request_irq failed: "
802 "error %d\n", rc);
803 ip2config.irq[i] = CIR_POLL;
804 printk(KERN_INFO "IP2: Polling %ld/sec.\n",
805 (POLL_TIMEOUT - jiffies));
806 goto retry;
1da177e4 807 }
f1ddfd95
JS
808 mark_requested_irq(ip2config.irq[i]);
809 /* Initialise the interrupt handler bottom half
810 * (aka slih). */
1da177e4
LT
811 }
812 }
f1ddfd95
JS
813
814 for (i = 0; i < IP2_MAX_BOARDS; ++i) {
815 if (i2BoardPtrTable[i]) {
816 /* set and enable board interrupt */
817 set_irq(i, ip2config.irq[i]);
818 }
819 }
820
821 ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
822
823 return 0;
1da177e4 824
1da177e4
LT
825out_chrdev:
826 unregister_chrdev(IP2_IPL_MAJOR, "ip2");
f1ddfd95 827 /* unregister and put tty here */
1da177e4
LT
828 return err;
829}
47babd4c 830module_init(ip2_loadmain);
1da177e4 831
1da177e4
LT
832/******************************************************************************/
833/* Function: ip2_init_board() */
834/* Parameters: Index of board in configuration structure */
835/* Returns: Success (0) */
836/* */
837/* Description: */
838/* This function initializes the specified board. The loadware is copied to */
839/* the board, the channel structures are initialized, and the board details */
840/* are reported on the console. */
841/******************************************************************************/
673e321c 842static void
547d8bb7 843ip2_init_board(int boardnum, const struct firmware *fw)
1da177e4
LT
844{
845 int i;
846 int nports = 0, nboxes = 0;
847 i2ChanStrPtr pCh;
848 i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
849
850 if ( !iiInitialize ( pB ) ) {
851 printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n",
852 pB->i2eBase, pB->i2eError );
853 goto err_initialize;
854 }
855 printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1,
856 ip2config.addr[boardnum], ip2config.irq[boardnum] );
857
858 if (!request_region( ip2config.addr[boardnum], 8, pcName )) {
859 printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]);
860 goto err_initialize;
861 }
862
547d8bb7 863 if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size )
1da177e4
LT
864 != II_DOWN_GOOD ) {
865 printk ( KERN_ERR "IP2: failed to download loadware\n" );
866 goto err_release_region;
867 } else {
868 printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n",
869 pB->i2ePom.e.porVersion,
870 pB->i2ePom.e.porRevision,
871 pB->i2ePom.e.porSubRev, pB->i2eLVersion,
872 pB->i2eLRevision, pB->i2eLSub );
873 }
874
875 switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) {
876
877 default:
878 printk( KERN_ERR "IP2: Unknown board type, ID = %x\n",
879 pB->i2ePom.e.porID );
880 nports = 0;
881 goto err_release_region;
882 break;
883
884 case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */
885 printk ( KERN_INFO "IP2: ISA-4\n" );
886 nports = 4;
887 break;
888
889 case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */
890 printk ( KERN_INFO "IP2: ISA-8 std\n" );
891 nports = 8;
892 break;
893
894 case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */
895 printk ( KERN_INFO "IP2: ISA-8 RJ11\n" );
896 nports = 8;
897 break;
898
899 case POR_ID_FIIEX: /* IntelliPort IIEX */
900 {
901 int portnum = IP2_PORTS_PER_BOARD * boardnum;
902 int box;
903
904 for( box = 0; box < ABS_MAX_BOXES; ++box ) {
905 if ( pB->i2eChannelMap[box] != 0 ) {
906 ++nboxes;
907 }
908 for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
909 if ( pB->i2eChannelMap[box] & 1<< i ) {
910 ++nports;
911 }
912 }
913 }
914 DevTableMem[boardnum] = pCh =
915 kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL );
916 if ( !pCh ) {
917 printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
918 goto err_release_region;
919 }
920 if ( !i2InitChannels( pB, nports, pCh ) ) {
921 printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
922 kfree ( pCh );
923 goto err_release_region;
924 }
925 pB->i2eChannelPtr = &DevTable[portnum];
926 pB->i2eChannelCnt = ABS_MOST_PORTS;
927
928 for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) {
929 for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
930 if ( pB->i2eChannelMap[box] & (1 << i) ) {
931 DevTable[portnum + i] = pCh;
932 pCh->port_index = portnum + i;
933 pCh++;
934 }
935 }
936 }
937 printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n",
938 nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 );
939 }
940 goto ex_exit;
941 }
942 DevTableMem[boardnum] = pCh =
943 kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL );
944 if ( !pCh ) {
945 printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
946 goto err_release_region;
947 }
948 pB->i2eChannelPtr = pCh;
949 pB->i2eChannelCnt = nports;
950 if ( !i2InitChannels( pB, nports, pCh ) ) {
951 printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
952 kfree ( pCh );
953 goto err_release_region;
954 }
955 pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum];
956
957 for( i = 0; i < pB->i2eChannelCnt; ++i ) {
958 DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh;
959 pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i;
960 pCh++;
961 }
962ex_exit:
c4028958 963 INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh);
1da177e4
LT
964 return;
965
966err_release_region:
967 release_region(ip2config.addr[boardnum], 8);
968err_initialize:
969 kfree ( pB );
970 i2BoardPtrTable[boardnum] = NULL;
971 return;
972}
973
974/******************************************************************************/
975/* Function: find_eisa_board ( int start_slot ) */
976/* Parameters: First slot to check */
977/* Returns: Address of EISA IntelliPort II controller */
978/* */
979/* Description: */
980/* This function searches for an EISA IntelliPort controller, starting */
981/* from the specified slot number. If the motherboard is not identified as an */
982/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
983/* it returns the base address of the controller. */
984/******************************************************************************/
673e321c 985static unsigned short
1da177e4
LT
986find_eisa_board( int start_slot )
987{
988 int i, j;
989 unsigned int idm = 0;
990 unsigned int idp = 0;
991 unsigned int base = 0;
992 unsigned int value;
993 int setup_address;
994 int setup_irq;
995 int ismine = 0;
996
997 /*
998 * First a check for an EISA motherboard, which we do by comparing the
999 * EISA ID registers for the system board and the first couple of slots.
1000 * No slot ID should match the system board ID, but on an ISA or PCI
1001 * machine the odds are that an empty bus will return similar values for
1002 * each slot.
1003 */
1004 i = 0x0c80;
1005 value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3);
1006 for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) {
1007 j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3);
1008 if ( value == j )
1009 return 0;
1010 }
1011
1012 /*
1013 * OK, so we are inclined to believe that this is an EISA machine. Find
1014 * an IntelliPort controller.
1015 */
1016 for( i = start_slot; i < 16; i++ ) {
1017 base = i << 12;
1018 idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff);
1019 idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff);
1020 ismine = 0;
1021 if ( idm == 0x0e8e ) {
1022 if ( idp == 0x0281 || idp == 0x0218 ) {
1023 ismine = 1;
1024 } else if ( idp == 0x0282 || idp == 0x0283 ) {
1025 ismine = 3; /* Can do edge-trigger */
1026 }
1027 if ( ismine ) {
1028 Eisa_slot = i;
1029 break;
1030 }
1031 }
1032 }
1033 if ( !ismine )
1034 return 0;
1035
1036 /* It's some sort of EISA card, but at what address is it configured? */
1037
1038 setup_address = base + 0xc88;
1039 value = inb(base + 0xc86);
1040 setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0;
1041
1042 if ( (ismine & 2) && !(value & 0x10) ) {
1043 ismine = 1; /* Could be edging, but not */
1044 }
1045
1046 if ( Eisa_irq == 0 ) {
1047 Eisa_irq = setup_irq;
1048 } else if ( Eisa_irq != setup_irq ) {
1049 printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" );
1050 }
1051
1052#ifdef IP2DEBUG_INIT
1053printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x",
1054 base >> 12, idm, idp, setup_address);
1055 if ( Eisa_irq ) {
1056 printk(KERN_DEBUG ", Interrupt %d %s\n",
1057 setup_irq, (ismine & 2) ? "(edge)" : "(level)");
1058 } else {
1059 printk(KERN_DEBUG ", (polled)\n");
1060 }
1061#endif
1062 return setup_address;
1063}
1064
1065/******************************************************************************/
1066/* Function: set_irq() */
1067/* Parameters: index to board in board table */
1068/* IRQ to use */
1069/* Returns: Success (0) */
1070/* */
1071/* Description: */
1072/******************************************************************************/
1073static void
1074set_irq( int boardnum, int boardIrq )
1075{
1076 unsigned char tempCommand[16];
1077 i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
1078 unsigned long flags;
1079
1080 /*
1081 * Notify the boards they may generate interrupts. This is done by
1082 * sending an in-line command to channel 0 on each board. This is why
1083 * the channels have to be defined already. For each board, if the
1084 * interrupt has never been defined, we must do so NOW, directly, since
1085 * board will not send flow control or even give an interrupt until this
1086 * is done. If polling we must send 0 as the interrupt parameter.
1087 */
1088
1089 // We will get an interrupt here at the end of this function
1090
1091 iiDisableMailIrq(pB);
1092
1093 /* We build up the entire packet header. */
1094 CHANNEL_OF(tempCommand) = 0;
1095 PTYPE_OF(tempCommand) = PTYPE_INLINE;
1096 CMD_COUNT_OF(tempCommand) = 2;
1097 (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ;
1098 (CMD_OF(tempCommand))[1] = boardIrq;
1099 /*
1100 * Write to FIFO; don't bother to adjust fifo capacity for this, since
1101 * board will respond almost immediately after SendMail hit.
1102 */
cf1c63c3 1103 write_lock_irqsave(&pB->write_fifo_spinlock, flags);
1da177e4 1104 iiWriteBuf(pB, tempCommand, 4);
cf1c63c3 1105 write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
1da177e4
LT
1106 pB->i2eUsingIrq = boardIrq;
1107 pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
1108
1109 /* Need to update number of boards before you enable mailbox int */
1110 ++i2nBoards;
1111
1112 CHANNEL_OF(tempCommand) = 0;
1113 PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1114 CMD_COUNT_OF(tempCommand) = 6;
1115 (CMD_OF(tempCommand))[0] = 88; // SILO
1116 (CMD_OF(tempCommand))[1] = 64; // chars
1117 (CMD_OF(tempCommand))[2] = 32; // ms
1118
1119 (CMD_OF(tempCommand))[3] = 28; // MAX_BLOCK
1120 (CMD_OF(tempCommand))[4] = 64; // chars
1121
1122 (CMD_OF(tempCommand))[5] = 87; // HW_TEST
cf1c63c3 1123 write_lock_irqsave(&pB->write_fifo_spinlock, flags);
1da177e4 1124 iiWriteBuf(pB, tempCommand, 8);
cf1c63c3 1125 write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
1da177e4
LT
1126
1127 CHANNEL_OF(tempCommand) = 0;
1128 PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1129 CMD_COUNT_OF(tempCommand) = 1;
1130 (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */
1131 iiWriteBuf(pB, tempCommand, 3);
1132
1133#ifdef XXX
1134 // enable heartbeat for test porpoises
1135 CHANNEL_OF(tempCommand) = 0;
1136 PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1137 CMD_COUNT_OF(tempCommand) = 2;
1138 (CMD_OF(tempCommand))[0] = 44; /* get ping */
1139 (CMD_OF(tempCommand))[1] = 200; /* 200 ms */
cf1c63c3 1140 write_lock_irqsave(&pB->write_fifo_spinlock, flags);
1da177e4 1141 iiWriteBuf(pB, tempCommand, 4);
cf1c63c3 1142 write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
1da177e4
LT
1143#endif
1144
1145 iiEnableMailIrq(pB);
1146 iiSendPendingMail(pB);
1147}
1148
1149/******************************************************************************/
1150/* Interrupt Handler Section */
1151/******************************************************************************/
1152
1153static inline void
1154service_all_boards(void)
1155{
1156 int i;
1157 i2eBordStrPtr pB;
1158
1159 /* Service every board on the list */
1160 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
1161 pB = i2BoardPtrTable[i];
1162 if ( pB ) {
1163 i2ServiceBoard( pB );
1164 }
1165 }
1166}
1167
1168
1169/******************************************************************************/
c4028958
DH
1170/* Function: ip2_interrupt_bh(work) */
1171/* Parameters: work - pointer to the board structure */
1da177e4
LT
1172/* Returns: Nothing */
1173/* */
1174/* Description: */
1175/* Service the board in a bottom half interrupt handler and then */
1176/* reenable the board's interrupts if it has an IRQ number */
1177/* */
1178/******************************************************************************/
1179static void
c4028958 1180ip2_interrupt_bh(struct work_struct *work)
1da177e4 1181{
c4028958 1182 i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt);
1da177e4
LT
1183// pB better well be set or we have a problem! We can only get
1184// here from the IMMEDIATE queue. Here, we process the boards.
1185// Checking pB doesn't cost much and it saves us from the sanity checkers.
1186
1187 bh_counter++;
1188
1189 if ( pB ) {
1190 i2ServiceBoard( pB );
1191 if( pB->i2eUsingIrq ) {
1192// Re-enable his interrupts
1193 iiEnableMailIrq(pB);
1194 }
1195 }
1196}
1197
1198
1199/******************************************************************************/
7d12e780 1200/* Function: ip2_interrupt(int irq, void *dev_id) */
1da177e4
LT
1201/* Parameters: irq - interrupt number */
1202/* pointer to optional device ID structure */
1da177e4
LT
1203/* Returns: Nothing */
1204/* */
1205/* Description: */
1206/* */
1207/* Our task here is simply to identify each board which needs servicing. */
1208/* If we are queuing then, queue it to be serviced, and disable its irq */
1209/* mask otherwise process the board directly. */
1210/* */
1211/* We could queue by IRQ but that just complicates things on both ends */
1212/* with very little gain in performance (how many instructions does */
1213/* it take to iterate on the immediate queue). */
1214/* */
1215/* */
1216/******************************************************************************/
f3518e4e
JG
1217static void
1218ip2_irq_work(i2eBordStrPtr pB)
1219{
1220#ifdef USE_IQI
1221 if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) {
1222// Disable his interrupt (will be enabled when serviced)
1223// This is mostly to protect from reentrancy.
1224 iiDisableMailIrq(pB);
1225
1226// Park the board on the immediate queue for processing.
1227 schedule_work(&pB->tqueue_interrupt);
1228
1229// Make sure the immediate queue is flagged to fire.
1230 }
1231#else
1232
1233// We are using immediate servicing here. This sucks and can
1234// cause all sorts of havoc with ppp and others. The failsafe
1235// check on iiSendPendingMail could also throw a hairball.
1236
1237 i2ServiceBoard( pB );
1238
1239#endif /* USE_IQI */
1240}
1241
6bd3bd67
JG
1242static void
1243ip2_polled_interrupt(void)
1da177e4
LT
1244{
1245 int i;
1246 i2eBordStrPtr pB;
1da177e4 1247
7ccd7020 1248 ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
1da177e4
LT
1249
1250 /* Service just the boards on the list using this irq */
1251 for( i = 0; i < i2nBoards; ++i ) {
1252 pB = i2BoardPtrTable[i];
1253
1254// Only process those boards which match our IRQ.
1255// IRQ = 0 for polled boards, we won't poll "IRQ" boards
1256
7ccd7020 1257 if (pB && pB->i2eUsingIrq == 0)
f3518e4e 1258 ip2_irq_work(pB);
1da177e4
LT
1259 }
1260
1261 ++irq_counter;
1262
1263 ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
6bd3bd67
JG
1264}
1265
1266static irqreturn_t
1267ip2_interrupt(int irq, void *dev_id)
1268{
1269 i2eBordStrPtr pB = dev_id;
1270
1271 ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq );
1272
1273 ip2_irq_work(pB);
1274
1275 ++irq_counter;
1276
1277 ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1278 return IRQ_HANDLED;
1da177e4
LT
1279}
1280
1281/******************************************************************************/
1282/* Function: ip2_poll(unsigned long arg) */
1283/* Parameters: ? */
1284/* Returns: Nothing */
1285/* */
1286/* Description: */
1287/* This function calls the library routine i2ServiceBoard for each board in */
1288/* the board table. This is used instead of the interrupt routine when polled */
1289/* mode is specified. */
1290/******************************************************************************/
1291static void
1292ip2_poll(unsigned long arg)
1293{
1294 ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
1295
1da177e4
LT
1296 // Just polled boards, IRQ = 0 will hit all non-interrupt boards.
1297 // It will NOT poll boards handled by hard interrupts.
8dfba4d7 1298 // The issue of queued BH interrupts is handled in ip2_interrupt().
6bd3bd67 1299 ip2_polled_interrupt();
1da177e4 1300
9d020a2e 1301 mod_timer(&PollTimer, POLL_TIMEOUT);
1da177e4
LT
1302
1303 ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1304}
1305
c4028958 1306static void do_input(struct work_struct *work)
1da177e4 1307{
c4028958 1308 i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input);
1da177e4
LT
1309 unsigned long flags;
1310
1311 ip2trace(CHANN, ITRC_INPUT, 21, 0 );
1312
1313 // Data input
1314 if ( pCh->pTTY != NULL ) {
cf1c63c3 1315 read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
1da177e4 1316 if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
cf1c63c3 1317 read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
1da177e4
LT
1318 i2Input( pCh );
1319 } else
cf1c63c3 1320 read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
1da177e4
LT
1321 } else {
1322 ip2trace(CHANN, ITRC_INPUT, 22, 0 );
1323
1324 i2InputFlush( pCh );
1325 }
1326}
1327
1328// code duplicated from n_tty (ldisc)
1329static inline void isig(int sig, struct tty_struct *tty, int flush)
1330{
a352def2 1331 /* FIXME: This is completely bogus */
ab521dc0
EB
1332 if (tty->pgrp)
1333 kill_pgrp(tty->pgrp, sig, 1);
1da177e4 1334 if (flush || !L_NOFLSH(tty)) {
c65c9bc3
AC
1335 if ( tty->ldisc->ops->flush_buffer )
1336 tty->ldisc->ops->flush_buffer(tty);
1da177e4
LT
1337 i2InputFlush( tty->driver_data );
1338 }
1339}
1340
c4028958 1341static void do_status(struct work_struct *work)
1da177e4 1342{
c4028958 1343 i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status);
1da177e4
LT
1344 int status;
1345
1346 status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
1347
1348 ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
1349
1350 if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
1351 if ( (status & I2_BRK) ) {
1352 // code duplicated from n_tty (ldisc)
1353 if (I_IGNBRK(pCh->pTTY))
1354 goto skip_this;
1355 if (I_BRKINT(pCh->pTTY)) {
1356 isig(SIGINT, pCh->pTTY, 1);
1357 goto skip_this;
1358 }
1359 wake_up_interruptible(&pCh->pTTY->read_wait);
1360 }
1361#ifdef NEVER_HAPPENS_AS_SETUP_XXX
1362 // and can't work because we don't know the_char
1363 // as the_char is reported on a separate path
1364 // The intelligent board does this stuff as setup
1365 {
1366 char brkf = TTY_NORMAL;
1367 unsigned char brkc = '\0';
1368 unsigned char tmp;
1369 if ( (status & I2_BRK) ) {
1370 brkf = TTY_BREAK;
1371 brkc = '\0';
1372 }
1373 else if (status & I2_PAR) {
1374 brkf = TTY_PARITY;
1375 brkc = the_char;
1376 } else if (status & I2_FRA) {
1377 brkf = TTY_FRAME;
1378 brkc = the_char;
1379 } else if (status & I2_OVR) {
1380 brkf = TTY_OVERRUN;
1381 brkc = the_char;
1382 }
1383 tmp = pCh->pTTY->real_raw;
1384 pCh->pTTY->real_raw = 0;
a352def2 1385 pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 );
1da177e4
LT
1386 pCh->pTTY->real_raw = tmp;
1387 }
1388#endif /* NEVER_HAPPENS_AS_SETUP_XXX */
1389 }
1390skip_this:
1391
1392 if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) {
1393 wake_up_interruptible(&pCh->delta_msr_wait);
1394
1395 if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) {
1396 if ( status & I2_DCD ) {
1397 if ( pCh->wopen ) {
1398 wake_up_interruptible ( &pCh->open_wait );
1399 }
1400 } else {
1401 if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) {
1402 tty_hangup( pCh->pTTY );
1403 }
1404 }
1405 }
1406 }
1407
1408 ip2trace (CHANN, ITRC_STATUS, 26, 0 );
1409}
1410
1411/******************************************************************************/
1412/* Device Open/Close/Ioctl Entry Point Section */
1413/******************************************************************************/
1414
1415/******************************************************************************/
1416/* Function: open_sanity_check() */
1417/* Parameters: Pointer to tty structure */
1418/* Pointer to file structure */
1419/* Returns: Success or failure */
1420/* */
1421/* Description: */
1422/* Verifies the structure magic numbers and cross links. */
1423/******************************************************************************/
1424#ifdef IP2DEBUG_OPEN
1425static void
1426open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd )
1427{
1428 if ( pBrd->i2eValid != I2E_MAGIC ) {
1429 printk(KERN_ERR "IP2: invalid board structure\n" );
1430 } else if ( pBrd != pCh->pMyBord ) {
1431 printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n",
1432 pCh->pMyBord );
1433 } else if ( pBrd->i2eChannelCnt < pCh->port_index ) {
1434 printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index );
1435 } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) {
1436 } else {
1437 printk(KERN_INFO "IP2: all pointers check out!\n" );
1438 }
1439}
1440#endif
1441
1442
1443/******************************************************************************/
1444/* Function: ip2_open() */
1445/* Parameters: Pointer to tty structure */
1446/* Pointer to file structure */
1447/* Returns: Success or failure */
1448/* */
1449/* Description: (MANDATORY) */
1450/* A successful device open has to run a gauntlet of checks before it */
1451/* completes. After some sanity checking and pointer setup, the function */
1452/* blocks until all conditions are satisfied. It then initialises the port to */
1453/* the default characteristics and returns. */
1454/******************************************************************************/
1455static int
1456ip2_open( PTTY tty, struct file *pFile )
1457{
1458 wait_queue_t wait;
1459 int rc = 0;
1460 int do_clocal = 0;
1461 i2ChanStrPtr pCh = DevTable[tty->index];
1462
1463 ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 );
1464
1465 if ( pCh == NULL ) {
1466 return -ENODEV;
1467 }
1468 /* Setup pointer links in device and tty structures */
1469 pCh->pTTY = tty;
1470 tty->driver_data = pCh;
1471
1472#ifdef IP2DEBUG_OPEN
1473 printk(KERN_DEBUG \
1474 "IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n",
1475 tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index);
1476 open_sanity_check ( pCh, pCh->pMyBord );
1477#endif
1478
1479 i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
1480 pCh->dataSetOut |= (I2_DTR | I2_RTS);
1481 serviceOutgoingFifo( pCh->pMyBord );
1482
1483 /* Block here until the port is ready (per serial and istallion) */
1484 /*
1485 * 1. If the port is in the middle of closing wait for the completion
1486 * and then return the appropriate error.
1487 */
1488 init_waitqueue_entry(&wait, current);
1489 add_wait_queue(&pCh->close_wait, &wait);
1490 set_current_state( TASK_INTERRUPTIBLE );
1491
1492 if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
1493 if ( pCh->flags & ASYNC_CLOSING ) {
e142a31d 1494 tty_unlock();
1da177e4 1495 schedule();
e142a31d 1496 tty_lock();
1da177e4
LT
1497 }
1498 if ( tty_hung_up_p(pFile) ) {
1499 set_current_state( TASK_RUNNING );
1500 remove_wait_queue(&pCh->close_wait, &wait);
1501 return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS;
1502 }
1503 }
1504 set_current_state( TASK_RUNNING );
1505 remove_wait_queue(&pCh->close_wait, &wait);
1506
1507 /*
1508 * 3. Handle a non-blocking open of a normal port.
1509 */
1510 if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) {
1511 pCh->flags |= ASYNC_NORMAL_ACTIVE;
1512 goto noblock;
1513 }
1514 /*
1515 * 4. Now loop waiting for the port to be free and carrier present
1516 * (if required).
1517 */
1518 if ( tty->termios->c_cflag & CLOCAL )
1519 do_clocal = 1;
1520
1521#ifdef IP2DEBUG_OPEN
1522 printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);
1523#endif
1524
1525 ++pCh->wopen;
1526
1527 init_waitqueue_entry(&wait, current);
1528 add_wait_queue(&pCh->open_wait, &wait);
1529
1530 for(;;) {
1531 i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
1532 pCh->dataSetOut |= (I2_DTR | I2_RTS);
1533 set_current_state( TASK_INTERRUPTIBLE );
1534 serviceOutgoingFifo( pCh->pMyBord );
1535 if ( tty_hung_up_p(pFile) ) {
1536 set_current_state( TASK_RUNNING );
1537 remove_wait_queue(&pCh->open_wait, &wait);
1538 return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS;
1539 }
1540 if (!(pCh->flags & ASYNC_CLOSING) &&
1541 (do_clocal || (pCh->dataSetIn & I2_DCD) )) {
1542 rc = 0;
1543 break;
1544 }
1545
1546#ifdef IP2DEBUG_OPEN
1547 printk(KERN_DEBUG "ASYNC_CLOSING = %s\n",
1548 (pCh->flags & ASYNC_CLOSING)?"True":"False");
1549 printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
1550#endif
1551 ip2trace (CHANN, ITRC_OPEN, 3, 2, 0,
1552 (pCh->flags & ASYNC_CLOSING) );
1553 /* check for signal */
1554 if (signal_pending(current)) {
1555 rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
1556 break;
1557 }
e142a31d 1558 tty_unlock();
1da177e4 1559 schedule();
e142a31d 1560 tty_lock();
1da177e4
LT
1561 }
1562 set_current_state( TASK_RUNNING );
1563 remove_wait_queue(&pCh->open_wait, &wait);
1564
1565 --pCh->wopen; //why count?
1566
1567 ip2trace (CHANN, ITRC_OPEN, 4, 0 );
1568
1569 if (rc != 0 ) {
1570 return rc;
1571 }
1572 pCh->flags |= ASYNC_NORMAL_ACTIVE;
1573
1574noblock:
1575
1576 /* first open - Assign termios structure to port */
1577 if ( tty->count == 1 ) {
1578 i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
1579 /* Now we must send the termios settings to the loadware */
1580 set_params( pCh, NULL );
1581 }
1582
1583 /*
1584 * Now set any i2lib options. These may go away if the i2lib code ends
1585 * up rolled into the mainline.
1586 */
1587 pCh->channelOptions |= CO_NBLOCK_WRITE;
1588
1589#ifdef IP2DEBUG_OPEN
1590 printk (KERN_DEBUG "IP2: open completed\n" );
1591#endif
1592 serviceOutgoingFifo( pCh->pMyBord );
1593
1594 ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
1595
1596 return 0;
1597}
1598
1599/******************************************************************************/
1600/* Function: ip2_close() */
1601/* Parameters: Pointer to tty structure */
1602/* Pointer to file structure */
1603/* Returns: Nothing */
1604/* */
1605/* Description: */
1606/* */
1607/* */
1608/******************************************************************************/
1609static void
1610ip2_close( PTTY tty, struct file *pFile )
1611{
1612 i2ChanStrPtr pCh = tty->driver_data;
1613
1614 if ( !pCh ) {
1615 return;
1616 }
1617
1618 ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
1619
1620#ifdef IP2DEBUG_OPEN
1621 printk(KERN_DEBUG "IP2:close %s:\n",tty->name);
1622#endif
1623
1624 if ( tty_hung_up_p ( pFile ) ) {
1625
1626 ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
1627
1628 return;
1629 }
1630 if ( tty->count > 1 ) { /* not the last close */
1631
1632 ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
1633
1634 return;
1635 }
1636 pCh->flags |= ASYNC_CLOSING; // last close actually
1637
1638 tty->closing = 1;
1639
1640 if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
1641 /*
1642 * Before we drop DTR, make sure the transmitter has completely drained.
1643 * This uses an timeout, after which the close
1644 * completes.
1645 */
1646 ip2_wait_until_sent(tty, pCh->ClosingWaitTime );
1647 }
1648 /*
1649 * At this point we stop accepting input. Here we flush the channel
1650 * input buffer which will allow the board to send up more data. Any
1651 * additional input is tossed at interrupt/poll time.
1652 */
1653 i2InputFlush( pCh );
1654
1655 /* disable DSS reporting */
1656 i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
1657 CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
f64ac983 1658 if (tty->termios->c_cflag & HUPCL) {
1da177e4
LT
1659 i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
1660 pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
1661 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
1662 }
1663
1664 serviceOutgoingFifo ( pCh->pMyBord );
1665
f34d7a5b 1666 tty_ldisc_flush(tty);
a6fc819e 1667 tty_driver_flush_buffer(tty);
1da177e4
LT
1668 tty->closing = 0;
1669
1670 pCh->pTTY = NULL;
1671
1672 if (pCh->wopen) {
1673 if (pCh->ClosingDelay) {
1674 msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay));
1675 }
1676 wake_up_interruptible(&pCh->open_wait);
1677 }
1678
1679 pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1680 wake_up_interruptible(&pCh->close_wait);
1681
1682#ifdef IP2DEBUG_OPEN
1683 DBG_CNT("ip2_close: after wakeups--");
1684#endif
1685
1686
1687 ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
1688
1689 return;
1690}
1691
1692/******************************************************************************/
1693/* Function: ip2_hangup() */
1694/* Parameters: Pointer to tty structure */
1695/* Returns: Nothing */
1696/* */
1697/* Description: */
1698/* */
1699/* */
1700/******************************************************************************/
1701static void
1702ip2_hangup ( PTTY tty )
1703{
1704 i2ChanStrPtr pCh = tty->driver_data;
1705
1706 if( !pCh ) {
1707 return;
1708 }
1709
1710 ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
1711
1712 ip2_flush_buffer(tty);
1713
1714 /* disable DSS reporting */
1715
1716 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP);
1717 i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
1718 if ( (tty->termios->c_cflag & HUPCL) ) {
1719 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN);
1720 pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
1721 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
1722 }
1723 i2QueueCommands(PTYPE_INLINE, pCh, 1, 3,
1724 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
1725 serviceOutgoingFifo ( pCh->pMyBord );
1726
1727 wake_up_interruptible ( &pCh->delta_msr_wait );
1728
1729 pCh->flags &= ~ASYNC_NORMAL_ACTIVE;
1730 pCh->pTTY = NULL;
1731 wake_up_interruptible ( &pCh->open_wait );
1732
1733 ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
1734}
1735
1736/******************************************************************************/
1737/******************************************************************************/
1738/* Device Output Section */
1739/******************************************************************************/
1740/******************************************************************************/
1741
1742/******************************************************************************/
1743/* Function: ip2_write() */
1744/* Parameters: Pointer to tty structure */
1745/* Flag denoting data is in user (1) or kernel (0) space */
1746/* Pointer to data */
1747/* Number of bytes to write */
1748/* Returns: Number of bytes actually written */
1749/* */
1750/* Description: (MANDATORY) */
1751/* */
1752/* */
1753/******************************************************************************/
1754static int
d9e39538 1755ip2_write( PTTY tty, const unsigned char *pData, int count)
1da177e4
LT
1756{
1757 i2ChanStrPtr pCh = tty->driver_data;
1758 int bytesSent = 0;
1759 unsigned long flags;
1760
1761 ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
1762
1763 /* Flush out any buffered data left over from ip2_putchar() calls. */
1764 ip2_flush_chars( tty );
1765
1766 /* This is the actual move bit. Make sure it does what we need!!!!! */
cf1c63c3 1767 write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
f061c584 1768 bytesSent = i2Output( pCh, pData, count);
cf1c63c3 1769 write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1da177e4
LT
1770
1771 ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
1772
1773 return bytesSent > 0 ? bytesSent : 0;
1774}
1775
1776/******************************************************************************/
1777/* Function: ip2_putchar() */
1778/* Parameters: Pointer to tty structure */
1779/* Character to write */
1780/* Returns: Nothing */
1781/* */
1782/* Description: */
1783/* */
1784/* */
1785/******************************************************************************/
f34d7a5b 1786static int
1da177e4
LT
1787ip2_putchar( PTTY tty, unsigned char ch )
1788{
1789 i2ChanStrPtr pCh = tty->driver_data;
1790 unsigned long flags;
1791
1792// ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
1793
cf1c63c3 1794 write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1da177e4
LT
1795 pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
1796 if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
cf1c63c3 1797 write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1da177e4
LT
1798 ip2_flush_chars( tty );
1799 } else
cf1c63c3 1800 write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
f34d7a5b 1801 return 1;
1da177e4
LT
1802
1803// ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
1804}
1805
1806/******************************************************************************/
1807/* Function: ip2_flush_chars() */
1808/* Parameters: Pointer to tty structure */
1809/* Returns: Nothing */
1810/* */
1811/* Description: */
1812/* */
1813/******************************************************************************/
1814static void
1815ip2_flush_chars( PTTY tty )
1816{
1817 int strip;
1818 i2ChanStrPtr pCh = tty->driver_data;
1819 unsigned long flags;
1820
cf1c63c3 1821 write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1da177e4
LT
1822 if ( pCh->Pbuf_stuff ) {
1823
1824// ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
1825
1826 //
25985edc 1827 // We may need to restart i2Output if it does not fulfill this request
1da177e4 1828 //
f061c584 1829 strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff);
1da177e4
LT
1830 if ( strip != pCh->Pbuf_stuff ) {
1831 memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
1832 }
1833 pCh->Pbuf_stuff -= strip;
1834 }
cf1c63c3 1835 write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1da177e4
LT
1836}
1837
1838/******************************************************************************/
1839/* Function: ip2_write_room() */
1840/* Parameters: Pointer to tty structure */
1841/* Returns: Number of bytes that the driver can accept */
1842/* */
1843/* Description: */
1844/* */
1845/******************************************************************************/
1846static int
1847ip2_write_room ( PTTY tty )
1848{
1849 int bytesFree;
1850 i2ChanStrPtr pCh = tty->driver_data;
1851 unsigned long flags;
1852
cf1c63c3 1853 read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1da177e4 1854 bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
cf1c63c3 1855 read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1da177e4
LT
1856
1857 ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
1858
1859 return ((bytesFree > 0) ? bytesFree : 0);
1860}
1861
1862/******************************************************************************/
1863/* Function: ip2_chars_in_buf() */
1864/* Parameters: Pointer to tty structure */
1865/* Returns: Number of bytes queued for transmission */
1866/* */
1867/* Description: */
1868/* */
1869/* */
1870/******************************************************************************/
1871static int
1872ip2_chars_in_buf ( PTTY tty )
1873{
1874 i2ChanStrPtr pCh = tty->driver_data;
1875 int rc;
1876 unsigned long flags;
1877
1878 ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
1879
1880#ifdef IP2DEBUG_WRITE
1881 printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
1882 pCh->Obuf_char_count + pCh->Pbuf_stuff,
1883 pCh->Obuf_char_count, pCh->Pbuf_stuff );
1884#endif
cf1c63c3 1885 read_lock_irqsave(&pCh->Obuf_spinlock, flags);
1da177e4 1886 rc = pCh->Obuf_char_count;
cf1c63c3
JS
1887 read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
1888 read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1da177e4 1889 rc += pCh->Pbuf_stuff;
cf1c63c3 1890 read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1da177e4
LT
1891 return rc;
1892}
1893
1894/******************************************************************************/
1895/* Function: ip2_flush_buffer() */
1896/* Parameters: Pointer to tty structure */
1897/* Returns: Nothing */
1898/* */
1899/* Description: */
1900/* */
1901/* */
1902/******************************************************************************/
1903static void
1904ip2_flush_buffer( PTTY tty )
1905{
1906 i2ChanStrPtr pCh = tty->driver_data;
1907 unsigned long flags;
1908
1909 ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
1910
1911#ifdef IP2DEBUG_WRITE
1912 printk (KERN_DEBUG "IP2: flush buffer\n" );
1913#endif
cf1c63c3 1914 write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1da177e4 1915 pCh->Pbuf_stuff = 0;
cf1c63c3 1916 write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1da177e4
LT
1917 i2FlushOutput( pCh );
1918 ip2_owake(tty);
1919
1920 ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
1921
1922}
1923
1924/******************************************************************************/
1925/* Function: ip2_wait_until_sent() */
1926/* Parameters: Pointer to tty structure */
1927/* Timeout for wait. */
1928/* Returns: Nothing */
1929/* */
1930/* Description: */
1931/* This function is used in place of the normal tty_wait_until_sent, which */
1932/* only waits for the driver buffers to be empty (or rather, those buffers */
1933/* reported by chars_in_buffer) which doesn't work for IP2 due to the */
1934/* indeterminate number of bytes buffered on the board. */
1935/******************************************************************************/
1936static void
1937ip2_wait_until_sent ( PTTY tty, int timeout )
1938{
1939 int i = jiffies;
1940 i2ChanStrPtr pCh = tty->driver_data;
1941
1942 tty_wait_until_sent(tty, timeout );
1943 if ( (i = timeout - (jiffies -i)) > 0)
1944 i2DrainOutput( pCh, i );
1945}
1946
1947/******************************************************************************/
1948/******************************************************************************/
1949/* Device Input Section */
1950/******************************************************************************/
1951/******************************************************************************/
1952
1953/******************************************************************************/
1954/* Function: ip2_throttle() */
1955/* Parameters: Pointer to tty structure */
1956/* Returns: Nothing */
1957/* */
1958/* Description: */
1959/* */
1960/* */
1961/******************************************************************************/
1962static void
1963ip2_throttle ( PTTY tty )
1964{
1965 i2ChanStrPtr pCh = tty->driver_data;
1966
1967#ifdef IP2DEBUG_READ
1968 printk (KERN_DEBUG "IP2: throttle\n" );
1969#endif
1970 /*
1971 * Signal the poll/interrupt handlers not to forward incoming data to
1972 * the line discipline. This will cause the buffers to fill up in the
1973 * library and thus cause the library routines to send the flow control
1974 * stuff.
1975 */
1976 pCh->throttled = 1;
1977}
1978
1979/******************************************************************************/
1980/* Function: ip2_unthrottle() */
1981/* Parameters: Pointer to tty structure */
1982/* Returns: Nothing */
1983/* */
1984/* Description: */
1985/* */
1986/* */
1987/******************************************************************************/
1988static void
1989ip2_unthrottle ( PTTY tty )
1990{
1991 i2ChanStrPtr pCh = tty->driver_data;
1992 unsigned long flags;
1993
1994#ifdef IP2DEBUG_READ
1995 printk (KERN_DEBUG "IP2: unthrottle\n" );
1996#endif
1997
1998 /* Pass incoming data up to the line discipline again. */
1999 pCh->throttled = 0;
2000 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
2001 serviceOutgoingFifo( pCh->pMyBord );
cf1c63c3 2002 read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
1da177e4 2003 if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
cf1c63c3 2004 read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
1da177e4
LT
2005#ifdef IP2DEBUG_READ
2006 printk (KERN_DEBUG "i2Input called from unthrottle\n" );
2007#endif
2008 i2Input( pCh );
2009 } else
cf1c63c3 2010 read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
1da177e4
LT
2011}
2012
2013static void
2014ip2_start ( PTTY tty )
2015{
2016 i2ChanStrPtr pCh = DevTable[tty->index];
2017
2018 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
2019 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
2020 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME);
2021#ifdef IP2DEBUG_WRITE
2022 printk (KERN_DEBUG "IP2: start tx\n" );
2023#endif
2024}
2025
2026static void
2027ip2_stop ( PTTY tty )
2028{
2029 i2ChanStrPtr pCh = DevTable[tty->index];
2030
2031 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
2032#ifdef IP2DEBUG_WRITE
2033 printk (KERN_DEBUG "IP2: stop tx\n" );
2034#endif
2035}
2036
2037/******************************************************************************/
2038/* Device Ioctl Section */
2039/******************************************************************************/
2040
60b33c13 2041static int ip2_tiocmget(struct tty_struct *tty)
1da177e4
LT
2042{
2043 i2ChanStrPtr pCh = DevTable[tty->index];
d9e39538 2044#ifdef ENABLE_DSSNOW
1da177e4 2045 wait_queue_t wait;
d9e39538 2046#endif
1da177e4
LT
2047
2048 if (pCh == NULL)
2049 return -ENODEV;
2050
2051/*
2052 FIXME - the following code is causing a NULL pointer dereference in
2053 2.3.51 in an interrupt handler. It's suppose to prompt the board
2054 to return the DSS signal status immediately. Why doesn't it do
2055 the same thing in 2.2.14?
2056*/
2057
2058/* This thing is still busted in the 1.2.12 driver on 2.4.x
2059 and even hoses the serial console so the oops can be trapped.
2060 /\/\|=mhw=|\/\/ */
2061
2062#ifdef ENABLE_DSSNOW
2063 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
2064
2065 init_waitqueue_entry(&wait, current);
2066 add_wait_queue(&pCh->dss_now_wait, &wait);
2067 set_current_state( TASK_INTERRUPTIBLE );
2068
2069 serviceOutgoingFifo( pCh->pMyBord );
2070
2071 schedule();
2072
2073 set_current_state( TASK_RUNNING );
2074 remove_wait_queue(&pCh->dss_now_wait, &wait);
2075
2076 if (signal_pending(current)) {
2077 return -EINTR;
2078 }
2079#endif
2080 return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
2081 | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
2082 | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0)
2083 | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0)
2084 | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0)
2085 | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0);
2086}
2087
20b9d177 2088static int ip2_tiocmset(struct tty_struct *tty,
1da177e4
LT
2089 unsigned int set, unsigned int clear)
2090{
2091 i2ChanStrPtr pCh = DevTable[tty->index];
2092
2093 if (pCh == NULL)
2094 return -ENODEV;
2095
2096 if (set & TIOCM_RTS) {
2097 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
2098 pCh->dataSetOut |= I2_RTS;
2099 }
2100 if (set & TIOCM_DTR) {
2101 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
2102 pCh->dataSetOut |= I2_DTR;
2103 }
2104
2105 if (clear & TIOCM_RTS) {
2106 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
2107 pCh->dataSetOut &= ~I2_RTS;
2108 }
2109 if (clear & TIOCM_DTR) {
2110 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
2111 pCh->dataSetOut &= ~I2_DTR;
2112 }
2113 serviceOutgoingFifo( pCh->pMyBord );
2114 return 0;
2115}
2116
2117/******************************************************************************/
2118/* Function: ip2_ioctl() */
2119/* Parameters: Pointer to tty structure */
2120/* Pointer to file structure */
2121/* Command */
2122/* Argument */
2123/* Returns: Success or failure */
2124/* */
2125/* Description: */
2126/* */
2127/* */
2128/******************************************************************************/
2129static int
6caa76b7 2130ip2_ioctl ( PTTY tty, UINT cmd, ULONG arg )
1da177e4
LT
2131{
2132 wait_queue_t wait;
2133 i2ChanStrPtr pCh = DevTable[tty->index];
d9e39538 2134 i2eBordStrPtr pB;
1da177e4 2135 struct async_icount cprev, cnow; /* kernel counter temps */
1da177e4
LT
2136 int rc = 0;
2137 unsigned long flags;
2138 void __user *argp = (void __user *)arg;
2139
d9e39538 2140 if ( pCh == NULL )
1da177e4 2141 return -ENODEV;
d9e39538
AC
2142
2143 pB = pCh->pMyBord;
1da177e4
LT
2144
2145 ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
2146
2147#ifdef IP2DEBUG_IOCTL
2148 printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg );
2149#endif
2150
2151 switch(cmd) {
2152 case TIOCGSERIAL:
2153
2154 ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
2155
2156 rc = get_serial_info(pCh, argp);
2157 if (rc)
2158 return rc;
2159 break;
2160
2161 case TIOCSSERIAL:
2162
2163 ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
2164
2165 rc = set_serial_info(pCh, argp);
2166 if (rc)
2167 return rc;
2168 break;
2169
2170 case TCXONC:
2171 rc = tty_check_change(tty);
2172 if (rc)
2173 return rc;
2174 switch (arg) {
2175 case TCOOFF:
2176 //return -ENOIOCTLCMD;
2177 break;
2178 case TCOON:
2179 //return -ENOIOCTLCMD;
2180 break;
2181 case TCIOFF:
2182 if (STOP_CHAR(tty) != __DISABLED_CHAR) {
2183 i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
2184 CMD_XMIT_NOW(STOP_CHAR(tty)));
2185 }
2186 break;
2187 case TCION:
2188 if (START_CHAR(tty) != __DISABLED_CHAR) {
2189 i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
2190 CMD_XMIT_NOW(START_CHAR(tty)));
2191 }
2192 break;
2193 default:
2194 return -EINVAL;
2195 }
2196 return 0;
2197
2198 case TCSBRK: /* SVID version: non-zero arg --> no break */
2199 rc = tty_check_change(tty);
2200
2201 ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
2202
2203 if (!rc) {
2204 ip2_wait_until_sent(tty,0);
2205 if (!arg) {
2206 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250));
2207 serviceOutgoingFifo( pCh->pMyBord );
2208 }
2209 }
2210 break;
2211
2212 case TCSBRKP: /* support for POSIX tcsendbreak() */
2213 rc = tty_check_change(tty);
2214
2215 ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
2216
2217 if (!rc) {
2218 ip2_wait_until_sent(tty,0);
2219 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
2220 CMD_SEND_BRK(arg ? arg*100 : 250));
2221 serviceOutgoingFifo ( pCh->pMyBord );
2222 }
2223 break;
2224
2225 case TIOCGSOFTCAR:
2226
2227 ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
2228
2229 rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
2230 if (rc)
2231 return rc;
2232 break;
2233
2234 case TIOCSSOFTCAR:
2235
2236 ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
2237
2238 rc = get_user(arg,(unsigned long __user *) argp);
2239 if (rc)
2240 return rc;
2241 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
2242 | (arg ? CLOCAL : 0));
2243
2244 break;
2245
2246 /*
2247 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
2248 * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
2249 * for masking). Caller should use TIOCGICOUNT to see which one it was
2250 */
2251 case TIOCMIWAIT:
cf1c63c3 2252 write_lock_irqsave(&pB->read_fifo_spinlock, flags);
1da177e4 2253 cprev = pCh->icount; /* note the counters on entry */
cf1c63c3 2254 write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
1da177e4
LT
2255 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4,
2256 CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
2257 init_waitqueue_entry(&wait, current);
2258 add_wait_queue(&pCh->delta_msr_wait, &wait);
2259 set_current_state( TASK_INTERRUPTIBLE );
2260
2261 serviceOutgoingFifo( pCh->pMyBord );
2262 for(;;) {
2263 ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
2264
2265 schedule();
2266
2267 ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
2268
2269 /* see if a signal did it */
2270 if (signal_pending(current)) {
2271 rc = -ERESTARTSYS;
2272 break;
2273 }
cf1c63c3 2274 write_lock_irqsave(&pB->read_fifo_spinlock, flags);
1da177e4 2275 cnow = pCh->icount; /* atomic copy */
cf1c63c3 2276 write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
1da177e4
LT
2277 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2278 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
2279 rc = -EIO; /* no change => rc */
2280 break;
2281 }
2282 if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2283 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2284 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
2285 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
2286 rc = 0;
2287 break;
2288 }
2289 cprev = cnow;
2290 }
2291 set_current_state( TASK_RUNNING );
2292 remove_wait_queue(&pCh->delta_msr_wait, &wait);
2293
2294 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3,
2295 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
2296 if ( ! (pCh->flags & ASYNC_CHECK_CD)) {
2297 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
2298 }
2299 serviceOutgoingFifo( pCh->pMyBord );
2300 return rc;
2301 break;
2302
1da177e4
LT
2303 /*
2304 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
2305 * will be passed to the line discipline for it to handle.
2306 */
2307 case TIOCSERCONFIG:
2308 case TIOCSERGWILD:
2309 case TIOCSERGETLSR:
2310 case TIOCSERSWILD:
2311 case TIOCSERGSTRUCT:
2312 case TIOCSERGETMULTI:
2313 case TIOCSERSETMULTI:
2314
2315 default:
2316 ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
2317
2318 rc = -ENOIOCTLCMD;
2319 break;
2320 }
2321
2322 ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
2323
2324 return rc;
2325}
2326
0587102c
AC
2327static int ip2_get_icount(struct tty_struct *tty,
2328 struct serial_icounter_struct *icount)
2329{
2330 i2ChanStrPtr pCh = DevTable[tty->index];
2331 i2eBordStrPtr pB;
2332 struct async_icount cnow; /* kernel counter temp */
2333 unsigned long flags;
2334
2335 if ( pCh == NULL )
2336 return -ENODEV;
2337
2338 pB = pCh->pMyBord;
2339
2340 /*
2341 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2342 * Return: write counters to the user passed counter struct
2343 * NB: both 1->0 and 0->1 transitions are counted except for RI where
2344 * only 0->1 is counted. The controller is quite capable of counting
2345 * both, but this done to preserve compatibility with the standard
2346 * serial driver.
2347 */
2348
2349 write_lock_irqsave(&pB->read_fifo_spinlock, flags);
2350 cnow = pCh->icount;
2351 write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
2352
2353 icount->cts = cnow.cts;
2354 icount->dsr = cnow.dsr;
2355 icount->rng = cnow.rng;
2356 icount->dcd = cnow.dcd;
2357 icount->rx = cnow.rx;
2358 icount->tx = cnow.tx;
2359 icount->frame = cnow.frame;
2360 icount->overrun = cnow.overrun;
2361 icount->parity = cnow.parity;
2362 icount->brk = cnow.brk;
2363 icount->buf_overrun = cnow.buf_overrun;
2364 return 0;
2365}
2366
1da177e4
LT
2367/******************************************************************************/
2368/* Function: GetSerialInfo() */
2369/* Parameters: Pointer to channel structure */
2370/* Pointer to old termios structure */
2371/* Returns: Nothing */
2372/* */
2373/* Description: */
2374/* This is to support the setserial command, and requires processing of the */
2375/* standard Linux serial structure. */
2376/******************************************************************************/
2377static int
2378get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo )
2379{
2380 struct serial_struct tmp;
2381
2382 memset ( &tmp, 0, sizeof(tmp) );
2383 tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16];
2384 if (BID_HAS_654(tmp.type)) {
2385 tmp.type = PORT_16650;
2386 } else {
2387 tmp.type = PORT_CIRRUS;
2388 }
2389 tmp.line = pCh->port_index;
2390 tmp.port = pCh->pMyBord->i2eBase;
2391 tmp.irq = ip2config.irq[pCh->port_index/64];
2392 tmp.flags = pCh->flags;
2393 tmp.baud_base = pCh->BaudBase;
2394 tmp.close_delay = pCh->ClosingDelay;
2395 tmp.closing_wait = pCh->ClosingWaitTime;
2396 tmp.custom_divisor = pCh->BaudDivisor;
2397 return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
2398}
2399
2400/******************************************************************************/
2401/* Function: SetSerialInfo() */
2402/* Parameters: Pointer to channel structure */
2403/* Pointer to old termios structure */
2404/* Returns: Nothing */
2405/* */
2406/* Description: */
2407/* This function provides support for setserial, which uses the TIOCSSERIAL */
2408/* ioctl. Not all setserial parameters are relevant. If the user attempts to */
2409/* change the IRQ, address or type of the port the ioctl fails. */
2410/******************************************************************************/
2411static int
2412set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info )
2413{
2414 struct serial_struct ns;
2415 int old_flags, old_baud_divisor;
2416
2417 if (copy_from_user(&ns, new_info, sizeof (ns)))
2418 return -EFAULT;
2419
2420 /*
2421 * We don't allow setserial to change IRQ, board address, type or baud
2422 * base. Also line nunber as such is meaningless but we use it for our
2423 * array index so it is fixed also.
2424 */
2425 if ( (ns.irq != ip2config.irq[pCh->port_index])
2426 || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase)))
2427 || (ns.baud_base != pCh->BaudBase)
2428 || (ns.line != pCh->port_index) ) {
2429 return -EINVAL;
2430 }
2431
2432 old_flags = pCh->flags;
2433 old_baud_divisor = pCh->BaudDivisor;
2434
2435 if ( !capable(CAP_SYS_ADMIN) ) {
2436 if ( ( ns.close_delay != pCh->ClosingDelay ) ||
2437 ( (ns.flags & ~ASYNC_USR_MASK) !=
2438 (pCh->flags & ~ASYNC_USR_MASK) ) ) {
2439 return -EPERM;
2440 }
2441
2442 pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) |
2443 (ns.flags & ASYNC_USR_MASK);
2444 pCh->BaudDivisor = ns.custom_divisor;
2445 } else {
2446 pCh->flags = (pCh->flags & ~ASYNC_FLAGS) |
2447 (ns.flags & ASYNC_FLAGS);
2448 pCh->BaudDivisor = ns.custom_divisor;
2449 pCh->ClosingDelay = ns.close_delay * HZ/100;
2450 pCh->ClosingWaitTime = ns.closing_wait * HZ/100;
2451 }
2452
2453 if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) )
2454 || (old_baud_divisor != pCh->BaudDivisor) ) {
2455 // Invalidate speed and reset parameters
2456 set_params( pCh, NULL );
2457 }
2458
2459 return 0;
2460}
2461
2462/******************************************************************************/
2463/* Function: ip2_set_termios() */
2464/* Parameters: Pointer to tty structure */
2465/* Pointer to old termios structure */
2466/* Returns: Nothing */
2467/* */
2468/* Description: */
2469/* */
2470/* */
2471/******************************************************************************/
2472static void
606d099c 2473ip2_set_termios( PTTY tty, struct ktermios *old_termios )
1da177e4
LT
2474{
2475 i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
2476
2477#ifdef IP2DEBUG_IOCTL
2478 printk (KERN_DEBUG "IP2: set termios %p\n", old_termios );
2479#endif
2480
2481 set_params( pCh, old_termios );
2482}
2483
2484/******************************************************************************/
2485/* Function: ip2_set_line_discipline() */
2486/* Parameters: Pointer to tty structure */
2487/* Returns: Nothing */
2488/* */
2489/* Description: Does nothing */
2490/* */
2491/* */
2492/******************************************************************************/
2493static void
2494ip2_set_line_discipline ( PTTY tty )
2495{
2496#ifdef IP2DEBUG_IOCTL
2497 printk (KERN_DEBUG "IP2: set line discipline\n" );
2498#endif
2499
2500 ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 );
2501
2502}
2503
2504/******************************************************************************/
2505/* Function: SetLine Characteristics() */
2506/* Parameters: Pointer to channel structure */
2507/* Returns: Nothing */
2508/* */
2509/* Description: */
2510/* This routine is called to update the channel structure with the new line */
2511/* characteristics, and send the appropriate commands to the board when they */
2512/* change. */
2513/******************************************************************************/
2514static void
606d099c 2515set_params( i2ChanStrPtr pCh, struct ktermios *o_tios )
1da177e4
LT
2516{
2517 tcflag_t cflag, iflag, lflag;
2518 char stop_char, start_char;
606d099c 2519 struct ktermios dummy;
1da177e4
LT
2520
2521 lflag = pCh->pTTY->termios->c_lflag;
2522 cflag = pCh->pTTY->termios->c_cflag;
2523 iflag = pCh->pTTY->termios->c_iflag;
2524
2525 if (o_tios == NULL) {
2526 dummy.c_lflag = ~lflag;
2527 dummy.c_cflag = ~cflag;
2528 dummy.c_iflag = ~iflag;
2529 o_tios = &dummy;
2530 }
2531
2532 {
2533 switch ( cflag & CBAUD ) {
2534 case B0:
2535 i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
2536 pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
2537 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
2538 pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag);
2539 goto service_it;
2540 break;
2541 case B38400:
2542 /*
2543 * This is the speed that is overloaded with all the other high
2544 * speeds, depending upon the flag settings.
2545 */
2546 if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) {
2547 pCh->speed = CBR_57600;
2548 } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) {
2549 pCh->speed = CBR_115200;
2550 } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) {
2551 pCh->speed = CBR_C1;
2552 } else {
2553 pCh->speed = CBR_38400;
2554 }
2555 break;
2556 case B50: pCh->speed = CBR_50; break;
2557 case B75: pCh->speed = CBR_75; break;
2558 case B110: pCh->speed = CBR_110; break;
2559 case B134: pCh->speed = CBR_134; break;
2560 case B150: pCh->speed = CBR_150; break;
2561 case B200: pCh->speed = CBR_200; break;
2562 case B300: pCh->speed = CBR_300; break;
2563 case B600: pCh->speed = CBR_600; break;
2564 case B1200: pCh->speed = CBR_1200; break;
2565 case B1800: pCh->speed = CBR_1800; break;
2566 case B2400: pCh->speed = CBR_2400; break;
2567 case B4800: pCh->speed = CBR_4800; break;
2568 case B9600: pCh->speed = CBR_9600; break;
2569 case B19200: pCh->speed = CBR_19200; break;
2570 case B57600: pCh->speed = CBR_57600; break;
2571 case B115200: pCh->speed = CBR_115200; break;
2572 case B153600: pCh->speed = CBR_153600; break;
2573 case B230400: pCh->speed = CBR_230400; break;
2574 case B307200: pCh->speed = CBR_307200; break;
2575 case B460800: pCh->speed = CBR_460800; break;
2576 case B921600: pCh->speed = CBR_921600; break;
2577 default: pCh->speed = CBR_9600; break;
2578 }
2579 if ( pCh->speed == CBR_C1 ) {
2580 // Process the custom speed parameters.
2581 int bps = pCh->BaudBase / pCh->BaudDivisor;
2582 if ( bps == 921600 ) {
2583 pCh->speed = CBR_921600;
2584 } else {
2585 bps = bps/10;
2586 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) );
2587 }
2588 }
2589 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed));
2590
2591 i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
2592 pCh->dataSetOut |= (I2_DTR | I2_RTS);
2593 }
2594 if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag))
2595 {
2596 i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
2597 CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1));
2598 }
2599 if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag))
2600 {
2601 i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
2602 CMD_SETPAR(
2603 (cflag & PARENB ? (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP)
2604 )
2605 );
2606 }
2607 /* byte size and parity */
2608 if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag))
2609 {
2610 int datasize;
2611 switch ( cflag & CSIZE ) {
2612 case CS5: datasize = CSZ_5; break;
2613 case CS6: datasize = CSZ_6; break;
2614 case CS7: datasize = CSZ_7; break;
2615 case CS8: datasize = CSZ_8; break;
2616 default: datasize = CSZ_5; break; /* as per serial.c */
2617 }
2618 i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) );
2619 }
2620 /* Process CTS flow control flag setting */
2621 if ( (cflag & CRTSCTS) ) {
2622 i2QueueCommands(PTYPE_INLINE, pCh, 100,
2623 2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB);
2624 } else {
2625 i2QueueCommands(PTYPE_INLINE, pCh, 100,
2626 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
2627 }
2628 //
2629 // Process XON/XOFF flow control flags settings
2630 //
2631 stop_char = STOP_CHAR(pCh->pTTY);
2632 start_char = START_CHAR(pCh->pTTY);
2633
2634 //////////// can't be \000
2635 if (stop_char == __DISABLED_CHAR )
2636 {
2637 stop_char = ~__DISABLED_CHAR;
2638 }
2639 if (start_char == __DISABLED_CHAR )
2640 {
2641 start_char = ~__DISABLED_CHAR;
2642 }
2643 /////////////////////////////////
2644
2645 if ( o_tios->c_cc[VSTART] != start_char )
2646 {
2647 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char));
2648 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char));
2649 }
2650 if ( o_tios->c_cc[VSTOP] != stop_char )
2651 {
2652 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char));
2653 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char));
2654 }
2655 if (stop_char == __DISABLED_CHAR )
2656 {
2657 stop_char = ~__DISABLED_CHAR; //TEST123
2658 goto no_xoff;
2659 }
2660 if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF)))
2661 {
2662 if ( iflag & IXOFF ) { // Enable XOFF output flow control
2663 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON));
2664 } else { // Disable XOFF output flow control
2665no_xoff:
2666 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE));
2667 }
2668 }
2669 if (start_char == __DISABLED_CHAR )
2670 {
2671 goto no_xon;
2672 }
2673 if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY)))
2674 {
2675 if ( iflag & IXON ) {
2676 if ( iflag & IXANY ) { // Enable XON/XANY output flow control
2677 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY));
2678 } else { // Enable XON output flow control
2679 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON));
2680 }
2681 } else { // Disable XON output flow control
2682no_xon:
2683 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE));
2684 }
2685 }
2686 if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) )
2687 {
2688 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
2689 CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0)));
2690 }
2691 if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) )
2692 {
2693 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
2694 CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB));
2695 }
2696
2697 if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR))
2698 ^ ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) )
2699 {
2700 char brkrpt = 0;
2701 char parrpt = 0;
2702
2703 if ( iflag & IGNBRK ) { /* Ignore breaks altogether */
2704 /* Ignore breaks altogether */
2705 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP);
2706 } else {
2707 if ( iflag & BRKINT ) {
2708 if ( iflag & PARMRK ) {
2709 brkrpt = 0x0a; // exception an inline triple
2710 } else {
2711 brkrpt = 0x1a; // exception and NULL
2712 }
2713 brkrpt |= 0x04; // flush input
2714 } else {
2715 if ( iflag & PARMRK ) {
2716 brkrpt = 0x0b; //POSIX triple \0377 \0 \0
2717 } else {
2718 brkrpt = 0x01; // Null only
2719 }
2720 }
2721 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt));
2722 }
2723
2724 if (iflag & IGNPAR) {
2725 parrpt = 0x20;
2726 /* would be 2 for not cirrus bug */
2727 /* would be 0x20 cept for cirrus bug */
2728 } else {
2729 if ( iflag & PARMRK ) {
2730 /*
2731 * Replace error characters with 3-byte sequence (\0377,\0,char)
2732 */
2733 parrpt = 0x04 ;
2734 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0));
2735 } else {
2736 parrpt = 0x03;
2737 }
2738 }
2739 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
2740 }
2741 if (cflag & CLOCAL) {
2742 // Status reporting fails for DCD if this is off
2743 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
2744 pCh->flags &= ~ASYNC_CHECK_CD;
2745 } else {
2746 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
2747 pCh->flags |= ASYNC_CHECK_CD;
2748 }
2749
1da177e4
LT
2750service_it:
2751 i2DrainOutput( pCh, 100 );
2752}
2753
2754/******************************************************************************/
2755/* IPL Device Section */
2756/******************************************************************************/
2757
2758/******************************************************************************/
2759/* Function: ip2_ipl_read() */
2760/* Parameters: Pointer to device inode */
2761/* Pointer to file structure */
2762/* Pointer to data */
2763/* Number of bytes to read */
2764/* Returns: Success or failure */
2765/* */
2766/* Description: Ugly */
2767/* */
2768/* */
2769/******************************************************************************/
2770
2771static
2772ssize_t
2773ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
2774{
a7113a96 2775 unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
1da177e4
LT
2776 int rc = 0;
2777
2778#ifdef IP2DEBUG_IPL
2779 printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count );
2780#endif
2781
2782 switch( minor ) {
2783 case 0: // IPL device
2784 rc = -EINVAL;
2785 break;
2786 case 1: // Status dump
2787 rc = -EINVAL;
2788 break;
2789 case 2: // Ping device
2790 rc = -EINVAL;
2791 break;
2792 case 3: // Trace device
2793 rc = DumpTraceBuffer ( pData, count );
2794 break;
2795 case 4: // Trace device
2796 rc = DumpFifoBuffer ( pData, count );
2797 break;
2798 default:
2799 rc = -ENODEV;
2800 break;
2801 }
2802 return rc;
2803}
2804
2805static int
2806DumpFifoBuffer ( char __user *pData, int count )
2807{
2808#ifdef DEBUG_FIFO
2809 int rc;
2810 rc = copy_to_user(pData, DBGBuf, count);
2811
2812 printk(KERN_DEBUG "Last index %d\n", I );
2813
2814 return count;
2815#endif /* DEBUG_FIFO */
2816 return 0;
2817}
2818
2819static int
2820DumpTraceBuffer ( char __user *pData, int count )
2821{
2822#ifdef IP2DEBUG_TRACE
2823 int rc;
2824 int dumpcount;
2825 int chunk;
2826 int *pIndex = (int __user *)pData;
2827
2828 if ( count < (sizeof(int) * 6) ) {
2829 return -EIO;
2830 }
2831 rc = put_user(tracewrap, pIndex );
2832 rc = put_user(TRACEMAX, ++pIndex );
2833 rc = put_user(tracestrip, ++pIndex );
2834 rc = put_user(tracestuff, ++pIndex );
2835 pData += sizeof(int) * 6;
2836 count -= sizeof(int) * 6;
2837
2838 dumpcount = tracestuff - tracestrip;
2839 if ( dumpcount < 0 ) {
2840 dumpcount += TRACEMAX;
2841 }
2842 if ( dumpcount > count ) {
2843 dumpcount = count;
2844 }
2845 chunk = TRACEMAX - tracestrip;
2846 if ( dumpcount > chunk ) {
2847 rc = copy_to_user(pData, &tracebuf[tracestrip],
2848 chunk * sizeof(tracebuf[0]) );
2849 pData += chunk * sizeof(tracebuf[0]);
2850 tracestrip = 0;
2851 chunk = dumpcount - chunk;
2852 } else {
2853 chunk = dumpcount;
2854 }
2855 rc = copy_to_user(pData, &tracebuf[tracestrip],
2856 chunk * sizeof(tracebuf[0]) );
2857 tracestrip += chunk;
2858 tracewrap = 0;
2859
2860 rc = put_user(tracestrip, ++pIndex );
2861 rc = put_user(tracestuff, ++pIndex );
2862
2863 return dumpcount;
2864#else
2865 return 0;
2866#endif
2867}
2868
2869/******************************************************************************/
2870/* Function: ip2_ipl_write() */
2871/* Parameters: */
2872/* Pointer to file structure */
2873/* Pointer to data */
2874/* Number of bytes to write */
2875/* Returns: Success or failure */
2876/* */
2877/* Description: */
2878/* */
2879/* */
2880/******************************************************************************/
2881static ssize_t
2882ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off)
2883{
2884#ifdef IP2DEBUG_IPL
2885 printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count );
2886#endif
2887 return 0;
2888}
2889
2890/******************************************************************************/
2891/* Function: ip2_ipl_ioctl() */
2892/* Parameters: Pointer to device inode */
2893/* Pointer to file structure */
2894/* Command */
2895/* Argument */
2896/* Returns: Success or failure */
2897/* */
2898/* Description: */
2899/* */
2900/* */
2901/******************************************************************************/
47be36a2
AC
2902static long
2903ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
1da177e4 2904{
47be36a2 2905 unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode);
1da177e4
LT
2906 int rc = 0;
2907 void __user *argp = (void __user *)arg;
2908 ULONG __user *pIndex = argp;
2909 i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
2910 i2ChanStrPtr pCh;
2911
2912#ifdef IP2DEBUG_IPL
2913 printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
2914#endif
2915
613655fa 2916 mutex_lock(&ip2_mutex);
47be36a2 2917
1da177e4
LT
2918 switch ( iplminor ) {
2919 case 0: // IPL device
2920 rc = -EINVAL;
2921 break;
2922 case 1: // Status dump
2923 case 5:
2924 case 9:
2925 case 13:
2926 switch ( cmd ) {
2927 case 64: /* Driver - ip2stat */
7d7b93c1 2928 rc = put_user(-1, pIndex++ );
1da177e4
LT
2929 rc = put_user(irq_counter, pIndex++ );
2930 rc = put_user(bh_counter, pIndex++ );
2931 break;
2932
2933 case 65: /* Board - ip2stat */
2934 if ( pB ) {
2935 rc = copy_to_user(argp, pB, sizeof(i2eBordStr));
cf1c63c3 2936 rc = put_user(inb(pB->i2eStatus),
1da177e4
LT
2937 (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
2938 } else {
2939 rc = -ENODEV;
2940 }
2941 break;
2942
2943 default:
2944 if (cmd < IP2_MAX_PORTS) {
2945 pCh = DevTable[cmd];
2946 if ( pCh )
2947 {
2948 rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
05254a20
DC
2949 if (rc)
2950 rc = -EFAULT;
1da177e4
LT
2951 } else {
2952 rc = -ENODEV;
2953 }
2954 } else {
2955 rc = -EINVAL;
2956 }
2957 }
2958 break;
2959
2960 case 2: // Ping device
2961 rc = -EINVAL;
2962 break;
2963 case 3: // Trace device
def9391c
AM
2964 /*
2965 * akpm: This used to write a whole bunch of function addresses
2966 * to userspace, which generated lots of put_user() warnings.
2967 * I killed it all. Just return "success" and don't do
2968 * anything.
2969 */
2970 if (cmd == 1)
2971 rc = 0;
2972 else
1da177e4 2973 rc = -EINVAL;
1da177e4
LT
2974 break;
2975
2976 default:
2977 rc = -ENODEV;
2978 break;
2979 }
613655fa 2980 mutex_unlock(&ip2_mutex);
1da177e4
LT
2981 return rc;
2982}
2983
2984/******************************************************************************/
2985/* Function: ip2_ipl_open() */
2986/* Parameters: Pointer to device inode */
2987/* Pointer to file structure */
2988/* Returns: Success or failure */
2989/* */
2990/* Description: */
2991/* */
2992/* */
2993/******************************************************************************/
2994static int
2995ip2_ipl_open( struct inode *pInode, struct file *pFile )
2996{
1da177e4
LT
2997
2998#ifdef IP2DEBUG_IPL
2999 printk (KERN_DEBUG "IP2IPL: open\n" );
3000#endif
1da177e4
LT
3001 return 0;
3002}
1da177e4
LT
3003
3004static int
4a5cdb5b 3005proc_ip2mem_show(struct seq_file *m, void *v)
1da177e4
LT
3006{
3007 i2eBordStrPtr pB;
3008 i2ChanStrPtr pCh;
3009 PTTY tty;
3010 int i;
3011
1da177e4
LT
3012#define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
3013#define FMTLIN2 " 0x%04x 0x%04x tx flow 0x%x\n"
3014#define FMTLIN3 " 0x%04x 0x%04x rc flow\n"
3015
4a5cdb5b 3016 seq_printf(m,"\n");
1da177e4
LT
3017
3018 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
3019 pB = i2BoardPtrTable[i];
3020 if ( pB ) {
4a5cdb5b
AD
3021 seq_printf(m,"board %d:\n",i);
3022 seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n",
1da177e4
LT
3023 pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
3024 }
3025 }
3026
4a5cdb5b 3027 seq_printf(m,"#: tty flags, port flags, cflags, iflags\n");
1da177e4 3028 for (i=0; i < IP2_MAX_PORTS; i++) {
1da177e4
LT
3029 pCh = DevTable[i];
3030 if (pCh) {
3031 tty = pCh->pTTY;
3032 if (tty && tty->count) {
4a5cdb5b 3033 seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags,
1da177e4
LT
3034 tty->termios->c_cflag,tty->termios->c_iflag);
3035
4a5cdb5b 3036 seq_printf(m,FMTLIN2,
1da177e4 3037 pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
4a5cdb5b 3038 seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room);
1da177e4
LT
3039 }
3040 }
3041 }
4a5cdb5b
AD
3042 return 0;
3043}
3044
3045static int proc_ip2mem_open(struct inode *inode, struct file *file)
3046{
3047 return single_open(file, proc_ip2mem_show, NULL);
1da177e4
LT
3048}
3049
4a5cdb5b
AD
3050static const struct file_operations ip2mem_proc_fops = {
3051 .owner = THIS_MODULE,
3052 .open = proc_ip2mem_open,
3053 .read = seq_read,
3054 .llseek = seq_lseek,
3055 .release = single_release,
3056};
3057
1da177e4
LT
3058/*
3059 * This is the handler for /proc/tty/driver/ip2
3060 *
3061 * This stretch of code has been largely plagerized from at least three
3062 * different sources including ip2mkdev.c and a couple of other drivers.
3063 * The bugs are all mine. :-) =mhw=
3064 */
cdda7cd9 3065static int ip2_proc_show(struct seq_file *m, void *v)
1da177e4
LT
3066{
3067 int i, j, box;
1da177e4
LT
3068 int boxes = 0;
3069 int ports = 0;
3070 int tports = 0;
1da177e4 3071 i2eBordStrPtr pB;
cdda7cd9 3072 char *sep;
1da177e4 3073
cdda7cd9
AD
3074 seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion);
3075 seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n",
1da177e4
LT
3076 IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR,
3077 IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX);
3078
3079 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
3080 /* This need to be reset for a board by board count... */
3081 boxes = 0;
3082 pB = i2BoardPtrTable[i];
3083 if( pB ) {
3084 switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED )
3085 {
3086 case POR_ID_FIIEX:
cdda7cd9
AD
3087 seq_printf(m, "Board %d: EX ports=", i);
3088 sep = "";
1da177e4
LT
3089 for( box = 0; box < ABS_MAX_BOXES; ++box )
3090 {
3091 ports = 0;
3092
3093 if( pB->i2eChannelMap[box] != 0 ) ++boxes;
3094 for( j = 0; j < ABS_BIGGEST_BOX; ++j )
3095 {
3096 if( pB->i2eChannelMap[box] & 1<< j ) {
3097 ++ports;
3098 }
3099 }
cdda7cd9
AD
3100 seq_printf(m, "%s%d", sep, ports);
3101 sep = ",";
1da177e4
LT
3102 tports += ports;
3103 }
cdda7cd9 3104 seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8);
1da177e4
LT
3105 break;
3106
3107 case POR_ID_II_4:
cdda7cd9 3108 seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i);
1da177e4
LT
3109 tports = ports = 4;
3110 break;
3111
3112 case POR_ID_II_8:
cdda7cd9 3113 seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i);
1da177e4
LT
3114 tports = ports = 8;
3115 break;
3116
3117 case POR_ID_II_8R:
cdda7cd9 3118 seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i);
1da177e4
LT
3119 tports = ports = 8;
3120 break;
3121
3122 default:
cdda7cd9 3123 seq_printf(m, "Board %d: unknown", i);
1da177e4
LT
3124 /* Don't try and probe for minor numbers */
3125 tports = ports = 0;
3126 }
3127
3128 } else {
3129 /* Don't try and probe for minor numbers */
cdda7cd9 3130 seq_printf(m, "Board %d: vacant", i);
1da177e4
LT
3131 tports = ports = 0;
3132 }
3133
3134 if( tports ) {
cdda7cd9
AD
3135 seq_puts(m, " minors=");
3136 sep = "";
1da177e4
LT
3137 for ( box = 0; box < ABS_MAX_BOXES; ++box )
3138 {
3139 for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
3140 {
3141 if ( pB->i2eChannelMap[box] & (1 << j) )
3142 {
cdda7cd9 3143 seq_printf(m, "%s%d", sep,
1da177e4
LT
3144 j + ABS_BIGGEST_BOX *
3145 (box+i*ABS_MAX_BOXES));
cdda7cd9 3146 sep = ",";
1da177e4
LT
3147 }
3148 }
3149 }
1da177e4 3150 }
cdda7cd9 3151 seq_putc(m, '\n');
1da177e4 3152 }
cdda7cd9
AD
3153 return 0;
3154 }
1da177e4 3155
cdda7cd9
AD
3156static int ip2_proc_open(struct inode *inode, struct file *file)
3157{
3158 return single_open(file, ip2_proc_show, NULL);
3159}
1da177e4 3160
cdda7cd9
AD
3161static const struct file_operations ip2_proc_fops = {
3162 .owner = THIS_MODULE,
3163 .open = ip2_proc_open,
3164 .read = seq_read,
3165 .llseek = seq_lseek,
3166 .release = single_release,
3167};
1da177e4
LT
3168
3169/******************************************************************************/
3170/* Function: ip2trace() */
3171/* Parameters: Value to add to trace buffer */
3172/* Returns: Nothing */
3173/* */
3174/* Description: */
3175/* */
3176/* */
3177/******************************************************************************/
3178#ifdef IP2DEBUG_TRACE
3179void
3180ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...)
3181{
3182 long flags;
3183 unsigned long *pCode = &codes;
3184 union ip2breadcrumb bc;
3185 i2ChanStrPtr pCh;
3186
3187
3188 tracebuf[tracestuff++] = jiffies;
3189 if ( tracestuff == TRACEMAX ) {
3190 tracestuff = 0;
3191 }
3192 if ( tracestuff == tracestrip ) {
3193 if ( ++tracestrip == TRACEMAX ) {
3194 tracestrip = 0;
3195 }
3196 ++tracewrap;
3197 }
3198
3199 bc.hdr.port = 0xff & pn;
3200 bc.hdr.cat = cat;
3201 bc.hdr.codes = (unsigned char)( codes & 0xff );
3202 bc.hdr.label = label;
3203 tracebuf[tracestuff++] = bc.value;
3204
3205 for (;;) {
3206 if ( tracestuff == TRACEMAX ) {
3207 tracestuff = 0;
3208 }
3209 if ( tracestuff == tracestrip ) {
3210 if ( ++tracestrip == TRACEMAX ) {
3211 tracestrip = 0;
3212 }
3213 ++tracewrap;
3214 }
3215
3216 if ( !codes-- )
3217 break;
3218
3219 tracebuf[tracestuff++] = *++pCode;
3220 }
3221}
3222#endif
3223
3224
3225MODULE_LICENSE("GPL");
eb0e71c7 3226
53139e36 3227static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = {
eb0e71c7
CS
3228 { PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) },
3229 { }
3230};
3231
3232MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
e6c4ef98
BH
3233
3234MODULE_FIRMWARE("intelliport2.bin");
This page took 0.71273 seconds and 5 git commands to generate.