OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [ip2main.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.