MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / char / nozomi / nozomi.c.bak-05252006
blob2401e5697bb52c31f92f53767043326f5b988f1a
2 /* nozomi.c  -- HSDPA driver Broadband Wireless Data Card - Globe Trotter
3  *
4  * Written by: Ulf Jakobsson,
5  *             Jan Ã…kerfeldt,
6  *             Stefan Thomasson,
7  *
8  * Maintained by: Paul Hardwick, p.hardwick@option.com
9  *
10  * Source has been ported from an implementation made by Filip Aben, f.aben@option.com
11  *
12  * --------------------------------------------------------------------------
14  Copyright (c) 2005 Option Wireless Sweden AB
15  All rights Reserved.
17  This program is free software; you can redistribute it and/or modify
18  it under the terms of the GNU General Public License as published by
19  the Free Software Foundation; either version 2 of the License, or
20  (at your option) any later version.
22  This program is distributed in the hope that it will be useful,
23  but WITHOUT ANY WARRANTY; without even the implied warranty of
24  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  GNU General Public License for more details.
27  You should have received a copy of the GNU General Public License
28  along with this program; if not, write to the Free Software
29  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
31  * --------------------------------------------------------------------------
32  */
34 /* CHANGELOG
35  *
36  * See CHANGELOG in this package
37  */
39 /* TODO
40  *
41  * See TODO file in this package
42  */
46 #include <linux/version.h>
48 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
49 #define KERNEL_2_6
50 #elif LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)
51 #define KERNEL_2_4
52 #endif
54 #include <linux/module.h>
55 #include <linux/pci.h>
56 #include <linux/ioport.h>
57 #include <linux/tty.h>
58 #include <linux/tty_driver.h>
59 #include <linux/tty_flip.h>
60 #include <linux/serial.h>
61 #include <linux/interrupt.h>
62 #include <linux/kmod.h>
63 #include <linux/proc_fs.h>
64 #include <linux/spinlock.h>
65 #include <asm/uaccess.h>
68 #define VERSION_STRING DRIVER_DESC " (build date: " __DATE__ " " __TIME__ ")"
70 //#ifdef KERNEL_2_6
71 //#include <linux/kfifo.h>
72 //#else
73 #include "kfifo.h"
74 //#endif
76 #ifdef KERNEL_2_4
77 #ifndef IRQ_NONE
78 #define IRQ_NONE
79 #endif
80 #ifndef IRQ_HANDLED
81 #define IRQ_HANDLED
82 typedef void irqreturn_t;
83 #endif
84 #endif
86 #ifndef CONFIG_PCI
87 #error "This driver needs PCI support to be available"
88 #endif
90 /*    Macros definitions */
92 /* Enable this to have a lot of debug printouts */
93 /* #define NOZOMI_DEBUG */
95 /* Default debug printout level */
96 #define NOZOMI_DEBUG_LEVEL 0x1
98 #define P_BUF_SIZE 128
99 #define NFO( _err_flag_, args...)                                            \
100   do{                                                                        \
101     char t_m_p_[P_BUF_SIZE];                                                 \
102       snprintf(t_m_p_, sizeof(t_m_p_), ##args);                              \
103       printk( _err_flag_ "[%d] %s(): %s\n", __LINE__, __FUNCTION__, t_m_p_); \
104 } while(0)
106 #define INFO(args...) NFO(KERN_INFO, ##args)
107 #define ERR(args...)  NFO( KERN_ERR, ##args)
109 #define D1(args...) D_(0x01, ##args)
110 #define D2(args...) D_(0x02, ##args)
111 #define D3(args...) D_(0x04, ##args)
112 #define D4(args...) D_(0x08, ##args)
113 #define D5(args...) D_(0x10, ##args)
114 #define D6(args...) D_(0x20, ##args)
115 #define D7(args...) D_(0x40, ##args)
116 #define D8(args...) D_(0x80, ##args)
119 #ifdef NOZOMI_DEBUG
120 #define D_(lvl, args...) D(lvl, ##args)
121   /* Do we need this settable at runtime? */
122 static int nzdebug = NOZOMI_DEBUG_LEVEL;
124 #define D(lvl, args...)  do{if(lvl & nzdebug) NFO(KERN_DEBUG, ##args );}while(0)
125 #define D_(lvl, args...) D(lvl, ##args)
127 /* These printouts are always printed */
129 #else
130   static const int nzdebug = 0;
131 #define D_(lvl, args...)
132 #endif
134 /* TODO: rewrite to optimize macros... */
135 #define SET_FCR(value__) \
136   do {  \
137         writew((value__), (void*) (dc->REG_FCR )); \
138 } while(0)
140 #define SET_IER(value__, mask__) \
141   do {  \
142         dc->ier_last_written = (dc->ier_last_written & ~mask__) | (value__ & mask__ );\
143     writew( dc->ier_last_written, (void*) (dc->REG_IER));\
144 } while(0)
146 #define GET_IER(read_val__) \
147   do {  \
148         (read_val__) = readw((void*) (dc->REG_IER));\
149 } while(0)
151 #define GET_IIR(read_val__) \
152   do {  \
153         (read_val__) = readw((void*) (dc->REG_IIR));\
154 } while(0)
156 #define GET_MEM(value__, addr__, length__) \
157   do {  \
158         read_mem32( (u32*) (value__), (u32) (addr__), (length__));\
159 } while(0)
161 #define GET_MEM_BUF(value__, addr__, length__) \
162   do {  \
163         read_mem32_buf( (u32*) (value__), (u32) (addr__), (length__));\
164 } while(0)
166 #define SET_MEM(addr__, value__, length__) \
167   do {  \
168   write_mem32( (addr__),  (u32*) (value__), (length__));\
169 } while(0)
171 #define SET_MEM_BUF(addr__, value__, length__) \
172   do {  \
173   write_mem32_buf( (addr__),  (u32*) (value__), (length__));\
174 } while(0)
177 #define TMP_BUF_MAX 256
179 #define DUMP(buf__,len__) \
180   do {  \
181     char tbuf[TMP_BUF_MAX]={0};\
182         if (len__>1) {\
183                 snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s",buf__);\
184                 if(tbuf[len__-2] == '\r') {\
185                         tbuf[len__-2] = 'r';\
186                 }\
187                 D1( "SENDING: '%s' (%d+n)", tbuf, len__);\
188         } else {\
189                 D1( "SENDING: '%s' (%d)", tbuf, len__);\
190         }\
191 } while(0)
193 #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
196 /*    Defines */
197 #define NOZOMI_NAME     "nozomi"
198 #define NOZOMI_NAME_TTY "nozomi_tty"
199 #define DRIVER_DESC     "Nozomi driver"
201 #define NTTY_TTY_MAJOR                  241
202 #define NTTY_TTY_MINORS                 MAX_PORT
203 #define NTTY_FIFO_BUFFER_SIZE   8192
205 /* Must be power of 2 */
206 #define FIFO_BUFFER_SIZE_UL     8192
208 /* Size of tmp send buffer to card */
209 #define SEND_BUF_MAX    1024
210 #define RECEIVE_BUF_MAX 4
212 /* Our fake UART values */
213 #define MCR_DTR         0x01
214 #define MCR_RTS         0x02
215 #define MCR_LOOP        0x04
216 #define MSR_CTS         0x08
217 #define MSR_CD          0x10
218 #define MSR_RI          0x20
219 #define MSR_DSR         0x40
221 /* Define all types of vendors and devices to support */
222 #define VENDOR1          0x1931 /* Vendor Option */
223 #define DEVICE1          0x000c /* HSDPA card */
225 #define R_IIR            0x0000  /* Interrupt Identity Register */
226 #define R_FCR            0x0000  /* Flow Control Register */
227 #define R_IER            0x0004  /* Interrupt Enable Register */
229 #define CONFIG_MAGIC 0xEFEFFEFE
230 #define TOGGLE_VALID 0x0000
232 /* Definition of interrupt tokens */
233 #define MDM_DL1  0x0001
234 #define MDM_UL1  0x0002
235 #define MDM_DL2  0x0004
236 #define MDM_UL2  0x0008
237 #define DIAG_DL1 0x0010
238 #define DIAG_DL2 0x0020
239 #define DIAG_UL  0x0040
240 #define APP1_DL  0x0080
241 #define APP1_UL  0x0100
242 #define APP2_DL  0x0200
243 #define APP2_UL  0x0400
244 #define CTRL_DL  0x0800
245 #define CTRL_UL  0x1000
246 #define RESET    0x8000
248 #define MDM_DL  (MDM_DL1  | MDM_DL2)
249 #define MDM_UL  (MDM_UL1  | MDM_UL2)
250 #define DIAG_DL (DIAG_DL1 | DIAG_DL2)
252 /* modem signal definition */
253 #define CTRL_DSR 0x0001
254 #define CTRL_DCD 0x0002
255 #define CTRL_RI  0x0004
256 #define CTRL_CTS 0x0008
258 #define CTRL_DTR 0x0001
259 #define CTRL_RTS 0x0002
261 #define MAX_PORT 4
262 #define NOZOMI_MAX_PORTS 5
264 /*    Type definitions */
266 /* There are two types of nozomi cards, one with 2048 memory and with 8192 memory */
267 typedef enum {
268         F32_2 = 2048, /* Has 512 bytes downlink and uplink * 2             -> 2048 */
269         F32_8 = 9192, /* Has 3072 bytes downlink and 1024 bytes uplink * 2 -> 8192 */
270 } card_type_t;
272 /* Two different toggle channels exist */
273 typedef enum {
274         CH_A=0,
275         CH_B=1,
276 } channel_t;
278 /* Port definition for the card regarding flow control */
279 typedef enum {
280         CTRL_CMD  = 0x00,
281         CTRL_MDM  = 0x01,
282         CTRL_DIAG = 0x02,
283         CTRL_APP1 = 0x03,
284         CTRL_APP2 = 0x04,
285         CTRL_ERROR = -1,
286 } ctrl_port_t;
288 /* Ports that the nozomi has */
289 typedef enum {
290         PORT_MDM = 0,
291         PORT_DIAG= 1,
292         PORT_APP1= 2,
293         PORT_APP2= 3,
294         PORT_CTRL= 4,
295         PORT_ERROR=-1,
296 } port_type_t;
298 #ifdef __ARMEB__
299 /* Big endian */
301 typedef struct {
302         unsigned enabled : 5; /* Toggle fields are valid if enabled is 0, else A-channels
303                                                          must always be used. */
304         unsigned diag_dl : 1;
305         unsigned mdm_dl : 1;
306         unsigned mdm_ul : 1;
307 } __attribute__ ((packed)) toggles_t;
309 /* Configuration table to read at startup of card */
310 /* Is for now only needed during initialization phase */
311 typedef struct {
312         u32             signature;
313         u16             product_information;
314         u16             version;
315         u8              pad3[3];
316         toggles_t       toggle;
317         u8              pad1[4];
318         u16             dl_mdm_len1; /* If this is 64, it can hold 60 bytes + 4 that is length field */
319         u16             dl_start;
321         u16             dl_diag_len1;
322         u16             dl_mdm_len2; /* If this is 64, it can hold 60 bytes + 4 that is length field */
323         u16             dl_app1_len;
325         u16             dl_diag_len2;
326         u16             dl_ctrl_len;
327         u16             dl_app2_len;
328         u8              pad2[16];
329         u16             ul_mdm_len1;
330         u16             ul_start;
331         u16             ul_diag_len;
332         u16             ul_mdm_len2;
333         u16             ul_app1_len;
334         u16             ul_app2_len;
335         u16             ul_ctrl_len;
336 } __attribute__((packed)) config_table_t;
338 /* This stores all control downlink flags */
339 typedef struct {
340         u8 port;
341         unsigned reserved : 4;
342         unsigned CTS : 1;
343         unsigned RI  : 1;
344         unsigned DCD : 1;
345         unsigned DSR : 1;
346 } __attribute__ ((packed)) ctrl_dl_t;
348 /* This stores all control uplink flags */
349 typedef struct {
350         u8 port;
351         unsigned reserved : 6;
352         unsigned RTS : 1;
353         unsigned DTR : 1;
354 } __attribute__ ((packed)) ctrl_ul_t;
356 #else
357 /* Little endian */
359 /* This represents the toggle information */
360 typedef struct {
361         unsigned mdm_ul : 1;
362         unsigned mdm_dl : 1;
363         unsigned diag_dl : 1;
364         unsigned enabled : 5; /* Toggle fields are valid if enabled is 0, else A-channels
365                                                          must always be used. */
366 } __attribute__ ((packed)) toggles_t;
368 /* Configuration table to read at startup of card */
369 typedef struct {
370         u32             signature;
371         u16             version;
372         u16             product_information;
373         toggles_t       toggle;
374         u8              pad1[7];
375         u16             dl_start;
376         u16             dl_mdm_len1; /* If this is 64, it can hold 60 bytes + 4 that is length field */
377         u16             dl_mdm_len2;
378         u16             dl_diag_len1;
379         u16             dl_diag_len2;
380         u16             dl_app1_len;
381         u16             dl_app2_len;
382         u16             dl_ctrl_len;
383         u8              pad2[16];
384         u16             ul_start;
385         u16             ul_mdm_len2;
386         u16             ul_mdm_len1;
387         u16             ul_diag_len;
388         u16             ul_app1_len;
389         u16             ul_app2_len;
390         u16             ul_ctrl_len;
391 } __attribute__((packed)) config_table_t;
393 /* This stores all control downlink flags */
394 typedef struct {
395         unsigned DSR : 1;
396         unsigned DCD : 1;
397         unsigned RI  : 1;
398         unsigned CTS : 1;
399         unsigned reserverd : 4;
400         u8 port;
401 } __attribute__ ((packed)) ctrl_dl_t;
403 /* This stores all control uplink flags */
404 typedef struct {
405         unsigned DTR : 1;
406         unsigned RTS : 1;
407         unsigned reserved : 6;
408         u8 port;
409 } __attribute__ ((packed)) ctrl_ul_t;
410 #endif
412 /* This holds all information that is needed regarding a port */
413 typedef struct {
414         u8                      update_flow_control;
415         ctrl_ul_t               ctrl_ul;
416         ctrl_dl_t               ctrl_dl;
417         struct kfifo            *fifo_ul;
418         u32                     dl_addr[2];
419         u32                     dl_size[2];
420         u8                      toggle_dl;
421         u32                     ul_addr[2];
422         u32                     ul_size[2];
423         u8                      toggle_ul;
424         u16                     token_dl;
425         struct tty_struct       *tty;
426         int                     tty_open_count;
427         struct semaphore        tty_sem;
428         wait_queue_head_t       tty_wait;
429         struct async_icount     tty_icount;
430         int                     tty_index;
431         u32                     rx_data, tx_data;
432         u8                      tty_dont_flip;
433 } port_t;
435 /* Private data one for each card in the system */
436 typedef struct {
437         u32                     base_addr;
438         u8                      closing;
439         /* Register addresses */
440         u32                     REG_IIR;
441         u32                     REG_FCR;
442         u32                     REG_IER;
443         volatile u16            ier_last_written;
444         card_type_t             card_type;
445         config_table_t          config_table; /* Configuration table */
446         struct pci_dev          *pdev;
447         port_t                  port[NOZOMI_MAX_PORTS];
448         u8                      *send_buf;
449         struct tty_driver       tty_driver;
451 #ifdef KERNEL_2_4
452         struct tty_struct       *tty_table[NTTY_TTY_MINORS];
453         struct tq_struct        tty_flip_queue;
454         s32                     tty_refcount;
455 #endif
456 #ifdef KERNEL_2_6
457         struct workqueue_struct *tty_flip_wq;
458         struct work_struct      tty_flip_wq_struct;
459 #endif
461         struct termios          *tty_termios[NTTY_TTY_MINORS];
462         struct termios          *tty_termios_locked[NTTY_TTY_MINORS];
463         spinlock_t              spin_mutex;
465         u32                     open_ttys;
466         struct proc_dir_entry   *proc_entry;
467 } dc_t;
469 /* This is a data packet that is read or written to/from card */
470 typedef struct {
471         u32     size; /* size is the length of the data buffer */
472         u8      *data;
473 } __attribute__ ((packed)) buf_t;
475 /*    Function declarations */
476 static int ntty_tty_init(dc_t *dc);
478 static void tty_flip_queue_function(void *tmp_dc);
480 /*    Global variables */
481 static struct pci_device_id nozomi_pci_tbl[] __devinitdata = {
482         {VENDOR1, DEVICE1},
483         {0, }
486 /* Used to store interrupt variables */
487 typedef struct {
488         volatile u16    read_iir; /* Holds current interrupt tokens */
489 } irq_t;
491 MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
493 /* Representing the pci device of interest */
494 static int      cards_found;
495 dc_t            *my_dev = NULL;
496 struct pci_dev  *my_pdev = NULL;
497 irq_t           my_irq;
499 static inline dc_t* get_dc_by_pdev(struct pci_dev* pdev)
501         return my_dev;
504 static inline dc_t* get_dc_by_index(s32 index )
506         return my_dev;
509 static inline s32 get_index(struct tty_struct *tty)
511 #ifdef KERNEL_2_6
512         return tty->index;
513 #else
514         return MINOR(tty->device) - tty->driver.minor_start;
515 #endif
518 static inline port_t* get_port_by_tty(struct tty_struct *tty)
520         return &my_dev->port[ get_index(tty) ];
523 static inline dc_t* get_dc_by_tty(struct tty_struct *tty )
525         return my_dev;
529 /* TODO: */
530 /* -Optimize */
531 /* -Rewrite cleaner */
532 static void read_mem32(u32 *buf, u32 mem_addr_start, u32 size_bytes)
534         u32     i = 0;
535         u32     *ptr = (u32*) mem_addr_start;
536         u16     *buf16;
538         /* 2 bytes */
539         if ( size_bytes == 2 ) {
540                 buf16 = (u16*) buf;
541                 *buf16 = readw( ptr );
542                 return;
543         }
545         while ( i < size_bytes ) {
546                 if ( size_bytes - i == 2) {
547                         /* Handle 2 bytes in the end */
548                         buf16 = (u16*) buf;
549                         *(buf16) = readw( ptr );
550                         i+=2;
551                 } else {
552                         /* Read 4 bytes */
553                         *(buf) = readl( ptr );
554                         i+=4;
555                 }
556                 buf++; ptr++;
557         }
560 /* TODO: */
561 /* - Rewrite cleaner */
562 /* - merge with read_mem32() */
563 static void read_mem32_buf(u32 *buf, u32 mem_addr_start, u32 size_bytes)
565 #ifdef __ARMEB__
566         u32     i = 0;
567         u32     *ptr =  (u32*) mem_addr_start;
568         u16     *buf16;
570         /* 2 bytes */
571         if ( size_bytes == 2 ) {
572                 buf16 = (u16*) buf;
573                 *buf16 = __le16_to_cpu( readw( ptr ));
574                 return;
575         }
577         while ( i < size_bytes ) {
578                 if ( size_bytes - i == 2) {
579                         /* Handle 2 bytes in the end */
580                         buf16 = (u16*) buf;
581                         *(buf16) = __le16_to_cpu( readw( ptr ));
582                         i+=2;
583                 } else {
584                         /* Read 4 bytes */
585                         *(buf) = __le32_to_cpu( readl( ptr ));
586                         i+=4;
587                 }
588                 buf++; ptr++;
589         }
590 #else
591         read_mem32(buf, mem_addr_start, size_bytes);
592 #endif
595 /* TODO: */
596 /* -Optimize */
597 /* -Rewrite cleaner */
598 static u32 write_mem32(u32 mem_addr_start, u32 *buf, u32 size_bytes)
600         u32     i = 0;
601         u32     *ptr = (u32*) mem_addr_start;
602         u16     *buf16;
604         /* 2 bytes */
605         if (size_bytes == 2) {
606                 buf16 = (u16*) buf;
607                 writew( *buf16, ptr);
608                 return 2;
609         }
611         while (i < size_bytes) {
612                 if ( size_bytes - i == 2) {
613                         /* 2 bytes */
614                         buf16 = (u16*) buf;
615                         writew( *buf16, ptr);
616                         i+=2;
617                 } else {
618                         /* 4 bytes */
619                         writel( *buf, ptr );
620                         i += 4;
621                 }
622                 buf++; ptr++;
623         }
624         return size_bytes;
627 /* Todo: */
628 /* - Merge with write_mem32() */
629 static u32 write_mem32_buf(u32 mem_addr_start, u32 *buf, u32 size_bytes)
631 #ifdef __ARMEB__
632         u32     i = 0;
633         u32     *ptr = (u32*) mem_addr_start;
634         u16     *buf16;
636         /* 2 bytes */
637         if (size_bytes == 2) {
638                 buf16 = (u16*) buf;
639                         writew( __le16_to_cpu(*buf16), ptr);
640                 return 2;
641         }
643         while (i < size_bytes) {
644                 if ( size_bytes - i == 2) {
645                         /* 2 bytes */
646                         buf16 = (u16*) buf;
647                         writew( __le16_to_cpu(*buf16), ptr);
648                         i+=2;
649                 } else {
650                         /* 4 bytes */
651                         writel( __cpu_to_le32( *buf ), ptr );
652                         i += 4;
653                 }
654                 buf++; ptr++;
655         }
656         return size_bytes;
657 #else
658         return write_mem32(mem_addr_start, buf, size_bytes);
659 #endif
662 /* Setup pointers to different channels and also setup buffer sizes. */
663 static void setup_memory(dc_t *dc)
665         /* The length reported is including the length field of 4 bytes, hence subtract with 4. */
666         u32     offset = dc->base_addr + dc->config_table.dl_start;
667         u16     buff_offset = 4;
669         /* Modem port dl configuration */
670         dc->port[PORT_MDM].dl_addr[CH_A] = offset;
671         dc->port[PORT_MDM].dl_addr[CH_B] = (offset += dc->config_table.dl_mdm_len1);
672         dc->port[PORT_MDM].dl_size[CH_A] = dc->config_table.dl_mdm_len1 - buff_offset;
673         dc->port[PORT_MDM].dl_size[CH_B] = dc->config_table.dl_mdm_len2 - buff_offset;
675         /* Diag port dl configuration */
676         dc->port[PORT_DIAG].dl_addr[CH_A] = (offset += dc->config_table.dl_mdm_len2);
677         dc->port[PORT_DIAG].dl_size[CH_A] = dc->config_table.dl_diag_len1 - buff_offset;
678         dc->port[PORT_DIAG].dl_addr[CH_B] = (offset += dc->config_table.dl_diag_len1);
679         dc->port[PORT_DIAG].dl_size[CH_B] = dc->config_table.dl_diag_len2 - buff_offset;
681         /* App1 port dl configuration */
682         dc->port[PORT_APP1].dl_addr[CH_A] = (offset += dc->config_table.dl_diag_len2);
683         dc->port[PORT_APP1].dl_size[CH_A] = dc->config_table.dl_app1_len - buff_offset;
685         /* App2 port dl configuration */
686         dc->port[PORT_APP2].dl_addr[CH_A] = (offset += dc->config_table.dl_app1_len);
687         dc->port[PORT_APP2].dl_size[CH_A] = dc->config_table.dl_app2_len - buff_offset;
689         /* Ctrl dl configuration */
690         dc->port[PORT_CTRL].dl_addr[CH_A] = (offset += dc->config_table.dl_app2_len);
691         dc->port[PORT_CTRL].dl_size[CH_A] = dc->config_table.dl_ctrl_len - buff_offset;
694         /* Modem Port ul configuration */
695         dc->port[PORT_MDM].ul_addr[CH_A] = (offset = dc->base_addr + dc->config_table.ul_start);
696         dc->port[PORT_MDM].ul_size[CH_A] = dc->config_table.ul_mdm_len1 - buff_offset;
697         dc->port[PORT_MDM].ul_addr[CH_B] = (offset += dc->config_table.ul_mdm_len1);
698         dc->port[PORT_MDM].ul_size[CH_B] = dc->config_table.ul_mdm_len2 - buff_offset;
700         /* Diag port ul configuration */
701         dc->port[PORT_DIAG].ul_addr[CH_A] = (offset += dc->config_table.ul_mdm_len2);
702         dc->port[PORT_DIAG].ul_size[CH_A] = dc->config_table.ul_diag_len - buff_offset;
704         /* App1 port ul configuration */
705         dc->port[PORT_APP1].ul_addr[CH_A] = (offset += dc->config_table.ul_diag_len);
706         dc->port[PORT_APP1].ul_size[CH_A] = dc->config_table.ul_app1_len - buff_offset;
708         /* App2 port ul configuration */
709         dc->port[PORT_APP2].ul_addr[CH_A] = (offset += dc->config_table.ul_app1_len);
710         dc->port[PORT_APP2].ul_size[CH_A] = dc->config_table.ul_app2_len - buff_offset;
712         /* Ctrl ul configuration */
713         dc->port[PORT_CTRL].ul_addr[CH_A] = (offset += dc->config_table.ul_app2_len);
714         dc->port[PORT_CTRL].ul_size[CH_A] = dc->config_table.ul_ctrl_len - buff_offset;
715         offset = dc->config_table.ul_start;
718 /* Dump config table under initalization phase */
719 #ifdef NOZOMI_DEBUG
720 static void dump_table(dc_t *dc)
722         D3("signature: 0x%08X", dc->config_table.signature);
723         D3("version: 0x%04X", dc->config_table.version);
724         D3("product_information: 0x%04X", dc->config_table.product_information);
725         D3("toggle enabled: %d", dc->config_table.toggle.enabled);
726         D3("toggle up_mdm: %d", dc->config_table.toggle.mdm_ul);
727         D3("toggle dl_mdm: %d", dc->config_table.toggle.mdm_dl);
728         D3("toggle dl_dbg: %d", dc->config_table.toggle.diag_dl);
730         D3("dl_start: 0x%04X", dc->config_table.dl_start);
731         D3("dl_mdm_len0: 0x%04X, %d", dc->config_table.dl_mdm_len1, dc->config_table.dl_mdm_len1);
732         D3("dl_mdm_len1: 0x%04X, %d", dc->config_table.dl_mdm_len2, dc->config_table.dl_mdm_len2);
733         D3("dl_diag_len0: 0x%04X, %d", dc->config_table.dl_diag_len1, dc->config_table.dl_diag_len1);
734         D3("dl_diag_len1: 0x%04X, %d", dc->config_table.dl_diag_len2, dc->config_table.dl_diag_len2);
735         D3("dl_app1_len: 0x%04X, %d", dc->config_table.dl_app1_len, dc->config_table.dl_app1_len);
736         D3("dl_app2_len: 0x%04X, %d", dc->config_table.dl_app2_len, dc->config_table.dl_app2_len);
737         D3("dl_ctrl_len: 0x%04X, %d", dc->config_table.dl_ctrl_len, dc->config_table.dl_ctrl_len);
738         D3("ul_start: 0x%04X, %d", dc->config_table.ul_start, dc->config_table.ul_start);
739         D3("ul_mdm_len[0]: 0x%04X, %d", dc->config_table.ul_mdm_len1, dc->config_table.ul_mdm_len1);
740         D3("ul_mdm_len[1]: 0x%04X, %d", dc->config_table.ul_mdm_len2, dc->config_table.ul_mdm_len2);
741         D3("ul_diag_len: 0x%04X, %d", dc->config_table.ul_diag_len, dc->config_table.ul_diag_len);
742         D3("ul_app1_len: 0x%04X, %d", dc->config_table.ul_app1_len, dc->config_table.ul_app1_len);
743         D3("ul_app2_len: 0x%04X, %d", dc->config_table.ul_app2_len, dc->config_table.ul_app2_len);
744         D3("ul_ctrl_len: 0x%04X, %d", dc->config_table.ul_ctrl_len, dc->config_table.ul_ctrl_len);
746 #endif
748 /* Read configuration table from card under intalization phase */
749 /* Returns 1 if ok, else 0 */
750 static int nozomi_read_config_table(dc_t *dc)
752         GET_MEM( &dc->config_table, dc->base_addr + 0, sizeof(config_table_t));
753         /* D1( "0x%08X == 0x%08X ", dc->config_table.signature, CONFIG_MAGIC); */
754         if ( dc->config_table.signature != CONFIG_MAGIC ) {
755                 ERR("ConfigTable Bad! 0x%08X != 0x%08X", dc->config_table.signature, CONFIG_MAGIC);
756                 return 0;
757         }
759         if ( (dc->config_table.version == 0) || (dc->config_table.toggle.enabled == TOGGLE_VALID) ) {
760                 int i;
762                 D1( "Second phase, configuring card");
763                 setup_memory(dc);
764                 dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul;
765                 dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl;
766                 dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl;
767                 D1( "toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d",
768                         dc->port[PORT_MDM].toggle_ul,
769                         dc->port[PORT_MDM].toggle_dl,
770                         dc->port[PORT_DIAG].toggle_dl);
772 #ifdef NOZOMI_DEBUG
773                 dump_table(dc);
774 #endif
775                 for (i=PORT_MDM; i< MAX_PORT;i++) {
776                         dc->port[i].fifo_ul = kfifo_alloc( FIFO_BUFFER_SIZE_UL, GFP_ATOMIC , NULL);
777                         memset( &dc->port[i].ctrl_dl, 0, sizeof (ctrl_dl_t));
778                         memset( &dc->port[i].ctrl_ul, 0, sizeof (ctrl_ul_t));
779                 }
781                 /* Enable control channel */
782                 SET_IER( CTRL_DL, CTRL_DL );
784                 INFO("Initialization OK!");
785                 return 1;
786         }
788         if( (dc->config_table.version > 0) && (dc->config_table.toggle.enabled != TOGGLE_VALID ) ) {
789                 u32 offset = 0;
790                 D1( "First phase: pushing upload buffers, clearing download");
791                 INFO("Version of card: %d", dc->config_table.version);
793                 /* Here we should disable all I/O over F32. */
794                 setup_memory(dc);
796                 /* We should send ALL channel pair tokens back along with reset token */
798                 /* push upload modem buffers */
799                 SET_MEM( dc->port[PORT_MDM].ul_addr[CH_A], &offset, 4);
800                 SET_MEM( dc->port[PORT_MDM].ul_addr[CH_B], &offset, 4);
802                 SET_FCR( MDM_UL | DIAG_DL | MDM_DL );
804                 D1( "First phase done");
805         }
807         return 1;
810 /* Enable uplink interrupts  */
811 static void enable_transmit_ul( port_type_t port , dc_t *dc )
813         switch( port ) {
814         case PORT_MDM:  SET_IER( MDM_UL , MDM_UL  ); break;
815         case PORT_DIAG: SET_IER( DIAG_UL, DIAG_UL ); break;
816         case PORT_APP1: SET_IER( APP1_UL, APP1_UL ); break;
817         case PORT_APP2: SET_IER( APP2_UL, APP2_UL ); break;
818         case PORT_CTRL: SET_IER( CTRL_UL, CTRL_UL ); break;
819         default:
820                 ERR("Called with wrong port?");
821                 break;
822         };
825 /* Disable uplink interrupts  */
826 static void disable_transmit_ul( port_type_t port , dc_t *dc )
828         switch( port ) {
829         case PORT_MDM:  SET_IER( 0 ,MDM_UL  ); break;
830         case PORT_DIAG: SET_IER( 0, DIAG_UL ); break;
831         case PORT_APP1: SET_IER( 0, APP1_UL ); break;
832         case PORT_APP2: SET_IER( 0, APP2_UL ); break;
833         case PORT_CTRL: SET_IER( 0, CTRL_UL ); break;
834         default:
835                 ERR("Called with wrong port?");
836                 break;
837         };
840 /* Enable downlink interrupts */
841 static void enable_transmit_dl( port_type_t port , dc_t *dc )
843         switch( port ) {
844         case PORT_MDM:  SET_IER( MDM_DL , MDM_DL  ); break;
845         case PORT_DIAG: SET_IER( DIAG_DL, DIAG_DL ); break;
846         case PORT_APP1: SET_IER( APP1_DL, APP1_DL ); break;
847         case PORT_APP2: SET_IER( APP2_DL, APP2_DL ); break;
848         case PORT_CTRL: SET_IER( CTRL_DL, CTRL_DL ); break;
849         default:
850                 ERR("Called with wrong port?");
851                 break;
852         };
855 /* Disable downlink interrupts */
856 static void disable_transmit_dl( port_type_t port , dc_t *dc )
858         switch( port ) {
859         case PORT_MDM:  SET_IER( 0 ,MDM_DL  ); break;
860         case PORT_DIAG: SET_IER( 0, DIAG_DL ); break;
861         case PORT_APP1: SET_IER( 0, APP1_DL ); break;
862         case PORT_APP2: SET_IER( 0, APP2_DL ); break;
863         case PORT_CTRL: SET_IER( 0, CTRL_DL ); break;
864         default:
865                 ERR("Called with wrong port?");
866                 break;
867         };
870 /* Return 1 - send buffer to card and ack. */
871 /* Return 0 - don't ack, don't send buffer to card. */
872 int send_data( port_type_t index, dc_t *dc )
874         u32                     size = 0;
875         port_t                  *port = &dc->port[index];
876         u8                      toggle = port->toggle_ul;
877         u32                     addr = port->ul_addr[toggle];
878         u32                     ul_size = port->ul_size[toggle];
879         struct tty_struct       *tty = port->tty;
881         if (index >= NTTY_TTY_MINORS) {
882                 ERR("Called with wrong index?");
883                 return 0;
884         }
886         /* Get data from tty and place in buf for now */
887         size = __kfifo_get( port->fifo_ul,      dc->send_buf, ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX );
889         if (size == 0) {
890                 D4("No more data to send, disable link:");
891                 return 0;
892         }
894         port->tx_data += size;
896         /* DUMP(buf, size); */
898         /* Write length + data */
899         SET_MEM( addr, &size, 4 );
900         SET_MEM_BUF( addr + 4, dc->send_buf, size);
902         if (port->tty) {
903                 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
904                         tty->ldisc.write_wakeup(tty);
905                 }
906                 wake_up_interruptible(&tty->write_wait);
907         }
909         return 1;
912 /* If all data has been read, return 1, else 0 */
913 static int receive_data( port_type_t index, dc_t* dc )
915         u8                      buf[RECEIVE_BUF_MAX];
916         int                     size;
917         u32                     offset=4;
918         port_t                  *port=&dc->port[index];
919         u8                      toggle=port->toggle_dl;
920         u32                     addr=port->dl_addr[toggle];
921         int                     i;
922         struct tty_struct       *tty=port->tty;
924         if ( !tty ) {
925                 D1("tty not open for port: %d?", index);
926                 return 1;
927         }
929         if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
930                 D6("TTY_DONT_FLIP set!! %d", index);
931                 /* Here we disable interrupt for that port and schedule */
932 /*              task. Task wakes up a little bit later and enables interrupt.. */
933                 port->tty_dont_flip = 1;
934                 disable_transmit_dl(index, dc);
935 #ifdef KERNEL_2_4
936                 schedule_task(&dc->tty_flip_queue);
937 #endif
938 #ifdef KERNEL_2_6
939                 if (!queue_work(dc->tty_flip_wq, &dc->tty_flip_wq_struct)) {
940                         ERR("Call to queue_work() failed.");
941                 }
942 #endif
943                 return 0;
944         }
946         GET_MEM( &size, addr, 4 );
947         /*  D1( "%d bytes port: %d", size, index); */
949         if ( test_bit( TTY_THROTTLED, & tty->flags) ) {
950                 D1("No room in tty, don't read data, don't ack interrupt, disable interrupt");
951                 /* disable interrupt in downlink... */
952                 disable_transmit_dl(index, dc);
953                 return 0;
954         }
956         if (size == 0) {
957                 ERR("size == 0?");
958                 return 1;
959         }
961         while( size > 0 ) {
962                 GET_MEM_BUF(buf, addr + offset, 4);
963                 i = 0;
964                 while (i < 4 && size > 0) {
965                         if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
966                                 tty_flip_buffer_push(tty);
967                         }
968                         tty_insert_flip_char(tty, buf[i], TTY_NORMAL);
969                         port->rx_data++;
970                         i++;
971                         size--;
972                 }
974                 offset += 4;
975         }
977         tty_flip_buffer_push(tty);
978         return 1;
981 /* Debug for interrupts */
982 #ifdef NOZOMI_DEBUG
983 static char* interrupt2str( u16 interrupt)
985         static char     buf[TMP_BUF_MAX];
986         char            *p = buf;
988         interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 "):0;
989         interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL2 "):0;
991         interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_UL1 "):0;
992         interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX, "MDM_UL2 "):0;
994         interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX, "DIAG_DL1 "):0;
995         interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX, "DIAG_DL2 "):0;
997         interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX, "DIAG_UL "):0;
999         interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX, "APP1_DL "):0;
1000         interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX, "APP2_DL "):0;
1002         interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX, "APP1_UL "):0;
1003         interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX, "APP2_UL "):0;
1005         interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX, "CTRL_DL "):0;
1006         interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX, "CTRL_UL "):0;
1008         interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX, "RESET "):0;
1010         return buf;
1012 #endif
1014 /* Receive flow control */
1015 /* Return 1 - If ok, else 0 */
1016 static int receive_flow_control( dc_t *dc, irq_t *m)
1018         port_type_t     port = PORT_MDM;
1019         ctrl_dl_t       ctrl_dl;
1020         ctrl_dl_t       old_ctrl;
1021         u16             enable_ier = 0;
1023         GET_MEM( &ctrl_dl, dc->port[PORT_CTRL].dl_addr[CH_A], 2);
1025         switch( ctrl_dl.port ) {
1026         case CTRL_CMD:
1027                 D1( "The Base Band sends this value as a response to a request for IMSI detach sent over the control channel uplink (see section 7.6.1).");
1028                 break;
1029         case CTRL_MDM:  port = PORT_MDM;  enable_ier = MDM_DL;  break;
1030         case CTRL_DIAG: port = PORT_DIAG; enable_ier = DIAG_DL; break;
1031         case CTRL_APP1: port = PORT_APP1; enable_ier = APP1_DL; break;
1032         case CTRL_APP2: port = PORT_APP2; enable_ier = APP2_DL; break;
1033         default:
1034                 ERR("ERROR: flow control received for non-existing port");
1035                 return 0;
1036         };
1038         D1( "0x%04X->0x%04X", *((u16*) &dc->port[port].ctrl_dl), *((u16*)&ctrl_dl));
1040         old_ctrl = dc->port[port].ctrl_dl;
1041         dc->port[port].ctrl_dl = ctrl_dl;
1043         if ( old_ctrl.CTS == 1 && ctrl_dl.CTS == 0 ) {
1044                 D1( "Disable interrupt (0x%04X) on port: %d", enable_ier, port);
1045                 disable_transmit_ul(port, dc);
1046         } else if ( old_ctrl.CTS == 0 && ctrl_dl.CTS == 1 ) {
1047                 if ( __kfifo_len(dc->port[port].fifo_ul) ) {
1048                         D1( "Enable interrupt (0x%04X) on port: %d", enable_ier, port);
1049                         D1( "Data in buffer [%d], enable transmit! ", __kfifo_len(dc->port[port].fifo_ul) );
1050                         enable_transmit_ul( port, dc );
1051                 } else {
1052                         D1( "No data in buffer...");
1053                 }
1054         }
1056         if(*(u16*)&old_ctrl == *(u16*)&ctrl_dl) {
1057                 D1( " No change in mctrl");
1058                 return 1;
1059         }
1060         /* Update statistics */
1061         if(old_ctrl.CTS != ctrl_dl.CTS) {
1062                 dc->port[port].tty_icount.cts++;
1063         }
1064         if(old_ctrl.DSR != ctrl_dl.DSR) {
1065                 dc->port[port].tty_icount.dsr++;
1066         }
1067         if(old_ctrl.RI != ctrl_dl.RI) {
1068                 dc->port[port].tty_icount.rng++;
1069         }
1070         if(old_ctrl.DCD != ctrl_dl.DCD) {
1071                 dc->port[port].tty_icount.dcd++;
1072         }
1073         D1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)", port,
1074                 dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts,
1075                 dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr);
1077         return 1;
1080 /* TODO:  */
1081 /* - return ctrl_port_t */
1082 static u8 port2ctrl(port_type_t port)
1084         switch( port ) {
1085         case PORT_MDM:
1086                 return CTRL_MDM;
1087         case PORT_DIAG:
1088                 return CTRL_DIAG;
1089         case PORT_APP1:
1090                 return CTRL_APP1;
1091         case PORT_APP2:
1092                 return CTRL_APP2;
1093         default:
1094                 ERR("ERROR: send flow control received for non-existing port");
1095                 return -1;
1096         };
1097         return -1;
1100 /* Send flow control, can only update one channel at a time */
1101 /* Return 0 - If we have updated all flow control */
1102 /* Return 1 - If we need to update more flow control, ack current enable more */
1103 static int send_flow_control( dc_t *dc )
1105         u32     i, more_flow_control_to_be_updated = 0;
1106         u16     *ctrl;
1108         for( i=PORT_MDM; i<MAX_PORT ; i++ ) {
1109                 if( dc->port[i].update_flow_control ) {
1110                         if ( more_flow_control_to_be_updated ) {
1111                                 /* We have more flow control to be updated */
1112                                 return 1;
1113                         }
1114                         dc->port[i].ctrl_ul.port = port2ctrl(i);
1115                         ctrl = (u16*) &dc->port[i].ctrl_ul;
1116                         /* D1( "sending flow control 0x%04X for port %d, %d", (u16) *ctrl, i, dc->port[i].ctrl_ul.port ); */
1117                         SET_MEM( dc->port[PORT_CTRL].ul_addr[0], (u32*) ctrl, 2 );
1118                         dc->port[i].update_flow_control = 0;
1119                         more_flow_control_to_be_updated = 1;
1120                 }
1121         }
1122         return 0;
1125 /* Handle donlink data, ports that are handled are modem and diagnostics */
1126 /* Return 1 - ok */
1127 /* Return 0 - toggle fields are out of sync */
1128 static int handle_data_dl(dc_t *dc, irq_t *m, port_type_t port, u8 *toggle, u16 mask1, u16 mask2)
1130         if ( *toggle == 0 && m->read_iir & mask1 ) {
1131                 if (receive_data( port, dc )) {
1132                         SET_FCR( mask1 );
1133                         *toggle = !(*toggle);
1134                 }
1136                 if ( m->read_iir & mask2 ) {
1137                         if (receive_data( port, dc )) {
1138                                 SET_FCR( mask2 );
1139                                 *toggle = !(*toggle);
1140                         }
1141                 }
1142         } else if ( *toggle == 1 && m->read_iir & mask2 ) {
1143                 if (receive_data( port, dc )) {
1144                         SET_FCR( mask2 );
1145                         *toggle = !(*toggle);
1146                 }
1148                 if ( m->read_iir & mask1 ) {
1149                         if (receive_data( port, dc )) {
1150                                 SET_FCR( mask1 );
1151                                 *toggle = !(*toggle);
1152                         }
1153                 }
1154         } else {
1155                 ERR("port out of sync!, toggle:%d", *toggle);
1156                 return 0;
1157         }
1158         return 1;
1161 /* Handle uplink data, this is currently for the modem port */
1162 /* Return 1 - ok */
1163 /* Return 0 - toggle field are out of sync */
1164 static int handle_data_ul(dc_t *dc, irq_t *m, port_type_t port)
1166         u8      *toggle = &(dc->port[port].toggle_ul);
1168         if ( *toggle==0 && m->read_iir & MDM_UL1 ) {
1169                 SET_IER( 0, MDM_UL );
1170                 if (send_data(port, dc)) {
1171                         SET_FCR( MDM_UL1 );
1172                         SET_IER( MDM_UL, MDM_UL);
1173                         *toggle = !*toggle;
1174                 }
1176                 if ( m->read_iir & MDM_UL2 ) {
1177                         SET_IER( 0, MDM_UL );
1178                         if (send_data(port, dc)) {
1179                                 SET_FCR( MDM_UL2 );
1180                                 SET_IER( MDM_UL, MDM_UL);
1181                                 *toggle = !*toggle;
1182                         }
1183                 }
1185         } else if ( *toggle==1 && m->read_iir & MDM_UL2 ) {
1186                 SET_IER( 0, MDM_UL );
1187                 if (send_data(port, dc)) {
1188                         SET_FCR( MDM_UL2 );
1189                         SET_IER( MDM_UL, MDM_UL);
1190                         *toggle = !*toggle;
1191                 }
1193                 if ( m->read_iir & MDM_UL1 ) {
1194                         SET_IER( 0, MDM_UL );
1195                         if (send_data(port, dc)) {
1196                                 SET_FCR( MDM_UL1 );
1197                                 SET_IER( MDM_UL, MDM_UL);
1198                                 *toggle = !*toggle;
1199                         }
1200                 }
1201         } else {
1202                 SET_FCR( m->read_iir & MDM_UL );
1203                 ERR("port out of sync!");
1204                 return 0;
1205         }
1206         return 1;
1209 static irqreturn_t interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
1211         dc_t    *dc = NULL;
1212         irq_t   *m = &my_irq;
1214         if (my_dev && my_dev->pdev != dev_id) {
1215                 return IRQ_NONE;
1216         }
1218         if ( !(dc = get_dc_by_pdev(dev_id)) )  {
1219                 ERR("Could not find device context from pci_dev: %d", (u32) dev_id);
1220                 return IRQ_NONE;
1221         }
1223         GET_IIR( m->read_iir );
1225 #if 1   // add by Victor Yu. 05-24-2006
1226         spin_lock(&dc->spin_mutex);
1227 #endif
1228         /* Just handle interrupt enabled in IER (by masking with dc->ier_last_written) */
1229         m->read_iir &= dc->ier_last_written;
1231         if (m->read_iir == 0) {
1232 #if 1   // add by Victor Yu. 05-24-2006
1233                 spin_unlock(&dc->spin_mutex);
1234 #endif
1235                 return IRQ_NONE;
1236         }
1238 #if 0   // mask by Victor Yu. 05-24-2006
1239         if (dc == NULL ) {
1240                 ERR("ERROR!!");
1241                 return IRQ_NONE;
1242         }
1243         spin_lock(&dc->spin_mutex);
1244 #endif
1246         D4( "%s irq:0x%04X, prev:0x%04X", interrupt2str(m->read_iir), m->read_iir, dc->ier_last_written);
1248         if ( m->read_iir & RESET) {
1249                 if( !nozomi_read_config_table(dc) ) {
1250                         SET_IER( 0, 0xFFFF);
1251                         ERR("ERR: Could not read status from card, we should disable interface");
1252                 } else {
1253                         SET_FCR( RESET );
1254                 }
1255                 goto exit_handler;  /* No more useful info if this was the reset interrupt. */
1256         }
1258         if ( m->read_iir & CTRL_UL ) {
1259                 D1( "CTRL_UL");
1260                 SET_IER( 0, CTRL_UL );
1261                 if ( send_flow_control(dc) ) {
1262                         SET_FCR( CTRL_UL );
1263                         SET_IER( CTRL_UL, CTRL_UL );
1264                 }
1265         }
1266         if ( m->read_iir & CTRL_DL ) {
1267                 receive_flow_control(dc, m);
1268                 SET_FCR( CTRL_DL );
1269         }
1270         if ( m->read_iir & MDM_DL ) {
1271                 if ( !(handle_data_dl(dc, m, PORT_MDM, &(dc->port[PORT_MDM].toggle_dl), MDM_DL1, MDM_DL2)) ) {
1272                         ERR("MDM_DL out of sync!");
1273                         goto exit_handler;
1274                 }
1275         }
1276         if ( m->read_iir & MDM_UL ) {
1277                 if ( !handle_data_ul(dc, m, PORT_MDM ) ) {
1278                         ERR("MDM_UL out of sync!");
1279                         goto exit_handler;
1280                 }
1281         }
1282         if ( m->read_iir & DIAG_DL ) {
1283                 if ( !(handle_data_dl(dc, m, PORT_DIAG, &(dc->port[PORT_DIAG].toggle_dl), DIAG_DL1, DIAG_DL2)) ) {
1284                         ERR("DIAG_DL out of sync!");
1285                         goto exit_handler;
1286                 }
1287         }
1288         if ( m->read_iir & DIAG_UL ) {
1289                 SET_IER( 0, DIAG_UL );
1290                 if( send_data( PORT_DIAG, dc ) ) {
1291                         SET_FCR( DIAG_UL );
1292                         SET_IER( DIAG_UL, DIAG_UL );
1293                 }
1294         }
1295         if ( m->read_iir & APP1_DL )  {
1296                 if (receive_data( PORT_APP1, dc ) ) {
1297                         SET_FCR( APP1_DL );
1298                 }
1299         }
1300         if ( m->read_iir & APP1_UL )  {
1301                 SET_IER( 0, APP1_UL );
1302                 if(send_data( PORT_APP1, dc )) {
1303                         SET_FCR( APP1_UL );
1304                         SET_IER( APP1_UL, APP1_UL );
1305                 }
1306         }
1307         if ( m->read_iir & APP2_DL ) {
1308                 if (receive_data( PORT_APP2, dc )) {
1309                         SET_FCR( APP2_DL );
1310                 }
1311         }
1312         if ( m->read_iir & APP2_UL ) {
1313                 SET_IER( 0, APP2_UL );
1314                 if(send_data( PORT_APP2, dc )) {
1315                         SET_FCR( APP2_UL );
1316                         SET_IER( APP2_UL, APP2_UL );
1317                 }
1318         }
1320   exit_handler:
1321         spin_unlock(&dc->spin_mutex);
1322         return IRQ_HANDLED;
1325 /* Request a shared IRQ from system */
1326 static int nozomi_setup_interrupt(struct pci_dev *pdev)
1328         int     rval;
1330         if ( (rval = request_irq( pdev->irq, &interrupt_handler, SA_SHIRQ, NOZOMI_NAME, pdev )) ) {
1331                 ERR("Cannot open because IRQ %d is already in use.", pdev->irq );
1332         }
1334         return rval;
1337 static void nozomi_get_card_type(dc_t *dc)
1339         u32     i, size=0;
1341         for( i=0; i<6; i++ ) {
1342                 size += pci_resource_len(dc->pdev, i);
1343         }
1345         /* Assume card type F32_8 if no match */
1346         dc->card_type = size == 2048 ? F32_2 : F32_8;
1348         INFO("Card type is: %d", dc->card_type );
1351 void nozomi_setup_private_data(dc_t *dc)
1353         u32     offset = dc->base_addr + dc->card_type/2;
1354         int     i;
1356         dc->REG_FCR = offset + R_FCR;
1357         dc->REG_IIR = offset + R_IIR;
1358         dc->REG_IER = offset + R_IER;
1359         dc->ier_last_written = 0;
1360         dc->closing = 0;
1362         dc->port[PORT_MDM ].token_dl = MDM_DL;
1363         dc->port[PORT_DIAG].token_dl = DIAG_DL;
1364         dc->port[PORT_APP1].token_dl = APP1_DL;
1365         dc->port[PORT_APP2].token_dl = APP2_DL;
1367         for( i=PORT_MDM; i<MAX_PORT; i++ ) {
1368                 dc->port[i].rx_data = dc->port[i].tx_data = 0;
1369                 dc->port[i].tty_dont_flip = 0;
1370         }
1374 static void tty_flip_queue_function(void *tmp_dc)
1376         dc_t    *dc = (dc_t*) tmp_dc;
1377         int     i;
1378 #if 1   // add by Victor Yu. 05-24-2006
1379         u32     flags;
1380 #endif
1382         /* Enable interrupt for that port */
1383         for(i=0;i<MAX_PORT;i++) {
1384                 if (dc->port[i].tty_dont_flip) {
1385                         D6("Enable for port: %d", i);
1386                         dc->port[i].tty_dont_flip = 0;
1387 #if 1   // add by Victor Yu. 05-24-2006
1388                         spin_lock_irqsave(&dc->spin_mutex, flags);
1389 #endif
1390                         enable_transmit_dl(dc->port[i].tty_index, dc);
1391 #if 1   // add by Victor Yu. 05-24-2006
1392                         spin_unlock_irqrestore(&dc->spin_mutex, flags);
1393 #endif
1394                 }
1395         }
1398 static int read_proc_card_type(char *buf, char **start, off_t offset, int len)
1400         dc_t    *dc = get_dc_by_index(0);
1402         len = 0;
1403         len += sprintf(buf+len,"%d\n", dc->card_type);
1404         return len;
1407 static int read_proc_open_ttys(char *buf, char **start, off_t offset, int len)
1409         dc_t    *dc = get_dc_by_index(0);
1411         len = 0;
1412         len += sprintf(buf+len,"%d\n", dc->open_ttys);
1413         return len;
1416 static int read_proc_version(char *buf, char **start, off_t offset, int len)
1418         len = 0;
1419         len += sprintf(buf+len, "%s\n", VERSION_STRING);
1420         return len;
1423 static int read_proc_rtx(char *buf, char **start, off_t offset, int len)
1425         dc_t    *dc = get_dc_by_index(0);
1426         int     i;
1428         len = 0;
1429         for(i=PORT_MDM;i<MAX_PORT;i++) {
1430                 len += sprintf(buf+len,"noz%d rx: %d, tx: %d\n", i, dc->port[i].rx_data, dc->port[i].tx_data);
1431         }
1432         return len;
1435 static void make_proc_dirs(void)
1437         dc_t    *dc = get_dc_by_index(0);
1439         dc->proc_entry = proc_mkdir("nozomi", &proc_root);
1440         /* Register the read_proc */
1441         if ( !create_proc_info_entry("card_type",0,dc->proc_entry,read_proc_card_type) ) {
1442                 ERR("ERROR: failed to register read_procmem");
1443         }
1444         if ( !create_proc_info_entry("open_ttys",0,dc->proc_entry,read_proc_open_ttys) ) {
1445                 ERR("ERROR: failed to register read_procmem");
1446         }
1447         if ( !create_proc_info_entry("rtx",0,dc->proc_entry,read_proc_rtx) ) {
1448                 ERR("ERROR: failed to register read_procmem");
1449         }
1450         if ( !create_proc_info_entry("version",0,dc->proc_entry,read_proc_version) ) {
1451                 ERR("ERROR: failed to register read_procmem");
1452         }
1455 static void remove_proc_dirs(void)
1457         dc_t    *dc = get_dc_by_index(0);
1459         remove_proc_entry("card_type", dc->proc_entry);
1460         remove_proc_entry("open_ttys", dc->proc_entry);
1461         remove_proc_entry("rtx", dc->proc_entry);
1462         remove_proc_entry("version", dc->proc_entry);
1463         remove_proc_entry("nozomi", &proc_root);
1466 /* Allocate memory for one device */
1467 static int __devinit nozomi_card_init(struct pci_dev *pdev,     const struct pci_device_id *ent)
1469         int     ret = -EIO;
1470         dc_t    *dc=NULL;
1472         cards_found++;
1473         INFO("Init, cards_found: %d", cards_found);
1475         if (!(my_dev = kmalloc(sizeof(dc_t), GFP_KERNEL))) {
1476                 D1( "Could not allocate memory");
1477                 return -EIO;
1478         }
1480         memset(my_dev, 0, sizeof( dc_t ));
1482         if (cards_found > 1) {
1483                 ERR("This driver only supports 1 device");
1484                 return -ENODEV;
1485         }
1487         my_dev->pdev = pdev;
1488         dc = my_dev;
1490         /* Find out what card type it is */
1491         nozomi_get_card_type(dc);
1493         if (pci_enable_device(dc->pdev)) {
1494                 ERR("Not possible to enable PCI Device");
1495                 return -ENODEV;
1496         }
1498         if ( (dc->base_addr = pci_resource_start(dc->pdev, 0)) == 0x0000) {
1499                 ERR("No I/O-Address for card detected");
1500                 ret = -ENODEV;
1501                 goto err_disable_device;
1502         }
1504         if (!(dc->base_addr = (u32) ioremap(dc->base_addr, dc->card_type))) {
1505                 ERR("No I/O-Address for card detected");
1506                 ret = -ENODEV;
1507                 goto err_disable_device;
1508         }
1510         dc->open_ttys=0;
1512         nozomi_setup_private_data(dc);
1514         if (pci_request_regions(dc->pdev, NOZOMI_NAME)) {
1515                 ERR("I/O address 0x%04x already in use",
1516                          (int) /* nozomi_private.io_addr */ 0);
1517                 ret = -EIO;
1518                 goto err_disable_regions;
1519         }
1521         if ( !(dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL))) {
1522                 ERR("Could not allocate send buffer?");
1523                 goto err_disable_regions;
1524         }
1526         /* Disable all interrupts */
1527         SET_IER( 0 , 0xFFFF );
1529         /* Setup interrupt handler */
1530         if (nozomi_setup_interrupt(dc->pdev)) {
1531                 ret = -EIO;
1532                 goto err_disable_regions;
1533         }
1535         D1( "base_addr: 0x%08X", dc->base_addr);
1537 #ifdef KERNEL_2_4
1538         dc->tty_flip_queue.list.next = NULL;
1539         dc->tty_flip_queue.list.prev = NULL;
1540         dc->tty_flip_queue.sync      = 0;
1541         dc->tty_flip_queue.data      = dc;
1542         dc->tty_flip_queue.routine   = tty_flip_queue_function;
1543 #endif
1544 #ifdef KERNEL_2_6
1545         if ( !(dc->tty_flip_wq = create_singlethread_workqueue(NOZOMI_NAME )) ) {
1546                 ERR("Could not create workqueue?");
1547                 BUG_ON(!dc->tty_flip_wq);
1548                 return -ENOMEM;
1549         }
1550         INIT_WORK( &dc->tty_flip_wq_struct, tty_flip_queue_function, (void*) dc);
1551 #endif
1553         spin_lock_init(&dc->spin_mutex);
1554         make_proc_dirs();
1555         ntty_tty_init(dc);
1557         /* Enable  RESET interrupt. */
1558         SET_IER( RESET, 0xFFFF );
1559         return 0;
1561 err_disable_regions:
1562         pci_release_regions(pdev);
1563         iounmap((void *)dc->base_addr );
1564         dc->base_addr = 0;
1566 err_disable_device:
1567         pci_disable_device(pdev);
1568         if(my_dev) {
1569                 kfree( my_dev );
1570         }
1571         return ret;
1574 static void tty_do_close(dc_t *dc, port_t *port)
1576 #if 1   // add by Victor Yu. 05-24-2006
1577         u32     flags;
1578 #endif
1579         down(&port->tty_sem);
1581         if ( !port->tty_open_count ) {
1582                 goto exit;
1583         }
1585         dc->open_ttys--;
1586         port->tty_open_count--;
1587 #ifdef KERNEL_2_4
1588         MOD_DEC_USE_COUNT;
1589 #endif
1591         if ( port->tty_open_count == 0) {
1592                 D1("close: %d", port->token_dl );
1593 #if 1   // add by Victor Yu. 05-24-2006
1594                 spin_lock_irqsave(&dc->spin_mutex, flags);
1595 #endif
1596                 SET_IER( 0,  port->token_dl );
1597 #if 1   // add by Victor Yu. 05-24-2006
1598                 spin_unlock_irqrestore(&dc->spin_mutex, flags);
1599 #endif
1600         }
1602 exit:
1603         up(&port->tty_sem);
1606 static void __exit tty_exit(void) {
1607         int     i;
1608         dc_t   *dc = my_dev;
1610         D1( " ");
1611 #ifdef KERNEL_2_6
1612         for (i = 0; i < NTTY_TTY_MINORS; ++i)
1613                 tty_unregister_device(&dc->tty_driver, i);
1614 #endif
1616         tty_unregister_driver(&dc->tty_driver);
1618         for (i = 0; i < NTTY_TTY_MINORS; i++) {
1619                 while (dc->port[i].tty_open_count) {
1620                         tty_do_close(dc, &dc->port[i]);
1621                 }
1622                 dc->port[i].tty = NULL;
1623         }
1626 /* Deallocate memory for one device */
1627 static void __devexit nozomi_card_exit(struct pci_dev *pdev)
1629         int             i;
1630         ctrl_ul_t       ctrl;
1631         dc_t            *dc = get_dc_by_pdev(pdev);
1633         /* Disable all interrupts */
1634         SET_IER( 0, 0xFFFF);
1636         /* Send 0x0001, command card to resend the reset token. */
1637         /* This is to get the reset when the module is reloaded. */
1638         ctrl.port = 0x00; ctrl.reserved = 0; ctrl.RTS=0; ctrl.DTR=1;
1639         D1( "sending flow control 0x%04X",  * ((u16*) &ctrl) );
1641         /* Setup dc->reg addresses to we can use defines here */
1642         nozomi_setup_private_data(dc);
1643         SET_MEM( dc->port[PORT_CTRL].ul_addr[0], (u32*) &ctrl, 2 );
1644         SET_FCR( CTRL_UL );     /* push the token to the card. */
1646         D1( "pci_release_regions");
1647         pci_release_regions(pdev);
1649         if(dc->base_addr)
1650                 iounmap((void *)dc->base_addr);
1652         D1( "pci_disable_device");
1653         pci_disable_device(pdev);
1655         free_irq( pdev->irq, pdev );
1657         for (i=PORT_MDM; i< MAX_PORT;i++) {
1658                 kfree ( dc->port[i].fifo_ul );
1659         }
1661         kfree( dc->send_buf );
1663         tty_exit();
1665         remove_proc_dirs();
1667 #ifdef KERNEL_2_6
1668         destroy_workqueue(dc->tty_flip_wq);
1669 #endif
1671         if (my_dev) {
1672                 kfree( my_dev );
1673         }
1675         cards_found--;
1678 static void set_rts(int index, int rts)
1680         dc_t    *dc = get_dc_by_index(index);
1682         dc->port[index].ctrl_ul.RTS = rts;
1683         dc->port[index].update_flow_control = 1;
1684         enable_transmit_ul(PORT_CTRL, dc);
1687 static void set_dtr(int index, int dtr)
1689         dc_t    *dc = get_dc_by_index(index);
1691         D1("SETTING DTR index: %d, dtr: %d", index, dtr);
1692         dc->port[index].ctrl_ul.DTR = dtr;
1693         dc->port[index].update_flow_control = 1;
1694         enable_transmit_ul(PORT_CTRL, dc);
1698 /*------------------------------------------------------------------------------------------
1699    TTY code
1700    -----------------------------------------------------------------------------------------*/
1703 /* Called when the userspace process opens the tty, /dev/noz*. */
1704 static int ntty_open(struct tty_struct *tty, struct file *file)
1706 #if 1   // add by Victor Yu. 05-24-2006
1707         u32     flags;
1708 #endif 
1709         s32     index = get_index(tty);
1710         port_t  *port = get_port_by_tty(tty);
1711         dc_t    *dc = get_dc_by_tty(tty);
1713         down(&port->tty_sem);
1715         tty->low_latency  = 1;
1716         tty->driver_data  = port;
1717         port->tty         = tty;
1718         port->tty_index   = index;
1720         port->tty_open_count++;
1721         dc->open_ttys++;
1723 #ifdef KERNEL_2_4
1724         MOD_INC_USE_COUNT;
1725 #endif
1727         /* Enable interrupt downlink for channel */
1728         if ( port->tty_open_count == 1) {
1729                 port->rx_data = port->tx_data = 0;
1730                 D1("open: %d", port->token_dl );
1731 #if 1   // add by Victor Yu. 05-24-2006
1732                 spin_lock_irqsave(&dc->spin_mutex, flags);
1733 #endif
1734                 SET_IER( port->token_dl,  port->token_dl );
1735 #if 1   // add by Victor Yu. 05-24-2006
1736                 spin_unlock_irqrestore(&dc->spin_mutex, flags);
1737 #endif
1738         }
1740         up(&port->tty_sem);
1742         return 0;
1745 /* Called when the userspace process close the tty, /dev/noz*. */
1746 static void ntty_close(struct tty_struct *tty, struct file *file)
1748         dc_t    *dc = get_dc_by_tty(tty);
1750         tty_do_close(dc, (port_t *) tty->driver_data);
1753 /* called when the userspace process writes to the tty (/dev/noz*).  */
1754 /* Data is inserted into a fifo, which is then read and transfered to the modem. */
1755 #ifdef KERNEL_2_6
1756 static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, int count)
1757 #else
1758 static s32 ntty_write(struct tty_struct *tty, s32 from_user, const u8 *buffer, s32 count)
1759 #endif
1761 #if 1   // add by Victor Yu. 05-24-2006
1762         u32     flags;
1763 #endif
1764         int     rval = -EINVAL;
1765         dc_t    *dc = get_dc_by_tty(tty);
1766         port_t  *port = (port_t *) tty->driver_data;
1768         /* D1( "WRITEx: %d, index = %d", count, index); */
1770         if (! port) {
1771                 return -ENODEV;
1772         }
1774         down(&port->tty_sem);
1776         if (! port->tty_open_count) {
1777                 D1( " ");
1778                 goto exit;
1779         }
1781 #ifdef KERNEL_2_4
1782         if (from_user) {
1783                 rval = __kfifo_put_user(port->fifo_ul, (unsigned char *) buffer, count);
1784         } else {
1785                 rval = __kfifo_put(port->fifo_ul, (unsigned char *) buffer, count);
1786         }
1787 #else
1788         rval = __kfifo_put(port->fifo_ul, (unsigned char *) buffer, count);
1789 #endif
1791         /* notify card */
1792         if ( dc == NULL) {
1793                 D1( "No device context?");
1794                 goto exit;
1795         }
1797         // CTS is only valid on the modem channel
1798         if ( port == &(dc->port[PORT_MDM]) ) {
1799                 if ( port->ctrl_dl.CTS ) {
1800                         D4( "Enable interrupt");
1801 #if 1   // add by Victor Yu. 05-24-2006
1802                         spin_lock_irqsave(&dc->spin_mutex, flags);
1803 #endif
1804                         enable_transmit_ul(port->tty_index, dc );
1805 #if 1   // add by Victor Yu. 05-24-2006
1806                         spin_unlock_irqrestore(&dc->spin_mutex, flags);
1807 #endif
1808                 } else {
1809                         ERR("CTS not active on modem port?");
1810                 }
1811         } else {
1812 #if 1   // add by Victor Yu. 05-24-2006
1813                 spin_lock_irqsave(&dc->spin_mutex, flags);
1814 #endif
1815                 enable_transmit_ul(port->tty_index, dc );
1816 #if 1   // add by Victor Yu. 05-24-2006
1817                 spin_unlock_irqrestore(&dc->spin_mutex, flags);
1818 #endif
1819         }
1821 exit:
1822         up(&port->tty_sem);
1823         return rval;
1826 /* Calculate how much is left in device */
1827 /* This method is called by the upper tty layer. */
1828 /*   #according to sources N_TTY.c it expects a value >= 0 and does not check for negative values. */
1829 static int ntty_write_room(struct tty_struct *tty)
1831         port_t  *port = (port_t *) tty->driver_data;
1832         int      room = 0;
1834         if (! port) {
1835                 return 0;
1836         }
1838         down(&port->tty_sem);
1840         if (! port->tty_open_count) {
1841                 goto exit;
1842         }
1844         room = port->fifo_ul->size - __kfifo_len(port->fifo_ul);
1846 exit:
1847         up(&port->tty_sem);
1848         return room;
1851 /* Sets termios flags, called by the tty layer. */
1852 static void ntty_set_termios(struct tty_struct *tty, struct termios *old_termios)
1854         unsigned int    cflag;
1856         cflag = tty->termios->c_cflag;
1857         if (old_termios) {
1858                 if ((cflag == old_termios->c_cflag) &&
1859                     (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
1860                         D1( " - nothing to change...");
1861                         goto exit_termios;
1862                 }
1863         }
1865         /* get the byte size */
1866         switch (cflag & CSIZE) {
1867         case CS5:
1868                 D1( " - data bits = 5");
1869                 break;
1870         case CS6:
1871                 D1( " - data bits = 6");
1872                 break;
1873         case CS7:
1874                 D1( " - data bits = 7");
1875                 break;
1876         case CS8:
1877         default:
1878                 D1( " - data bits = 8");
1879                 break;
1880         }
1882         /* determine the parity */
1883         if (cflag & PARENB) {
1884                 if (cflag & PARODD) {
1885                         D1( " - parity = odd");
1886                 } else {
1887                         D1( " - parity = even");
1888                 }
1889         } else {
1890                 D1( " - parity = none");
1891         }
1893         /* figure out the stop bits requested */
1894         if (cflag & CSTOPB) {
1895                 D1( " - stop bits = 2");
1896         } else {
1897                 D1( " - stop bits = 1");
1898         }
1900         /* figure out the hardware flow control settings */
1901         if (cflag & CRTSCTS) {
1902                 D1( " - RTS/CTS is enabled");
1903         } else {
1904                 D1( " - RTS/CTS is disabled");
1905         }
1907         /* determine software flow control */
1908         /* if we are implementing XON/XOFF, set the start and
1909          * stop character in the device */
1910         if (I_IXOFF(tty) || I_IXON(tty)) {
1911 #ifdef NOZOMI_DEBUG
1912                 unsigned char stop_char  = STOP_CHAR(tty);
1913                 unsigned char start_char = START_CHAR(tty);
1914 #endif
1915                 /* if we are implementing INBOUND XON/XOFF */
1916                 if (I_IXOFF(tty)) {
1917                         D1( " - INBOUND XON/XOFF is enabled, "
1918                                 "XON = %2x, XOFF = %2x", start_char, stop_char);
1919                 } else {
1920                         D1( " - INBOUND XON/XOFF is disabled");
1921                 }
1923                 /* if we are implementing OUTBOUND XON/XOFF */
1924                 if (I_IXON(tty)) {
1925                         D1( " - OUTBOUND XON/XOFF is enabled, "
1926                                 "XON = %2x, XOFF = %2x", start_char, stop_char);
1927                 } else {
1928                         D1( " - OUTBOUND XON/XOFF is disabled");
1929                 }
1930         }
1932   exit_termios:
1933         return;
1936 /* Gets io control parameters */
1937 static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
1939         port_t          *port = (port_t *) tty->driver_data;
1940         ctrl_dl_t       *ctrl_dl = &port->ctrl_dl;
1941         ctrl_ul_t       *ctrl_ul = &port->ctrl_ul;
1943         return 0
1944                 | (ctrl_ul->RTS ? TIOCM_RTS : 0)
1945                 | (ctrl_ul->DTR ? TIOCM_DTR : 0)
1946                 | (ctrl_dl->DCD ? TIOCM_CAR : 0)
1947             | (ctrl_dl->RI  ? TIOCM_RNG : 0)
1948             | (ctrl_dl->DSR ? TIOCM_DSR : 0)
1949             | (ctrl_dl->CTS ? TIOCM_CTS : 0);
1952 /* Sets io controls parameters */
1953 static int ntty_tiocmset(struct tty_struct *tty, struct file *file, u32 arg)
1955 #if 1   // add by Victor Yu. 05-24-2006
1956         u32     flags;
1957         dc_t    *dc = get_dc_by_tty(tty);
1958 #endif
1959         port_t  *port = (port_t *) tty->driver_data;
1961 #if 1   // add by Victor Yu. 05-24-2006
1962         spin_lock_irqsave(&dc->spin_mutex, flags);
1963 #endif
1964         set_rts(port->tty_index, (arg & TIOCM_RTS) ? 1 : 0);
1965         set_dtr(port->tty_index, (arg & TIOCM_DTR) ? 1 : 0);
1966 #if 1   // add by Victor Yu. 05-24-2006
1967         spin_unlock_irqrestore(&dc->spin_mutex, flags);
1968 #endif
1970         return 0;
1973 static int ntty_ioctl_tiocmiwait(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1975         port_t  *port = (port_t *) tty->driver_data;
1977         if (cmd == TIOCMIWAIT) {
1978                 DECLARE_WAITQUEUE(wait, current);
1979                 struct async_icount cnow;
1980                 struct async_icount cprev;
1982                 cprev = port->tty_icount;
1983                 while (1) {
1984                         add_wait_queue(&port->tty_wait, &wait);
1985                         set_current_state(TASK_INTERRUPTIBLE);
1986                         schedule();
1987                         remove_wait_queue(&port->tty_wait, &wait);
1989                         /* see if a signal woke us up */
1990                         if (signal_pending(current))
1991                                 return -ERESTARTSYS;
1993                         cnow = port->tty_icount;
1994                         if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
1995                             cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
1996                                 return -EIO; /* no change => error */
1997                         if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
1998                             ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
1999                             ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
2000                             ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
2001                                 return 0;
2002                         }
2003                         cprev = cnow;
2004                 }
2006         }
2007         return -ENOIOCTLCMD;
2010 static int ntty_ioctl_tiocgicount(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
2012         port_t  *port = (port_t *) tty->driver_data;
2014         if (cmd == TIOCGICOUNT) {
2015                 struct async_icount cnow = port->tty_icount;
2016                 struct serial_icounter_struct icount;
2018                 icount.cts      = cnow.cts;
2019                 icount.dsr      = cnow.dsr;
2020                 icount.rng      = cnow.rng;
2021                 icount.dcd      = cnow.dcd;
2022                 icount.rx       = cnow.rx;
2023                 icount.tx       = cnow.tx;
2024                 icount.frame    = cnow.frame;
2025                 icount.overrun  = cnow.overrun;
2026                 icount.parity   = cnow.parity;
2027                 icount.brk      = cnow.brk;
2028                 icount.buf_overrun = cnow.buf_overrun;
2030                 if (copy_to_user((void *)arg, &icount, sizeof(icount)))
2031                         return -EFAULT;
2032                 return 0;
2033         }
2034         return -ENOIOCTLCMD;
2037 static int ntty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
2039 #if 1   // add by Victor Yu. 05-24-2006
2040         u32     flags;
2041         dc_t    *dc = get_dc_by_tty(tty);
2042 #endif
2043         port_t  *port = (port_t *) tty->driver_data;
2044         int     mask;
2045         int     rval = -ENOIOCTLCMD;
2047         D1("******** IOCTL, cmd: %d", cmd);
2048         switch (cmd) {
2049 #if 0   // mask by Victor Yu. 05-25-2006
2050         case TCGETS:
2051                 D1( "IOCTL TCGETS ...");
2052                 rval = -ENOIOCTLCMD;
2053                 break;
2054         case TCSETS:
2055                 D1( "IOCTL TCSETS ...");
2056                 rval = -ENOIOCTLCMD;
2057                 break;
2058 #endif
2059         case TIOCMIWAIT:
2060                 rval = ntty_ioctl_tiocmiwait(tty, file, cmd, arg);
2061                 break;
2062         case TIOCGICOUNT:
2063                 rval =  ntty_ioctl_tiocgicount(tty, file, cmd, arg);
2064                 break;
2065         case TIOCMGET:
2066                 rval = ntty_tiocmget(tty, file);
2067                 break;
2068         case TIOCMSET:
2069                 rval = ntty_tiocmset(tty, file, arg);
2070                 break;
2071         case TIOCMBIC:
2072                 if (get_user(mask, (unsigned long *) arg))
2073                         return -EFAULT;
2075 #if 1   // add by Victor Yu. 05-24-2006
2076                 spin_lock_irqsave(&dc->spin_mutex, flags);
2077 #endif
2078                 if (mask & TIOCM_RTS)
2079                         set_rts(port->tty_index, 0);
2080                 if (mask & TIOCM_DTR)
2081                         set_dtr(port->tty_index, 0);
2082 #if 1   // add by Victor Yu. 05-24-2006
2083                 spin_unlock_irqrestore(&dc->spin_mutex, flags);
2084 #endif
2085                 rval = 0;
2086                 break;
2087         case TIOCMBIS:
2088                 if (get_user(mask, (unsigned long *) arg))
2089                         return -EFAULT;
2091 #if 1   // add by Victor Yu. 05-24-2006
2092                 spin_lock_irqsave(&dc->spin_mutex, flags);
2093 #endif
2094                 if (mask & TIOCM_RTS)
2095                         set_rts(port->tty_index, 1);
2096                 if (mask & TIOCM_DTR)
2097                         set_dtr(port->tty_index, 1);
2098 #if 1   // add by Victor Yu. 05-24-2006
2099                 spin_unlock_irqrestore(&dc->spin_mutex, flags);
2100 #endif
2101                 rval = 0;
2102                 break;
2103 #if 0   // mask by  Victor Yu.
2104         case TCFLSH:
2105                 D1( "IOCTL TCFLSH ...");
2106                 rval = -ENOIOCTLCMD;
2107                 break;
2109         default:
2110                 D1( "ERR: 0x%08X, %d", cmd, cmd);
2111                 break;
2112 #endif
2113         };
2115         return rval;
2118 /* Called by the upper tty layer when tty buffers are ready */
2119 /* to receive data again after a call to throttle. */
2120 static void ntty_unthrottle(struct tty_struct *tty)
2122         port_t  *port = (port_t *) tty->driver_data;
2123         dc_t    *dc = get_dc_by_tty(tty);
2124         u32      flags;
2126         D1( "UNTHROTTLE");
2127         spin_lock_irqsave(&dc->spin_mutex, flags);
2128         enable_transmit_dl(port->tty_index, dc);
2129         set_rts(port->tty_index, 1);
2131         spin_unlock_irqrestore(&dc->spin_mutex, flags);
2134 /* Called by the upper tty layer when the tty buffers are almost full. */
2135 /* The driver should stop send more data. */
2136 static void ntty_throttle(struct tty_struct *tty)
2138         port_t  *port = (port_t *) tty->driver_data;
2139         dc_t    *dc = get_dc_by_tty(tty);
2140         u32      flags;
2142         D1( "THROTTLE");
2143         spin_lock_irqsave(&dc->spin_mutex, flags);
2144         set_rts(port->tty_index, 0);
2145         spin_unlock_irqrestore(&dc->spin_mutex, flags);
2148 static void ntty_put_char(struct tty_struct *tty, unsigned char c)
2150         D2("PUT CHAR Function: %c", c);
2153 /* Returns number of chars in buffer, called by tty layer */
2154 static s32 ntty_chars_in_buffer(struct tty_struct *tty)
2156         port_t  *port = (port_t *) tty->driver_data;
2157         s32     rval;
2159         if (! port) {
2160                 rval = -ENODEV;
2161                 goto exit_in_buffer;
2162         }
2164         if (! port->tty_open_count) {
2165                 ERR("No tty open?");
2166                 rval = -ENODEV;
2167                 goto exit_in_buffer;
2168         }
2170         rval = __kfifo_len(port->fifo_ul);
2172   exit_in_buffer:
2173         return rval;
2176 /* Initializes the tty */
2177 static int ntty_tty_init(dc_t *dc)
2179         struct tty_driver  *td = &dc->tty_driver;
2180         int                 rval;
2181         int                 i;
2183         memset(td, 0, sizeof(struct tty_driver));
2185         td->magic                 = TTY_DRIVER_MAGIC;
2186         td->driver_name           = NOZOMI_NAME_TTY;
2187         td->name                  = "noz";
2188         td->major                 = NTTY_TTY_MAJOR,
2189         td->type                  = TTY_DRIVER_TYPE_SERIAL,
2190         td->subtype               = SERIAL_TYPE_NORMAL,
2191         td->flags                 = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
2192         td->init_termios          = tty_std_termios;
2193         td->init_termios.c_cflag  = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
2195         td->num                   = MAX_PORT;
2196         td->name_base             = 0;
2197         td->minor_start           = 0;
2199 #ifdef KERNEL_2_4
2200         td->table                 = dc->tty_table;
2201         td->refcount              = &dc->tty_refcount;
2202 #endif
2204         td->termios               = dc->tty_termios;
2205         td->termios_locked        = dc->tty_termios_locked;
2207         td->ioctl                 = ntty_ioctl;
2208         td->open                  = ntty_open;
2209         td->close                 = ntty_close;
2210         td->write                 = ntty_write;
2211         td->write_room            = ntty_write_room;
2212         td->unthrottle            = ntty_unthrottle;
2213         td->throttle              = ntty_throttle;
2214         td->set_termios           = ntty_set_termios;
2215         td->chars_in_buffer       = ntty_chars_in_buffer;
2216         td->put_char              = ntty_put_char;
2218         rval = tty_register_driver(td);
2220         if (rval) {
2221                 printk(KERN_ERR "failed to register ntty tty driver");
2222         D1( "failed to register ntty tty driver");
2223                 return rval;
2224         }
2226         for (i = 0; i < NTTY_TTY_MINORS; i++) {
2227                 init_MUTEX(&dc->port[i].tty_sem);
2228                 dc->port[i].tty_open_count = 0;
2229                 dc->port[i].tty = NULL;
2231 #ifdef KERNEL_2_6
2232                 tty_register_device(td, i, NULL);
2233 #endif
2234         }
2236         printk(KERN_INFO DRIVER_DESC " " NOZOMI_NAME_TTY);
2237         D1( " ");
2238         return rval;
2241 /* Module initialization */
2242 static struct pci_driver nozomi_driver = {
2243         .name           = NOZOMI_NAME,
2244         .id_table       = nozomi_pci_tbl,
2245         .probe          = nozomi_card_init,
2246         .remove         = __devexit_p(nozomi_card_exit),
2249 static int __init nozomi_init(void)
2251         int     rval;
2253         rval = pci_module_init(&nozomi_driver);
2254         printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
2255         return rval;
2258 static void nozomi_exit(void)
2260         printk(KERN_INFO "Unloading %s", DRIVER_DESC);
2261         pci_unregister_driver(&nozomi_driver);
2264 module_init(nozomi_init);
2265 module_exit(nozomi_exit);
2267 #ifdef NOZOMI_DEBUG
2268 MODULE_PARM(nzdebug, "i");
2269 #endif
2271 MODULE_LICENSE("Dual BSD/GPL");
2272 MODULE_DESCRIPTION( DRIVER_DESC );