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