Blame view

drivers/tty/cyclades.c 111 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  #undef	BLOCKMOVE
  #define	Z_WAKE
  #undef	Z_EXT_CHARS_IN_BUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
   * This file contains the driver for the Cyclades async multiport
   * serial boards.
   *
   * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
   * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
   *
ebdb51359   Jiri Slaby   cyclades: overall...
12
   * Copyright (C) 2007-2009 Jiri Slaby <jirislaby@gmail.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
17
   *
   * Much of the design and some of the code came from serial.c
   * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
   * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
   * and then fixed as suggested by Michael K. Johnson 12/12/92.
c8e1693a4   Jiri Slaby   Char: cyclades, c...
18
   * Converted to pci probing and cleaned up by Jiri Slaby.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
   */
ebdb51359   Jiri Slaby   cyclades: overall...
21
  #define CY_VERSION	"2.6"
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
22

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
  /* If you need to install more boards than NR_CARDS, change the constant
     in the definition below. No other change is necessary to support up to
     eight boards. Beyond that you'll have to extend cy_isa_addresses. */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
26
  #define NR_CARDS	4
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
  
  /*
     If the total number of ports is larger than NR_PORTS, change this
     constant in the definition below. No other change is necessary to
     support more boards/ports. */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
32
  #define NR_PORTS	256
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
40
41
42
43
44
  #define ZO_V1	0
  #define ZO_V2	1
  #define ZE_V1	2
  
  #define	SERIAL_PARANOIA_CHECK
  #undef	CY_DEBUG_OPEN
  #undef	CY_DEBUG_THROTTLE
  #undef	CY_DEBUG_OTHER
  #undef	CY_DEBUG_IO
  #undef	CY_DEBUG_COUNT
  #undef	CY_DEBUG_DTR
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
  #undef	CY_DEBUG_INTERRUPTS
  #undef	CY_16Y_HACK
  #undef	CY_ENABLE_MONITORING
  #undef	CY_PCI_DEBUG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  /*
15ed6cc0b   Alan Cox   cyclades: coding ...
50
   * Include section
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
58
  #include <linux/module.h>
  #include <linux/errno.h>
  #include <linux/signal.h>
  #include <linux/sched.h>
  #include <linux/timer.h>
  #include <linux/interrupt.h>
  #include <linux/tty.h>
33f0f88f1   Alan Cox   [PATCH] TTY layer...
59
  #include <linux/tty_flip.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
65
66
67
68
69
70
71
  #include <linux/serial.h>
  #include <linux/major.h>
  #include <linux/string.h>
  #include <linux/fcntl.h>
  #include <linux/ptrace.h>
  #include <linux/cyclades.h>
  #include <linux/mm.h>
  #include <linux/ioport.h>
  #include <linux/init.h>
  #include <linux/delay.h>
  #include <linux/spinlock.h>
  #include <linux/bitops.h>
054f5b0aa   Jiri Slaby   Char: cyclades, a...
72
  #include <linux/firmware.h>
9f56fad74   Scott James Remnant   cyclades: Auto-lo...
73
  #include <linux/device.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
74
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75

15ed6cc0b   Alan Cox   cyclades: coding ...
76
  #include <linux/io.h>
15ed6cc0b   Alan Cox   cyclades: coding ...
77
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
  #include <linux/kernel.h>
  #include <linux/pci.h>
  
  #include <linux/stat.h>
  #include <linux/proc_fs.h>
444697d61   Alexey Dobriyan   proc tty: switch ...
84
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
86
  static void cy_send_xchar(struct tty_struct *tty, char ch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
  #ifndef SERIAL_XMIT_SIZE
  #define	SERIAL_XMIT_SIZE	(min(PAGE_SIZE, 4096))
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
  
  #define STD_COM_FLAGS (0)
054f5b0aa   Jiri Slaby   Char: cyclades, a...
93
94
95
96
  /* firmware stuff */
  #define ZL_MAX_BLOCKS	16
  #define DRIVER_VERSION	0x02010203
  #define RAM_SIZE 0x80000
054f5b0aa   Jiri Slaby   Char: cyclades, a...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  enum zblock_type {
  	ZBLOCK_PRG = 0,
  	ZBLOCK_FPGA = 1
  };
  
  struct zfile_header {
  	char name[64];
  	char date[32];
  	char aux[32];
  	u32 n_config;
  	u32 config_offset;
  	u32 n_blocks;
  	u32 block_offset;
  	u32 reserved[9];
  } __attribute__ ((packed));
  
  struct zfile_config {
  	char name[64];
  	u32 mailbox;
  	u32 function;
  	u32 n_blocks;
  	u32 block_list[ZL_MAX_BLOCKS];
  } __attribute__ ((packed));
  
  struct zfile_block {
  	u32 type;
  	u32 file_offset;
  	u32 ram_offset;
  	u32 size;
  } __attribute__ ((packed));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
131
132
133
134
  static struct tty_driver *cy_serial_driver;
  
  #ifdef CONFIG_ISA
  /* This is the address lookup table. The driver will probe for
     Cyclom-Y/ISA boards at all addresses in here. If you want the
     driver to probe addresses at a different address, add it to
     this table.  If the driver is probing some other board and
     causing problems, remove the offending address from this table.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
137
  */
  
  static unsigned int cy_isa_addresses[] = {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
138
139
140
141
142
143
144
145
146
  	0xD0000,
  	0xD2000,
  	0xD4000,
  	0xD6000,
  	0xD8000,
  	0xDA000,
  	0xDC000,
  	0xDE000,
  	0, 0, 0, 0, 0, 0, 0, 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  };
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
148

fe971071a   Tobias Klauser   [PATCH] drivers/c...
149
  #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150

3046d50ea   Jiri Slaby   Char: cyclades, s...
151
152
  static long maddr[NR_CARDS];
  static int irq[NR_CARDS];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
  
  module_param_array(maddr, long, NULL, 0);
  module_param_array(irq, int, NULL, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
157
  #endif				/* CONFIG_ISA */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
162
  
  /* This is the per-card data structure containing address, irq, number of
     channels, etc. This driver supports a maximum of NR_CARDS cards.
  */
  static struct cyclades_card cy_card[NR_CARDS];
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
163
  static int cy_next_channel;	/* next minor available */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
   * This is used to look up the divisor speeds and the timeouts
   * We're normally limited to 15 distinct baud rates.  The extra
77451e53e   Alan Cox   cyclades: use tty...
168
   * are accessed via settings in info->port.flags.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
172
173
   *      0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
   *     10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
   *                                               HI            VHI
   *     20
   */
ebdb51359   Jiri Slaby   cyclades: overall...
174
  static const int baud_table[] = {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
175
176
177
178
  	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
  	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
  	230400, 0
  };
ebdb51359   Jiri Slaby   cyclades: overall...
179
  static const char baud_co_25[] = {	/* 25 MHz clock option table */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
180
181
182
183
184
  	/* value =>    00    01   02    03    04 */
  	/* divide by    8    32   128   512  2048 */
  	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
  	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };
ebdb51359   Jiri Slaby   cyclades: overall...
185
  static const char baud_bpr_25[] = {	/* 25 MHz baud rate period table */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
186
187
188
  	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
  	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
  };
ebdb51359   Jiri Slaby   cyclades: overall...
189
  static const char baud_co_60[] = {	/* 60 MHz clock option table (CD1400 J) */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
190
191
192
193
194
195
  	/* value =>    00    01   02    03    04 */
  	/* divide by    8    32   128   512  2048 */
  	0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
  	0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00
  };
ebdb51359   Jiri Slaby   cyclades: overall...
196
  static const char baud_bpr_60[] = {	/* 60 MHz baud rate period table (CD1400 J) */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
197
198
199
200
  	0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
  	0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
  	0x21
  };
ebdb51359   Jiri Slaby   cyclades: overall...
201
  static const char baud_cor3[] = {	/* receive threshold */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
202
203
204
205
  	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
  	0x07
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
  
  /*
   * The Cyclades driver implements HW flow control as any serial driver.
15ed6cc0b   Alan Cox   cyclades: coding ...
209
210
211
212
213
214
   * The cyclades_port structure member rflow and the vector rflow_thr
   * allows us to take advantage of a special feature in the CD1400 to avoid
   * data loss even when the system interrupt latency is too high. These flags
   * are to be used only with very special applications. Setting these flags
   * requires the use of a special cable (DTR and RTS reversed). In the new
   * CD1400-based boards (rev. 6.00 or later), there is no need for special
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
   * cables.
   */
ebdb51359   Jiri Slaby   cyclades: overall...
217
  static const char rflow_thr[] = {	/* rflow threshold */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
218
219
220
221
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  	0x0a
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
  
  /*  The Cyclom-Ye has placed the sequential chips in non-sequential
   *  address order.  This look-up table overcomes that problem.
   */
f0eefdc30   Jiri Slaby   cyclades: avoid a...
226
  static const unsigned int cy_chip_offset[] = { 0x0000,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
227
228
229
230
231
232
233
234
  	0x0400,
  	0x0800,
  	0x0C00,
  	0x0200,
  	0x0600,
  	0x0A00,
  	0x0E00
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  
  /* PCI related definitions */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  #ifdef CONFIG_PCI
ebdb51359   Jiri Slaby   cyclades: overall...
238
  static const struct pci_device_id cy_pci_dev_id[] = {
15ed6cc0b   Alan Cox   cyclades: coding ...
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  	/* PCI < 1Mb */
  	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
  	/* PCI > 1Mb */
  	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },
  	/* 4Y PCI < 1Mb */
  	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },
  	/* 4Y PCI > 1Mb */
  	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },
  	/* 8Y PCI < 1Mb */
  	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },
  	/* 8Y PCI > 1Mb */
  	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },
  	/* Z PCI < 1Mb */
  	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },
  	/* Z PCI > 1Mb */
  	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },
893de2dff   Jiri Slaby   [PATCH] Char: cyc...
255
  	{ }			/* end of table */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
256
  };
893de2dff   Jiri Slaby   [PATCH] Char: cyc...
257
  MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
  #endif
  
  static void cy_start(struct tty_struct *);
d13549f80   Jiri Slaby   cyclades: add tty...
261
  static void cy_set_line_char(struct cyclades_port *, struct tty_struct *);
1a86b5e34   Klaus Kudielka   cyclades: remove ...
262
  static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
  #ifdef CONFIG_ISA
  static unsigned detect_isa_irq(void __iomem *);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
265
  #endif				/* CONFIG_ISA */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
270
271
  #ifndef CONFIG_CYZ_INTR
  static void cyz_poll(unsigned long);
  
  /* The Cyclades-Z polling cycle is defined by this variable */
  static long cyz_polling_cycle = CZ_DEF_POLL;
8d06afab7   Ingo Molnar   [PATCH] timer ini...
272
  static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
274
  #else				/* CONFIG_CYZ_INTR */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
  static void cyz_rx_restart(unsigned long);
  static struct timer_list cyz_rx_full_timer[NR_PORTS];
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
277
  #endif				/* CONFIG_CYZ_INTR */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

3aeea5b92   Jiri Slaby   cyclades: introdu...
279
280
281
282
283
284
285
286
287
288
289
290
291
  static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val)
  {
  	struct cyclades_card *card = port->card;
  
  	cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val);
  }
  
  static inline u8 cyy_readb(struct cyclades_port *port, u32 reg)
  {
  	struct cyclades_card *card = port->card;
  
  	return readb(port->u.cyy.base_addr + (reg << card->bus_index));
  }
2693f485c   Jiri Slaby   tty: cyclades, co...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  static inline bool cy_is_Z(struct cyclades_card *card)
  {
  	return card->num_chips == (unsigned int)-1;
  }
  
  static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr)
  {
  	return readl(&ctl_addr->init_ctrl) & (1 << 17);
  }
  
  static inline bool cyz_fpga_loaded(struct cyclades_card *card)
  {
  	return __cyz_fpga_loaded(card->ctl_addr.p9060);
  }
  
  static inline bool cyz_is_loaded(struct cyclades_card *card)
  {
  	struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS;
  
  	return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) &&
  			readl(&fw_id->signature) == ZFIRM_ID;
  }
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
314
  static inline int serial_paranoia_check(struct cyclades_port *info,
ebdb51359   Jiri Slaby   cyclades: overall...
315
  		const char *name, const char *routine)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
  {
  #ifdef SERIAL_PARANOIA_CHECK
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
318
  	if (!info) {
217191910   Jiri Slaby   Char: cyclades, p...
319
320
321
  		printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) "
  				"in %s
  ", name, routine);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
322
323
  		return 1;
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
324
  	if (info->magic != CYCLADES_MAGIC) {
217191910   Jiri Slaby   Char: cyclades, p...
325
326
327
  		printk(KERN_WARNING "cyc Warning: bad magic number for serial "
  				"struct (%s) in %s
  ", name, routine);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
328
329
  		return 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
331
  	return 0;
ebdb51359   Jiri Slaby   cyclades: overall...
332
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
338
339
340
341
342
343
  /***********************************************************/
  /********* Start of block of Cyclom-Y specific code ********/
  
  /* This routine waits up to 1000 micro-seconds for the previous
     command to the Cirrus chip to complete and then issues the
     new command.  An error is returned if the previous command
     didn't finish within the time limit.
  
     This function is only called from inside spinlock-protected code.
   */
3aeea5b92   Jiri Slaby   cyclades: introdu...
344
  static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  {
3aeea5b92   Jiri Slaby   cyclades: introdu...
346
  	void __iomem *ccr = base_addr + (CyCCR << index);
ad39c3004   Jiri Slaby   Char: cyclades, r...
347
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
349
350
  	/* Check to see that the previous command has completed */
  	for (i = 0; i < 100; i++) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
351
  		if (readb(ccr) == 0)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
352
  			break;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
353
  		udelay(10L);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
355
356
357
  	/* if the CCR never cleared, the previous command
  	   didn't finish within the "reasonable time" */
  	if (i == 100)
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
358
  		return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
360
  	/* Issue the new command */
3aeea5b92   Jiri Slaby   cyclades: introdu...
361
  	cy_writeb(ccr, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362

096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
363
  	return 0;
3aeea5b92   Jiri Slaby   cyclades: introdu...
364
365
366
367
368
369
370
  }
  
  static inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd)
  {
  	return __cyy_issue_cmd(port->u.cyy.base_addr, cmd,
  			port->card->bus_index);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
  
  #ifdef CONFIG_ISA
  /* ISA interrupt detection code */
15ed6cc0b   Alan Cox   cyclades: coding ...
374
  static unsigned detect_isa_irq(void __iomem *address)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  	int irq;
  	unsigned long irqs, flags;
  	int save_xir, save_car;
  	int index = 0;		/* IRQ probing is only for ISA */
  
  	/* forget possible initially masked and pending IRQ */
  	irq = probe_irq_off(probe_irq_on());
  
  	/* Clear interrupts on the board first */
  	cy_writeb(address + (Cy_ClrIntr << index), 0);
  	/* Cy_ClrIntr is 0x1800 */
  
  	irqs = probe_irq_on();
  	/* Wait ... */
f6e208c11   Jiri Slaby   cyclades: sleep i...
390
  	msleep(5);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
391
392
393
394
  
  	/* Enable the Tx interrupts on the CD1400 */
  	local_irq_save(flags);
  	cy_writeb(address + (CyCAR << index), 0);
3aeea5b92   Jiri Slaby   cyclades: introdu...
395
  	__cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
396
397
398
  
  	cy_writeb(address + (CyCAR << index), 0);
  	cy_writeb(address + (CySRER << index),
db05c3b1d   Jiri Slaby   Char: cyclades, c...
399
  		  readb(address + (CySRER << index)) | CyTxRdy);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
400
401
402
  	local_irq_restore(flags);
  
  	/* Wait ... */
f6e208c11   Jiri Slaby   cyclades: sleep i...
403
  	msleep(5);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
404
405
406
407
408
  
  	/* Check which interrupt is in use */
  	irq = probe_irq_off(irqs);
  
  	/* Clean up */
db05c3b1d   Jiri Slaby   Char: cyclades, c...
409
410
  	save_xir = (u_char) readb(address + (CyTIR << index));
  	save_car = readb(address + (CyCAR << index));
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
411
412
  	cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
  	cy_writeb(address + (CySRER << index),
db05c3b1d   Jiri Slaby   Char: cyclades, c...
413
  		  readb(address + (CySRER << index)) & ~CyTxRdy);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
414
415
416
417
418
419
  	cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
  	cy_writeb(address + (CyCAR << index), (save_car));
  	cy_writeb(address + (Cy_ClrIntr << index), 0);
  	/* Cy_ClrIntr is 0x1800 */
  
  	return (irq > 0) ? irq : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  }
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
421
  #endif				/* CONFIG_ISA */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422

ce97a0976   Jiri Slaby   Char: cyclades, m...
423
424
  static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
  		void __iomem *base_addr)
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
425
426
427
  {
  	struct cyclades_port *info;
  	struct tty_struct *tty;
65f76a82e   Jiri Slaby   Char: cyclades, f...
428
  	int len, index = cinfo->bus_index;
3aeea5b92   Jiri Slaby   cyclades: introdu...
429
  	u8 ivr, save_xir, channel, save_car, data, char_count;
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
430

e941027f5   Jiri Slaby   [PATCH] Char: cyc...
431
  #ifdef CY_DEBUG_INTERRUPTS
ce97a0976   Jiri Slaby   Char: cyclades, m...
432
433
  	printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d
  ", chip);
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
434
  #endif
ce97a0976   Jiri Slaby   Char: cyclades, m...
435
  	/* determine the channel & change to that context */
65f76a82e   Jiri Slaby   Char: cyclades, f...
436
437
  	save_xir = readb(base_addr + (CyRIR << index));
  	channel = save_xir & CyIRChannel;
ce97a0976   Jiri Slaby   Char: cyclades, m...
438
  	info = &cinfo->ports[channel + chip * 4];
3aeea5b92   Jiri Slaby   cyclades: introdu...
439
440
441
  	save_car = cyy_readb(info, CyCAR);
  	cyy_writeb(info, CyCAR, save_xir);
  	ivr = cyy_readb(info, CyRIVR) & CyIVRMask;
ce97a0976   Jiri Slaby   Char: cyclades, m...
442

d13549f80   Jiri Slaby   cyclades: add tty...
443
  	tty = tty_port_tty_get(&info->port);
ce97a0976   Jiri Slaby   Char: cyclades, m...
444
  	/* if there is nowhere to put the data, discard it */
d13549f80   Jiri Slaby   cyclades: add tty...
445
  	if (tty == NULL) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
446
447
  		if (ivr == CyIVRRxEx) {	/* exception */
  			data = cyy_readb(info, CyRDSR);
ce97a0976   Jiri Slaby   Char: cyclades, m...
448
  		} else {	/* normal character reception */
3aeea5b92   Jiri Slaby   cyclades: introdu...
449
  			char_count = cyy_readb(info, CyRDCR);
ce97a0976   Jiri Slaby   Char: cyclades, m...
450
  			while (char_count--)
3aeea5b92   Jiri Slaby   cyclades: introdu...
451
  				data = cyy_readb(info, CyRDSR);
ce97a0976   Jiri Slaby   Char: cyclades, m...
452
453
454
455
  		}
  		goto end;
  	}
  	/* there is an open port for this data */
3aeea5b92   Jiri Slaby   cyclades: introdu...
456
457
  	if (ivr == CyIVRRxEx) {	/* exception */
  		data = cyy_readb(info, CyRDSR);
ce97a0976   Jiri Slaby   Char: cyclades, m...
458
459
460
461
462
463
464
465
466
467
468
469
470
  
  		/* For statistics only */
  		if (data & CyBREAK)
  			info->icount.brk++;
  		else if (data & CyFRAME)
  			info->icount.frame++;
  		else if (data & CyPARITY)
  			info->icount.parity++;
  		else if (data & CyOVERRUN)
  			info->icount.overrun++;
  
  		if (data & info->ignore_status_mask) {
  			info->icount.rx++;
d13549f80   Jiri Slaby   cyclades: add tty...
471
  			tty_kref_put(tty);
ce97a0976   Jiri Slaby   Char: cyclades, m...
472
473
474
475
476
477
  			return;
  		}
  		if (tty_buffer_request_room(tty, 1)) {
  			if (data & info->read_status_mask) {
  				if (data & CyBREAK) {
  					tty_insert_flip_char(tty,
3aeea5b92   Jiri Slaby   cyclades: introdu...
478
479
  						cyy_readb(info, CyRDSR),
  						TTY_BREAK);
ce97a0976   Jiri Slaby   Char: cyclades, m...
480
  					info->icount.rx++;
77451e53e   Alan Cox   cyclades: use tty...
481
  					if (info->port.flags & ASYNC_SAK)
ce97a0976   Jiri Slaby   Char: cyclades, m...
482
483
  						do_SAK(tty);
  				} else if (data & CyFRAME) {
15ed6cc0b   Alan Cox   cyclades: coding ...
484
  					tty_insert_flip_char(tty,
3aeea5b92   Jiri Slaby   cyclades: introdu...
485
486
  						cyy_readb(info, CyRDSR),
  						TTY_FRAME);
ce97a0976   Jiri Slaby   Char: cyclades, m...
487
488
489
490
491
  					info->icount.rx++;
  					info->idle_stats.frame_errs++;
  				} else if (data & CyPARITY) {
  					/* Pieces of seven... */
  					tty_insert_flip_char(tty,
3aeea5b92   Jiri Slaby   cyclades: introdu...
492
493
  						cyy_readb(info, CyRDSR),
  						TTY_PARITY);
ce97a0976   Jiri Slaby   Char: cyclades, m...
494
495
496
497
498
499
500
501
502
503
504
  					info->icount.rx++;
  					info->idle_stats.parity_errs++;
  				} else if (data & CyOVERRUN) {
  					tty_insert_flip_char(tty, 0,
  							TTY_OVERRUN);
  					info->icount.rx++;
  					/* If the flip buffer itself is
  					   overflowing, we still lose
  					   the next incoming character.
  					 */
  					tty_insert_flip_char(tty,
3aeea5b92   Jiri Slaby   cyclades: introdu...
505
506
  						cyy_readb(info, CyRDSR),
  						TTY_FRAME);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
507
  					info->icount.rx++;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
508
  					info->idle_stats.overruns++;
ce97a0976   Jiri Slaby   Char: cyclades, m...
509
510
511
512
513
514
515
516
  				/* These two conditions may imply */
  				/* a normal read should be done. */
  				/* } else if(data & CyTIMEOUT) { */
  				/* } else if(data & CySPECHAR) { */
  				} else {
  					tty_insert_flip_char(tty, 0,
  							TTY_NORMAL);
  					info->icount.rx++;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
517
  				}
ce97a0976   Jiri Slaby   Char: cyclades, m...
518
519
520
521
522
523
524
525
526
527
528
529
  			} else {
  				tty_insert_flip_char(tty, 0, TTY_NORMAL);
  				info->icount.rx++;
  			}
  		} else {
  			/* there was a software buffer overrun and nothing
  			 * could be done about it!!! */
  			info->icount.buf_overrun++;
  			info->idle_stats.overruns++;
  		}
  	} else {	/* normal character reception */
  		/* load # chars available from the chip */
3aeea5b92   Jiri Slaby   cyclades: introdu...
530
  		char_count = cyy_readb(info, CyRDCR);
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
531
532
  
  #ifdef CY_ENABLE_MONITORING
ce97a0976   Jiri Slaby   Char: cyclades, m...
533
534
535
536
537
  		++info->mon.int_count;
  		info->mon.char_count += char_count;
  		if (char_count > info->mon.char_max)
  			info->mon.char_max = char_count;
  		info->mon.char_last = char_count;
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
538
  #endif
ce97a0976   Jiri Slaby   Char: cyclades, m...
539
540
  		len = tty_buffer_request_room(tty, char_count);
  		while (len--) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
541
  			data = cyy_readb(info, CyRDSR);
ce97a0976   Jiri Slaby   Char: cyclades, m...
542
543
544
  			tty_insert_flip_char(tty, data, TTY_NORMAL);
  			info->idle_stats.recv_bytes++;
  			info->icount.rx++;
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
545
  #ifdef CY_16Y_HACK
ce97a0976   Jiri Slaby   Char: cyclades, m...
546
  			udelay(10L);
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
547
  #endif
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
548
  		}
ce97a0976   Jiri Slaby   Char: cyclades, m...
549
  		info->idle_stats.recv_idle = jiffies;
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
550
  	}
ce97a0976   Jiri Slaby   Char: cyclades, m...
551
  	tty_schedule_flip(tty);
d13549f80   Jiri Slaby   cyclades: add tty...
552
  	tty_kref_put(tty);
ce97a0976   Jiri Slaby   Char: cyclades, m...
553
554
  end:
  	/* end of service */
3aeea5b92   Jiri Slaby   cyclades: introdu...
555
556
  	cyy_writeb(info, CyRIR, save_xir & 0x3f);
  	cyy_writeb(info, CyCAR, save_car);
ce97a0976   Jiri Slaby   Char: cyclades, m...
557
  }
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
558

65f76a82e   Jiri Slaby   Char: cyclades, f...
559
  static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
ce97a0976   Jiri Slaby   Char: cyclades, m...
560
561
562
  		void __iomem *base_addr)
  {
  	struct cyclades_port *info;
d13549f80   Jiri Slaby   cyclades: add tty...
563
  	struct tty_struct *tty;
65f76a82e   Jiri Slaby   Char: cyclades, f...
564
565
  	int char_count, index = cinfo->bus_index;
  	u8 save_xir, channel, save_car, outch;
ce97a0976   Jiri Slaby   Char: cyclades, m...
566
567
568
569
  
  	/* Since we only get here when the transmit buffer
  	   is empty, we know we can always stuff a dozen
  	   characters. */
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
570
  #ifdef CY_DEBUG_INTERRUPTS
ce97a0976   Jiri Slaby   Char: cyclades, m...
571
572
  	printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d
  ", chip);
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
573
  #endif
ce97a0976   Jiri Slaby   Char: cyclades, m...
574
  	/* determine the channel & change to that context */
65f76a82e   Jiri Slaby   Char: cyclades, f...
575
576
  	save_xir = readb(base_addr + (CyTIR << index));
  	channel = save_xir & CyIRChannel;
ce97a0976   Jiri Slaby   Char: cyclades, m...
577
578
  	save_car = readb(base_addr + (CyCAR << index));
  	cy_writeb(base_addr + (CyCAR << index), save_xir);
ce97a0976   Jiri Slaby   Char: cyclades, m...
579
  	info = &cinfo->ports[channel + chip * 4];
d13549f80   Jiri Slaby   cyclades: add tty...
580
581
  	tty = tty_port_tty_get(&info->port);
  	if (tty == NULL) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
582
  		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
ce97a0976   Jiri Slaby   Char: cyclades, m...
583
584
  		goto end;
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
585

ce97a0976   Jiri Slaby   Char: cyclades, m...
586
587
  	/* load the on-chip space for outbound data */
  	char_count = info->xmit_fifo_size;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
588

ce97a0976   Jiri Slaby   Char: cyclades, m...
589
590
  	if (info->x_char) {	/* send special char */
  		outch = info->x_char;
3aeea5b92   Jiri Slaby   cyclades: introdu...
591
  		cyy_writeb(info, CyTDR, outch);
ce97a0976   Jiri Slaby   Char: cyclades, m...
592
593
594
595
  		char_count--;
  		info->icount.tx++;
  		info->x_char = 0;
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
596

ce97a0976   Jiri Slaby   Char: cyclades, m...
597
598
  	if (info->breakon || info->breakoff) {
  		if (info->breakon) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
599
600
  			cyy_writeb(info, CyTDR, 0);
  			cyy_writeb(info, CyTDR, 0x81);
ce97a0976   Jiri Slaby   Char: cyclades, m...
601
602
  			info->breakon = 0;
  			char_count -= 2;
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
603
  		}
ce97a0976   Jiri Slaby   Char: cyclades, m...
604
  		if (info->breakoff) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
605
606
  			cyy_writeb(info, CyTDR, 0);
  			cyy_writeb(info, CyTDR, 0x83);
ce97a0976   Jiri Slaby   Char: cyclades, m...
607
608
  			info->breakoff = 0;
  			char_count -= 2;
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
609
  		}
ce97a0976   Jiri Slaby   Char: cyclades, m...
610
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
611

ce97a0976   Jiri Slaby   Char: cyclades, m...
612
613
  	while (char_count-- > 0) {
  		if (!info->xmit_cnt) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
614
615
616
  			if (cyy_readb(info, CySRER) & CyTxMpty) {
  				cyy_writeb(info, CySRER,
  					cyy_readb(info, CySRER) & ~CyTxMpty);
ce97a0976   Jiri Slaby   Char: cyclades, m...
617
  			} else {
3aeea5b92   Jiri Slaby   cyclades: introdu...
618
619
  				cyy_writeb(info, CySRER, CyTxMpty |
  					(cyy_readb(info, CySRER) & ~CyTxRdy));
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
620
  			}
ce97a0976   Jiri Slaby   Char: cyclades, m...
621
622
  			goto done;
  		}
77451e53e   Alan Cox   cyclades: use tty...
623
  		if (info->port.xmit_buf == NULL) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
624
625
  			cyy_writeb(info, CySRER,
  				cyy_readb(info, CySRER) & ~CyTxRdy);
ce97a0976   Jiri Slaby   Char: cyclades, m...
626
627
  			goto done;
  		}
d13549f80   Jiri Slaby   cyclades: add tty...
628
  		if (tty->stopped || tty->hw_stopped) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
629
630
  			cyy_writeb(info, CySRER,
  				cyy_readb(info, CySRER) & ~CyTxRdy);
ce97a0976   Jiri Slaby   Char: cyclades, m...
631
632
633
634
635
636
637
638
639
640
641
  			goto done;
  		}
  		/* Because the Embedded Transmit Commands have been enabled,
  		 * we must check to see if the escape character, NULL, is being
  		 * sent. If it is, we must ensure that there is room for it to
  		 * be doubled in the output stream.  Therefore we no longer
  		 * advance the pointer when the character is fetched, but
  		 * rather wait until after the check for a NULL output
  		 * character. This is necessary because there may not be room
  		 * for the two chars needed to send a NULL.)
  		 */
77451e53e   Alan Cox   cyclades: use tty...
642
  		outch = info->port.xmit_buf[info->xmit_tail];
ce97a0976   Jiri Slaby   Char: cyclades, m...
643
644
645
646
  		if (outch) {
  			info->xmit_cnt--;
  			info->xmit_tail = (info->xmit_tail + 1) &
  					(SERIAL_XMIT_SIZE - 1);
3aeea5b92   Jiri Slaby   cyclades: introdu...
647
  			cyy_writeb(info, CyTDR, outch);
ce97a0976   Jiri Slaby   Char: cyclades, m...
648
649
650
  			info->icount.tx++;
  		} else {
  			if (char_count > 1) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
651
652
  				info->xmit_cnt--;
  				info->xmit_tail = (info->xmit_tail + 1) &
ce97a0976   Jiri Slaby   Char: cyclades, m...
653
  					(SERIAL_XMIT_SIZE - 1);
3aeea5b92   Jiri Slaby   cyclades: introdu...
654
655
  				cyy_writeb(info, CyTDR, outch);
  				cyy_writeb(info, CyTDR, 0);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
656
  				info->icount.tx++;
ce97a0976   Jiri Slaby   Char: cyclades, m...
657
  				char_count--;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
658
  			}
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
659
  		}
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
660
  	}
ce97a0976   Jiri Slaby   Char: cyclades, m...
661
  done:
d13549f80   Jiri Slaby   cyclades: add tty...
662
663
  	tty_wakeup(tty);
  	tty_kref_put(tty);
ce97a0976   Jiri Slaby   Char: cyclades, m...
664
665
  end:
  	/* end of service */
3aeea5b92   Jiri Slaby   cyclades: introdu...
666
667
  	cyy_writeb(info, CyTIR, save_xir & 0x3f);
  	cyy_writeb(info, CyCAR, save_car);
ce97a0976   Jiri Slaby   Char: cyclades, m...
668
  }
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
669

ce97a0976   Jiri Slaby   Char: cyclades, m...
670
671
672
673
  static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
  		void __iomem *base_addr)
  {
  	struct cyclades_port *info;
d13549f80   Jiri Slaby   cyclades: add tty...
674
  	struct tty_struct *tty;
65f76a82e   Jiri Slaby   Char: cyclades, f...
675
676
  	int index = cinfo->bus_index;
  	u8 save_xir, channel, save_car, mdm_change, mdm_status;
ce97a0976   Jiri Slaby   Char: cyclades, m...
677
678
  
  	/* determine the channel & change to that context */
65f76a82e   Jiri Slaby   Char: cyclades, f...
679
680
  	save_xir = readb(base_addr + (CyMIR << index));
  	channel = save_xir & CyIRChannel;
ce97a0976   Jiri Slaby   Char: cyclades, m...
681
  	info = &cinfo->ports[channel + chip * 4];
3aeea5b92   Jiri Slaby   cyclades: introdu...
682
683
  	save_car = cyy_readb(info, CyCAR);
  	cyy_writeb(info, CyCAR, save_xir);
ce97a0976   Jiri Slaby   Char: cyclades, m...
684

3aeea5b92   Jiri Slaby   cyclades: introdu...
685
686
  	mdm_change = cyy_readb(info, CyMISR);
  	mdm_status = cyy_readb(info, CyMSVR1);
ce97a0976   Jiri Slaby   Char: cyclades, m...
687

d13549f80   Jiri Slaby   cyclades: add tty...
688
689
  	tty = tty_port_tty_get(&info->port);
  	if (!tty)
ce97a0976   Jiri Slaby   Char: cyclades, m...
690
691
692
693
694
695
696
697
698
699
700
701
  		goto end;
  
  	if (mdm_change & CyANY_DELTA) {
  		/* For statistics only */
  		if (mdm_change & CyDCD)
  			info->icount.dcd++;
  		if (mdm_change & CyCTS)
  			info->icount.cts++;
  		if (mdm_change & CyDSR)
  			info->icount.dsr++;
  		if (mdm_change & CyRI)
  			info->icount.rng++;
bdc04e317   Alan Cox   serial: move delt...
702
  		wake_up_interruptible(&info->port.delta_msr_wait);
ce97a0976   Jiri Slaby   Char: cyclades, m...
703
  	}
77451e53e   Alan Cox   cyclades: use tty...
704
  	if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
174e6fe01   Jiri Slaby   cyclades: switch ...
705
706
707
  		if (mdm_status & CyDCD)
  			wake_up_interruptible(&info->port.open_wait);
  		else
d13549f80   Jiri Slaby   cyclades: add tty...
708
  			tty_hangup(tty);
ce97a0976   Jiri Slaby   Char: cyclades, m...
709
  	}
77451e53e   Alan Cox   cyclades: use tty...
710
  	if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
d13549f80   Jiri Slaby   cyclades: add tty...
711
  		if (tty->hw_stopped) {
ce97a0976   Jiri Slaby   Char: cyclades, m...
712
713
714
  			if (mdm_status & CyCTS) {
  				/* cy_start isn't used
  				   because... !!! */
d13549f80   Jiri Slaby   cyclades: add tty...
715
  				tty->hw_stopped = 0;
3aeea5b92   Jiri Slaby   cyclades: introdu...
716
717
  				cyy_writeb(info, CySRER,
  					cyy_readb(info, CySRER) | CyTxRdy);
d13549f80   Jiri Slaby   cyclades: add tty...
718
  				tty_wakeup(tty);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
719
  			}
ce97a0976   Jiri Slaby   Char: cyclades, m...
720
721
722
723
  		} else {
  			if (!(mdm_status & CyCTS)) {
  				/* cy_stop isn't used
  				   because ... !!! */
d13549f80   Jiri Slaby   cyclades: add tty...
724
  				tty->hw_stopped = 1;
3aeea5b92   Jiri Slaby   cyclades: introdu...
725
726
  				cyy_writeb(info, CySRER,
  					cyy_readb(info, CySRER) & ~CyTxRdy);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
727
  			}
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
728
  		}
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
729
  	}
ce97a0976   Jiri Slaby   Char: cyclades, m...
730
731
732
733
  /*	if (mdm_change & CyDSR) {
  	}
  	if (mdm_change & CyRI) {
  	}*/
d13549f80   Jiri Slaby   cyclades: add tty...
734
  	tty_kref_put(tty);
ce97a0976   Jiri Slaby   Char: cyclades, m...
735
736
  end:
  	/* end of service */
3aeea5b92   Jiri Slaby   cyclades: introdu...
737
738
  	cyy_writeb(info, CyMIR, save_xir & 0x3f);
  	cyy_writeb(info, CyCAR, save_car);
e941027f5   Jiri Slaby   [PATCH] Char: cyc...
739
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
741
742
743
  /* The real interrupt service routine is called
     whenever the card wants its hand held--chars
     received, out buffer empty, modem change, etc.
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
744
  static irqreturn_t cyy_interrupt(int irq, void *dev_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
746
  	int status;
f74290342   Jiri Slaby   Char: cyclades, c...
747
  	struct cyclades_card *cinfo = dev_id;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
748
  	void __iomem *base_addr, *card_base_addr;
65f76a82e   Jiri Slaby   Char: cyclades, f...
749
  	unsigned int chip, too_many, had_work;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
750
  	int index;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
751

f74290342   Jiri Slaby   Char: cyclades, c...
752
  	if (unlikely(cinfo == NULL)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
  #ifdef CY_DEBUG_INTERRUPTS
15ed6cc0b   Alan Cox   cyclades: coding ...
754
755
756
  		printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d
  ",
  				irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
758
759
760
761
762
  		return IRQ_NONE;	/* spurious interrupt */
  	}
  
  	card_base_addr = cinfo->base_addr;
  	index = cinfo->bus_index;
f1e83c6c1   Jiri Slaby   Char: cyclades, a...
763
764
765
  	/* card was not initialized yet (e.g. DEBUG_SHIRQ) */
  	if (unlikely(card_base_addr == NULL))
  		return IRQ_HANDLED;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
766
767
768
769
770
771
772
773
774
775
776
  	/* This loop checks all chips in the card.  Make a note whenever
  	   _any_ chip had some work to do, as this is considered an
  	   indication that there will be more to do.  Only when no chip
  	   has any work does this outermost loop exit.
  	 */
  	do {
  		had_work = 0;
  		for (chip = 0; chip < cinfo->num_chips; chip++) {
  			base_addr = cinfo->base_addr +
  					(cy_chip_offset[chip] << index);
  			too_many = 0;
db05c3b1d   Jiri Slaby   Char: cyclades, c...
777
  			while ((status = readb(base_addr +
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
778
779
780
781
782
783
784
  						(CySVRR << index))) != 0x00) {
  				had_work++;
  			/* The purpose of the following test is to ensure that
  			   no chip can monopolize the driver.  This forces the
  			   chips to be checked in a round-robin fashion (after
  			   draining each of a bunch (1000) of characters).
  			 */
ce97a0976   Jiri Slaby   Char: cyclades, m...
785
  				if (1000 < too_many++)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
786
  					break;
1c0a387c1   Jiri Slaby   Char: cyclades, m...
787
  				spin_lock(&cinfo->card_lock);
ce97a0976   Jiri Slaby   Char: cyclades, m...
788
789
790
791
792
793
  				if (status & CySRReceive) /* rx intr */
  					cyy_chip_rx(cinfo, chip, base_addr);
  				if (status & CySRTransmit) /* tx intr */
  					cyy_chip_tx(cinfo, chip, base_addr);
  				if (status & CySRModem) /* modem intr */
  					cyy_chip_modem(cinfo, chip, base_addr);
1c0a387c1   Jiri Slaby   Char: cyclades, m...
794
  				spin_unlock(&cinfo->card_lock);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
795
796
797
798
799
800
801
802
803
804
805
  			}
  		}
  	} while (had_work);
  
  	/* clear interrupts */
  	spin_lock(&cinfo->card_lock);
  	cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0);
  	/* Cy_ClrIntr is 0x1800 */
  	spin_unlock(&cinfo->card_lock);
  	return IRQ_HANDLED;
  }				/* cyy_interrupt */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806

4d7682005   Jiri Slaby   cyclades: use dtr...
807
808
809
810
  static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
  		unsigned int clear)
  {
  	struct cyclades_card *card = info->card;
3aeea5b92   Jiri Slaby   cyclades: introdu...
811
  	int channel = info->line - card->first_line;
0d3487294   Jiri Slaby   cyclades: tiocm c...
812
  	u32 rts, dtr, msvrr, msvrd;
4d7682005   Jiri Slaby   cyclades: use dtr...
813

4d7682005   Jiri Slaby   cyclades: use dtr...
814
  	channel &= 0x03;
4d7682005   Jiri Slaby   cyclades: use dtr...
815

0d3487294   Jiri Slaby   cyclades: tiocm c...
816
817
818
819
820
821
822
823
824
825
826
  	if (info->rtsdtr_inv) {
  		msvrr = CyMSVR2;
  		msvrd = CyMSVR1;
  		rts = CyDTR;
  		dtr = CyRTS;
  	} else {
  		msvrr = CyMSVR1;
  		msvrd = CyMSVR2;
  		rts = CyRTS;
  		dtr = CyDTR;
  	}
4d7682005   Jiri Slaby   cyclades: use dtr...
827
  	if (set & TIOCM_RTS) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
828
829
  		cyy_writeb(info, CyCAR, channel);
  		cyy_writeb(info, msvrr, rts);
4d7682005   Jiri Slaby   cyclades: use dtr...
830
831
  	}
  	if (clear & TIOCM_RTS) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
832
833
  		cyy_writeb(info, CyCAR, channel);
  		cyy_writeb(info, msvrr, ~rts);
4d7682005   Jiri Slaby   cyclades: use dtr...
834
835
  	}
  	if (set & TIOCM_DTR) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
836
837
  		cyy_writeb(info, CyCAR, channel);
  		cyy_writeb(info, msvrd, dtr);
4d7682005   Jiri Slaby   cyclades: use dtr...
838
839
840
841
842
  #ifdef CY_DEBUG_DTR
  		printk(KERN_DEBUG "cyc:set_modem_info raising DTR
  ");
  		printk(KERN_DEBUG "     status: 0x%x, 0x%x
  ",
3aeea5b92   Jiri Slaby   cyclades: introdu...
843
844
  			cyy_readb(info, CyMSVR1),
  			cyy_readb(info, CyMSVR2));
4d7682005   Jiri Slaby   cyclades: use dtr...
845
846
847
  #endif
  	}
  	if (clear & TIOCM_DTR) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
848
849
  		cyy_writeb(info, CyCAR, channel);
  		cyy_writeb(info, msvrd, ~dtr);
4d7682005   Jiri Slaby   cyclades: use dtr...
850
851
852
853
854
  #ifdef CY_DEBUG_DTR
  		printk(KERN_DEBUG "cyc:set_modem_info dropping DTR
  ");
  		printk(KERN_DEBUG "     status: 0x%x, 0x%x
  ",
3aeea5b92   Jiri Slaby   cyclades: introdu...
855
856
  			cyy_readb(info, CyMSVR1),
  			cyy_readb(info, CyMSVR2));
4d7682005   Jiri Slaby   cyclades: use dtr...
857
858
859
  #endif
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
  /***********************************************************/
  /********* End of block of Cyclom-Y specific code **********/
15ed6cc0b   Alan Cox   cyclades: coding ...
862
  /******** Start of block of Cyclades-Z specific code *******/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
864
865
  /***********************************************************/
  
  static int
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
866
  cyz_fetch_msg(struct cyclades_card *cinfo,
15ed6cc0b   Alan Cox   cyclades: coding ...
867
  		__u32 *channel, __u8 *cmd, __u32 *param)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
  {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
869
  	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
870
  	unsigned long loc_doorbell;
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
871
  	loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
872
873
  	if (loc_doorbell) {
  		*cmd = (char)(0xff & loc_doorbell);
db05c3b1d   Jiri Slaby   Char: cyclades, c...
874
875
  		*channel = readl(&board_ctrl->fwcmd_channel);
  		*param = (__u32) readl(&board_ctrl->fwcmd_param);
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
876
  		cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
877
878
879
880
  		return 1;
  	}
  	return 0;
  }				/* cyz_fetch_msg */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
882
  
  static int
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
883
  cyz_issue_cmd(struct cyclades_card *cinfo,
1a86b5e34   Klaus Kudielka   cyclades: remove ...
884
  		__u32 channel, __u8 cmd, __u32 param)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
  {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
886
  	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
1a86b5e34   Klaus Kudielka   cyclades: remove ...
887
  	__u32 __iomem *pci_doorbell;
65f76a82e   Jiri Slaby   Char: cyclades, f...
888
  	unsigned int index;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
889

2693f485c   Jiri Slaby   tty: cyclades, co...
890
  	if (!cyz_is_loaded(cinfo))
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
891
  		return -1;
15ed6cc0b   Alan Cox   cyclades: coding ...
892

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
893
  	index = 0;
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
894
  	pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
db05c3b1d   Jiri Slaby   Char: cyclades, c...
895
  	while ((readl(pci_doorbell) & 0xff) != 0) {
15ed6cc0b   Alan Cox   cyclades: coding ...
896
  		if (index++ == 1000)
db05c3b1d   Jiri Slaby   Char: cyclades, c...
897
  			return (int)(readl(pci_doorbell) & 0xff);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
898
899
900
901
902
  		udelay(50L);
  	}
  	cy_writel(&board_ctrl->hcmd_channel, channel);
  	cy_writel(&board_ctrl->hcmd_param, param);
  	cy_writel(pci_doorbell, (long)cmd);
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
903
  	return 0;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
904
  }				/* cyz_issue_cmd */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905

f0eefdc30   Jiri Slaby   cyclades: avoid a...
906
  static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
  {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
908
  	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
875b206b5   Jiri Slaby   Char: cyclades, m...
909
  	struct cyclades_card *cinfo = info->card;
65f76a82e   Jiri Slaby   Char: cyclades, f...
910
  	unsigned int char_count;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
911
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
  #ifdef BLOCKMOVE
ce71b0ffd   Jiri Slaby   Char: cyclades, f...
913
  	unsigned char *buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
  #else
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
915
  	char data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
  #endif
ad39c3004   Jiri Slaby   Char: cyclades, r...
917
  	__u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918

db05c3b1d   Jiri Slaby   Char: cyclades, c...
919
920
921
922
  	rx_get = new_rx_get = readl(&buf_ctrl->rx_get);
  	rx_put = readl(&buf_ctrl->rx_put);
  	rx_bufsize = readl(&buf_ctrl->rx_bufsize);
  	rx_bufaddr = readl(&buf_ctrl->rx_bufaddr);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
923
924
925
926
  	if (rx_put >= rx_get)
  		char_count = rx_put - rx_get;
  	else
  		char_count = rx_put - rx_get + rx_bufsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
928
  	if (char_count) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
  #ifdef CY_ENABLE_MONITORING
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
930
931
932
933
934
  		info->mon.int_count++;
  		info->mon.char_count += char_count;
  		if (char_count > info->mon.char_max)
  			info->mon.char_max = char_count;
  		info->mon.char_last = char_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935
  #endif
f74290342   Jiri Slaby   Char: cyclades, c...
936
  		if (tty == NULL) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
937
938
939
940
941
  			/* flush received characters */
  			new_rx_get = (new_rx_get + char_count) &
  					(rx_bufsize - 1);
  			info->rflush_count++;
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
  #ifdef BLOCKMOVE
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
943
944
945
  		/* we'd like to use memcpy(t, f, n) and memset(s, c, count)
  		   for performance, but because of buffer boundaries, there
  		   may be several steps to the operation */
ce71b0ffd   Jiri Slaby   Char: cyclades, f...
946
947
948
949
950
951
952
953
954
955
956
957
958
  			while (1) {
  				len = tty_prepare_flip_string(tty, &buf,
  						char_count);
  				if (!len)
  					break;
  
  				len = min_t(unsigned int, min(len, char_count),
  						rx_bufsize - new_rx_get);
  
  				memcpy_fromio(buf, cinfo->base_addr +
  						rx_bufaddr + new_rx_get, len);
  
  				new_rx_get = (new_rx_get + len) &
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
959
  						(rx_bufsize - 1);
ce71b0ffd   Jiri Slaby   Char: cyclades, f...
960
961
962
  				char_count -= len;
  				info->icount.rx += len;
  				info->idle_stats.recv_bytes += len;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
963
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
  #else
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
965
966
  			len = tty_buffer_request_room(tty, char_count);
  			while (len--) {
db05c3b1d   Jiri Slaby   Char: cyclades, c...
967
  				data = readb(cinfo->base_addr + rx_bufaddr +
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
968
  						new_rx_get);
15ed6cc0b   Alan Cox   cyclades: coding ...
969
970
  				new_rx_get = (new_rx_get + 1) &
  							(rx_bufsize - 1);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
971
972
973
974
  				tty_insert_flip_char(tty, data, TTY_NORMAL);
  				info->idle_stats.recv_bytes++;
  				info->icount.rx++;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
  #endif
  #ifdef CONFIG_CYZ_INTR
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
977
978
  		/* Recalculate the number of chars in the RX buffer and issue
  		   a cmd in case it's higher than the RX high water mark */
db05c3b1d   Jiri Slaby   Char: cyclades, c...
979
  			rx_put = readl(&buf_ctrl->rx_put);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
980
981
982
983
  			if (rx_put >= rx_get)
  				char_count = rx_put - rx_get;
  			else
  				char_count = rx_put - rx_get + rx_bufsize;
65f76a82e   Jiri Slaby   Char: cyclades, f...
984
  			if (char_count >= readl(&buf_ctrl->rx_threshold) &&
ebafeeff0   Jiri Slaby   Char: cyclades, r...
985
986
987
988
  					!timer_pending(&cyz_rx_full_timer[
  							info->line]))
  				mod_timer(&cyz_rx_full_timer[info->line],
  						jiffies + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
990
991
992
993
994
  			info->idle_stats.recv_idle = jiffies;
  			tty_schedule_flip(tty);
  		}
  		/* Update rx_get */
  		cy_writel(&buf_ctrl->rx_get, new_rx_get);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
  }
f0eefdc30   Jiri Slaby   cyclades: avoid a...
997
  static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998
  {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
999
  	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
875b206b5   Jiri Slaby   Char: cyclades, m...
1000
  	struct cyclades_card *cinfo = info->card;
65f76a82e   Jiri Slaby   Char: cyclades, f...
1001
1002
  	u8 data;
  	unsigned int char_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
  #ifdef BLOCKMOVE
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1004
  	int small_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
  #endif
ad39c3004   Jiri Slaby   Char: cyclades, r...
1006
  	__u32 tx_put, tx_get, tx_bufsize, tx_bufaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1008
1009
  	if (info->xmit_cnt <= 0)	/* Nothing to transmit */
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010

db05c3b1d   Jiri Slaby   Char: cyclades, c...
1011
1012
1013
1014
  	tx_get = readl(&buf_ctrl->tx_get);
  	tx_put = readl(&buf_ctrl->tx_put);
  	tx_bufsize = readl(&buf_ctrl->tx_bufsize);
  	tx_bufaddr = readl(&buf_ctrl->tx_bufaddr);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1015
1016
1017
1018
  	if (tx_put >= tx_get)
  		char_count = tx_get - tx_put - 1 + tx_bufsize;
  	else
  		char_count = tx_get - tx_put - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1020
  	if (char_count) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021

f74290342   Jiri Slaby   Char: cyclades, c...
1022
  		if (tty == NULL)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1023
  			goto ztxdone;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1025
1026
  		if (info->x_char) {	/* send special char */
  			data = info->x_char;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1028
1029
1030
1031
1032
  			cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
  			tx_put = (tx_put + 1) & (tx_bufsize - 1);
  			info->x_char = 0;
  			char_count--;
  			info->icount.tx++;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1033
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  #ifdef BLOCKMOVE
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1035
1036
1037
1038
1039
1040
1041
1042
  		while (0 < (small_count = min_t(unsigned int,
  				tx_bufsize - tx_put, min_t(unsigned int,
  					(SERIAL_XMIT_SIZE - info->xmit_tail),
  					min_t(unsigned int, info->xmit_cnt,
  						char_count))))) {
  
  			memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
  					tx_put),
77451e53e   Alan Cox   cyclades: use tty...
1043
  					&info->port.xmit_buf[info->xmit_tail],
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1044
1045
1046
1047
1048
1049
1050
1051
  					small_count);
  
  			tx_put = (tx_put + small_count) & (tx_bufsize - 1);
  			char_count -= small_count;
  			info->icount.tx += small_count;
  			info->xmit_cnt -= small_count;
  			info->xmit_tail = (info->xmit_tail + small_count) &
  					(SERIAL_XMIT_SIZE - 1);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1052
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
  #else
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1054
  		while (info->xmit_cnt && char_count) {
77451e53e   Alan Cox   cyclades: use tty...
1055
  			data = info->port.xmit_buf[info->xmit_tail];
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1056
1057
1058
1059
1060
1061
1062
1063
  			info->xmit_cnt--;
  			info->xmit_tail = (info->xmit_tail + 1) &
  					(SERIAL_XMIT_SIZE - 1);
  
  			cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
  			tx_put = (tx_put + 1) & (tx_bufsize - 1);
  			char_count--;
  			info->icount.tx++;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1064
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
  #endif
ebafeeff0   Jiri Slaby   Char: cyclades, r...
1066
  		tty_wakeup(tty);
7fa57a0cd   Jiri Slaby   Char: cyclades, f...
1067
  ztxdone:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1068
1069
  		/* Update tx_put */
  		cy_writel(&buf_ctrl->tx_put, tx_put);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1071
  }
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1072
  static void cyz_handle_cmd(struct cyclades_card *cinfo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
  {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1074
  	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1075
1076
  	struct tty_struct *tty;
  	struct cyclades_port *info;
101b81590   Jiri Slaby   tty: cyclades, ca...
1077
  	__u32 channel, param, fw_ver;
1a86b5e34   Klaus Kudielka   cyclades: remove ...
1078
  	__u8 cmd;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1079
1080
  	int special_count;
  	int delta_count;
db05c3b1d   Jiri Slaby   Char: cyclades, c...
1081
  	fw_ver = readl(&board_ctrl->fw_version);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1082
1083
1084
1085
  
  	while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
  		special_count = 0;
  		delta_count = 0;
dd025c0c7   Jiri Slaby   Char: cyclades, d...
1086
  		info = &cinfo->ports[channel];
d13549f80   Jiri Slaby   cyclades: add tty...
1087
  		tty = tty_port_tty_get(&info->port);
15ed6cc0b   Alan Cox   cyclades: coding ...
1088
  		if (tty == NULL)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1089
  			continue;
f74290342   Jiri Slaby   Char: cyclades, c...
1090

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
  		switch (cmd) {
  		case C_CM_PR_ERROR:
  			tty_insert_flip_char(tty, 0, TTY_PARITY);
  			info->icount.rx++;
  			special_count++;
  			break;
  		case C_CM_FR_ERROR:
  			tty_insert_flip_char(tty, 0, TTY_FRAME);
  			info->icount.rx++;
  			special_count++;
  			break;
  		case C_CM_RXBRK:
  			tty_insert_flip_char(tty, 0, TTY_BREAK);
  			info->icount.rx++;
  			special_count++;
  			break;
  		case C_CM_MDCD:
  			info->icount.dcd++;
  			delta_count++;
77451e53e   Alan Cox   cyclades: use tty...
1110
  			if (info->port.flags & ASYNC_CHECK_CD) {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1111
1112
  				u32 dcd = fw_ver > 241 ? param :
  					readl(&info->u.cyz.ch_ctrl->rs_status);
174e6fe01   Jiri Slaby   cyclades: switch ...
1113
  				if (dcd & C_RS_DCD)
77451e53e   Alan Cox   cyclades: use tty...
1114
  					wake_up_interruptible(&info->port.open_wait);
174e6fe01   Jiri Slaby   cyclades: switch ...
1115
  				else
d13549f80   Jiri Slaby   cyclades: add tty...
1116
  					tty_hangup(tty);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
  			}
  			break;
  		case C_CM_MCTS:
  			info->icount.cts++;
  			delta_count++;
  			break;
  		case C_CM_MRI:
  			info->icount.rng++;
  			delta_count++;
  			break;
  		case C_CM_MDSR:
  			info->icount.dsr++;
  			delta_count++;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131
  #ifdef Z_WAKE
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1132
  		case C_CM_IOCTLW:
ebafeeff0   Jiri Slaby   Char: cyclades, r...
1133
  			complete(&info->shutdown_wait);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1134
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
  #endif
  #ifdef CONFIG_CYZ_INTR
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1137
1138
1139
1140
  		case C_CM_RXHIWM:
  		case C_CM_RXNNDT:
  		case C_CM_INTBACK2:
  			/* Reception Interrupt */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
  #ifdef CY_DEBUG_INTERRUPTS
217191910   Jiri Slaby   Char: cyclades, p...
1142
1143
1144
  			printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
  					"port %ld
  ", info->card, channel);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1145
  #endif
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1146
  			cyz_handle_rx(info, tty);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1147
1148
1149
1150
1151
  			break;
  		case C_CM_TXBEMPTY:
  		case C_CM_TXLOWWM:
  		case C_CM_INTBACK:
  			/* Transmission Interrupt */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
  #ifdef CY_DEBUG_INTERRUPTS
217191910   Jiri Slaby   Char: cyclades, p...
1153
1154
1155
  			printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
  					"port %ld
  ", info->card, channel);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156
  #endif
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1157
  			cyz_handle_tx(info, tty);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1158
1159
1160
1161
1162
1163
1164
1165
1166
  			break;
  #endif				/* CONFIG_CYZ_INTR */
  		case C_CM_FATAL:
  			/* should do something with this !!! */
  			break;
  		default:
  			break;
  		}
  		if (delta_count)
bdc04e317   Alan Cox   serial: move delt...
1167
  			wake_up_interruptible(&info->port.delta_msr_wait);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1168
1169
  		if (special_count)
  			tty_schedule_flip(tty);
d13549f80   Jiri Slaby   cyclades: add tty...
1170
  		tty_kref_put(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
1173
1174
  }
  
  #ifdef CONFIG_CYZ_INTR
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1175
  static irqreturn_t cyz_interrupt(int irq, void *dev_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
  {
f74290342   Jiri Slaby   Char: cyclades, c...
1177
  	struct cyclades_card *cinfo = dev_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178

2693f485c   Jiri Slaby   tty: cyclades, co...
1179
  	if (unlikely(!cyz_is_loaded(cinfo))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  #ifdef CY_DEBUG_INTERRUPTS
217191910   Jiri Slaby   Char: cyclades, p...
1181
1182
1183
  		printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
  				"(IRQ%d).
  ", irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1185
1186
  		return IRQ_NONE;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1188
1189
  	/* Handle the interrupts */
  	cyz_handle_cmd(cinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1191
1192
  	return IRQ_HANDLED;
  }				/* cyz_interrupt */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1194
  static void cyz_rx_restart(unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1196
  	struct cyclades_port *info = (struct cyclades_port *)arg;
875b206b5   Jiri Slaby   Char: cyclades, m...
1197
  	struct cyclades_card *card = info->card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1198
  	int retval;
875b206b5   Jiri Slaby   Char: cyclades, m...
1199
  	__u32 channel = info->line - card->first_line;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1200
  	unsigned long flags;
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1201
  	spin_lock_irqsave(&card->card_lock, flags);
875b206b5   Jiri Slaby   Char: cyclades, m...
1202
  	retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1203
  	if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
1204
1205
  		printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x
  ",
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1206
1207
  			info->line, retval);
  	}
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1208
  	spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
  }
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1210
  #else				/* CONFIG_CYZ_INTR */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1212
  static void cyz_poll(unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1214
1215
  	struct cyclades_card *cinfo;
  	struct cyclades_port *info;
b70509066   Jiri Slaby   Char: cyclades, t...
1216
  	unsigned long expires = jiffies + HZ;
65f76a82e   Jiri Slaby   Char: cyclades, f...
1217
  	unsigned int port, card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1219
1220
  	for (card = 0; card < NR_CARDS; card++) {
  		cinfo = &cy_card[card];
2693f485c   Jiri Slaby   tty: cyclades, co...
1221
  		if (!cy_is_Z(cinfo))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1222
  			continue;
2693f485c   Jiri Slaby   tty: cyclades, co...
1223
  		if (!cyz_is_loaded(cinfo))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1224
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
  	/* Skip first polling cycle to avoid racing conditions with the FW */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1226
  		if (!cinfo->intr_enabled) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1227
1228
1229
  			cinfo->intr_enabled = 1;
  			continue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1231
  		cyz_handle_cmd(cinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1233
  		for (port = 0; port < cinfo->nports; port++) {
d13549f80   Jiri Slaby   cyclades: add tty...
1234
  			struct tty_struct *tty;
dd025c0c7   Jiri Slaby   Char: cyclades, d...
1235
  			info = &cinfo->ports[port];
d13549f80   Jiri Slaby   cyclades: add tty...
1236
1237
1238
  			tty = tty_port_tty_get(&info->port);
  			/* OK to pass NULL to the handle functions below.
  			   They need to drop the data in that case. */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1239
  			if (!info->throttle)
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1240
1241
  				cyz_handle_rx(info, tty);
  			cyz_handle_tx(info, tty);
d13549f80   Jiri Slaby   cyclades: add tty...
1242
  			tty_kref_put(tty);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1243
1244
  		}
  		/* poll every 'cyz_polling_cycle' period */
b70509066   Jiri Slaby   Char: cyclades, t...
1245
  		expires = jiffies + cyz_polling_cycle;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
  	}
b70509066   Jiri Slaby   Char: cyclades, t...
1247
  	mod_timer(&cyz_timerlist, expires);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1248
  }				/* cyz_poll */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1250
  #endif				/* CONFIG_CYZ_INTR */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1251
1252
1253
  
  /********** End of block of Cyclades-Z specific code *********/
  /***********************************************************/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
1256
  /* This is called whenever a port becomes active;
     interrupts are enabled and DTR & RTS are turned on.
   */
d13549f80   Jiri Slaby   cyclades: add tty...
1257
  static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
  {
875b206b5   Jiri Slaby   Char: cyclades, m...
1259
  	struct cyclades_card *card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1260
1261
  	unsigned long flags;
  	int retval = 0;
cc7fdf49d   Jiri Slaby   cyclades: merge c...
1262
  	int channel;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1263
  	unsigned long page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1265
  	card = info->card;
875b206b5   Jiri Slaby   Char: cyclades, m...
1266
  	channel = info->line - card->first_line;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1268
1269
1270
  	page = get_zeroed_page(GFP_KERNEL);
  	if (!page)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1272
  	spin_lock_irqsave(&card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273

cc7fdf49d   Jiri Slaby   cyclades: merge c...
1274
  	if (info->port.flags & ASYNC_INITIALIZED)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1275
  		goto errout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1277
  	if (!info->type) {
d13549f80   Jiri Slaby   cyclades: add tty...
1278
  		set_bit(TTY_IO_ERROR, &tty->flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1279
1280
  		goto errout;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281

77451e53e   Alan Cox   cyclades: use tty...
1282
  	if (info->port.xmit_buf)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1283
1284
  		free_page(page);
  	else
77451e53e   Alan Cox   cyclades: use tty...
1285
  		info->port.xmit_buf = (unsigned char *)page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1287
  	spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288

d13549f80   Jiri Slaby   cyclades: add tty...
1289
  	cy_set_line_char(info, tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290

2693f485c   Jiri Slaby   tty: cyclades, co...
1291
  	if (!cy_is_Z(card)) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1292
  		channel &= 0x03;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1294
  		spin_lock_irqsave(&card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295

3aeea5b92   Jiri Slaby   cyclades: introdu...
1296
  		cyy_writeb(info, CyCAR, channel);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297

3aeea5b92   Jiri Slaby   cyclades: introdu...
1298
  		cyy_writeb(info, CyRTPR,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1299
1300
  			(info->default_timeout ? info->default_timeout : 0x02));
  		/* 10ms rx timeout */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301

3aeea5b92   Jiri Slaby   cyclades: introdu...
1302
  		cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303

4d7682005   Jiri Slaby   cyclades: use dtr...
1304
  		cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305

3aeea5b92   Jiri Slaby   cyclades: introdu...
1306
  		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1307
  	} else {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1308
  		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309

2693f485c   Jiri Slaby   tty: cyclades, co...
1310
  		if (!cyz_is_loaded(card))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1311
  			return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1312

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
  #ifdef CY_DEBUG_OPEN
217191910   Jiri Slaby   Char: cyclades, p...
1314
  		printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1315
1316
  			"base_addr %p
  ", card, channel, card->base_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
  #endif
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1318
  		spin_lock_irqsave(&card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319

f0eefdc30   Jiri Slaby   cyclades: avoid a...
1320
  		cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321
1322
  #ifdef Z_WAKE
  #ifdef CONFIG_CYZ_INTR
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1323
  		cy_writel(&ch_ctrl->intr_enable,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1324
1325
  			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
  			  C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326
  #else
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1327
  		cy_writel(&ch_ctrl->intr_enable,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1328
1329
  			  C_IN_IOCTLW | C_IN_MDCD);
  #endif				/* CONFIG_CYZ_INTR */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330
1331
  #else
  #ifdef CONFIG_CYZ_INTR
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1332
  		cy_writel(&ch_ctrl->intr_enable,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1333
1334
  			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
  			  C_IN_RXNNDT | C_IN_MDCD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
  #else
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1336
  		cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1337
1338
  #endif				/* CONFIG_CYZ_INTR */
  #endif				/* Z_WAKE */
875b206b5   Jiri Slaby   Char: cyclades, m...
1339
  		retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1340
  		if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
1341
1342
1343
  			printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was "
  				"%x
  ", info->line, retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1344
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1346
  		/* Flush RX buffers before raising DTR and RTS */
875b206b5   Jiri Slaby   Char: cyclades, m...
1347
  		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1348
  		if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
1349
1350
1351
  			printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was "
  				"%x
  ", info->line, retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1352
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1354
1355
  		/* set timeout !!! */
  		/* set RTS and DTR !!! */
4d7682005   Jiri Slaby   cyclades: use dtr...
1356
  		tty_port_raise_dtr_rts(&info->port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1358
  		/* enable send, recv, modem !!! */
cc7fdf49d   Jiri Slaby   cyclades: merge c...
1359
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1360

cc7fdf49d   Jiri Slaby   cyclades: merge c...
1361
  	info->port.flags |= ASYNC_INITIALIZED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1362

cc7fdf49d   Jiri Slaby   cyclades: merge c...
1363
1364
1365
1366
1367
1368
1369
1370
1371
  	clear_bit(TTY_IO_ERROR, &tty->flags);
  	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
  	info->breakon = info->breakoff = 0;
  	memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
  	info->idle_stats.in_use =
  	info->idle_stats.recv_idle =
  	info->idle_stats.xmit_idle = jiffies;
  
  	spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1372
1373
  
  #ifdef CY_DEBUG_OPEN
217191910   Jiri Slaby   Char: cyclades, p...
1374
1375
  	printk(KERN_DEBUG "cyc startup done
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
1377
1378
1379
  #endif
  	return 0;
  
  errout:
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1380
  	spin_unlock_irqrestore(&card->card_lock, flags);
cc7fdf49d   Jiri Slaby   cyclades: merge c...
1381
  	free_page(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
  	return retval;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1383
  }				/* startup */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1385
  static void start_xmit(struct cyclades_port *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
  {
3aeea5b92   Jiri Slaby   cyclades: introdu...
1387
  	struct cyclades_card *card = info->card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1388
  	unsigned long flags;
3aeea5b92   Jiri Slaby   cyclades: introdu...
1389
  	int channel = info->line - card->first_line;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390

2693f485c   Jiri Slaby   tty: cyclades, co...
1391
  	if (!cy_is_Z(card)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1392
  		spin_lock_irqsave(&card->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
1393
1394
  		cyy_writeb(info, CyCAR, channel & 0x03);
  		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1395
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1396
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
  #ifdef CONFIG_CYZ_INTR
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1398
  		int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1399

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1400
  		spin_lock_irqsave(&card->card_lock, flags);
875b206b5   Jiri Slaby   Char: cyclades, m...
1401
  		retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1402
  		if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
1403
1404
1405
  			printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was "
  				"%x
  ", info->line, retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1406
  		}
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1407
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1408
1409
1410
1411
1412
  #else				/* CONFIG_CYZ_INTR */
  		/* Don't have to do anything at this time */
  #endif				/* CONFIG_CYZ_INTR */
  	}
  }				/* start_xmit */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413
1414
1415
1416
1417
  
  /*
   * This routine shuts down a serial port; interrupts are disabled,
   * and DTR is dropped if the hangup on close termio flag is on.
   */
d13549f80   Jiri Slaby   cyclades: add tty...
1418
  static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419
  {
875b206b5   Jiri Slaby   Char: cyclades, m...
1420
  	struct cyclades_card *card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1421
  	unsigned long flags;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1422

77451e53e   Alan Cox   cyclades: use tty...
1423
  	if (!(info->port.flags & ASYNC_INITIALIZED))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1424
  		return;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1425
1426
  
  	card = info->card;
2693f485c   Jiri Slaby   tty: cyclades, co...
1427
  	if (!cy_is_Z(card)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1428
  		spin_lock_irqsave(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1429
1430
  
  		/* Clear delta_msr_wait queue to avoid mem leaks. */
bdc04e317   Alan Cox   serial: move delt...
1431
  		wake_up_interruptible(&info->port.delta_msr_wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432

77451e53e   Alan Cox   cyclades: use tty...
1433
  		if (info->port.xmit_buf) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1434
  			unsigned char *temp;
77451e53e   Alan Cox   cyclades: use tty...
1435
1436
  			temp = info->port.xmit_buf;
  			info->port.xmit_buf = NULL;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1437
1438
  			free_page((unsigned long)temp);
  		}
4d7682005   Jiri Slaby   cyclades: use dtr...
1439
1440
  		if (tty->termios->c_cflag & HUPCL)
  			cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
3aeea5b92   Jiri Slaby   cyclades: introdu...
1441
  		cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1442
1443
  		/* it may be appropriate to clear _XMIT at
  		   some later date (after testing)!!! */
d13549f80   Jiri Slaby   cyclades: add tty...
1444
  		set_bit(TTY_IO_ERROR, &tty->flags);
77451e53e   Alan Cox   cyclades: use tty...
1445
  		info->port.flags &= ~ASYNC_INITIALIZED;
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1446
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1447
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
  #ifdef CY_DEBUG_OPEN
0e7f4194a   Jiri Slaby   Char: cyclades, f...
1449
  		int channel = info->line - card->first_line;
217191910   Jiri Slaby   Char: cyclades, p...
1450
  		printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1451
1452
  			"base_addr %p
  ", card, channel, card->base_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
  #endif
2693f485c   Jiri Slaby   tty: cyclades, co...
1454
  		if (!cyz_is_loaded(card))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1455
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1457
  		spin_lock_irqsave(&card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458

77451e53e   Alan Cox   cyclades: use tty...
1459
  		if (info->port.xmit_buf) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1460
  			unsigned char *temp;
77451e53e   Alan Cox   cyclades: use tty...
1461
1462
  			temp = info->port.xmit_buf;
  			info->port.xmit_buf = NULL;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1463
  			free_page((unsigned long)temp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
  		}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1465

4d7682005   Jiri Slaby   cyclades: use dtr...
1466
1467
  		if (tty->termios->c_cflag & HUPCL)
  			tty_port_lower_dtr_rts(&info->port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468

d13549f80   Jiri Slaby   cyclades: add tty...
1469
  		set_bit(TTY_IO_ERROR, &tty->flags);
77451e53e   Alan Cox   cyclades: use tty...
1470
  		info->port.flags &= ~ASYNC_INITIALIZED;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1471

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1472
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1473
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
1475
  
  #ifdef CY_DEBUG_OPEN
217191910   Jiri Slaby   Char: cyclades, p...
1476
1477
  	printk(KERN_DEBUG "cyc shutdown done
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1479
  }				/* shutdown */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
1481
1482
1483
1484
1485
  
  /*
   * ------------------------------------------------------------
   * cy_open() and friends
   * ------------------------------------------------------------
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486
1487
1488
1489
  /*
   * This routine is called whenever a serial port is opened.  It
   * performs the serial-specific initialization for the tty structure.
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1490
  static int cy_open(struct tty_struct *tty, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1491
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1492
  	struct cyclades_port *info;
65f76a82e   Jiri Slaby   Char: cyclades, f...
1493
1494
  	unsigned int i, line;
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1496
  	line = tty->index;
15ed6cc0b   Alan Cox   cyclades: coding ...
1497
  	if (tty->index < 0 || NR_PORTS <= line)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1498
  		return -ENODEV;
15ed6cc0b   Alan Cox   cyclades: coding ...
1499

dd025c0c7   Jiri Slaby   Char: cyclades, d...
1500
1501
1502
1503
1504
1505
1506
  	for (i = 0; i < NR_CARDS; i++)
  		if (line < cy_card[i].first_line + cy_card[i].nports &&
  				line >= cy_card[i].first_line)
  			break;
  	if (i >= NR_CARDS)
  		return -ENODEV;
  	info = &cy_card[i].ports[line - cy_card[i].first_line];
15ed6cc0b   Alan Cox   cyclades: coding ...
1507
  	if (info->line < 0)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1508
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1510
1511
1512
1513
  	/* If the card's firmware hasn't been loaded,
  	   treat it as absent from the system.  This
  	   will make the user pay attention.
  	 */
2693f485c   Jiri Slaby   tty: cyclades, co...
1514
  	if (cy_is_Z(info->card)) {
875b206b5   Jiri Slaby   Char: cyclades, m...
1515
  		struct cyclades_card *cinfo = info->card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1516
  		struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
2693f485c   Jiri Slaby   tty: cyclades, co...
1517
1518
  		if (!cyz_is_loaded(cinfo)) {
  			if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) &&
101b81590   Jiri Slaby   tty: cyclades, ca...
1519
1520
  					readl(&firm_id->signature) ==
  					ZFIRM_HLT) {
217191910   Jiri Slaby   Char: cyclades, p...
1521
1522
1523
1524
1525
1526
  				printk(KERN_ERR "cyc:Cyclades-Z Error: you "
  					"need an external power supply for "
  					"this number of ports.
  Firmware "
  					"halted.
  ");
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1527
  			} else {
217191910   Jiri Slaby   Char: cyclades, p...
1528
1529
1530
  				printk(KERN_ERR "cyc:Cyclades-Z firmware not "
  					"yet loaded
  ");
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1531
1532
1533
1534
1535
1536
1537
1538
1539
  			}
  			return -ENODEV;
  		}
  #ifdef CONFIG_CYZ_INTR
  		else {
  		/* In case this Z board is operating in interrupt mode, its
  		   interrupts should be enabled as soon as the first open
  		   happens to one of its ports. */
  			if (!cinfo->intr_enabled) {
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
1540
  				u16 intr;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1541

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1542
  				/* Enable interrupts on the PLX chip */
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
1543
1544
1545
1546
  				intr = readw(&cinfo->ctl_addr.p9060->
  						intr_ctrl_stat) | 0x0900;
  				cy_writew(&cinfo->ctl_addr.p9060->
  						intr_ctrl_stat, intr);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1547
1548
1549
1550
  				/* Enable interrupts on the FW */
  				retval = cyz_issue_cmd(cinfo, 0,
  						C_CM_IRQ_ENBL, 0L);
  				if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
1551
1552
1553
  					printk(KERN_ERR "cyc:IRQ enable retval "
  						"was %x
  ", retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1554
  				}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1555
1556
  				cinfo->intr_enabled = 1;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1557
  		}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1558
1559
1560
1561
  #endif				/* CONFIG_CYZ_INTR */
  		/* Make sure this Z port really exists in hardware */
  		if (info->line > (cinfo->first_line + cinfo->nports - 1))
  			return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1562
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
  #ifdef CY_DEBUG_OTHER
217191910   Jiri Slaby   Char: cyclades, p...
1564
1565
  	printk(KERN_DEBUG "cyc:cy_open ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1566
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1567
  	tty->driver_data = info;
15ed6cc0b   Alan Cox   cyclades: coding ...
1568
  	if (serial_paranoia_check(info, tty->name, "cy_open"))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1569
  		return -ENODEV;
15ed6cc0b   Alan Cox   cyclades: coding ...
1570

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
  #ifdef CY_DEBUG_OPEN
217191910   Jiri Slaby   Char: cyclades, p...
1572
1573
  	printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d
  ", info->line,
77451e53e   Alan Cox   cyclades: use tty...
1574
  			info->port.count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575
  #endif
77451e53e   Alan Cox   cyclades: use tty...
1576
  	info->port.count++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
  #ifdef CY_DEBUG_COUNT
217191910   Jiri Slaby   Char: cyclades, p...
1578
1579
  	printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d
  ",
77451e53e   Alan Cox   cyclades: use tty...
1580
  		current->pid, info->port.count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1581
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1582

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1583
1584
1585
  	/*
  	 * If the port is the middle of closing, bail out now
  	 */
77451e53e   Alan Cox   cyclades: use tty...
1586
  	if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
be1bc2889   Arnd Bergmann   tty: introduce wa...
1587
  		wait_event_interruptible_tty(info->port.close_wait,
77451e53e   Alan Cox   cyclades: use tty...
1588
1589
  				!(info->port.flags & ASYNC_CLOSING));
  		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1590
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1592
1593
1594
  	/*
  	 * Start up serial port
  	 */
d13549f80   Jiri Slaby   cyclades: add tty...
1595
  	retval = cy_startup(info, tty);
15ed6cc0b   Alan Cox   cyclades: coding ...
1596
  	if (retval)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1597
  		return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1598

f07375794   Jiri Slaby   cyclades: remove ...
1599
  	retval = tty_port_block_til_ready(&info->port, tty, filp);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1600
  	if (retval) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1601
  #ifdef CY_DEBUG_OPEN
217191910   Jiri Slaby   Char: cyclades, p...
1602
1603
1604
  		printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready "
  			"with %d
  ", retval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1605
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1606
1607
  		return retval;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1609
  	info->throttle = 0;
d13549f80   Jiri Slaby   cyclades: add tty...
1610
  	tty_port_tty_set(&info->port, tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1611

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1612
  #ifdef CY_DEBUG_OPEN
217191910   Jiri Slaby   Char: cyclades, p...
1613
1614
  	printk(KERN_DEBUG "cyc:cy_open done
  ");
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1615
1616
1617
  #endif
  	return 0;
  }				/* cy_open */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1618
1619
1620
1621
  
  /*
   * cy_wait_until_sent() --- wait until the transmitter is empty
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1622
  static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1623
  {
875b206b5   Jiri Slaby   Char: cyclades, m...
1624
  	struct cyclades_card *card;
cab9bdd14   Jiri Slaby   Char: cyclades, r...
1625
  	struct cyclades_port *info = tty->driver_data;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1626
1627
1628
1629
1630
1631
1632
1633
  	unsigned long orig_jiffies;
  	int char_time;
  
  	if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
  		return;
  
  	if (info->xmit_fifo_size == 0)
  		return;		/* Just in case.... */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1634

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
  	orig_jiffies = jiffies;
  	/*
  	 * Set the check interval to be 1/5 of the estimated time to
  	 * send a single character, and make it at least 1.  The check
  	 * interval should also be less than the timeout.
  	 *
  	 * Note: we have to use pretty tight timings here to satisfy
  	 * the NIST-PCTS.
  	 */
  	char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
  	char_time = char_time / 5;
  	if (char_time <= 0)
  		char_time = 1;
  	if (timeout < 0)
  		timeout = 0;
  	if (timeout)
  		char_time = min(char_time, timeout);
  	/*
  	 * If the transmitter hasn't cleared in twice the approximate
  	 * amount of time to send the entire FIFO, it probably won't
  	 * ever clear.  This assumes the UART isn't doing flow
  	 * control, which is currently the case.  Hence, if it ever
  	 * takes longer than info->timeout, this is probably due to a
  	 * UART bug of some kind.  So, we clamp the timeout parameter at
  	 * 2*info->timeout.
  	 */
  	if (!timeout || timeout > 2 * info->timeout)
  		timeout = 2 * info->timeout;
8bab534b5   Jiri Slaby   TTY: mxser+cyclad...
1663

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1664
  	card = info->card;
2693f485c   Jiri Slaby   tty: cyclades, co...
1665
  	if (!cy_is_Z(card)) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
1666
  		while (cyy_readb(info, CySRER) & CyTxRdy) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1667
1668
1669
1670
1671
1672
  			if (msleep_interruptible(jiffies_to_msecs(char_time)))
  				break;
  			if (timeout && time_after(jiffies, orig_jiffies +
  					timeout))
  				break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1674
1675
  	/* Run one more char cycle */
  	msleep_interruptible(jiffies_to_msecs(char_time * 5));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
  }
978e595f8   Alan Cox   tty/serial: lay t...
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  static void cy_flush_buffer(struct tty_struct *tty)
  {
  	struct cyclades_port *info = tty->driver_data;
  	struct cyclades_card *card;
  	int channel, retval;
  	unsigned long flags;
  
  #ifdef CY_DEBUG_IO
  	printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d
  ", info->line);
  #endif
  
  	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
  		return;
  
  	card = info->card;
  	channel = info->line - card->first_line;
  
  	spin_lock_irqsave(&card->card_lock, flags);
  	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
  	spin_unlock_irqrestore(&card->card_lock, flags);
2693f485c   Jiri Slaby   tty: cyclades, co...
1698
  	if (cy_is_Z(card)) {	/* If it is a Z card, flush the on-board
978e595f8   Alan Cox   tty/serial: lay t...
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
  					   buffers as well */
  		spin_lock_irqsave(&card->card_lock, flags);
  		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
  		if (retval != 0) {
  			printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
  				"was %x
  ", info->line, retval);
  		}
  		spin_unlock_irqrestore(&card->card_lock, flags);
  	}
  	tty_wakeup(tty);
  }				/* cy_flush_buffer */
e936ffd5c   Alan Cox   cyclades: use the...
1711
  static void cy_do_close(struct tty_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712
  {
e936ffd5c   Alan Cox   cyclades: use the...
1713
1714
  	struct cyclades_port *info = container_of(port, struct cyclades_port,
  								port);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1715
  	struct cyclades_card *card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1716
  	unsigned long flags;
3aeea5b92   Jiri Slaby   cyclades: introdu...
1717
  	int channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1718

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1719
  	card = info->card;
3aeea5b92   Jiri Slaby   cyclades: introdu...
1720
  	channel = info->line - card->first_line;
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1721
  	spin_lock_irqsave(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1722

2693f485c   Jiri Slaby   tty: cyclades, co...
1723
  	if (!cy_is_Z(card)) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1724
  		/* Stop accepting input */
3aeea5b92   Jiri Slaby   cyclades: introdu...
1725
1726
  		cyy_writeb(info, CyCAR, channel & 0x03);
  		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData);
77451e53e   Alan Cox   cyclades: use tty...
1727
  		if (info->port.flags & ASYNC_INITIALIZED) {
15ed6cc0b   Alan Cox   cyclades: coding ...
1728
1729
  			/* Waiting for on-board buffers to be empty before
  			   closing the port */
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1730
  			spin_unlock_irqrestore(&card->card_lock, flags);
e936ffd5c   Alan Cox   cyclades: use the...
1731
  			cy_wait_until_sent(port->tty, info->timeout);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1732
  			spin_lock_irqsave(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1733
1734
1735
  		}
  	} else {
  #ifdef Z_WAKE
15ed6cc0b   Alan Cox   cyclades: coding ...
1736
1737
  		/* Waiting for on-board buffers to be empty before closing
  		   the port */
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1738
  		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1739
  		int retval;
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1740
  		if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1741
  			retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1742
  			if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
1743
1744
1745
  				printk(KERN_DEBUG "cyc:cy_close retval on "
  					"ttyC%d was %x
  ", info->line, retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1746
  			}
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1747
  			spin_unlock_irqrestore(&card->card_lock, flags);
2c7fea992   Jiri Slaby   Char: cyclades, r...
1748
  			wait_for_completion_interruptible(&info->shutdown_wait);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1749
  			spin_lock_irqsave(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1750
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1752
  	}
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1753
  	spin_unlock_irqrestore(&card->card_lock, flags);
e936ffd5c   Alan Cox   cyclades: use the...
1754
1755
  	cy_shutdown(info, port->tty);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1756

e936ffd5c   Alan Cox   cyclades: use the...
1757
1758
1759
1760
1761
1762
1763
1764
1765
  /*
   * This routine is called when a particular tty device is closed.
   */
  static void cy_close(struct tty_struct *tty, struct file *filp)
  {
  	struct cyclades_port *info = tty->driver_data;
  	if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
  		return;
  	tty_port_close(&info->port, tty, filp);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1766
  }				/* cy_close */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
  
  /* This routine gets called when tty_write has put something into
   * the write_queue.  The characters may come from user space or
   * kernel space.
   *
   * This routine will return the number of characters actually
   * accepted for writing.
   *
   * If the port is not already transmitting stuff, start it off by
   * enabling interrupts.  The interrupt service routine will then
   * ensure that the characters are sent.
   * If the port is already active, there is no need to kick it.
   *
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1781
  static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1782
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
1783
  	struct cyclades_port *info = tty->driver_data;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1784
1785
  	unsigned long flags;
  	int c, ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1786
1787
  
  #ifdef CY_DEBUG_IO
217191910   Jiri Slaby   Char: cyclades, p...
1788
1789
  	printk(KERN_DEBUG "cyc:cy_write ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1790
  #endif
15ed6cc0b   Alan Cox   cyclades: coding ...
1791
  	if (serial_paranoia_check(info, tty->name, "cy_write"))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1792
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1793

77451e53e   Alan Cox   cyclades: use tty...
1794
  	if (!info->port.xmit_buf)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1795
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1797
  	spin_lock_irqsave(&info->card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1798
  	while (1) {
1a4e2351e   Harvey Harrison   cyclades.c: fix s...
1799
1800
  		c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1));
  		c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head));
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1801
1802
1803
  
  		if (c <= 0)
  			break;
77451e53e   Alan Cox   cyclades: use tty...
1804
  		memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1805
1806
1807
1808
1809
1810
1811
  		info->xmit_head = (info->xmit_head + c) &
  			(SERIAL_XMIT_SIZE - 1);
  		info->xmit_cnt += c;
  		buf += c;
  		count -= c;
  		ret += c;
  	}
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1812
  	spin_unlock_irqrestore(&info->card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1813
1814
1815
  
  	info->idle_stats.xmit_bytes += ret;
  	info->idle_stats.xmit_idle = jiffies;
15ed6cc0b   Alan Cox   cyclades: coding ...
1816
  	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1817
  		start_xmit(info);
15ed6cc0b   Alan Cox   cyclades: coding ...
1818

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1819
1820
  	return ret;
  }				/* cy_write */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1821
1822
1823
1824
1825
1826
1827
1828
  
  /*
   * This routine is called by the kernel to write a single
   * character to the tty device.  If the kernel uses this routine,
   * it must call the flush_chars() routine (if defined) when it is
   * done stuffing characters into the driver.  If there is no room
   * in the queue, the character is ignored.
   */
76b25a550   Alan Cox   char: switch gs, ...
1829
  static int cy_put_char(struct tty_struct *tty, unsigned char ch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
1831
  	struct cyclades_port *info = tty->driver_data;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1832
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833
1834
  
  #ifdef CY_DEBUG_IO
217191910   Jiri Slaby   Char: cyclades, p...
1835
1836
  	printk(KERN_DEBUG "cyc:cy_put_char ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1837
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1838
  	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
76b25a550   Alan Cox   char: switch gs, ...
1839
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1840

77451e53e   Alan Cox   cyclades: use tty...
1841
  	if (!info->port.xmit_buf)
76b25a550   Alan Cox   char: switch gs, ...
1842
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1844
  	spin_lock_irqsave(&info->card->card_lock, flags);
90cc30185   Jiri Slaby   [PATCH] Char: cyc...
1845
  	if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1846
  		spin_unlock_irqrestore(&info->card->card_lock, flags);
76b25a550   Alan Cox   char: switch gs, ...
1847
  		return 0;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1848
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1849

77451e53e   Alan Cox   cyclades: use tty...
1850
  	info->port.xmit_buf[info->xmit_head++] = ch;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1851
1852
  	info->xmit_head &= SERIAL_XMIT_SIZE - 1;
  	info->xmit_cnt++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1853
1854
  	info->idle_stats.xmit_bytes++;
  	info->idle_stats.xmit_idle = jiffies;
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
1855
  	spin_unlock_irqrestore(&info->card->card_lock, flags);
76b25a550   Alan Cox   char: switch gs, ...
1856
  	return 1;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1857
  }				/* cy_put_char */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1858
1859
1860
  
  /*
   * This routine is called by the kernel after it has written a
15ed6cc0b   Alan Cox   cyclades: coding ...
1861
   * series of characters to the tty device using put_char().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1862
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1863
  static void cy_flush_chars(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1864
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
1865
  	struct cyclades_port *info = tty->driver_data;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1866

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1867
  #ifdef CY_DEBUG_IO
217191910   Jiri Slaby   Char: cyclades, p...
1868
1869
  	printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1871
1872
  	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1873

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1874
  	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
77451e53e   Alan Cox   cyclades: use tty...
1875
  			!info->port.xmit_buf)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1876
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1877

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1878
1879
  	start_xmit(info);
  }				/* cy_flush_chars */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880
1881
1882
1883
1884
1885
1886
  
  /*
   * This routine returns the numbers of characters the tty driver
   * will accept for queuing to be written.  This number is subject
   * to change as output buffers get emptied, or if the output flow
   * control is activated.
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1887
  static int cy_write_room(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1888
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
1889
  	struct cyclades_port *info = tty->driver_data;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1890
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891
  #ifdef CY_DEBUG_IO
217191910   Jiri Slaby   Char: cyclades, p...
1892
1893
  	printk(KERN_DEBUG "cyc:cy_write_room ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1894
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1895
1896
1897
1898
1899
1900
1901
  	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
  		return 0;
  	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
  	if (ret < 0)
  		ret = 0;
  	return ret;
  }				/* cy_write_room */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1903
  static int cy_chars_in_buffer(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
1905
  	struct cyclades_port *info = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1907
1908
  	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1909
  #ifdef Z_EXT_CHARS_IN_BUFFER
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1910
  	if (!cy_is_Z(info->card)) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1911
  #endif				/* Z_EXT_CHARS_IN_BUFFER */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
  #ifdef CY_DEBUG_IO
217191910   Jiri Slaby   Char: cyclades, p...
1913
1914
1915
  		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d
  ",
  			info->line, info->xmit_cnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1916
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1917
  		return info->xmit_cnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1918
  #ifdef Z_EXT_CHARS_IN_BUFFER
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1919
  	} else {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
1920
  		struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1921
  		int char_count;
ad39c3004   Jiri Slaby   Char: cyclades, r...
1922
  		__u32 tx_put, tx_get, tx_bufsize;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1923

db05c3b1d   Jiri Slaby   Char: cyclades, c...
1924
1925
1926
  		tx_get = readl(&buf_ctrl->tx_get);
  		tx_put = readl(&buf_ctrl->tx_put);
  		tx_bufsize = readl(&buf_ctrl->tx_bufsize);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1927
1928
1929
1930
  		if (tx_put >= tx_get)
  			char_count = tx_put - tx_get;
  		else
  			char_count = tx_put - tx_get + tx_bufsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1931
  #ifdef CY_DEBUG_IO
217191910   Jiri Slaby   Char: cyclades, p...
1932
1933
1934
  		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d
  ",
  			info->line, info->xmit_cnt + char_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1935
  #endif
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
1936
  		return info->xmit_cnt + char_count;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1937
1938
1939
  	}
  #endif				/* Z_EXT_CHARS_IN_BUFFER */
  }				/* cy_chars_in_buffer */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1940
1941
1942
1943
1944
1945
  
  /*
   * ------------------------------------------------------------
   * cy_ioctl() and friends
   * ------------------------------------------------------------
   */
1a86b5e34   Klaus Kudielka   cyclades: remove ...
1946
  static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1947
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1948
  	int co, co_val, bpr;
1a86b5e34   Klaus Kudielka   cyclades: remove ...
1949
  	__u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1950
  			25000000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1951

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1952
1953
1954
1955
  	if (baud == 0) {
  		info->tbpr = info->tco = info->rbpr = info->rco = 0;
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1957
1958
1959
1960
1961
  	/* determine which prescaler to use */
  	for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
  		if (cy_clock / co_val / baud > 63)
  			break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1962

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1963
1964
1965
  	bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
  	if (bpr > 255)
  		bpr = 255;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1966

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1967
1968
  	info->tbpr = info->rbpr = bpr;
  	info->tco = info->rco = co;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1969
1970
1971
1972
1973
1974
  }
  
  /*
   * This routine finds or computes the various line characteristics.
   * It used to be called config_setup
   */
d13549f80   Jiri Slaby   cyclades: add tty...
1975
  static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1976
  {
875b206b5   Jiri Slaby   Char: cyclades, m...
1977
  	struct cyclades_card *card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1978
  	unsigned long flags;
3aeea5b92   Jiri Slaby   cyclades: introdu...
1979
  	int channel;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1980
  	unsigned cflag, iflag;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1981
1982
  	int baud, baud_rate = 0;
  	int i;
d13549f80   Jiri Slaby   cyclades: add tty...
1983
  	if (!tty->termios) /* XXX can this happen at all? */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1984
  		return;
15ed6cc0b   Alan Cox   cyclades: coding ...
1985
1986
  
  	if (info->line == -1)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1987
  		return;
15ed6cc0b   Alan Cox   cyclades: coding ...
1988

d13549f80   Jiri Slaby   cyclades: add tty...
1989
1990
  	cflag = tty->termios->c_cflag;
  	iflag = tty->termios->c_iflag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1991

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
1992
1993
1994
  	/*
  	 * Set up the tty->alt_speed kludge
  	 */
d13549f80   Jiri Slaby   cyclades: add tty...
1995
1996
1997
1998
1999
2000
2001
2002
  	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
  		tty->alt_speed = 57600;
  	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
  		tty->alt_speed = 115200;
  	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
  		tty->alt_speed = 230400;
  	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
  		tty->alt_speed = 460800;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2003
2004
  
  	card = info->card;
875b206b5   Jiri Slaby   Char: cyclades, m...
2005
  	channel = info->line - card->first_line;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2006

2693f485c   Jiri Slaby   tty: cyclades, co...
2007
  	if (!cy_is_Z(card)) {
46fb78252   Jiri Slaby   cyclades: remove ...
2008
  		u32 cflags;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2009
  		/* baud rate */
d13549f80   Jiri Slaby   cyclades: add tty...
2010
  		baud = tty_get_baud_rate(tty);
77451e53e   Alan Cox   cyclades: use tty...
2011
  		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
  				ASYNC_SPD_CUST) {
  			if (info->custom_divisor)
  				baud_rate = info->baud / info->custom_divisor;
  			else
  				baud_rate = info->baud;
  		} else if (baud > CD1400_MAX_SPEED) {
  			baud = CD1400_MAX_SPEED;
  		}
  		/* find the baud index */
  		for (i = 0; i < 20; i++) {
15ed6cc0b   Alan Cox   cyclades: coding ...
2022
  			if (baud == baud_table[i])
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2023
  				break;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2024
  		}
15ed6cc0b   Alan Cox   cyclades: coding ...
2025
  		if (i == 20)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2026
  			i = 19;	/* CD1400_MAX_SPEED */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2027

77451e53e   Alan Cox   cyclades: use tty...
2028
  		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
  				ASYNC_SPD_CUST) {
  			cyy_baud_calc(info, baud_rate);
  		} else {
  			if (info->chip_rev >= CD1400_REV_J) {
  				/* It is a CD1400 rev. J or later */
  				info->tbpr = baud_bpr_60[i];	/* Tx BPR */
  				info->tco = baud_co_60[i];	/* Tx CO */
  				info->rbpr = baud_bpr_60[i];	/* Rx BPR */
  				info->rco = baud_co_60[i];	/* Rx CO */
  			} else {
  				info->tbpr = baud_bpr_25[i];	/* Tx BPR */
  				info->tco = baud_co_25[i];	/* Tx CO */
  				info->rbpr = baud_bpr_25[i];	/* Rx BPR */
  				info->rco = baud_co_25[i];	/* Rx CO */
  			}
  		}
  		if (baud_table[i] == 134) {
  			/* get it right for 134.5 baud */
  			info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
  					2;
77451e53e   Alan Cox   cyclades: use tty...
2049
  		} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
  				ASYNC_SPD_CUST) {
  			info->timeout = (info->xmit_fifo_size * HZ * 15 /
  					baud_rate) + 2;
  		} else if (baud_table[i]) {
  			info->timeout = (info->xmit_fifo_size * HZ * 15 /
  					baud_table[i]) + 2;
  			/* this needs to be propagated into the card info */
  		} else {
  			info->timeout = 0;
  		}
  		/* By tradition (is it a standard?) a baud rate of zero
  		   implies the line should be/has been closed.  A bit
  		   later in this routine such a test is performed. */
  
  		/* byte size and parity */
  		info->cor5 = 0;
  		info->cor4 = 0;
  		/* receive threshold */
  		info->cor3 = (info->default_threshold ?
  				info->default_threshold : baud_cor3[i]);
  		info->cor2 = CyETC;
  		switch (cflag & CSIZE) {
  		case CS5:
  			info->cor1 = Cy_5_BITS;
  			break;
  		case CS6:
  			info->cor1 = Cy_6_BITS;
  			break;
  		case CS7:
  			info->cor1 = Cy_7_BITS;
  			break;
  		case CS8:
  			info->cor1 = Cy_8_BITS;
  			break;
  		}
15ed6cc0b   Alan Cox   cyclades: coding ...
2085
  		if (cflag & CSTOPB)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2086
  			info->cor1 |= Cy_2_STOP;
15ed6cc0b   Alan Cox   cyclades: coding ...
2087

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2088
  		if (cflag & PARENB) {
15ed6cc0b   Alan Cox   cyclades: coding ...
2089
  			if (cflag & PARODD)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2090
  				info->cor1 |= CyPARITY_O;
15ed6cc0b   Alan Cox   cyclades: coding ...
2091
  			else
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2092
  				info->cor1 |= CyPARITY_E;
15ed6cc0b   Alan Cox   cyclades: coding ...
2093
  		} else
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2094
  			info->cor1 |= CyPARITY_NONE;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2095
2096
2097
  
  		/* CTS flow control flag */
  		if (cflag & CRTSCTS) {
77451e53e   Alan Cox   cyclades: use tty...
2098
  			info->port.flags |= ASYNC_CTS_FLOW;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2099
2100
  			info->cor2 |= CyCtsAE;
  		} else {
77451e53e   Alan Cox   cyclades: use tty...
2101
  			info->port.flags &= ~ASYNC_CTS_FLOW;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2102
2103
2104
  			info->cor2 &= ~CyCtsAE;
  		}
  		if (cflag & CLOCAL)
77451e53e   Alan Cox   cyclades: use tty...
2105
  			info->port.flags &= ~ASYNC_CHECK_CD;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2106
  		else
77451e53e   Alan Cox   cyclades: use tty...
2107
  			info->port.flags |= ASYNC_CHECK_CD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
  
  	 /***********************************************
  	    The hardware option, CyRtsAO, presents RTS when
  	    the chip has characters to send.  Since most modems
  	    use RTS as reverse (inbound) flow control, this
  	    option is not used.  If inbound flow control is
  	    necessary, DTR can be programmed to provide the
  	    appropriate signals for use with a non-standard
  	    cable.  Contact Marcio Saito for details.
  	 ***********************************************/
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2118
  		channel &= 0x03;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2119

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2120
  		spin_lock_irqsave(&card->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
2121
  		cyy_writeb(info, CyCAR, channel);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2122
2123
  
  		/* tx and rx baud rate */
3aeea5b92   Jiri Slaby   cyclades: introdu...
2124
2125
2126
2127
  		cyy_writeb(info, CyTCOR, info->tco);
  		cyy_writeb(info, CyTBPR, info->tbpr);
  		cyy_writeb(info, CyRCOR, info->rco);
  		cyy_writeb(info, CyRBPR, info->rbpr);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2128
2129
  
  		/* set line characteristics  according configuration */
3aeea5b92   Jiri Slaby   cyclades: introdu...
2130
2131
2132
2133
2134
2135
2136
  		cyy_writeb(info, CySCHR1, START_CHAR(tty));
  		cyy_writeb(info, CySCHR2, STOP_CHAR(tty));
  		cyy_writeb(info, CyCOR1, info->cor1);
  		cyy_writeb(info, CyCOR2, info->cor2);
  		cyy_writeb(info, CyCOR3, info->cor3);
  		cyy_writeb(info, CyCOR4, info->cor4);
  		cyy_writeb(info, CyCOR5, info->cor5);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2137

3aeea5b92   Jiri Slaby   cyclades: introdu...
2138
2139
  		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
  				CyCOR3ch);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2140

15ed6cc0b   Alan Cox   cyclades: coding ...
2141
  		/* !!! Is this needed? */
3aeea5b92   Jiri Slaby   cyclades: introdu...
2142
2143
  		cyy_writeb(info, CyCAR, channel);
  		cyy_writeb(info, CyRTPR,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2144
2145
  			(info->default_timeout ? info->default_timeout : 0x02));
  		/* 10ms rx timeout */
46fb78252   Jiri Slaby   cyclades: remove ...
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
  		cflags = CyCTS;
  		if (!C_CLOCAL(tty))
  			cflags |= CyDSR | CyRI | CyDCD;
  		/* without modem intr */
  		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh);
  		/* act on 1->0 modem transitions */
  		if ((cflag & CRTSCTS) && info->rflow)
  			cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]);
  		else
  			cyy_writeb(info, CyMCOR1, cflags);
  		/* act on 0->1 modem transitions */
  		cyy_writeb(info, CyMCOR2, cflags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2158

4d7682005   Jiri Slaby   cyclades: use dtr...
2159
2160
2161
2162
  		if (i == 0)	/* baud rate is zero, turn off line */
  			cyy_change_rts_dtr(info, 0, TIOCM_DTR);
  		else
  			cyy_change_rts_dtr(info, TIOCM_DTR, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2163

d13549f80   Jiri Slaby   cyclades: add tty...
2164
  		clear_bit(TTY_IO_ERROR, &tty->flags);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2165
  		spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2166

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2167
  	} else {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
2168
  		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
1a86b5e34   Klaus Kudielka   cyclades: remove ...
2169
  		__u32 sw_flow;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2170
  		int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2171

2693f485c   Jiri Slaby   tty: cyclades, co...
2172
  		if (!cyz_is_loaded(card))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2173
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2174

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2175
  		/* baud rate */
d13549f80   Jiri Slaby   cyclades: add tty...
2176
  		baud = tty_get_baud_rate(tty);
77451e53e   Alan Cox   cyclades: use tty...
2177
  		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
  				ASYNC_SPD_CUST) {
  			if (info->custom_divisor)
  				baud_rate = info->baud / info->custom_divisor;
  			else
  				baud_rate = info->baud;
  		} else if (baud > CYZ_MAX_SPEED) {
  			baud = CYZ_MAX_SPEED;
  		}
  		cy_writel(&ch_ctrl->comm_baud, baud);
  
  		if (baud == 134) {
  			/* get it right for 134.5 baud */
  			info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
  					2;
77451e53e   Alan Cox   cyclades: use tty...
2192
  		} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
  				ASYNC_SPD_CUST) {
  			info->timeout = (info->xmit_fifo_size * HZ * 15 /
  					baud_rate) + 2;
  		} else if (baud) {
  			info->timeout = (info->xmit_fifo_size * HZ * 15 /
  					baud) + 2;
  			/* this needs to be propagated into the card info */
  		} else {
  			info->timeout = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2203

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
  		/* byte size and parity */
  		switch (cflag & CSIZE) {
  		case CS5:
  			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5);
  			break;
  		case CS6:
  			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6);
  			break;
  		case CS7:
  			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7);
  			break;
  		case CS8:
  			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8);
  			break;
  		}
  		if (cflag & CSTOPB) {
  			cy_writel(&ch_ctrl->comm_data_l,
db05c3b1d   Jiri Slaby   Char: cyclades, c...
2221
  				  readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2222
2223
  		} else {
  			cy_writel(&ch_ctrl->comm_data_l,
db05c3b1d   Jiri Slaby   Char: cyclades, c...
2224
  				  readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2225
2226
  		}
  		if (cflag & PARENB) {
15ed6cc0b   Alan Cox   cyclades: coding ...
2227
  			if (cflag & PARODD)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2228
  				cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
15ed6cc0b   Alan Cox   cyclades: coding ...
2229
  			else
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2230
  				cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
15ed6cc0b   Alan Cox   cyclades: coding ...
2231
  		} else
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2232
  			cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2233

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2234
2235
2236
  		/* CTS flow control flag */
  		if (cflag & CRTSCTS) {
  			cy_writel(&ch_ctrl->hw_flow,
db05c3b1d   Jiri Slaby   Char: cyclades, c...
2237
  				readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2238
  		} else {
db05c3b1d   Jiri Slaby   Char: cyclades, c...
2239
2240
  			cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) &
  					~(C_RS_CTS | C_RS_RTS));
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2241
2242
2243
  		}
  		/* As the HW flow control is done in firmware, the driver
  		   doesn't need to care about it */
77451e53e   Alan Cox   cyclades: use tty...
2244
  		info->port.flags &= ~ASYNC_CTS_FLOW;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2245
2246
2247
2248
2249
2250
2251
2252
2253
  
  		/* XON/XOFF/XANY flow control flags */
  		sw_flow = 0;
  		if (iflag & IXON) {
  			sw_flow |= C_FL_OXX;
  			if (iflag & IXANY)
  				sw_flow |= C_FL_OIXANY;
  		}
  		cy_writel(&ch_ctrl->sw_flow, sw_flow);
875b206b5   Jiri Slaby   Char: cyclades, m...
2254
  		retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2255
  		if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
2256
2257
2258
  			printk(KERN_ERR "cyc:set_line_char retval on ttyC%d "
  				"was %x
  ", info->line, retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2259
2260
2261
  		}
  
  		/* CD sensitivity */
15ed6cc0b   Alan Cox   cyclades: coding ...
2262
  		if (cflag & CLOCAL)
77451e53e   Alan Cox   cyclades: use tty...
2263
  			info->port.flags &= ~ASYNC_CHECK_CD;
15ed6cc0b   Alan Cox   cyclades: coding ...
2264
  		else
77451e53e   Alan Cox   cyclades: use tty...
2265
  			info->port.flags |= ASYNC_CHECK_CD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2266

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2267
2268
  		if (baud == 0) {	/* baud rate is zero, turn off line */
  			cy_writel(&ch_ctrl->rs_control,
db05c3b1d   Jiri Slaby   Char: cyclades, c...
2269
  				  readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2270
  #ifdef CY_DEBUG_DTR
217191910   Jiri Slaby   Char: cyclades, p...
2271
2272
  			printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2273
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2274
2275
  		} else {
  			cy_writel(&ch_ctrl->rs_control,
db05c3b1d   Jiri Slaby   Char: cyclades, c...
2276
  				  readl(&ch_ctrl->rs_control) | C_RS_DTR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2277
  #ifdef CY_DEBUG_DTR
217191910   Jiri Slaby   Char: cyclades, p...
2278
2279
  			printk(KERN_DEBUG "cyc:set_line_char raising Z DTR
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2280
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2281
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2282

15ed6cc0b   Alan Cox   cyclades: coding ...
2283
  		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2284
  		if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
2285
2286
2287
  			printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
  				"was %x
  ", info->line, retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2288
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2289

d13549f80   Jiri Slaby   cyclades: add tty...
2290
  		clear_bit(TTY_IO_ERROR, &tty->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2291
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2292
  }				/* set_line_char */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2293

6c28181cf   Jiri Slaby   cyclades: ioctls ...
2294
  static int cy_get_serial_info(struct cyclades_port *info,
15ed6cc0b   Alan Cox   cyclades: coding ...
2295
  		struct serial_struct __user *retinfo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2296
  {
875b206b5   Jiri Slaby   Char: cyclades, m...
2297
  	struct cyclades_card *cinfo = info->card;
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
  	struct serial_struct tmp = {
  		.type = info->type,
  		.line = info->line,
  		.port = (info->card - cy_card) * 0x100 + info->line -
  			cinfo->first_line,
  		.irq = cinfo->irq,
  		.flags = info->port.flags,
  		.close_delay = info->port.close_delay,
  		.closing_wait = info->port.closing_wait,
  		.baud_base = info->baud,
  		.custom_divisor = info->custom_divisor,
  		.hub6 = 0,		/*!!! */
  	};
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2311
  	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2312
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2313
2314
  
  static int
d13549f80   Jiri Slaby   cyclades: add tty...
2315
  cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
15ed6cc0b   Alan Cox   cyclades: coding ...
2316
  		struct serial_struct __user *new_info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2317
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2318
  	struct serial_struct new_serial;
25c3cdf80   Alan Cox   cyclades: Kill of...
2319
  	int ret;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2320
2321
2322
  
  	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
  		return -EFAULT;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2323

25c3cdf80   Alan Cox   cyclades: Kill of...
2324
  	mutex_lock(&info->port.mutex);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2325
  	if (!capable(CAP_SYS_ADMIN)) {
44b7d1b37   Alan Cox   tty: add more tty...
2326
  		if (new_serial.close_delay != info->port.close_delay ||
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2327
2328
2329
  				new_serial.baud_base != info->baud ||
  				(new_serial.flags & ASYNC_FLAGS &
  					~ASYNC_USR_MASK) !=
77451e53e   Alan Cox   cyclades: use tty...
2330
  				(info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
25c3cdf80   Alan Cox   cyclades: Kill of...
2331
2332
  		{
  			mutex_unlock(&info->port.mutex);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2333
  			return -EPERM;
25c3cdf80   Alan Cox   cyclades: Kill of...
2334
  		}
77451e53e   Alan Cox   cyclades: use tty...
2335
  		info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
  				(new_serial.flags & ASYNC_USR_MASK);
  		info->baud = new_serial.baud_base;
  		info->custom_divisor = new_serial.custom_divisor;
  		goto check_and_exit;
  	}
  
  	/*
  	 * OK, past this point, all the error checking has been done.
  	 * At this point, we start making changes.....
  	 */
  
  	info->baud = new_serial.baud_base;
  	info->custom_divisor = new_serial.custom_divisor;
77451e53e   Alan Cox   cyclades: use tty...
2349
  	info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2350
  			(new_serial.flags & ASYNC_FLAGS);
44b7d1b37   Alan Cox   tty: add more tty...
2351
2352
  	info->port.close_delay = new_serial.close_delay * HZ / 100;
  	info->port.closing_wait = new_serial.closing_wait * HZ / 100;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2353
2354
  
  check_and_exit:
77451e53e   Alan Cox   cyclades: use tty...
2355
  	if (info->port.flags & ASYNC_INITIALIZED) {
d13549f80   Jiri Slaby   cyclades: add tty...
2356
  		cy_set_line_char(info, tty);
25c3cdf80   Alan Cox   cyclades: Kill of...
2357
  		ret = 0;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2358
  	} else {
25c3cdf80   Alan Cox   cyclades: Kill of...
2359
  		ret = cy_startup(info, tty);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2360
  	}
25c3cdf80   Alan Cox   cyclades: Kill of...
2361
2362
  	mutex_unlock(&info->port.mutex);
  	return ret;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2363
  }				/* set_serial_info */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
  
  /*
   * get_lsr_info - get line status register info
   *
   * Purpose: Let user call ioctl() to get info when the UART physically
   *	    is emptied.  On bus types like RS485, the transmitter must
   *	    release the bus after transmitting. This must be done when
   *	    the transmit shift register is empty, not be done when the
   *	    transmit holding register is empty.  This functionality
   *	    allows an RS485 driver to be written in user space.
   */
15ed6cc0b   Alan Cox   cyclades: coding ...
2375
  static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2376
  {
3aeea5b92   Jiri Slaby   cyclades: introdu...
2377
  	struct cyclades_card *card = info->card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2378
2379
  	unsigned int result;
  	unsigned long flags;
3aeea5b92   Jiri Slaby   cyclades: introdu...
2380
  	u8 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2381

2693f485c   Jiri Slaby   tty: cyclades, co...
2382
  	if (!cy_is_Z(card)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2383
  		spin_lock_irqsave(&card->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
2384
  		status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2385
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2386
2387
2388
2389
2390
2391
  		result = (status ? 0 : TIOCSER_TEMT);
  	} else {
  		/* Not supported yet */
  		return -EINVAL;
  	}
  	return put_user(result, (unsigned long __user *)value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2392
  }
60b33c133   Alan Cox   tiocmget: kill of...
2393
  static int cy_tiocmget(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2394
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2395
  	struct cyclades_port *info = tty->driver_data;
875b206b5   Jiri Slaby   Char: cyclades, m...
2396
  	struct cyclades_card *card;
3aeea5b92   Jiri Slaby   cyclades: introdu...
2397
  	int result;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2398

bf9d89295   Harvey Harrison   drivers/char: rep...
2399
  	if (serial_paranoia_check(info, tty->name, __func__))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2400
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2401

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2402
  	card = info->card;
0d3487294   Jiri Slaby   cyclades: tiocm c...
2403

2693f485c   Jiri Slaby   tty: cyclades, co...
2404
  	if (!cy_is_Z(card)) {
0d3487294   Jiri Slaby   cyclades: tiocm c...
2405
  		unsigned long flags;
3aeea5b92   Jiri Slaby   cyclades: introdu...
2406
2407
  		int channel = info->line - card->first_line;
  		u8 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2408

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2409
  		spin_lock_irqsave(&card->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
2410
2411
2412
  		cyy_writeb(info, CyCAR, channel & 0x03);
  		status = cyy_readb(info, CyMSVR1);
  		status |= cyy_readb(info, CyMSVR2);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2413
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
  
  		if (info->rtsdtr_inv) {
  			result = ((status & CyRTS) ? TIOCM_DTR : 0) |
  				((status & CyDTR) ? TIOCM_RTS : 0);
  		} else {
  			result = ((status & CyRTS) ? TIOCM_RTS : 0) |
  				((status & CyDTR) ? TIOCM_DTR : 0);
  		}
  		result |= ((status & CyDCD) ? TIOCM_CAR : 0) |
  			((status & CyRI) ? TIOCM_RNG : 0) |
  			((status & CyDSR) ? TIOCM_DSR : 0) |
  			((status & CyCTS) ? TIOCM_CTS : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2426
  	} else {
0d3487294   Jiri Slaby   cyclades: tiocm c...
2427
2428
2429
2430
2431
  		u32 lstatus;
  
  		if (!cyz_is_loaded(card)) {
  			result = -ENODEV;
  			goto end;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2432
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2433

0d3487294   Jiri Slaby   cyclades: tiocm c...
2434
2435
2436
2437
2438
2439
2440
  		lstatus = readl(&info->u.cyz.ch_ctrl->rs_status);
  		result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
  			((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
  			((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
  			((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
  			((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
  			((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2441
  	}
0d3487294   Jiri Slaby   cyclades: tiocm c...
2442
  end:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2443
2444
  	return result;
  }				/* cy_tiomget */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2445
2446
  
  static int
20b9d1771   Alan Cox   tiocmset: kill th...
2447
  cy_tiocmset(struct tty_struct *tty,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2448
  		unsigned int set, unsigned int clear)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2449
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2450
  	struct cyclades_port *info = tty->driver_data;
875b206b5   Jiri Slaby   Char: cyclades, m...
2451
  	struct cyclades_card *card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2452
  	unsigned long flags;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2453

bf9d89295   Harvey Harrison   drivers/char: rep...
2454
  	if (serial_paranoia_check(info, tty->name, __func__))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2455
2456
2457
  		return -ENODEV;
  
  	card = info->card;
2693f485c   Jiri Slaby   tty: cyclades, co...
2458
  	if (!cy_is_Z(card)) {
4d7682005   Jiri Slaby   cyclades: use dtr...
2459
2460
2461
  		spin_lock_irqsave(&card->card_lock, flags);
  		cyy_change_rts_dtr(info, set, clear);
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2462
  	} else {
0d3487294   Jiri Slaby   cyclades: tiocm c...
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
  		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
  		int retval, channel = info->line - card->first_line;
  		u32 rs;
  
  		if (!cyz_is_loaded(card))
  			return -ENODEV;
  
  		spin_lock_irqsave(&card->card_lock, flags);
  		rs = readl(&ch_ctrl->rs_control);
  		if (set & TIOCM_RTS)
  			rs |= C_RS_RTS;
  		if (clear & TIOCM_RTS)
  			rs &= ~C_RS_RTS;
  		if (set & TIOCM_DTR) {
  			rs |= C_RS_DTR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2478
  #ifdef CY_DEBUG_DTR
0d3487294   Jiri Slaby   cyclades: tiocm c...
2479
2480
  			printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2481
  #endif
0d3487294   Jiri Slaby   cyclades: tiocm c...
2482
2483
2484
  		}
  		if (clear & TIOCM_DTR) {
  			rs &= ~C_RS_DTR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2485
  #ifdef CY_DEBUG_DTR
0d3487294   Jiri Slaby   cyclades: tiocm c...
2486
2487
2488
  			printk(KERN_DEBUG "cyc:set_modem_info clearing "
  				"Z DTR
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2489
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2490
  		}
0d3487294   Jiri Slaby   cyclades: tiocm c...
2491
  		cy_writel(&ch_ctrl->rs_control, rs);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2492
  		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
0d3487294   Jiri Slaby   cyclades: tiocm c...
2493
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2494
  		if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
2495
2496
2497
  			printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
  				"was %x
  ", info->line, retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2498
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2499
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2500
  	return 0;
0d3487294   Jiri Slaby   cyclades: tiocm c...
2501
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2502
2503
2504
2505
  
  /*
   * cy_break() --- routine which turns the break handling on or off
   */
9e98966c7   Alan Cox   tty: rework break...
2506
  static int cy_break(struct tty_struct *tty, int break_state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2507
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2508
  	struct cyclades_port *info = tty->driver_data;
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2509
  	struct cyclades_card *card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2510
  	unsigned long flags;
9e98966c7   Alan Cox   tty: rework break...
2511
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2512

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2513
  	if (serial_paranoia_check(info, tty->name, "cy_break"))
9e98966c7   Alan Cox   tty: rework break...
2514
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2515

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2516
2517
2518
  	card = info->card;
  
  	spin_lock_irqsave(&card->card_lock, flags);
2693f485c   Jiri Slaby   tty: cyclades, co...
2519
  	if (!cy_is_Z(card)) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2520
2521
2522
2523
2524
2525
2526
  		/* Let the transmit ISR take care of this (since it
  		   requires stuffing characters into the output stream).
  		 */
  		if (break_state == -1) {
  			if (!info->breakon) {
  				info->breakon = 1;
  				if (!info->xmit_cnt) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2527
  					spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2528
  					start_xmit(info);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2529
  					spin_lock_irqsave(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2530
2531
2532
2533
2534
2535
  				}
  			}
  		} else {
  			if (!info->breakoff) {
  				info->breakoff = 1;
  				if (!info->xmit_cnt) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2536
  					spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2537
  					start_xmit(info);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2538
  					spin_lock_irqsave(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2539
2540
  				}
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2541
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2542
  	} else {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2543
  		if (break_state == -1) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2544
2545
  			retval = cyz_issue_cmd(card,
  				info->line - card->first_line,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2546
2547
  				C_CM_SET_BREAK, 0L);
  			if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
2548
2549
2550
  				printk(KERN_ERR "cyc:cy_break (set) retval on "
  					"ttyC%d was %x
  ", info->line, retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2551
2552
  			}
  		} else {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2553
2554
  			retval = cyz_issue_cmd(card,
  				info->line - card->first_line,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2555
2556
  				C_CM_CLR_BREAK, 0L);
  			if (retval != 0) {
217191910   Jiri Slaby   Char: cyclades, p...
2557
2558
2559
2560
  				printk(KERN_DEBUG "cyc:cy_break (clr) retval "
  					"on ttyC%d was %x
  ", info->line,
  					retval);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2561
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2562
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2563
  	}
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2564
  	spin_unlock_irqrestore(&card->card_lock, flags);
9e98966c7   Alan Cox   tty: rework break...
2565
  	return retval;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2566
  }				/* cy_break */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2567

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2568
  static int set_threshold(struct cyclades_port *info, unsigned long value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2569
  {
3aeea5b92   Jiri Slaby   cyclades: introdu...
2570
  	struct cyclades_card *card = info->card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2571
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2572

2693f485c   Jiri Slaby   tty: cyclades, co...
2573
  	if (!cy_is_Z(card)) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2574
2575
  		info->cor3 &= ~CyREC_FIFO;
  		info->cor3 |= value & CyREC_FIFO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2576

9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2577
  		spin_lock_irqsave(&card->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
2578
2579
  		cyy_writeb(info, CyCOR3, info->cor3);
  		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2580
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2581
2582
2583
  	}
  	return 0;
  }				/* set_threshold */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2584

15ed6cc0b   Alan Cox   cyclades: coding ...
2585
2586
  static int get_threshold(struct cyclades_port *info,
  						unsigned long __user *value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2587
  {
3aeea5b92   Jiri Slaby   cyclades: introdu...
2588
  	struct cyclades_card *card = info->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2589

2693f485c   Jiri Slaby   tty: cyclades, co...
2590
  	if (!cy_is_Z(card)) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
2591
  		u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2592
  		return put_user(tmp, value);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2593
  	}
f74290342   Jiri Slaby   Char: cyclades, c...
2594
  	return 0;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2595
  }				/* get_threshold */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2596

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2597
  static int set_timeout(struct cyclades_port *info, unsigned long value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2598
  {
3aeea5b92   Jiri Slaby   cyclades: introdu...
2599
  	struct cyclades_card *card = info->card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2600
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2601

2693f485c   Jiri Slaby   tty: cyclades, co...
2602
  	if (!cy_is_Z(card)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2603
  		spin_lock_irqsave(&card->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
2604
  		cyy_writeb(info, CyRTPR, value & 0xff);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2605
  		spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2606
2607
2608
  	}
  	return 0;
  }				/* set_timeout */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2609

15ed6cc0b   Alan Cox   cyclades: coding ...
2610
2611
  static int get_timeout(struct cyclades_port *info,
  						unsigned long __user *value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2612
  {
3aeea5b92   Jiri Slaby   cyclades: introdu...
2613
  	struct cyclades_card *card = info->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2614

2693f485c   Jiri Slaby   tty: cyclades, co...
2615
  	if (!cy_is_Z(card)) {
3aeea5b92   Jiri Slaby   cyclades: introdu...
2616
  		u8 tmp = cyy_readb(info, CyRTPR);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2617
  		return put_user(tmp, value);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2618
  	}
f74290342   Jiri Slaby   Char: cyclades, c...
2619
  	return 0;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2620
  }				/* get_timeout */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2621

6c28181cf   Jiri Slaby   cyclades: ioctls ...
2622
2623
  static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg,
  		struct cyclades_icount *cprev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2624
  {
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2625
2626
2627
  	struct cyclades_icount cnow;
  	unsigned long flags;
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2628

6c28181cf   Jiri Slaby   cyclades: ioctls ...
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
  	spin_lock_irqsave(&info->card->card_lock, flags);
  	cnow = info->icount;	/* atomic copy */
  	spin_unlock_irqrestore(&info->card->card_lock, flags);
  
  	ret =	((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
  		((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
  		((arg & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
  		((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
  
  	*cprev = cnow;
  
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2642
2643
2644
2645
2646
2647
2648
  
  /*
   * This routine allows the tty driver to implement device-
   * specific ioctl's.  If the ioctl number passed in cmd is
   * not recognized by the driver, it should return ENOIOCTLCMD.
   */
  static int
6caa76b77   Alan Cox   tty: now phase ou...
2649
  cy_ioctl(struct tty_struct *tty,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2650
  	 unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2651
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2652
  	struct cyclades_port *info = tty->driver_data;
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2653
  	struct cyclades_icount cnow;	/* kernel counter temps */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2654
2655
2656
2657
2658
2659
  	int ret_val = 0;
  	unsigned long flags;
  	void __user *argp = (void __user *)arg;
  
  	if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2660
2661
  
  #ifdef CY_DEBUG_OTHER
217191910   Jiri Slaby   Char: cyclades, p...
2662
2663
2664
  	printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx
  ",
  		info->line, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2665
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2666
2667
  	switch (cmd) {
  	case CYGETMON:
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2668
2669
2670
2671
2672
  		if (copy_to_user(argp, &info->mon, sizeof(info->mon))) {
  			ret_val = -EFAULT;
  			break;
  		}
  		memset(&info->mon, 0, sizeof(info->mon));
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2673
2674
2675
2676
2677
2678
2679
2680
  		break;
  	case CYGETTHRESH:
  		ret_val = get_threshold(info, argp);
  		break;
  	case CYSETTHRESH:
  		ret_val = set_threshold(info, arg);
  		break;
  	case CYGETDEFTHRESH:
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2681
2682
  		ret_val = put_user(info->default_threshold,
  				(unsigned long __user *)argp);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2683
2684
  		break;
  	case CYSETDEFTHRESH:
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2685
  		info->default_threshold = arg & 0x0f;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2686
2687
2688
2689
2690
2691
2692
2693
  		break;
  	case CYGETTIMEOUT:
  		ret_val = get_timeout(info, argp);
  		break;
  	case CYSETTIMEOUT:
  		ret_val = set_timeout(info, arg);
  		break;
  	case CYGETDEFTIMEOUT:
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2694
2695
  		ret_val = put_user(info->default_timeout,
  				(unsigned long __user *)argp);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2696
2697
  		break;
  	case CYSETDEFTIMEOUT:
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2698
  		info->default_timeout = arg & 0xff;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2699
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2700
  	case CYSETRFLOW:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2701
  		info->rflow = (int)arg;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2702
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2703
  	case CYGETRFLOW:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2704
2705
  		ret_val = info->rflow;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2706
  	case CYSETRTSDTR_INV:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2707
  		info->rtsdtr_inv = (int)arg;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2708
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2709
  	case CYGETRTSDTR_INV:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2710
2711
  		ret_val = info->rtsdtr_inv;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2712
  	case CYGETCD1400VER:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2713
2714
  		ret_val = info->chip_rev;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2715
2716
  #ifndef CONFIG_CYZ_INTR
  	case CYZSETPOLLCYCLE:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2717
  		cyz_polling_cycle = (arg * HZ) / 1000;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2718
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2719
  	case CYZGETPOLLCYCLE:
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2720
2721
2722
  		ret_val = (cyz_polling_cycle * 1000) / HZ;
  		break;
  #endif				/* CONFIG_CYZ_INTR */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2723
  	case CYSETWAIT:
44b7d1b37   Alan Cox   tty: add more tty...
2724
  		info->port.closing_wait = (unsigned short)arg * HZ / 100;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2725
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2726
  	case CYGETWAIT:
44b7d1b37   Alan Cox   tty: add more tty...
2727
  		ret_val = info->port.closing_wait / (HZ / 100);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2728
2729
  		break;
  	case TIOCGSERIAL:
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2730
  		ret_val = cy_get_serial_info(info, argp);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2731
2732
  		break;
  	case TIOCSSERIAL:
d13549f80   Jiri Slaby   cyclades: add tty...
2733
  		ret_val = cy_set_serial_info(info, tty, argp);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
  		break;
  	case TIOCSERGETLSR:	/* Get line status register */
  		ret_val = get_lsr_info(info, argp);
  		break;
  		/*
  		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
  		 * - mask passed in arg for lines of interest
  		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
  		 * Caller should use TIOCGICOUNT to see which one it was
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2744
  	case TIOCMIWAIT:
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2745
  		spin_lock_irqsave(&info->card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2746
  		/* note the counters on entry */
2c7fea992   Jiri Slaby   Char: cyclades, r...
2747
  		cnow = info->icount;
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2748
  		spin_unlock_irqrestore(&info->card->card_lock, flags);
bdc04e317   Alan Cox   serial: move delt...
2749
  		ret_val = wait_event_interruptible(info->port.delta_msr_wait,
6c28181cf   Jiri Slaby   cyclades: ioctls ...
2750
  				cy_cflags_changed(info, arg, &cnow));
2c7fea992   Jiri Slaby   Char: cyclades, r...
2751
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2752

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2753
2754
2755
2756
2757
2758
  		/*
  		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
  		 * Return: write counters to the user passed counter struct
  		 * NB: both 1->0 and 0->1 transitions are counted except for
  		 *     RI where only 0->1 is counted.
  		 */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2759
2760
2761
  	default:
  		ret_val = -ENOIOCTLCMD;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2762
2763
  
  #ifdef CY_DEBUG_OTHER
217191910   Jiri Slaby   Char: cyclades, p...
2764
2765
  	printk(KERN_DEBUG "cyc:cy_ioctl done
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2766
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2767
2768
  	return ret_val;
  }				/* cy_ioctl */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2769

0587102cf   Alan Cox   tty: icount chang...
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
  static int cy_get_icount(struct tty_struct *tty,
  				struct serial_icounter_struct *sic)
  {
  	struct cyclades_port *info = tty->driver_data;
  	struct cyclades_icount cnow;	/* Used to snapshot */
  	unsigned long flags;
  
  	spin_lock_irqsave(&info->card->card_lock, flags);
  	cnow = info->icount;
  	spin_unlock_irqrestore(&info->card->card_lock, flags);
  
  	sic->cts = cnow.cts;
  	sic->dsr = cnow.dsr;
  	sic->rng = cnow.rng;
  	sic->dcd = cnow.dcd;
  	sic->rx = cnow.rx;
  	sic->tx = cnow.tx;
  	sic->frame = cnow.frame;
  	sic->overrun = cnow.overrun;
  	sic->parity = cnow.parity;
  	sic->brk = cnow.brk;
  	sic->buf_overrun = cnow.buf_overrun;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2794
2795
2796
2797
2798
2799
  /*
   * This routine allows the tty driver to be notified when
   * device's termios settings have changed.  Note that a
   * well-designed tty driver should be prepared to accept the case
   * where old == NULL, and try to do something rational.
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2800
  static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2801
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2802
  	struct cyclades_port *info = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2803
2804
  
  #ifdef CY_DEBUG_OTHER
217191910   Jiri Slaby   Char: cyclades, p...
2805
2806
  	printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2807
  #endif
d13549f80   Jiri Slaby   cyclades: add tty...
2808
  	cy_set_line_char(info, tty);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2809
2810
2811
2812
2813
2814
  
  	if ((old_termios->c_cflag & CRTSCTS) &&
  			!(tty->termios->c_cflag & CRTSCTS)) {
  		tty->hw_stopped = 0;
  		cy_start(tty);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2815
  #if 0
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2816
2817
2818
2819
2820
2821
2822
2823
  	/*
  	 * No need to wake up processes in open wait, since they
  	 * sample the CLOCAL flag once, and don't recheck it.
  	 * XXX  It's not clear whether the current behavior is correct
  	 * or not.  Hence, this may change.....
  	 */
  	if (!(old_termios->c_cflag & CLOCAL) &&
  	    (tty->termios->c_cflag & CLOCAL))
77451e53e   Alan Cox   cyclades: use tty...
2824
  		wake_up_interruptible(&info->port.open_wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2825
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2826
  }				/* cy_set_termios */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2827
2828
2829
2830
  
  /* This function is used to send a high-priority XON/XOFF character to
     the device.
  */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2831
  static void cy_send_xchar(struct tty_struct *tty, char ch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2832
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2833
  	struct cyclades_port *info = tty->driver_data;
875b206b5   Jiri Slaby   Char: cyclades, m...
2834
2835
  	struct cyclades_card *card;
  	int channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2836

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2837
  	if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2838
  		return;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2839
  	info->x_char = ch;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2840
2841
  
  	if (ch)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2842
  		cy_start(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2843
2844
  
  	card = info->card;
875b206b5   Jiri Slaby   Char: cyclades, m...
2845
  	channel = info->line - card->first_line;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2846

2693f485c   Jiri Slaby   tty: cyclades, co...
2847
  	if (cy_is_Z(card)) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2848
  		if (ch == STOP_CHAR(tty))
875b206b5   Jiri Slaby   Char: cyclades, m...
2849
  			cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2850
  		else if (ch == START_CHAR(tty))
875b206b5   Jiri Slaby   Char: cyclades, m...
2851
  			cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2852
2853
2854
2855
2856
2857
2858
  	}
  }
  
  /* This routine is called by the upper-layer tty layer to signal
     that incoming characters should be throttled because the input
     buffers are close to full.
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2859
  static void cy_throttle(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2860
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2861
  	struct cyclades_port *info = tty->driver_data;
875b206b5   Jiri Slaby   Char: cyclades, m...
2862
  	struct cyclades_card *card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2863
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2864
2865
  
  #ifdef CY_DEBUG_THROTTLE
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2866
  	char buf[64];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2867

217191910   Jiri Slaby   Char: cyclades, p...
2868
2869
  	printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d
  ", tty_name(tty, buf),
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2870
  			tty->ldisc.chars_in_buffer(tty), info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2871
  #endif
15ed6cc0b   Alan Cox   cyclades: coding ...
2872
  	if (serial_paranoia_check(info, tty->name, "cy_throttle"))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2873
  		return;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2874
2875
2876
2877
  
  	card = info->card;
  
  	if (I_IXOFF(tty)) {
2693f485c   Jiri Slaby   tty: cyclades, co...
2878
  		if (!cy_is_Z(card))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2879
2880
2881
2882
  			cy_send_xchar(tty, STOP_CHAR(tty));
  		else
  			info->throttle = 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2883

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2884
  	if (tty->termios->c_cflag & CRTSCTS) {
2693f485c   Jiri Slaby   tty: cyclades, co...
2885
  		if (!cy_is_Z(card)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2886
  			spin_lock_irqsave(&card->card_lock, flags);
4d7682005   Jiri Slaby   cyclades: use dtr...
2887
  			cyy_change_rts_dtr(info, 0, TIOCM_RTS);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2888
  			spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2889
2890
2891
2892
  		} else {
  			info->throttle = 1;
  		}
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2893
  }				/* cy_throttle */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2894
2895
2896
2897
2898
2899
  
  /*
   * This routine notifies the tty driver that it should signal
   * that characters can now be sent to the tty without fear of
   * overrunning the input buffers of the line disciplines.
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2900
  static void cy_unthrottle(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2901
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2902
  	struct cyclades_port *info = tty->driver_data;
875b206b5   Jiri Slaby   Char: cyclades, m...
2903
  	struct cyclades_card *card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2904
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2905
2906
  
  #ifdef CY_DEBUG_THROTTLE
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2907
  	char buf[64];
217191910   Jiri Slaby   Char: cyclades, p...
2908
2909
  	printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d
  ",
15ed6cc0b   Alan Cox   cyclades: coding ...
2910
  		tty_name(tty, buf), tty_chars_in_buffer(tty), info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2911
  #endif
15ed6cc0b   Alan Cox   cyclades: coding ...
2912
  	if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2913
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2914

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2915
2916
2917
2918
2919
  	if (I_IXOFF(tty)) {
  		if (info->x_char)
  			info->x_char = 0;
  		else
  			cy_send_xchar(tty, START_CHAR(tty));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2920
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2921

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2922
2923
  	if (tty->termios->c_cflag & CRTSCTS) {
  		card = info->card;
2693f485c   Jiri Slaby   tty: cyclades, co...
2924
  		if (!cy_is_Z(card)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2925
  			spin_lock_irqsave(&card->card_lock, flags);
4d7682005   Jiri Slaby   cyclades: use dtr...
2926
  			cyy_change_rts_dtr(info, TIOCM_RTS, 0);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2927
  			spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2928
2929
2930
2931
  		} else {
  			info->throttle = 0;
  		}
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2932
  }				/* cy_unthrottle */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2933
2934
2935
2936
  
  /* cy_start and cy_stop provide software output flow control as a
     function of XON/XOFF, software CTS, and other such stuff.
  */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2937
  static void cy_stop(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2938
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2939
  	struct cyclades_card *cinfo;
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2940
  	struct cyclades_port *info = tty->driver_data;
3aeea5b92   Jiri Slaby   cyclades: introdu...
2941
  	int channel;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2942
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2943
2944
  
  #ifdef CY_DEBUG_OTHER
217191910   Jiri Slaby   Char: cyclades, p...
2945
2946
  	printk(KERN_DEBUG "cyc:cy_stop ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2947
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2948
2949
  	if (serial_paranoia_check(info, tty->name, "cy_stop"))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2950

875b206b5   Jiri Slaby   Char: cyclades, m...
2951
  	cinfo = info->card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2952
  	channel = info->line - cinfo->first_line;
2693f485c   Jiri Slaby   tty: cyclades, co...
2953
  	if (!cy_is_Z(cinfo)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2954
  		spin_lock_irqsave(&cinfo->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
2955
2956
  		cyy_writeb(info, CyCAR, channel & 0x03);
  		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2957
  		spin_unlock_irqrestore(&cinfo->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2958
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2959
  }				/* cy_stop */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2960

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2961
  static void cy_start(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2962
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2963
  	struct cyclades_card *cinfo;
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2964
  	struct cyclades_port *info = tty->driver_data;
3aeea5b92   Jiri Slaby   cyclades: introdu...
2965
  	int channel;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2966
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2967
2968
  
  #ifdef CY_DEBUG_OTHER
217191910   Jiri Slaby   Char: cyclades, p...
2969
2970
  	printk(KERN_DEBUG "cyc:cy_start ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2971
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2972
2973
  	if (serial_paranoia_check(info, tty->name, "cy_start"))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2974

875b206b5   Jiri Slaby   Char: cyclades, m...
2975
  	cinfo = info->card;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2976
  	channel = info->line - cinfo->first_line;
2693f485c   Jiri Slaby   tty: cyclades, co...
2977
  	if (!cy_is_Z(cinfo)) {
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2978
  		spin_lock_irqsave(&cinfo->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
2979
2980
  		cyy_writeb(info, CyCAR, channel & 0x03);
  		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
9fa1b3b18   Jiri Slaby   Char: cyclades, r...
2981
  		spin_unlock_irqrestore(&cinfo->card_lock, flags);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2982
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2983
  }				/* cy_start */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2984

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2985
2986
2987
  /*
   * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2988
  static void cy_hangup(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2989
  {
cab9bdd14   Jiri Slaby   Char: cyclades, r...
2990
  	struct cyclades_port *info = tty->driver_data;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2991

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2992
  #ifdef CY_DEBUG_OTHER
217191910   Jiri Slaby   Char: cyclades, p...
2993
2994
  	printk(KERN_DEBUG "cyc:cy_hangup ttyC%d
  ", info->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2995
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2996
2997
  	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2998

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
2999
  	cy_flush_buffer(tty);
d13549f80   Jiri Slaby   cyclades: add tty...
3000
  	cy_shutdown(info, tty);
174e6fe01   Jiri Slaby   cyclades: switch ...
3001
  	tty_port_hangup(&info->port);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3002
  }				/* cy_hangup */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3003

f07375794   Jiri Slaby   cyclades: remove ...
3004
3005
3006
3007
3008
  static int cyy_carrier_raised(struct tty_port *port)
  {
  	struct cyclades_port *info = container_of(port, struct cyclades_port,
  			port);
  	struct cyclades_card *cinfo = info->card;
f07375794   Jiri Slaby   cyclades: remove ...
3009
3010
  	unsigned long flags;
  	int channel = info->line - cinfo->first_line;
f07375794   Jiri Slaby   cyclades: remove ...
3011
  	u32 cd;
f07375794   Jiri Slaby   cyclades: remove ...
3012
  	spin_lock_irqsave(&cinfo->card_lock, flags);
3aeea5b92   Jiri Slaby   cyclades: introdu...
3013
3014
  	cyy_writeb(info, CyCAR, channel & 0x03);
  	cd = cyy_readb(info, CyMSVR1) & CyDCD;
f07375794   Jiri Slaby   cyclades: remove ...
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
  	spin_unlock_irqrestore(&cinfo->card_lock, flags);
  
  	return cd;
  }
  
  static void cyy_dtr_rts(struct tty_port *port, int raise)
  {
  	struct cyclades_port *info = container_of(port, struct cyclades_port,
  			port);
  	struct cyclades_card *cinfo = info->card;
f07375794   Jiri Slaby   cyclades: remove ...
3025
  	unsigned long flags;
f07375794   Jiri Slaby   cyclades: remove ...
3026
3027
  
  	spin_lock_irqsave(&cinfo->card_lock, flags);
4d7682005   Jiri Slaby   cyclades: use dtr...
3028
3029
  	cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0,
  			raise ? 0 : TIOCM_RTS | TIOCM_DTR);
f07375794   Jiri Slaby   cyclades: remove ...
3030
3031
3032
3033
3034
3035
3036
  	spin_unlock_irqrestore(&cinfo->card_lock, flags);
  }
  
  static int cyz_carrier_raised(struct tty_port *port)
  {
  	struct cyclades_port *info = container_of(port, struct cyclades_port,
  			port);
f07375794   Jiri Slaby   cyclades: remove ...
3037

f0eefdc30   Jiri Slaby   cyclades: avoid a...
3038
  	return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD;
f07375794   Jiri Slaby   cyclades: remove ...
3039
3040
3041
3042
3043
3044
3045
  }
  
  static void cyz_dtr_rts(struct tty_port *port, int raise)
  {
  	struct cyclades_port *info = container_of(port, struct cyclades_port,
  			port);
  	struct cyclades_card *cinfo = info->card;
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3046
  	struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
f07375794   Jiri Slaby   cyclades: remove ...
3047
3048
  	int ret, channel = info->line - cinfo->first_line;
  	u32 rs;
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3049
  	rs = readl(&ch_ctrl->rs_control);
f07375794   Jiri Slaby   cyclades: remove ...
3050
3051
3052
3053
  	if (raise)
  		rs |= C_RS_RTS | C_RS_DTR;
  	else
  		rs &= ~(C_RS_RTS | C_RS_DTR);
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3054
  	cy_writel(&ch_ctrl->rs_control, rs);
f07375794   Jiri Slaby   cyclades: remove ...
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
  	ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L);
  	if (ret != 0)
  		printk(KERN_ERR "%s: retval on ttyC%d was %x
  ",
  				__func__, info->line, ret);
  #ifdef CY_DEBUG_DTR
  	printk(KERN_DEBUG "%s: raising Z DTR
  ", __func__);
  #endif
  }
  
  static const struct tty_port_operations cyy_port_ops = {
  	.carrier_raised = cyy_carrier_raised,
  	.dtr_rts = cyy_dtr_rts,
e936ffd5c   Alan Cox   cyclades: use the...
3069
  	.shutdown = cy_do_close,
f07375794   Jiri Slaby   cyclades: remove ...
3070
3071
3072
3073
3074
  };
  
  static const struct tty_port_operations cyz_port_ops = {
  	.carrier_raised = cyz_carrier_raised,
  	.dtr_rts = cyz_dtr_rts,
e936ffd5c   Alan Cox   cyclades: use the...
3075
  	.shutdown = cy_do_close,
f07375794   Jiri Slaby   cyclades: remove ...
3076
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3077
3078
3079
3080
3081
3082
3083
  /*
   * ---------------------------------------------------------------------
   * cy_init() and friends
   *
   * cy_init() is called at boot-time to initialize the serial driver.
   * ---------------------------------------------------------------------
   */
dd025c0c7   Jiri Slaby   Char: cyclades, d...
3084
  static int __devinit cy_init_card(struct cyclades_card *cinfo)
0809e2671   Jiri Slaby   Char: cyclades, m...
3085
3086
  {
  	struct cyclades_port *info;
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3087
  	unsigned int channel, port;
0809e2671   Jiri Slaby   Char: cyclades, m...
3088

3046d50ea   Jiri Slaby   Char: cyclades, s...
3089
  	spin_lock_init(&cinfo->card_lock);
963118eef   Jiri Slaby   tty: cyclades, fi...
3090
  	cinfo->intr_enabled = 0;
3046d50ea   Jiri Slaby   Char: cyclades, s...
3091

963118eef   Jiri Slaby   tty: cyclades, fi...
3092
3093
  	cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
  			GFP_KERNEL);
dd025c0c7   Jiri Slaby   Char: cyclades, d...
3094
3095
3096
3097
3098
  	if (cinfo->ports == NULL) {
  		printk(KERN_ERR "Cyclades: cannot allocate ports
  ");
  		return -ENOMEM;
  	}
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3099
3100
3101
  	for (channel = 0, port = cinfo->first_line; channel < cinfo->nports;
  			channel++, port++) {
  		info = &cinfo->ports[channel];
44b7d1b37   Alan Cox   tty: add more tty...
3102
  		tty_port_init(&info->port);
3046d50ea   Jiri Slaby   Char: cyclades, s...
3103
  		info->magic = CYCLADES_MAGIC;
875b206b5   Jiri Slaby   Char: cyclades, m...
3104
  		info->card = cinfo;
3046d50ea   Jiri Slaby   Char: cyclades, s...
3105
  		info->line = port;
3046d50ea   Jiri Slaby   Char: cyclades, s...
3106

44b7d1b37   Alan Cox   tty: add more tty...
3107
3108
  		info->port.closing_wait = CLOSING_WAIT_DELAY;
  		info->port.close_delay = 5 * HZ / 10;
77451e53e   Alan Cox   cyclades: use tty...
3109
  		info->port.flags = STD_COM_FLAGS;
2c7fea992   Jiri Slaby   Char: cyclades, r...
3110
  		init_completion(&info->shutdown_wait);
3046d50ea   Jiri Slaby   Char: cyclades, s...
3111

2693f485c   Jiri Slaby   tty: cyclades, co...
3112
  		if (cy_is_Z(cinfo)) {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3113
3114
  			struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS;
  			struct ZFW_CTRL *zfw_ctrl;
f07375794   Jiri Slaby   cyclades: remove ...
3115
  			info->port.ops = &cyz_port_ops;
0809e2671   Jiri Slaby   Char: cyclades, m...
3116
  			info->type = PORT_STARTECH;
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3117
3118
3119
3120
3121
  
  			zfw_ctrl = cinfo->base_addr +
  				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
  			info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel];
  			info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
101b81590   Jiri Slaby   tty: cyclades, ca...
3122
  			if (cinfo->hw_ver == ZO_V1)
0809e2671   Jiri Slaby   Char: cyclades, m...
3123
3124
  				info->xmit_fifo_size = CYZ_FIFO_SIZE;
  			else
3046d50ea   Jiri Slaby   Char: cyclades, s...
3125
  				info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
0809e2671   Jiri Slaby   Char: cyclades, m...
3126
  #ifdef CONFIG_CYZ_INTR
3991428d9   Jiri Slaby   Char: cyclades, t...
3127
3128
  			setup_timer(&cyz_rx_full_timer[port],
  				cyz_rx_restart, (unsigned long)info);
0809e2671   Jiri Slaby   Char: cyclades, m...
3129
  #endif
3046d50ea   Jiri Slaby   Char: cyclades, s...
3130
  		} else {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3131
  			unsigned short chip_number;
963118eef   Jiri Slaby   tty: cyclades, fi...
3132
  			int index = cinfo->bus_index;
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3133

f07375794   Jiri Slaby   cyclades: remove ...
3134
  			info->port.ops = &cyy_port_ops;
0809e2671   Jiri Slaby   Char: cyclades, m...
3135
  			info->type = PORT_CIRRUS;
0809e2671   Jiri Slaby   Char: cyclades, m...
3136
  			info->xmit_fifo_size = CyMAX_CHAR_FIFO;
3046d50ea   Jiri Slaby   Char: cyclades, s...
3137
  			info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
0809e2671   Jiri Slaby   Char: cyclades, m...
3138
3139
  			info->cor2 = CyETC;
  			info->cor3 = 0x08;	/* _very_ small rcv threshold */
3046d50ea   Jiri Slaby   Char: cyclades, s...
3140

f0eefdc30   Jiri Slaby   cyclades: avoid a...
3141
  			chip_number = channel / CyPORTS_PER_CHIP;
3aeea5b92   Jiri Slaby   cyclades: introdu...
3142
3143
3144
  			info->u.cyy.base_addr = cinfo->base_addr +
  				(cy_chip_offset[chip_number] << index);
  			info->chip_rev = cyy_readb(info, CyGFRCR);
15ed6cc0b   Alan Cox   cyclades: coding ...
3145
3146
  
  			if (info->chip_rev >= CD1400_REV_J) {
0809e2671   Jiri Slaby   Char: cyclades, m...
3147
3148
3149
3150
3151
  				/* It is a CD1400 rev. J or later */
  				info->tbpr = baud_bpr_60[13];	/* Tx BPR */
  				info->tco = baud_co_60[13];	/* Tx CO */
  				info->rbpr = baud_bpr_60[13];	/* Rx BPR */
  				info->rco = baud_co_60[13];	/* Rx CO */
0809e2671   Jiri Slaby   Char: cyclades, m...
3152
3153
3154
3155
3156
3157
  				info->rtsdtr_inv = 1;
  			} else {
  				info->tbpr = baud_bpr_25[13];	/* Tx BPR */
  				info->tco = baud_co_25[13];	/* Tx CO */
  				info->rbpr = baud_bpr_25[13];	/* Rx BPR */
  				info->rco = baud_co_25[13];	/* Rx CO */
0809e2671   Jiri Slaby   Char: cyclades, m...
3158
3159
  				info->rtsdtr_inv = 0;
  			}
3046d50ea   Jiri Slaby   Char: cyclades, s...
3160
3161
  			info->read_status_mask = CyTIMEOUT | CySPECHAR |
  				CyBREAK | CyPARITY | CyFRAME | CyOVERRUN;
0809e2671   Jiri Slaby   Char: cyclades, m...
3162
  		}
3046d50ea   Jiri Slaby   Char: cyclades, s...
3163

0809e2671   Jiri Slaby   Char: cyclades, m...
3164
  	}
3046d50ea   Jiri Slaby   Char: cyclades, s...
3165
3166
  
  #ifndef CONFIG_CYZ_INTR
2693f485c   Jiri Slaby   tty: cyclades, co...
3167
  	if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) {
3046d50ea   Jiri Slaby   Char: cyclades, s...
3168
3169
3170
3171
3172
3173
3174
  		mod_timer(&cyz_timerlist, jiffies + 1);
  #ifdef CY_PCI_DEBUG
  		printk(KERN_DEBUG "Cyclades-Z polling initialized
  ");
  #endif
  	}
  #endif
dd025c0c7   Jiri Slaby   Char: cyclades, d...
3175
  	return 0;
0809e2671   Jiri Slaby   Char: cyclades, m...
3176
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3177
3178
  /* initialize chips on Cyclom-Y card -- return number of valid
     chips (which is number of ports/4) */
31b4f0a11   Jiri Slaby   Char: cyclades, m...
3179
3180
  static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
  		int index)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3181
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3182
3183
3184
3185
3186
3187
3188
3189
  	unsigned int chip_number;
  	void __iomem *base_addr;
  
  	cy_writeb(true_base_addr + (Cy_HwReset << index), 0);
  	/* Cy_HwReset is 0x1400 */
  	cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0);
  	/* Cy_ClrIntr is 0x1800 */
  	udelay(500L);
15ed6cc0b   Alan Cox   cyclades: coding ...
3190
3191
  	for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD;
  							chip_number++) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3192
3193
3194
  		base_addr =
  		    true_base_addr + (cy_chip_offset[chip_number] << index);
  		mdelay(1);
db05c3b1d   Jiri Slaby   Char: cyclades, c...
3195
  		if (readb(base_addr + (CyCCR << index)) != 0x00) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
  			/*************
  			printk(" chip #%d at %#6lx is never idle (CCR != 0)
  ",
  			chip_number, (unsigned long)base_addr);
  			*************/
  			return chip_number;
  		}
  
  		cy_writeb(base_addr + (CyGFRCR << index), 0);
  		udelay(10L);
  
  		/* The Cyclom-16Y does not decode address bit 9 and therefore
  		   cannot distinguish between references to chip 0 and a non-
  		   existent chip 4.  If the preceding clearing of the supposed
  		   chip 4 GFRCR register appears at chip 0, there is no chip 4
  		   and this must be a Cyclom-16Y, not a Cyclom-32Ye.
  		 */
db05c3b1d   Jiri Slaby   Char: cyclades, c...
3213
  		if (chip_number == 4 && readb(true_base_addr +
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3214
3215
3216
3217
3218
3219
3220
  				(cy_chip_offset[0] << index) +
  				(CyGFRCR << index)) == 0) {
  			return chip_number;
  		}
  
  		cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
  		mdelay(1);
db05c3b1d   Jiri Slaby   Char: cyclades, c...
3221
  		if (readb(base_addr + (CyGFRCR << index)) == 0x00) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3222
3223
3224
3225
3226
3227
3228
3229
  			/*
  			   printk(" chip #%d at %#6lx is not responding ",
  			   chip_number, (unsigned long)base_addr);
  			   printk("(GFRCR stayed 0)
  ",
  			 */
  			return chip_number;
  		}
db05c3b1d   Jiri Slaby   Char: cyclades, c...
3230
  		if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) !=
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
  				0x40) {
  			/*
  			printk(" chip #%d at %#6lx is not valid (GFRCR == "
  					"%#2x)
  ",
  					chip_number, (unsigned long)base_addr,
  					base_addr[CyGFRCR<<index]);
  			 */
  			return chip_number;
  		}
  		cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
db05c3b1d   Jiri Slaby   Char: cyclades, c...
3242
  		if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3243
3244
3245
3246
3247
3248
3249
3250
  			/* It is a CD1400 rev. J or later */
  			/* Impossible to reach 5ms with this chip.
  			   Changed to 2ms instead (f = 500 Hz). */
  			cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS);
  		} else {
  			/* f = 200 Hz */
  			cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3251

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3252
3253
3254
3255
  		/*
  		   printk(" chip #%d at %#6lx is rev 0x%2x
  ",
  		   chip_number, (unsigned long)base_addr,
db05c3b1d   Jiri Slaby   Char: cyclades, c...
3256
  		   readb(base_addr+(CyGFRCR<<index)));
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3257
3258
3259
3260
  		 */
  	}
  	return chip_number;
  }				/* cyy_init_card */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3261
3262
3263
3264
3265
3266
3267
  
  /*
   * ---------------------------------------------------------------------
   * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
   * sets global variables and return the number of ISA boards found.
   * ---------------------------------------------------------------------
   */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3268
  static int __init cy_detect_isa(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3269
3270
  {
  #ifdef CONFIG_ISA
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3271
3272
3273
  	unsigned short cy_isa_irq, nboard;
  	void __iomem *cy_isa_address;
  	unsigned short i, j, cy_isa_nchan;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3274
  	int isparam = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3275

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3276
  	nboard = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3277

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3278
  	/* Check for module parameters */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3279
3280
3281
3282
3283
3284
3285
  	for (i = 0; i < NR_CARDS; i++) {
  		if (maddr[i] || i) {
  			isparam = 1;
  			cy_isa_addresses[i] = maddr[i];
  		}
  		if (!maddr[i])
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3286
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3287

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3288
3289
3290
  	/* scan the address table probing for Cyclom-Y/ISA boards */
  	for (i = 0; i < NR_ISA_ADDRS; i++) {
  		unsigned int isa_address = cy_isa_addresses[i];
15ed6cc0b   Alan Cox   cyclades: coding ...
3291
  		if (isa_address == 0x0000)
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
3292
  			return nboard;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3293

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3294
  		/* probe for CD1400... */
cd989b3a8   Alan Cox   cyclades: use ior...
3295
  		cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin);
3137553d3   Jiri Slaby   Char: cyclades, p...
3296
3297
3298
3299
3300
3301
  		if (cy_isa_address == NULL) {
  			printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
  					"address
  ");
  			continue;
  		}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3302
3303
3304
  		cy_isa_nchan = CyPORTS_PER_CHIP *
  			cyy_init_card(cy_isa_address, 0);
  		if (cy_isa_nchan == 0) {
3137553d3   Jiri Slaby   Char: cyclades, p...
3305
  			iounmap(cy_isa_address);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3306
3307
  			continue;
  		}
209043635   Bartlomiej Zolnierkiewicz   serial: cyclades:...
3308

196b3167e   Roel Kluin   cyclades: fix rea...
3309
  		if (isparam && i < NR_CARDS && irq[i])
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3310
  			cy_isa_irq = irq[i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3311
  		else
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3312
3313
3314
  			/* find out the board's irq by probing */
  			cy_isa_irq = detect_isa_irq(cy_isa_address);
  		if (cy_isa_irq == 0) {
217191910   Jiri Slaby   Char: cyclades, p...
3315
3316
3317
  			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the "
  				"IRQ could not be detected.
  ",
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3318
  				(unsigned long)cy_isa_address);
3137553d3   Jiri Slaby   Char: cyclades, p...
3319
  			iounmap(cy_isa_address);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3320
3321
3322
3323
  			continue;
  		}
  
  		if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
217191910   Jiri Slaby   Char: cyclades, p...
3324
3325
3326
3327
  			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
  				"more channels are available. Change NR_PORTS "
  				"in cyclades.c and recompile kernel.
  ",
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3328
  				(unsigned long)cy_isa_address);
3137553d3   Jiri Slaby   Char: cyclades, p...
3329
  			iounmap(cy_isa_address);
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
3330
  			return nboard;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3331
3332
3333
  		}
  		/* fill the next cy_card structure available */
  		for (j = 0; j < NR_CARDS; j++) {
f74290342   Jiri Slaby   Char: cyclades, c...
3334
  			if (cy_card[j].base_addr == NULL)
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3335
3336
3337
  				break;
  		}
  		if (j == NR_CARDS) {	/* no more cy_cards available */
217191910   Jiri Slaby   Char: cyclades, p...
3338
3339
3340
3341
  			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
  				"more cards can be used. Change NR_CARDS in "
  				"cyclades.c and recompile kernel.
  ",
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3342
  				(unsigned long)cy_isa_address);
3137553d3   Jiri Slaby   Char: cyclades, p...
3343
  			iounmap(cy_isa_address);
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
3344
  			return nboard;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3345
3346
3347
3348
  		}
  
  		/* allocate IRQ */
  		if (request_irq(cy_isa_irq, cyy_interrupt,
9cfb5c05f   Yong Zhang   TTY: irq: Remove ...
3349
  				0, "Cyclom-Y", &cy_card[j])) {
217191910   Jiri Slaby   Char: cyclades, p...
3350
3351
3352
3353
  			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
  				"could not allocate IRQ#%d.
  ",
  				(unsigned long)cy_isa_address, cy_isa_irq);
3137553d3   Jiri Slaby   Char: cyclades, p...
3354
  			iounmap(cy_isa_address);
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
3355
  			return nboard;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3356
3357
3358
3359
  		}
  
  		/* set cy_card */
  		cy_card[j].base_addr = cy_isa_address;
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
3360
  		cy_card[j].ctl_addr.p9050 = NULL;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3361
3362
3363
  		cy_card[j].irq = (int)cy_isa_irq;
  		cy_card[j].bus_index = 0;
  		cy_card[j].first_line = cy_next_channel;
963118eef   Jiri Slaby   tty: cyclades, fi...
3364
3365
  		cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
  		cy_card[j].nports = cy_isa_nchan;
3137553d3   Jiri Slaby   Char: cyclades, p...
3366
3367
3368
3369
3370
3371
  		if (cy_init_card(&cy_card[j])) {
  			cy_card[j].base_addr = NULL;
  			free_irq(cy_isa_irq, &cy_card[j]);
  			iounmap(cy_isa_address);
  			continue;
  		}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3372
  		nboard++;
217191910   Jiri Slaby   Char: cyclades, p...
3373
3374
3375
  		printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: "
  			"%d channels starting from port %d
  ",
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3376
3377
  			j + 1, (unsigned long)cy_isa_address,
  			(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
217191910   Jiri Slaby   Char: cyclades, p...
3378
  			cy_isa_irq, cy_isa_nchan, cy_next_channel);
6ad1ccc19   Jiri Slaby   Char: cyclades, t...
3379
3380
3381
  		for (j = cy_next_channel;
  				j < cy_next_channel + cy_isa_nchan; j++)
  			tty_register_device(cy_serial_driver, j, NULL);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3382
3383
  		cy_next_channel += cy_isa_nchan;
  	}
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
3384
  	return nboard;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3385
  #else
096dcfce3   Jiri Slaby   [PATCH] Char: cyc...
3386
  	return 0;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3387
3388
  #endif				/* CONFIG_ISA */
  }				/* cy_detect_isa */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3389

58936d8d9   Jiri Slaby   Char: cyclades, c...
3390
  #ifdef CONFIG_PCI
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
  static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
  {
  	unsigned int a;
  
  	for (a = 0; a < size && *str; a++, str++)
  		if (*str & 0x80)
  			return -EINVAL;
  
  	for (; a < size; a++, str++)
  		if (*str)
  			return -EINVAL;
  
  	return 0;
  }
f61e761e2   David Woodhouse   cyclades: treat f...
3405
  static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
  		unsigned int size)
  {
  	for (; size > 0; size--) {
  		cy_writel(fpga, *data++);
  		udelay(10);
  	}
  }
  
  static void __devinit plx_init(struct pci_dev *pdev, int irq,
  		struct RUNTIME_9060 __iomem *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3416
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3417
  	/* Reset PLX */
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3418
  	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3419
  	udelay(100L);
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3420
  	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3421
3422
  
  	/* Reload Config. Registers from EEPROM */
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3423
  	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3424
  	udelay(100L);
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
  	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
  
  	/* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
  	 * the IRQ is lost and, thus, we have to re-write it to the PCI config.
  	 * registers. This will remain here until we find a permanent fix.
  	 */
  	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
  }
  
  static int __devinit __cyz_load_fw(const struct firmware *fw,
  		const char *name, const u32 mailbox, void __iomem *base,
  		void __iomem *fpga)
  {
f61e761e2   David Woodhouse   cyclades: treat f...
3438
3439
3440
3441
  	const void *ptr = fw->data;
  	const struct zfile_header *h = ptr;
  	const struct zfile_config *c, *cs;
  	const struct zfile_block *b, *bs;
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
  	unsigned int a, tmp, len = fw->size;
  #define BAD_FW KERN_ERR "Bad firmware: "
  	if (len < sizeof(*h)) {
  		printk(BAD_FW "too short: %u<%zu
  ", len, sizeof(*h));
  		return -EINVAL;
  	}
  
  	cs = ptr + h->config_offset;
  	bs = ptr + h->block_offset;
  
  	if ((void *)(cs + h->n_config) > ptr + len ||
  			(void *)(bs + h->n_blocks) > ptr + len) {
  		printk(BAD_FW "too short");
  		return  -EINVAL;
  	}
  
  	if (cyc_isfwstr(h->name, sizeof(h->name)) ||
  			cyc_isfwstr(h->date, sizeof(h->date))) {
  		printk(BAD_FW "bad formatted header string
  ");
  		return -EINVAL;
  	}
  
  	if (strncmp(name, h->name, sizeof(h->name))) {
  		printk(BAD_FW "bad name '%s' (expected '%s')
  ", h->name, name);
  		return -EINVAL;
  	}
  
  	tmp = 0;
  	for (c = cs; c < cs + h->n_config; c++) {
  		for (a = 0; a < c->n_blocks; a++)
  			if (c->block_list[a] > h->n_blocks) {
  				printk(BAD_FW "bad block ref number in cfgs
  ");
  				return -EINVAL;
  			}
  		if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
  			tmp++;
  	}
  	if (!tmp) {
  		printk(BAD_FW "nothing appropriate
  ");
  		return -EINVAL;
  	}
  
  	for (b = bs; b < bs + h->n_blocks; b++)
  		if (b->file_offset + b->size > len) {
  			printk(BAD_FW "bad block data offset
  ");
  			return -EINVAL;
  		}
  
  	/* everything is OK, let's seek'n'load it */
  	for (c = cs; c < cs + h->n_config; c++)
  		if (c->mailbox == mailbox && c->function == 0)
  			break;
  
  	for (a = 0; a < c->n_blocks; a++) {
  		b = &bs[c->block_list[a]];
  		if (b->type == ZBLOCK_FPGA) {
  			if (fpga != NULL)
  				cyz_fpga_copy(fpga, ptr + b->file_offset,
  						b->size);
  		} else {
  			if (base != NULL)
  				memcpy_toio(base + b->ram_offset,
  					       ptr + b->file_offset, b->size);
  		}
  	}
  #undef BAD_FW
  	return 0;
  }
  
  static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
  		struct RUNTIME_9060 __iomem *ctl_addr, int irq)
  {
  	const struct firmware *fw;
  	struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
  	struct CUSTOM_REG __iomem *cust = base_addr;
  	struct ZFW_CTRL __iomem *pt_zfwctrl;
c4923b4f1   Jiri Slaby   Char: cyclades, f...
3524
  	void __iomem *tmp;
963118eef   Jiri Slaby   tty: cyclades, fi...
3525
  	u32 mailbox, status, nchan;
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
  	unsigned int i;
  	int retval;
  
  	retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
  	if (retval) {
  		dev_err(&pdev->dev, "can't get firmware
  ");
  		goto err;
  	}
  
  	/* Check whether the firmware is already loaded and running. If
  	   positive, skip this board */
2693f485c   Jiri Slaby   tty: cyclades, co...
3538
  	if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
  		u32 cntval = readl(base_addr + 0x190);
  
  		udelay(100);
  		if (cntval != readl(base_addr + 0x190)) {
  			/* FW counter is working, FW is running */
  			dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
  					"Skipping board.
  ");
  			retval = 0;
  			goto err_rel;
  		}
  	}
  
  	/* start boot */
  	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
  			~0x00030800UL);
  
  	mailbox = readl(&ctl_addr->mail_box_0);
2693f485c   Jiri Slaby   tty: cyclades, co...
3557
  	if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) {
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
  		/* stops CPU and set window to beginning of RAM */
  		cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
  		cy_writel(&cust->cpu_stop, 0);
  		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
  		udelay(100);
  	}
  
  	plx_init(pdev, irq, ctl_addr);
  
  	if (mailbox != 0) {
  		/* load FPGA */
  		retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
  				base_addr);
  		if (retval)
  			goto err_rel;
2693f485c   Jiri Slaby   tty: cyclades, co...
3573
  		if (!__cyz_fpga_loaded(ctl_addr)) {
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
  			dev_err(&pdev->dev, "fw upload successful, but fw is "
  					"not loaded
  ");
  			goto err_rel;
  		}
  	}
  
  	/* stops CPU and set window to beginning of RAM */
  	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
  	cy_writel(&cust->cpu_stop, 0);
  	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
  	udelay(100);
  
  	/* clear memory */
c4923b4f1   Jiri Slaby   Char: cyclades, f...
3588
  	for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3589
3590
3591
3592
  		cy_writeb(tmp, 255);
  	if (mailbox != 0) {
  		/* set window to last 512K of RAM */
  		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
c4923b4f1   Jiri Slaby   Char: cyclades, f...
3593
  		for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3594
3595
3596
  			cy_writeb(tmp, 255);
  		/* set window to beginning of RAM */
  		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
  	}
  
  	retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
  	release_firmware(fw);
  	if (retval)
  		goto err;
  
  	/* finish boot and start boards */
  	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
  	cy_writel(&cust->cpu_start, 0);
  	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
  	i = 0;
  	while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
  		msleep(100);
  	if (status != ZFIRM_ID) {
  		if (status == ZFIRM_HLT) {
  			dev_err(&pdev->dev, "you need an external power supply "
  				"for this number of ports. Firmware halted and "
  				"board reset.
  ");
  			retval = -EIO;
  			goto err;
  		}
  		dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
  				"some more time
  ", status);
  		while ((status = readl(&fid->signature)) != ZFIRM_ID &&
  				i++ < 200)
  			msleep(100);
  		if (status != ZFIRM_ID) {
  			dev_err(&pdev->dev, "Board not started in 20 seconds! "
  					"Giving up. (fid->signature = 0x%x)
  ",
  					status);
  			dev_info(&pdev->dev, "*** Warning ***: if you are "
  				"upgrading the FW, please power cycle the "
  				"system before loading the new FW to the "
  				"Cyclades-Z.
  ");
2693f485c   Jiri Slaby   tty: cyclades, co...
3636
  			if (__cyz_fpga_loaded(ctl_addr))
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
  				plx_init(pdev, irq, ctl_addr);
  
  			retval = -EIO;
  			goto err;
  		}
  		dev_dbg(&pdev->dev, "Firmware started after %d seconds.
  ",
  				i / 10);
  	}
  	pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
  
  	dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p
  ",
  			base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
  			base_addr + readl(&fid->zfwctrl_addr));
963118eef   Jiri Slaby   tty: cyclades, fi...
3652
  	nchan = readl(&pt_zfwctrl->board_ctrl.n_channel);
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3653
3654
  	dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u
  ",
963118eef   Jiri Slaby   tty: cyclades, fi...
3655
  		readl(&pt_zfwctrl->board_ctrl.fw_version), nchan);
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3656

963118eef   Jiri Slaby   tty: cyclades, fi...
3657
  	if (nchan == 0) {
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3658
3659
3660
3661
  		dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
  			"check the connection between the Z host card and the "
  			"serial expanders.
  ");
2693f485c   Jiri Slaby   tty: cyclades, co...
3662
  		if (__cyz_fpga_loaded(ctl_addr))
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
  			plx_init(pdev, irq, ctl_addr);
  
  		dev_info(&pdev->dev, "Null number of ports detected. Board "
  				"reset.
  ");
  		retval = 0;
  		goto err;
  	}
  
  	cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
  	cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
  
  	/*
  	   Early firmware failed to start looking for commands.
  	   This enables firmware interrupts for those commands.
  	 */
  	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
  			(1 << 17));
  	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
  			0x00030800UL);
963118eef   Jiri Slaby   tty: cyclades, fi...
3683
  	return nchan;
054f5b0aa   Jiri Slaby   Char: cyclades, a...
3684
3685
3686
3687
  err_rel:
  	release_firmware(fw);
  err:
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3688
  }
58936d8d9   Jiri Slaby   Char: cyclades, c...
3689
3690
  static int __devinit cy_pci_probe(struct pci_dev *pdev,
  		const struct pci_device_id *ent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3691
  {
3137553d3   Jiri Slaby   Char: cyclades, p...
3692
3693
  	void __iomem *addr0 = NULL, *addr2 = NULL;
  	char *card_name = NULL;
101b81590   Jiri Slaby   tty: cyclades, ca...
3694
  	u32 uninitialized_var(mailbox);
3137553d3   Jiri Slaby   Char: cyclades, p...
3695
3696
3697
  	unsigned int device_id, nchan = 0, card_no, i;
  	unsigned char plx_ver;
  	int retval, irq;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3698

58936d8d9   Jiri Slaby   Char: cyclades, c...
3699
3700
3701
3702
  	retval = pci_enable_device(pdev);
  	if (retval) {
  		dev_err(&pdev->dev, "cannot enable device
  ");
3137553d3   Jiri Slaby   Char: cyclades, p...
3703
  		goto err;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3704
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3705

58936d8d9   Jiri Slaby   Char: cyclades, c...
3706
  	/* read PCI configuration area */
3137553d3   Jiri Slaby   Char: cyclades, p...
3707
  	irq = pdev->irq;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3708
  	device_id = pdev->device & ~PCI_DEVICE_ID_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3709

3137553d3   Jiri Slaby   Char: cyclades, p...
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
  #if defined(__alpha__)
  	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) {	/* below 1M? */
  		dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low "
  			"addresses on Alpha systems.
  ");
  		retval = -EIO;
  		goto err_dis;
  	}
  #endif
  	if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
  		dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low "
  			"addresses
  ");
  		retval = -EIO;
  		goto err_dis;
  	}
  
  	if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
  		dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring "
  				"it...
  ");
  		pdev->resource[2].flags &= ~IORESOURCE_IO;
  	}
  
  	retval = pci_request_regions(pdev, "cyclades");
  	if (retval) {
  		dev_err(&pdev->dev, "failed to reserve resources
  ");
  		goto err_dis;
  	}
  
  	retval = -EIO;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3742
3743
  	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
  			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
3137553d3   Jiri Slaby   Char: cyclades, p...
3744
  		card_name = "Cyclom-Y";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3745

24e6fd4cd   Jiri Slaby   Char: cyclades. r...
3746
3747
  		addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
  				CyPCI_Yctl);
3137553d3   Jiri Slaby   Char: cyclades, p...
3748
3749
3750
3751
  		if (addr0 == NULL) {
  			dev_err(&pdev->dev, "can't remap ctl region
  ");
  			goto err_reg;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3752
  		}
24e6fd4cd   Jiri Slaby   Char: cyclades. r...
3753
3754
  		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
  				CyPCI_Ywin);
3137553d3   Jiri Slaby   Char: cyclades, p...
3755
3756
3757
3758
  		if (addr2 == NULL) {
  			dev_err(&pdev->dev, "can't remap base region
  ");
  			goto err_unmap;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3759
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3760

3137553d3   Jiri Slaby   Char: cyclades, p...
3761
3762
  		nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1);
  		if (nchan == 0) {
217191910   Jiri Slaby   Char: cyclades, p...
3763
3764
3765
  			dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
  					"Serial-Modules
  ");
c847d47cb   Andrew Morton   drivers/char/cycl...
3766
  			goto err_unmap;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3767
  		}
58936d8d9   Jiri Slaby   Char: cyclades, c...
3768
  	} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
3137553d3   Jiri Slaby   Char: cyclades, p...
3769
  		struct RUNTIME_9060 __iomem *ctl_addr;
217191910   Jiri Slaby   Char: cyclades, p...
3770

24e6fd4cd   Jiri Slaby   Char: cyclades. r...
3771
3772
  		ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
  				CyPCI_Zctl);
3137553d3   Jiri Slaby   Char: cyclades, p...
3773
3774
3775
3776
3777
  		if (addr0 == NULL) {
  			dev_err(&pdev->dev, "can't remap ctl region
  ");
  			goto err_reg;
  		}
58936d8d9   Jiri Slaby   Char: cyclades, c...
3778
3779
  
  		/* Disable interrupts on the PLX before resetting it */
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
3780
3781
  		cy_writew(&ctl_addr->intr_ctrl_stat,
  				readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
58936d8d9   Jiri Slaby   Char: cyclades, c...
3782

054f5b0aa   Jiri Slaby   Char: cyclades, a...
3783
  		plx_init(pdev, irq, addr0);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3784

101b81590   Jiri Slaby   tty: cyclades, ca...
3785
  		mailbox = readl(&ctl_addr->mail_box_0);
58936d8d9   Jiri Slaby   Char: cyclades, c...
3786

24e6fd4cd   Jiri Slaby   Char: cyclades. r...
3787
3788
  		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
  				mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
3137553d3   Jiri Slaby   Char: cyclades, p...
3789
3790
3791
3792
  		if (addr2 == NULL) {
  			dev_err(&pdev->dev, "can't remap base region
  ");
  			goto err_unmap;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3793
3794
3795
  		}
  
  		if (mailbox == ZE_V1) {
3137553d3   Jiri Slaby   Char: cyclades, p...
3796
  			card_name = "Cyclades-Ze";
58936d8d9   Jiri Slaby   Char: cyclades, c...
3797
  		} else {
3137553d3   Jiri Slaby   Char: cyclades, p...
3798
  			card_name = "Cyclades-8Zo";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3799
  #ifdef CY_PCI_DEBUG
3137553d3   Jiri Slaby   Char: cyclades, p...
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
  			if (mailbox == ZO_V1) {
  				cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
  				dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA "
  					"id %lx, ver %lx
  ", (ulong)(0xff &
  					readl(&((struct CUSTOM_REG *)addr2)->
  						fpga_id)), (ulong)(0xff &
  					readl(&((struct CUSTOM_REG *)addr2)->
  						fpga_version)));
  				cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
  			} else {
  				dev_info(&pdev->dev, "Cyclades-Z/PCI: New "
  					"Cyclades-Z board.  FPGA not loaded
  ");
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3815
  #endif
3137553d3   Jiri Slaby   Char: cyclades, p...
3816
3817
3818
3819
3820
3821
  			/* The following clears the firmware id word.  This
  			   ensures that the driver will not attempt to talk to
  			   the board until it has been properly initialized.
  			 */
  			if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
  				cy_writel(addr2 + ID_ADDRESS, 0L);
58936d8d9   Jiri Slaby   Char: cyclades, c...
3822
  		}
ace08c3c4   Jiri Slaby   tty:cyclades, loa...
3823
3824
  
  		retval = cyz_load_fw(pdev, addr2, addr0, irq);
963118eef   Jiri Slaby   tty: cyclades, fi...
3825
  		if (retval <= 0)
ace08c3c4   Jiri Slaby   tty:cyclades, loa...
3826
  			goto err_unmap;
963118eef   Jiri Slaby   tty: cyclades, fi...
3827
  		nchan = retval;
3137553d3   Jiri Slaby   Char: cyclades, p...
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
  	}
  
  	if ((cy_next_channel + nchan) > NR_PORTS) {
  		dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
  			"channels are available. Change NR_PORTS in "
  			"cyclades.c and recompile kernel.
  ");
  		goto err_unmap;
  	}
  	/* fill the next cy_card structure available */
  	for (card_no = 0; card_no < NR_CARDS; card_no++) {
  		if (cy_card[card_no].base_addr == NULL)
  			break;
  	}
  	if (card_no == NR_CARDS) {	/* no more cy_cards available */
  		dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
  			"more cards can be used. Change NR_CARDS in "
  			"cyclades.c and recompile kernel.
  ");
  		goto err_unmap;
  	}
  
  	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
  			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
  		/* allocate IRQ */
  		retval = request_irq(irq, cyy_interrupt,
  				IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
  		if (retval) {
  			dev_err(&pdev->dev, "could not allocate IRQ
  ");
  			goto err_unmap;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3859
  		}
963118eef   Jiri Slaby   tty: cyclades, fi...
3860
  		cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
3137553d3   Jiri Slaby   Char: cyclades, p...
3861
  	} else {
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3862
3863
3864
3865
  		struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
  		struct ZFW_CTRL __iomem *zfw_ctrl;
  
  		zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
101b81590   Jiri Slaby   tty: cyclades, ca...
3866
3867
  		cy_card[card_no].hw_ver = mailbox;
  		cy_card[card_no].num_chips = (unsigned int)-1;
f0eefdc30   Jiri Slaby   cyclades: avoid a...
3868
  		cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3869
  #ifdef CONFIG_CYZ_INTR
58936d8d9   Jiri Slaby   Char: cyclades, c...
3870
  		/* allocate IRQ only if board has an IRQ */
3137553d3   Jiri Slaby   Char: cyclades, p...
3871
3872
  		if (irq != 0 && irq != 255) {
  			retval = request_irq(irq, cyz_interrupt,
58936d8d9   Jiri Slaby   Char: cyclades, c...
3873
  					IRQF_SHARED, "Cyclades-Z",
3137553d3   Jiri Slaby   Char: cyclades, p...
3874
  					&cy_card[card_no]);
58936d8d9   Jiri Slaby   Char: cyclades, c...
3875
  			if (retval) {
217191910   Jiri Slaby   Char: cyclades, p...
3876
3877
  				dev_err(&pdev->dev, "could not allocate IRQ
  ");
3137553d3   Jiri Slaby   Char: cyclades, p...
3878
  				goto err_unmap;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3879
  			}
58936d8d9   Jiri Slaby   Char: cyclades, c...
3880
  		}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3881
  #endif				/* CONFIG_CYZ_INTR */
3137553d3   Jiri Slaby   Char: cyclades, p...
3882
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3883

3137553d3   Jiri Slaby   Char: cyclades, p...
3884
3885
  	/* set cy_card */
  	cy_card[card_no].base_addr = addr2;
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
3886
  	cy_card[card_no].ctl_addr.p9050 = addr0;
3137553d3   Jiri Slaby   Char: cyclades, p...
3887
3888
3889
  	cy_card[card_no].irq = irq;
  	cy_card[card_no].bus_index = 1;
  	cy_card[card_no].first_line = cy_next_channel;
963118eef   Jiri Slaby   tty: cyclades, fi...
3890
  	cy_card[card_no].nports = nchan;
3137553d3   Jiri Slaby   Char: cyclades, p...
3891
3892
3893
  	retval = cy_init_card(&cy_card[card_no]);
  	if (retval)
  		goto err_null;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3894

3137553d3   Jiri Slaby   Char: cyclades, p...
3895
  	pci_set_drvdata(pdev, &cy_card[card_no]);
58936d8d9   Jiri Slaby   Char: cyclades, c...
3896

3137553d3   Jiri Slaby   Char: cyclades, p...
3897
3898
3899
3900
3901
3902
  	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
  			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
  		/* enable interrupts in the PCI interface */
  		plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
  		switch (plx_ver) {
  		case PLX_9050:
3137553d3   Jiri Slaby   Char: cyclades, p...
3903
3904
3905
3906
3907
3908
  			cy_writeb(addr0 + 0x4c, 0x43);
  			break;
  
  		case PLX_9060:
  		case PLX_9080:
  		default:	/* Old boards, use PLX_9060 */
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
3909
3910
3911
3912
3913
  		{
  			struct RUNTIME_9060 __iomem *ctl_addr = addr0;
  			plx_init(pdev, irq, ctl_addr);
  			cy_writew(&ctl_addr->intr_ctrl_stat,
  				readw(&ctl_addr->intr_ctrl_stat) | 0x0900);
3137553d3   Jiri Slaby   Char: cyclades, p...
3914
3915
  			break;
  		}
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
3916
  		}
58936d8d9   Jiri Slaby   Char: cyclades, c...
3917
  	}
3137553d3   Jiri Slaby   Char: cyclades, p...
3918
3919
3920
3921
3922
3923
  	dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
  		"port %d.
  ", card_name, card_no + 1, nchan, cy_next_channel);
  	for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
  		tty_register_device(cy_serial_driver, i, &pdev->dev);
  	cy_next_channel += nchan;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3924
  	return 0;
3137553d3   Jiri Slaby   Char: cyclades, p...
3925
3926
3927
3928
  err_null:
  	cy_card[card_no].base_addr = NULL;
  	free_irq(irq, &cy_card[card_no]);
  err_unmap:
24e6fd4cd   Jiri Slaby   Char: cyclades. r...
3929
  	iounmap(addr0);
3137553d3   Jiri Slaby   Char: cyclades, p...
3930
  	if (addr2)
24e6fd4cd   Jiri Slaby   Char: cyclades. r...
3931
  		iounmap(addr2);
3137553d3   Jiri Slaby   Char: cyclades, p...
3932
3933
3934
3935
3936
3937
  err_reg:
  	pci_release_regions(pdev);
  err_dis:
  	pci_disable_device(pdev);
  err:
  	return retval;
58936d8d9   Jiri Slaby   Char: cyclades, c...
3938
  }
58936d8d9   Jiri Slaby   Char: cyclades, c...
3939

6747cd93f   Jiri Slaby   Char: cyclades, s...
3940
  static void __devexit cy_pci_remove(struct pci_dev *pdev)
58936d8d9   Jiri Slaby   Char: cyclades, c...
3941
  {
38d090932   Jiri Slaby   Char: cyclades, u...
3942
  	struct cyclades_card *cinfo = pci_get_drvdata(pdev);
f3851e73e   Jiri Slaby   Char: cyclades, i...
3943
  	unsigned int i;
38d090932   Jiri Slaby   Char: cyclades, u...
3944

85c93fa95   Jiri Slaby   Char: cyclades, c...
3945
  	/* non-Z with old PLX */
2693f485c   Jiri Slaby   tty: cyclades, co...
3946
  	if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
c2ad4c751   Jiri Slaby   Char: cyclades, u...
3947
  			PLX_9050)
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
3948
  		cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
85c93fa95   Jiri Slaby   Char: cyclades, c...
3949
3950
  	else
  #ifndef CONFIG_CYZ_INTR
2693f485c   Jiri Slaby   tty: cyclades, co...
3951
  		if (!cy_is_Z(cinfo))
85c93fa95   Jiri Slaby   Char: cyclades, c...
3952
  #endif
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
3953
3954
3955
  		cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat,
  			readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) &
  			~0x0900);
85c93fa95   Jiri Slaby   Char: cyclades, c...
3956

24e6fd4cd   Jiri Slaby   Char: cyclades. r...
3957
  	iounmap(cinfo->base_addr);
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
3958
3959
  	if (cinfo->ctl_addr.p9050)
  		iounmap(cinfo->ctl_addr.p9050);
38d090932   Jiri Slaby   Char: cyclades, u...
3960
3961
  	if (cinfo->irq
  #ifndef CONFIG_CYZ_INTR
2693f485c   Jiri Slaby   tty: cyclades, co...
3962
  		&& !cy_is_Z(cinfo)
38d090932   Jiri Slaby   Char: cyclades, u...
3963
3964
3965
3966
3967
3968
  #endif /* CONFIG_CYZ_INTR */
  		)
  		free_irq(cinfo->irq, cinfo);
  	pci_release_regions(pdev);
  
  	cinfo->base_addr = NULL;
6ad1ccc19   Jiri Slaby   Char: cyclades, t...
3969
3970
3971
  	for (i = cinfo->first_line; i < cinfo->first_line +
  			cinfo->nports; i++)
  		tty_unregister_device(cy_serial_driver, i);
dd025c0c7   Jiri Slaby   Char: cyclades, d...
3972
3973
  	cinfo->nports = 0;
  	kfree(cinfo->ports);
38d090932   Jiri Slaby   Char: cyclades, u...
3974
  }
6747cd93f   Jiri Slaby   Char: cyclades, s...
3975
3976
3977
3978
3979
3980
3981
  static struct pci_driver cy_pci_driver = {
  	.name = "cyclades",
  	.id_table = cy_pci_dev_id,
  	.probe = cy_pci_probe,
  	.remove = __devexit_p(cy_pci_remove)
  };
  #endif
444697d61   Alexey Dobriyan   proc tty: switch ...
3982
  static int cyclades_proc_show(struct seq_file *m, void *v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3983
  {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3984
  	struct cyclades_port *info;
dd025c0c7   Jiri Slaby   Char: cyclades, d...
3985
  	unsigned int i, j;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3986
  	__u32 cur_jifs = jiffies;
444697d61   Alexey Dobriyan   proc tty: switch ...
3987
  	seq_puts(m, "Dev TimeOpen   BytesOut  IdleOut    BytesIn   "
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3988
3989
  			"IdleIn  Overruns  Ldisc
  ");
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
3990
  	/* Output one line for each known port */
dd025c0c7   Jiri Slaby   Char: cyclades, d...
3991
3992
3993
  	for (i = 0; i < NR_CARDS; i++)
  		for (j = 0; j < cy_card[i].nports; j++) {
  			info = &cy_card[i].ports[j];
d13549f80   Jiri Slaby   cyclades: add tty...
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
  			if (info->port.count) {
  				/* XXX is the ldisc num worth this? */
  				struct tty_struct *tty;
  				struct tty_ldisc *ld;
  				int num = 0;
  				tty = tty_port_tty_get(&info->port);
  				if (tty) {
  					ld = tty_ldisc_ref(tty);
  					if (ld) {
  						num = ld->ops->num;
  						tty_ldisc_deref(ld);
  					}
  					tty_kref_put(tty);
  				}
444697d61   Alexey Dobriyan   proc tty: switch ...
4008
  				seq_printf(m, "%3d %8lu %10lu %8lu "
d13549f80   Jiri Slaby   cyclades: add tty...
4009
4010
  					"%10lu %8lu %9lu %6d
  ", info->line,
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4011
4012
4013
4014
4015
4016
  					(cur_jifs - info->idle_stats.in_use) /
  					HZ, info->idle_stats.xmit_bytes,
  					(cur_jifs - info->idle_stats.xmit_idle)/
  					HZ, info->idle_stats.recv_bytes,
  					(cur_jifs - info->idle_stats.recv_idle)/
  					HZ, info->idle_stats.overruns,
d13549f80   Jiri Slaby   cyclades: add tty...
4017
4018
  					num);
  			} else
444697d61   Alexey Dobriyan   proc tty: switch ...
4019
  				seq_printf(m, "%3d %8lu %10lu %8lu "
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4020
4021
4022
  					"%10lu %8lu %9lu %6ld
  ",
  					info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4023
  		}
444697d61   Alexey Dobriyan   proc tty: switch ...
4024
4025
4026
4027
4028
4029
  	return 0;
  }
  
  static int cyclades_proc_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, cyclades_proc_show, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4030
  }
444697d61   Alexey Dobriyan   proc tty: switch ...
4031
4032
4033
4034
4035
4036
4037
  static const struct file_operations cyclades_proc_fops = {
  	.owner		= THIS_MODULE,
  	.open		= cyclades_proc_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
  /* The serial driver boot-time initialization code!
      Hardware I/O ports are mapped to character special devices on a
      first found, first allocated manner.  That is, this code searches
      for Cyclom cards in the system.  As each is found, it is probed
      to discover how many chips (and thus how many ports) are present.
      These ports are mapped to the tty ports 32 and upward in monotonic
      fashion.  If an 8-port card is replaced with a 16-port card, the
      port mapping on a following card will shift.
  
      This approach is different from what is used in the other serial
      device driver because the Cyclom is more properly a multiplexer,
      not just an aggregation of serial ports on one card.
  
      If there are more cards with more ports than have been
      statically allocated above, a warning is printed and the
      extra ports are ignored.
   */
b68e31d0e   Jeff Dike   [PATCH] const str...
4055
  static const struct tty_operations cy_ops = {
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
  	.open = cy_open,
  	.close = cy_close,
  	.write = cy_write,
  	.put_char = cy_put_char,
  	.flush_chars = cy_flush_chars,
  	.write_room = cy_write_room,
  	.chars_in_buffer = cy_chars_in_buffer,
  	.flush_buffer = cy_flush_buffer,
  	.ioctl = cy_ioctl,
  	.throttle = cy_throttle,
  	.unthrottle = cy_unthrottle,
  	.set_termios = cy_set_termios,
  	.stop = cy_stop,
  	.start = cy_start,
  	.hangup = cy_hangup,
  	.break_ctl = cy_break,
  	.wait_until_sent = cy_wait_until_sent,
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4073
4074
  	.tiocmget = cy_tiocmget,
  	.tiocmset = cy_tiocmset,
0587102cf   Alan Cox   tty: icount chang...
4075
  	.get_icount = cy_get_icount,
444697d61   Alexey Dobriyan   proc tty: switch ...
4076
  	.proc_fops = &cyclades_proc_fops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4077
  };
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4078
  static int __init cy_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4079
  {
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4080
  	unsigned int nboards;
9dacf3b2f   Jiri Slaby   Char: cyclades, c...
4081
  	int retval = -ENOMEM;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4082
4083
4084
  
  	cy_serial_driver = alloc_tty_driver(NR_PORTS);
  	if (!cy_serial_driver)
9dacf3b2f   Jiri Slaby   Char: cyclades, c...
4085
  		goto err;
217191910   Jiri Slaby   Char: cyclades, p...
4086

64a14b51b   Michal Marek   cyclades: Drop __...
4087
4088
  	printk(KERN_INFO "Cyclades driver " CY_VERSION "
  ");
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
  
  	/* Initialize the tty_driver structure */
  
  	cy_serial_driver->owner = THIS_MODULE;
  	cy_serial_driver->driver_name = "cyclades";
  	cy_serial_driver->name = "ttyC";
  	cy_serial_driver->major = CYCLADES_MAJOR;
  	cy_serial_driver->minor_start = 0;
  	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
  	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
  	cy_serial_driver->init_termios = tty_std_termios;
  	cy_serial_driver->init_termios.c_cflag =
  	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
6ad1ccc19   Jiri Slaby   Char: cyclades, t...
4102
  	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4103
  	tty_set_operations(cy_serial_driver, &cy_ops);
9dacf3b2f   Jiri Slaby   Char: cyclades, c...
4104
4105
4106
4107
4108
4109
  	retval = tty_register_driver(cy_serial_driver);
  	if (retval) {
  		printk(KERN_ERR "Couldn't register Cyclades serial driver
  ");
  		goto err_frtty;
  	}
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4110

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4111
4112
4113
4114
4115
4116
4117
4118
  	/* the code below is responsible to find the boards. Each different
  	   type of board has its own detection routine. If a board is found,
  	   the next cy_card structure available is set by the detection
  	   routine. These functions are responsible for checking the
  	   availability of cy_card and cy_port data structures and updating
  	   the cy_next_channel. */
  
  	/* look for isa boards */
14a55a678   Jiri Slaby   Char: cyclades, r...
4119
  	nboards = cy_detect_isa();
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4120

6747cd93f   Jiri Slaby   Char: cyclades, s...
4121
  #ifdef CONFIG_PCI
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4122
  	/* look for pci boards */
6747cd93f   Jiri Slaby   Char: cyclades, s...
4123
  	retval = pci_register_driver(&cy_pci_driver);
d941ea7d4   Jesper Juhl   Cyclades: Avoid l...
4124
4125
4126
4127
  	if (retval && !nboards) {
  		tty_unregister_driver(cy_serial_driver);
  		goto err_frtty;
  	}
6747cd93f   Jiri Slaby   Char: cyclades, s...
4128
  #endif
9dacf3b2f   Jiri Slaby   Char: cyclades, c...
4129
4130
  
  	return 0;
9dacf3b2f   Jiri Slaby   Char: cyclades, c...
4131
4132
4133
4134
  err_frtty:
  	put_tty_driver(cy_serial_driver);
  err:
  	return retval;
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4135
  }				/* cy_init */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4136

02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4137
  static void __exit cy_cleanup_module(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4138
  {
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4139
  	struct cyclades_card *card;
65f76a82e   Jiri Slaby   Char: cyclades, f...
4140
  	unsigned int i, e1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4141
4142
  
  #ifndef CONFIG_CYZ_INTR
b70509066   Jiri Slaby   Char: cyclades, t...
4143
  	del_timer_sync(&cyz_timerlist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4144
  #endif /* CONFIG_CYZ_INTR */
15ed6cc0b   Alan Cox   cyclades: coding ...
4145
4146
  	e1 = tty_unregister_driver(cy_serial_driver);
  	if (e1)
217191910   Jiri Slaby   Char: cyclades, p...
4147
4148
4149
  		printk(KERN_ERR "failed to unregister Cyclades serial "
  				"driver(%d)
  ", e1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4150

6747cd93f   Jiri Slaby   Char: cyclades, s...
4151
4152
4153
  #ifdef CONFIG_PCI
  	pci_unregister_driver(&cy_pci_driver);
  #endif
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4154
  	for (i = 0; i < NR_CARDS; i++) {
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4155
4156
  		card = &cy_card[i];
  		if (card->base_addr) {
85c93fa95   Jiri Slaby   Char: cyclades, c...
4157
  			/* clear interrupt */
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4158
4159
  			cy_writeb(card->base_addr + Cy_ClrIntr, 0);
  			iounmap(card->base_addr);
97e87f8eb   Jiri Slaby   tty: cyclades, pl...
4160
4161
  			if (card->ctl_addr.p9050)
  				iounmap(card->ctl_addr.p9050);
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4162
  			if (card->irq
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4163
  #ifndef CONFIG_CYZ_INTR
2693f485c   Jiri Slaby   tty: cyclades, co...
4164
  				&& !cy_is_Z(card)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4165
  #endif /* CONFIG_CYZ_INTR */
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4166
  				)
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4167
  				free_irq(card->irq, card);
65f76a82e   Jiri Slaby   Char: cyclades, f...
4168
  			for (e1 = card->first_line; e1 < card->first_line +
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4169
  					card->nports; e1++)
6ad1ccc19   Jiri Slaby   Char: cyclades, t...
4170
  				tty_unregister_device(cy_serial_driver, e1);
dd025c0c7   Jiri Slaby   Char: cyclades, d...
4171
  			kfree(card->ports);
02f1175c8   Jiri Slaby   [PATCH] Char: cyc...
4172
4173
  		}
  	}
f2462bfe5   Jiri Slaby   Char: cyclades, f...
4174
4175
  
  	put_tty_driver(cy_serial_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4176
4177
4178
4179
4180
4181
  } /* cy_cleanup_module */
  
  module_init(cy_init);
  module_exit(cy_cleanup_module);
  
  MODULE_LICENSE("GPL");
c8e1693a4   Jiri Slaby   Char: cyclades, c...
4182
  MODULE_VERSION(CY_VERSION);
9f56fad74   Scott James Remnant   cyclades: Auto-lo...
4183
  MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
e6c4ef984   Ben Hutchings   tty: declare MODU...
4184
  MODULE_FIRMWARE("cyzfirm.bin");