Blame view
drivers/tty/cyclades.c
111 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
#undef BLOCKMOVE #define Z_WAKE #undef Z_EXT_CHARS_IN_BUFFER |
1da177e4c Linux-2.6.12-rc2 |
4 5 |
/* |
1da177e4c 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 Linux-2.6.12-rc2 |
11 |
* |
ebdb51359 cyclades: overall... |
12 |
* Copyright (C) 2007-2009 Jiri Slaby <jirislaby@gmail.com> |
1da177e4c 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 Char: cyclades, c... |
18 |
* Converted to pci probing and cleaned up by Jiri Slaby. |
1da177e4c Linux-2.6.12-rc2 |
19 |
* |
1da177e4c Linux-2.6.12-rc2 |
20 |
*/ |
ebdb51359 cyclades: overall... |
21 |
#define CY_VERSION "2.6" |
096dcfce3 [PATCH] Char: cyc... |
22 |
|
1da177e4c 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 [PATCH] Char: cyc... |
26 |
#define NR_CARDS 4 |
1da177e4c 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 [PATCH] Char: cyc... |
32 |
#define NR_PORTS 256 |
1da177e4c Linux-2.6.12-rc2 |
33 |
|
1da177e4c 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 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 Linux-2.6.12-rc2 |
49 |
/* |
15ed6cc0b cyclades: coding ... |
50 |
* Include section |
1da177e4c Linux-2.6.12-rc2 |
51 |
*/ |
1da177e4c 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 [PATCH] TTY layer... |
59 |
#include <linux/tty_flip.h> |
1da177e4c 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 Char: cyclades, a... |
72 |
#include <linux/firmware.h> |
9f56fad74 cyclades: Auto-lo... |
73 |
#include <linux/device.h> |
5a0e3ad6a include cleanup: ... |
74 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
75 |
|
15ed6cc0b cyclades: coding ... |
76 |
#include <linux/io.h> |
15ed6cc0b cyclades: coding ... |
77 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
78 |
|
1da177e4c 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 proc tty: switch ... |
84 |
#include <linux/seq_file.h> |
1da177e4c Linux-2.6.12-rc2 |
85 |
|
02f1175c8 [PATCH] Char: cyc... |
86 |
static void cy_send_xchar(struct tty_struct *tty, char ch); |
1da177e4c Linux-2.6.12-rc2 |
87 |
|
1da177e4c Linux-2.6.12-rc2 |
88 89 90 |
#ifndef SERIAL_XMIT_SIZE #define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) #endif |
1da177e4c Linux-2.6.12-rc2 |
91 92 |
#define STD_COM_FLAGS (0) |
054f5b0aa Char: cyclades, a... |
93 94 95 96 |
/* firmware stuff */ #define ZL_MAX_BLOCKS 16 #define DRIVER_VERSION 0x02010203 #define RAM_SIZE 0x80000 |
054f5b0aa 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 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 Linux-2.6.12-rc2 |
135 136 137 |
*/ static unsigned int cy_isa_addresses[] = { |
02f1175c8 [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 Linux-2.6.12-rc2 |
147 |
}; |
02f1175c8 [PATCH] Char: cyc... |
148 |
|
fe971071a [PATCH] drivers/c... |
149 |
#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) |
1da177e4c Linux-2.6.12-rc2 |
150 |
|
3046d50ea Char: cyclades, s... |
151 152 |
static long maddr[NR_CARDS]; static int irq[NR_CARDS]; |
1da177e4c Linux-2.6.12-rc2 |
153 154 155 |
module_param_array(maddr, long, NULL, 0); module_param_array(irq, int, NULL, 0); |
1da177e4c Linux-2.6.12-rc2 |
156 |
|
02f1175c8 [PATCH] Char: cyc... |
157 |
#endif /* CONFIG_ISA */ |
1da177e4c 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 [PATCH] Char: cyc... |
163 |
static int cy_next_channel; /* next minor available */ |
1da177e4c Linux-2.6.12-rc2 |
164 165 |
/* |
1da177e4c 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 cyclades: use tty... |
168 |
* are accessed via settings in info->port.flags. |
1da177e4c 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 cyclades: overall... |
174 |
static const int baud_table[] = { |
02f1175c8 [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 cyclades: overall... |
179 |
static const char baud_co_25[] = { /* 25 MHz clock option table */ |
02f1175c8 [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 cyclades: overall... |
185 |
static const char baud_bpr_25[] = { /* 25 MHz baud rate period table */ |
02f1175c8 [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 cyclades: overall... |
189 |
static const char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */ |
02f1175c8 [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 cyclades: overall... |
196 |
static const char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */ |
02f1175c8 [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 cyclades: overall... |
201 |
static const char baud_cor3[] = { /* receive threshold */ |
02f1175c8 [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 Linux-2.6.12-rc2 |
206 207 208 |
/* * The Cyclades driver implements HW flow control as any serial driver. |
15ed6cc0b 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 Linux-2.6.12-rc2 |
215 216 |
* cables. */ |
ebdb51359 cyclades: overall... |
217 |
static const char rflow_thr[] = { /* rflow threshold */ |
02f1175c8 [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 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 cyclades: avoid a... |
226 |
static const unsigned int cy_chip_offset[] = { 0x0000, |
02f1175c8 [PATCH] Char: cyc... |
227 228 229 230 231 232 233 234 |
0x0400, 0x0800, 0x0C00, 0x0200, 0x0600, 0x0A00, 0x0E00 }; |
1da177e4c Linux-2.6.12-rc2 |
235 236 |
/* PCI related definitions */ |
1da177e4c Linux-2.6.12-rc2 |
237 |
#ifdef CONFIG_PCI |
ebdb51359 cyclades: overall... |
238 |
static const struct pci_device_id cy_pci_dev_id[] = { |
15ed6cc0b 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 [PATCH] Char: cyc... |
255 |
{ } /* end of table */ |
02f1175c8 [PATCH] Char: cyc... |
256 |
}; |
893de2dff [PATCH] Char: cyc... |
257 |
MODULE_DEVICE_TABLE(pci, cy_pci_dev_id); |
1da177e4c Linux-2.6.12-rc2 |
258 259 260 |
#endif static void cy_start(struct tty_struct *); |
d13549f80 cyclades: add tty... |
261 |
static void cy_set_line_char(struct cyclades_port *, struct tty_struct *); |
1a86b5e34 cyclades: remove ... |
262 |
static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); |
1da177e4c Linux-2.6.12-rc2 |
263 264 |
#ifdef CONFIG_ISA static unsigned detect_isa_irq(void __iomem *); |
02f1175c8 [PATCH] Char: cyc... |
265 |
#endif /* CONFIG_ISA */ |
1da177e4c Linux-2.6.12-rc2 |
266 |
|
1da177e4c 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 [PATCH] timer ini... |
272 |
static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); |
1da177e4c Linux-2.6.12-rc2 |
273 |
|
02f1175c8 [PATCH] Char: cyc... |
274 |
#else /* CONFIG_CYZ_INTR */ |
1da177e4c 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 [PATCH] Char: cyc... |
277 |
#endif /* CONFIG_CYZ_INTR */ |
1da177e4c Linux-2.6.12-rc2 |
278 |
|
3aeea5b92 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 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 [PATCH] Char: cyc... |
314 |
static inline int serial_paranoia_check(struct cyclades_port *info, |
ebdb51359 cyclades: overall... |
315 |
const char *name, const char *routine) |
1da177e4c Linux-2.6.12-rc2 |
316 317 |
{ #ifdef SERIAL_PARANOIA_CHECK |
02f1175c8 [PATCH] Char: cyc... |
318 |
if (!info) { |
217191910 Char: cyclades, p... |
319 320 321 |
printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) " "in %s ", name, routine); |
02f1175c8 [PATCH] Char: cyc... |
322 323 |
return 1; } |
02f1175c8 [PATCH] Char: cyc... |
324 |
if (info->magic != CYCLADES_MAGIC) { |
217191910 Char: cyclades, p... |
325 326 327 |
printk(KERN_WARNING "cyc Warning: bad magic number for serial " "struct (%s) in %s ", name, routine); |
02f1175c8 [PATCH] Char: cyc... |
328 329 |
return 1; } |
1da177e4c Linux-2.6.12-rc2 |
330 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
331 |
return 0; |
ebdb51359 cyclades: overall... |
332 |
} |
1da177e4c Linux-2.6.12-rc2 |
333 |
|
1da177e4c 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 cyclades: introdu... |
344 |
static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index) |
1da177e4c Linux-2.6.12-rc2 |
345 |
{ |
3aeea5b92 cyclades: introdu... |
346 |
void __iomem *ccr = base_addr + (CyCCR << index); |
ad39c3004 Char: cyclades, r... |
347 |
unsigned int i; |
1da177e4c Linux-2.6.12-rc2 |
348 |
|
02f1175c8 [PATCH] Char: cyc... |
349 350 |
/* Check to see that the previous command has completed */ for (i = 0; i < 100; i++) { |
3aeea5b92 cyclades: introdu... |
351 |
if (readb(ccr) == 0) |
02f1175c8 [PATCH] Char: cyc... |
352 |
break; |
02f1175c8 [PATCH] Char: cyc... |
353 |
udelay(10L); |
1da177e4c Linux-2.6.12-rc2 |
354 |
} |
02f1175c8 [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 [PATCH] Char: cyc... |
358 |
return -1; |
1da177e4c Linux-2.6.12-rc2 |
359 |
|
02f1175c8 [PATCH] Char: cyc... |
360 |
/* Issue the new command */ |
3aeea5b92 cyclades: introdu... |
361 |
cy_writeb(ccr, cmd); |
1da177e4c Linux-2.6.12-rc2 |
362 |
|
096dcfce3 [PATCH] Char: cyc... |
363 |
return 0; |
3aeea5b92 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 Linux-2.6.12-rc2 |
371 372 373 |
#ifdef CONFIG_ISA /* ISA interrupt detection code */ |
15ed6cc0b cyclades: coding ... |
374 |
static unsigned detect_isa_irq(void __iomem *address) |
1da177e4c Linux-2.6.12-rc2 |
375 |
{ |
02f1175c8 [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 cyclades: sleep i... |
390 |
msleep(5); |
02f1175c8 [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 cyclades: introdu... |
395 |
__cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index); |
02f1175c8 [PATCH] Char: cyc... |
396 397 398 |
cy_writeb(address + (CyCAR << index), 0); cy_writeb(address + (CySRER << index), |
db05c3b1d Char: cyclades, c... |
399 |
readb(address + (CySRER << index)) | CyTxRdy); |
02f1175c8 [PATCH] Char: cyc... |
400 401 402 |
local_irq_restore(flags); /* Wait ... */ |
f6e208c11 cyclades: sleep i... |
403 |
msleep(5); |
02f1175c8 [PATCH] Char: cyc... |
404 405 406 407 408 |
/* Check which interrupt is in use */ irq = probe_irq_off(irqs); /* Clean up */ |
db05c3b1d Char: cyclades, c... |
409 410 |
save_xir = (u_char) readb(address + (CyTIR << index)); save_car = readb(address + (CyCAR << index)); |
02f1175c8 [PATCH] Char: cyc... |
411 412 |
cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); cy_writeb(address + (CySRER << index), |
db05c3b1d Char: cyclades, c... |
413 |
readb(address + (CySRER << index)) & ~CyTxRdy); |
02f1175c8 [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 Linux-2.6.12-rc2 |
420 |
} |
02f1175c8 [PATCH] Char: cyc... |
421 |
#endif /* CONFIG_ISA */ |
1da177e4c Linux-2.6.12-rc2 |
422 |
|
ce97a0976 Char: cyclades, m... |
423 424 |
static void cyy_chip_rx(struct cyclades_card *cinfo, int chip, void __iomem *base_addr) |
e941027f5 [PATCH] Char: cyc... |
425 426 427 |
{ struct cyclades_port *info; struct tty_struct *tty; |
65f76a82e Char: cyclades, f... |
428 |
int len, index = cinfo->bus_index; |
3aeea5b92 cyclades: introdu... |
429 |
u8 ivr, save_xir, channel, save_car, data, char_count; |
e941027f5 [PATCH] Char: cyc... |
430 |
|
e941027f5 [PATCH] Char: cyc... |
431 |
#ifdef CY_DEBUG_INTERRUPTS |
ce97a0976 Char: cyclades, m... |
432 433 |
printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d ", chip); |
e941027f5 [PATCH] Char: cyc... |
434 |
#endif |
ce97a0976 Char: cyclades, m... |
435 |
/* determine the channel & change to that context */ |
65f76a82e Char: cyclades, f... |
436 437 |
save_xir = readb(base_addr + (CyRIR << index)); channel = save_xir & CyIRChannel; |
ce97a0976 Char: cyclades, m... |
438 |
info = &cinfo->ports[channel + chip * 4]; |
3aeea5b92 cyclades: introdu... |
439 440 441 |
save_car = cyy_readb(info, CyCAR); cyy_writeb(info, CyCAR, save_xir); ivr = cyy_readb(info, CyRIVR) & CyIVRMask; |
ce97a0976 Char: cyclades, m... |
442 |
|
d13549f80 cyclades: add tty... |
443 |
tty = tty_port_tty_get(&info->port); |
ce97a0976 Char: cyclades, m... |
444 |
/* if there is nowhere to put the data, discard it */ |
d13549f80 cyclades: add tty... |
445 |
if (tty == NULL) { |
3aeea5b92 cyclades: introdu... |
446 447 |
if (ivr == CyIVRRxEx) { /* exception */ data = cyy_readb(info, CyRDSR); |
ce97a0976 Char: cyclades, m... |
448 |
} else { /* normal character reception */ |
3aeea5b92 cyclades: introdu... |
449 |
char_count = cyy_readb(info, CyRDCR); |
ce97a0976 Char: cyclades, m... |
450 |
while (char_count--) |
3aeea5b92 cyclades: introdu... |
451 |
data = cyy_readb(info, CyRDSR); |
ce97a0976 Char: cyclades, m... |
452 453 454 455 |
} goto end; } /* there is an open port for this data */ |
3aeea5b92 cyclades: introdu... |
456 457 |
if (ivr == CyIVRRxEx) { /* exception */ data = cyy_readb(info, CyRDSR); |
ce97a0976 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 cyclades: add tty... |
471 |
tty_kref_put(tty); |
ce97a0976 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 cyclades: introdu... |
478 479 |
cyy_readb(info, CyRDSR), TTY_BREAK); |
ce97a0976 Char: cyclades, m... |
480 |
info->icount.rx++; |
77451e53e cyclades: use tty... |
481 |
if (info->port.flags & ASYNC_SAK) |
ce97a0976 Char: cyclades, m... |
482 483 |
do_SAK(tty); } else if (data & CyFRAME) { |
15ed6cc0b cyclades: coding ... |
484 |
tty_insert_flip_char(tty, |
3aeea5b92 cyclades: introdu... |
485 486 |
cyy_readb(info, CyRDSR), TTY_FRAME); |
ce97a0976 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 cyclades: introdu... |
492 493 |
cyy_readb(info, CyRDSR), TTY_PARITY); |
ce97a0976 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 cyclades: introdu... |
505 506 |
cyy_readb(info, CyRDSR), TTY_FRAME); |
02f1175c8 [PATCH] Char: cyc... |
507 |
info->icount.rx++; |
02f1175c8 [PATCH] Char: cyc... |
508 |
info->idle_stats.overruns++; |
ce97a0976 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 [PATCH] Char: cyc... |
517 |
} |
ce97a0976 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 cyclades: introdu... |
530 |
char_count = cyy_readb(info, CyRDCR); |
e941027f5 [PATCH] Char: cyc... |
531 532 |
#ifdef CY_ENABLE_MONITORING |
ce97a0976 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 [PATCH] Char: cyc... |
538 |
#endif |
ce97a0976 Char: cyclades, m... |
539 540 |
len = tty_buffer_request_room(tty, char_count); while (len--) { |
3aeea5b92 cyclades: introdu... |
541 |
data = cyy_readb(info, CyRDSR); |
ce97a0976 Char: cyclades, m... |
542 543 544 |
tty_insert_flip_char(tty, data, TTY_NORMAL); info->idle_stats.recv_bytes++; info->icount.rx++; |
e941027f5 [PATCH] Char: cyc... |
545 |
#ifdef CY_16Y_HACK |
ce97a0976 Char: cyclades, m... |
546 |
udelay(10L); |
e941027f5 [PATCH] Char: cyc... |
547 |
#endif |
e941027f5 [PATCH] Char: cyc... |
548 |
} |
ce97a0976 Char: cyclades, m... |
549 |
info->idle_stats.recv_idle = jiffies; |
e941027f5 [PATCH] Char: cyc... |
550 |
} |
ce97a0976 Char: cyclades, m... |
551 |
tty_schedule_flip(tty); |
d13549f80 cyclades: add tty... |
552 |
tty_kref_put(tty); |
ce97a0976 Char: cyclades, m... |
553 554 |
end: /* end of service */ |
3aeea5b92 cyclades: introdu... |
555 556 |
cyy_writeb(info, CyRIR, save_xir & 0x3f); cyy_writeb(info, CyCAR, save_car); |
ce97a0976 Char: cyclades, m... |
557 |
} |
e941027f5 [PATCH] Char: cyc... |
558 |
|
65f76a82e Char: cyclades, f... |
559 |
static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip, |
ce97a0976 Char: cyclades, m... |
560 561 562 |
void __iomem *base_addr) { struct cyclades_port *info; |
d13549f80 cyclades: add tty... |
563 |
struct tty_struct *tty; |
65f76a82e Char: cyclades, f... |
564 565 |
int char_count, index = cinfo->bus_index; u8 save_xir, channel, save_car, outch; |
ce97a0976 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 [PATCH] Char: cyc... |
570 |
#ifdef CY_DEBUG_INTERRUPTS |
ce97a0976 Char: cyclades, m... |
571 572 |
printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d ", chip); |
e941027f5 [PATCH] Char: cyc... |
573 |
#endif |
ce97a0976 Char: cyclades, m... |
574 |
/* determine the channel & change to that context */ |
65f76a82e Char: cyclades, f... |
575 576 |
save_xir = readb(base_addr + (CyTIR << index)); channel = save_xir & CyIRChannel; |
ce97a0976 Char: cyclades, m... |
577 578 |
save_car = readb(base_addr + (CyCAR << index)); cy_writeb(base_addr + (CyCAR << index), save_xir); |
ce97a0976 Char: cyclades, m... |
579 |
info = &cinfo->ports[channel + chip * 4]; |
d13549f80 cyclades: add tty... |
580 581 |
tty = tty_port_tty_get(&info->port); if (tty == NULL) { |
3aeea5b92 cyclades: introdu... |
582 |
cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); |
ce97a0976 Char: cyclades, m... |
583 584 |
goto end; } |
02f1175c8 [PATCH] Char: cyc... |
585 |
|
ce97a0976 Char: cyclades, m... |
586 587 |
/* load the on-chip space for outbound data */ char_count = info->xmit_fifo_size; |
02f1175c8 [PATCH] Char: cyc... |
588 |
|
ce97a0976 Char: cyclades, m... |
589 590 |
if (info->x_char) { /* send special char */ outch = info->x_char; |
3aeea5b92 cyclades: introdu... |
591 |
cyy_writeb(info, CyTDR, outch); |
ce97a0976 Char: cyclades, m... |
592 593 594 595 |
char_count--; info->icount.tx++; info->x_char = 0; } |
02f1175c8 [PATCH] Char: cyc... |
596 |
|
ce97a0976 Char: cyclades, m... |
597 598 |
if (info->breakon || info->breakoff) { if (info->breakon) { |
3aeea5b92 cyclades: introdu... |
599 600 |
cyy_writeb(info, CyTDR, 0); cyy_writeb(info, CyTDR, 0x81); |
ce97a0976 Char: cyclades, m... |
601 602 |
info->breakon = 0; char_count -= 2; |
e941027f5 [PATCH] Char: cyc... |
603 |
} |
ce97a0976 Char: cyclades, m... |
604 |
if (info->breakoff) { |
3aeea5b92 cyclades: introdu... |
605 606 |
cyy_writeb(info, CyTDR, 0); cyy_writeb(info, CyTDR, 0x83); |
ce97a0976 Char: cyclades, m... |
607 608 |
info->breakoff = 0; char_count -= 2; |
e941027f5 [PATCH] Char: cyc... |
609 |
} |
ce97a0976 Char: cyclades, m... |
610 |
} |
02f1175c8 [PATCH] Char: cyc... |
611 |
|
ce97a0976 Char: cyclades, m... |
612 613 |
while (char_count-- > 0) { if (!info->xmit_cnt) { |
3aeea5b92 cyclades: introdu... |
614 615 616 |
if (cyy_readb(info, CySRER) & CyTxMpty) { cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxMpty); |
ce97a0976 Char: cyclades, m... |
617 |
} else { |
3aeea5b92 cyclades: introdu... |
618 619 |
cyy_writeb(info, CySRER, CyTxMpty | (cyy_readb(info, CySRER) & ~CyTxRdy)); |
02f1175c8 [PATCH] Char: cyc... |
620 |
} |
ce97a0976 Char: cyclades, m... |
621 622 |
goto done; } |
77451e53e cyclades: use tty... |
623 |
if (info->port.xmit_buf == NULL) { |
3aeea5b92 cyclades: introdu... |
624 625 |
cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); |
ce97a0976 Char: cyclades, m... |
626 627 |
goto done; } |
d13549f80 cyclades: add tty... |
628 |
if (tty->stopped || tty->hw_stopped) { |
3aeea5b92 cyclades: introdu... |
629 630 |
cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); |
ce97a0976 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 cyclades: use tty... |
642 |
outch = info->port.xmit_buf[info->xmit_tail]; |
ce97a0976 Char: cyclades, m... |
643 644 645 646 |
if (outch) { info->xmit_cnt--; info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); |
3aeea5b92 cyclades: introdu... |
647 |
cyy_writeb(info, CyTDR, outch); |
ce97a0976 Char: cyclades, m... |
648 649 650 |
info->icount.tx++; } else { if (char_count > 1) { |
02f1175c8 [PATCH] Char: cyc... |
651 652 |
info->xmit_cnt--; info->xmit_tail = (info->xmit_tail + 1) & |
ce97a0976 Char: cyclades, m... |
653 |
(SERIAL_XMIT_SIZE - 1); |
3aeea5b92 cyclades: introdu... |
654 655 |
cyy_writeb(info, CyTDR, outch); cyy_writeb(info, CyTDR, 0); |
02f1175c8 [PATCH] Char: cyc... |
656 |
info->icount.tx++; |
ce97a0976 Char: cyclades, m... |
657 |
char_count--; |
02f1175c8 [PATCH] Char: cyc... |
658 |
} |
e941027f5 [PATCH] Char: cyc... |
659 |
} |
e941027f5 [PATCH] Char: cyc... |
660 |
} |
ce97a0976 Char: cyclades, m... |
661 |
done: |
d13549f80 cyclades: add tty... |
662 663 |
tty_wakeup(tty); tty_kref_put(tty); |
ce97a0976 Char: cyclades, m... |
664 665 |
end: /* end of service */ |
3aeea5b92 cyclades: introdu... |
666 667 |
cyy_writeb(info, CyTIR, save_xir & 0x3f); cyy_writeb(info, CyCAR, save_car); |
ce97a0976 Char: cyclades, m... |
668 |
} |
02f1175c8 [PATCH] Char: cyc... |
669 |
|
ce97a0976 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 cyclades: add tty... |
674 |
struct tty_struct *tty; |
65f76a82e Char: cyclades, f... |
675 676 |
int index = cinfo->bus_index; u8 save_xir, channel, save_car, mdm_change, mdm_status; |
ce97a0976 Char: cyclades, m... |
677 678 |
/* determine the channel & change to that context */ |
65f76a82e Char: cyclades, f... |
679 680 |
save_xir = readb(base_addr + (CyMIR << index)); channel = save_xir & CyIRChannel; |
ce97a0976 Char: cyclades, m... |
681 |
info = &cinfo->ports[channel + chip * 4]; |
3aeea5b92 cyclades: introdu... |
682 683 |
save_car = cyy_readb(info, CyCAR); cyy_writeb(info, CyCAR, save_xir); |
ce97a0976 Char: cyclades, m... |
684 |
|
3aeea5b92 cyclades: introdu... |
685 686 |
mdm_change = cyy_readb(info, CyMISR); mdm_status = cyy_readb(info, CyMSVR1); |
ce97a0976 Char: cyclades, m... |
687 |
|
d13549f80 cyclades: add tty... |
688 689 |
tty = tty_port_tty_get(&info->port); if (!tty) |
ce97a0976 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 serial: move delt... |
702 |
wake_up_interruptible(&info->port.delta_msr_wait); |
ce97a0976 Char: cyclades, m... |
703 |
} |
77451e53e cyclades: use tty... |
704 |
if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) { |
174e6fe01 cyclades: switch ... |
705 706 707 |
if (mdm_status & CyDCD) wake_up_interruptible(&info->port.open_wait); else |
d13549f80 cyclades: add tty... |
708 |
tty_hangup(tty); |
ce97a0976 Char: cyclades, m... |
709 |
} |
77451e53e cyclades: use tty... |
710 |
if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) { |
d13549f80 cyclades: add tty... |
711 |
if (tty->hw_stopped) { |
ce97a0976 Char: cyclades, m... |
712 713 714 |
if (mdm_status & CyCTS) { /* cy_start isn't used because... !!! */ |
d13549f80 cyclades: add tty... |
715 |
tty->hw_stopped = 0; |
3aeea5b92 cyclades: introdu... |
716 717 |
cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); |
d13549f80 cyclades: add tty... |
718 |
tty_wakeup(tty); |
02f1175c8 [PATCH] Char: cyc... |
719 |
} |
ce97a0976 Char: cyclades, m... |
720 721 722 723 |
} else { if (!(mdm_status & CyCTS)) { /* cy_stop isn't used because ... !!! */ |
d13549f80 cyclades: add tty... |
724 |
tty->hw_stopped = 1; |
3aeea5b92 cyclades: introdu... |
725 726 |
cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); |
02f1175c8 [PATCH] Char: cyc... |
727 |
} |
e941027f5 [PATCH] Char: cyc... |
728 |
} |
e941027f5 [PATCH] Char: cyc... |
729 |
} |
ce97a0976 Char: cyclades, m... |
730 731 732 733 |
/* if (mdm_change & CyDSR) { } if (mdm_change & CyRI) { }*/ |
d13549f80 cyclades: add tty... |
734 |
tty_kref_put(tty); |
ce97a0976 Char: cyclades, m... |
735 736 |
end: /* end of service */ |
3aeea5b92 cyclades: introdu... |
737 738 |
cyy_writeb(info, CyMIR, save_xir & 0x3f); cyy_writeb(info, CyCAR, save_car); |
e941027f5 [PATCH] Char: cyc... |
739 |
} |
1da177e4c 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 [PATCH] Char: cyc... |
744 |
static irqreturn_t cyy_interrupt(int irq, void *dev_id) |
1da177e4c Linux-2.6.12-rc2 |
745 |
{ |
02f1175c8 [PATCH] Char: cyc... |
746 |
int status; |
f74290342 Char: cyclades, c... |
747 |
struct cyclades_card *cinfo = dev_id; |
02f1175c8 [PATCH] Char: cyc... |
748 |
void __iomem *base_addr, *card_base_addr; |
65f76a82e Char: cyclades, f... |
749 |
unsigned int chip, too_many, had_work; |
02f1175c8 [PATCH] Char: cyc... |
750 |
int index; |
02f1175c8 [PATCH] Char: cyc... |
751 |
|
f74290342 Char: cyclades, c... |
752 |
if (unlikely(cinfo == NULL)) { |
1da177e4c Linux-2.6.12-rc2 |
753 |
#ifdef CY_DEBUG_INTERRUPTS |
15ed6cc0b cyclades: coding ... |
754 755 756 |
printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d ", irq); |
1da177e4c Linux-2.6.12-rc2 |
757 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
758 759 760 761 762 |
return IRQ_NONE; /* spurious interrupt */ } card_base_addr = cinfo->base_addr; index = cinfo->bus_index; |
f1e83c6c1 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 [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 Char: cyclades, c... |
777 |
while ((status = readb(base_addr + |
02f1175c8 [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 Char: cyclades, m... |
785 |
if (1000 < too_many++) |
02f1175c8 [PATCH] Char: cyc... |
786 |
break; |
1c0a387c1 Char: cyclades, m... |
787 |
spin_lock(&cinfo->card_lock); |
ce97a0976 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 Char: cyclades, m... |
794 |
spin_unlock(&cinfo->card_lock); |
02f1175c8 [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 Linux-2.6.12-rc2 |
806 |
|
4d7682005 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 cyclades: introdu... |
811 |
int channel = info->line - card->first_line; |
0d3487294 cyclades: tiocm c... |
812 |
u32 rts, dtr, msvrr, msvrd; |
4d7682005 cyclades: use dtr... |
813 |
|
4d7682005 cyclades: use dtr... |
814 |
channel &= 0x03; |
4d7682005 cyclades: use dtr... |
815 |
|
0d3487294 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 cyclades: use dtr... |
827 |
if (set & TIOCM_RTS) { |
3aeea5b92 cyclades: introdu... |
828 829 |
cyy_writeb(info, CyCAR, channel); cyy_writeb(info, msvrr, rts); |
4d7682005 cyclades: use dtr... |
830 831 |
} if (clear & TIOCM_RTS) { |
3aeea5b92 cyclades: introdu... |
832 833 |
cyy_writeb(info, CyCAR, channel); cyy_writeb(info, msvrr, ~rts); |
4d7682005 cyclades: use dtr... |
834 835 |
} if (set & TIOCM_DTR) { |
3aeea5b92 cyclades: introdu... |
836 837 |
cyy_writeb(info, CyCAR, channel); cyy_writeb(info, msvrd, dtr); |
4d7682005 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 cyclades: introdu... |
843 844 |
cyy_readb(info, CyMSVR1), cyy_readb(info, CyMSVR2)); |
4d7682005 cyclades: use dtr... |
845 846 847 |
#endif } if (clear & TIOCM_DTR) { |
3aeea5b92 cyclades: introdu... |
848 849 |
cyy_writeb(info, CyCAR, channel); cyy_writeb(info, msvrd, ~dtr); |
4d7682005 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 cyclades: introdu... |
855 856 |
cyy_readb(info, CyMSVR1), cyy_readb(info, CyMSVR2)); |
4d7682005 cyclades: use dtr... |
857 858 859 |
#endif } } |
1da177e4c Linux-2.6.12-rc2 |
860 861 |
/***********************************************************/ /********* End of block of Cyclom-Y specific code **********/ |
15ed6cc0b cyclades: coding ... |
862 |
/******** Start of block of Cyclades-Z specific code *******/ |
1da177e4c Linux-2.6.12-rc2 |
863 864 865 |
/***********************************************************/ static int |
02f1175c8 [PATCH] Char: cyc... |
866 |
cyz_fetch_msg(struct cyclades_card *cinfo, |
15ed6cc0b cyclades: coding ... |
867 |
__u32 *channel, __u8 *cmd, __u32 *param) |
1da177e4c Linux-2.6.12-rc2 |
868 |
{ |
f0eefdc30 cyclades: avoid a... |
869 |
struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; |
02f1175c8 [PATCH] Char: cyc... |
870 |
unsigned long loc_doorbell; |
97e87f8eb tty: cyclades, pl... |
871 |
loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell); |
02f1175c8 [PATCH] Char: cyc... |
872 873 |
if (loc_doorbell) { *cmd = (char)(0xff & loc_doorbell); |
db05c3b1d Char: cyclades, c... |
874 875 |
*channel = readl(&board_ctrl->fwcmd_channel); *param = (__u32) readl(&board_ctrl->fwcmd_param); |
97e87f8eb tty: cyclades, pl... |
876 |
cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff); |
02f1175c8 [PATCH] Char: cyc... |
877 878 879 880 |
return 1; } return 0; } /* cyz_fetch_msg */ |
1da177e4c Linux-2.6.12-rc2 |
881 882 |
static int |
02f1175c8 [PATCH] Char: cyc... |
883 |
cyz_issue_cmd(struct cyclades_card *cinfo, |
1a86b5e34 cyclades: remove ... |
884 |
__u32 channel, __u8 cmd, __u32 param) |
1da177e4c Linux-2.6.12-rc2 |
885 |
{ |
f0eefdc30 cyclades: avoid a... |
886 |
struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; |
1a86b5e34 cyclades: remove ... |
887 |
__u32 __iomem *pci_doorbell; |
65f76a82e Char: cyclades, f... |
888 |
unsigned int index; |
02f1175c8 [PATCH] Char: cyc... |
889 |
|
2693f485c tty: cyclades, co... |
890 |
if (!cyz_is_loaded(cinfo)) |
096dcfce3 [PATCH] Char: cyc... |
891 |
return -1; |
15ed6cc0b cyclades: coding ... |
892 |
|
02f1175c8 [PATCH] Char: cyc... |
893 |
index = 0; |
97e87f8eb tty: cyclades, pl... |
894 |
pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell; |
db05c3b1d Char: cyclades, c... |
895 |
while ((readl(pci_doorbell) & 0xff) != 0) { |
15ed6cc0b cyclades: coding ... |
896 |
if (index++ == 1000) |
db05c3b1d Char: cyclades, c... |
897 |
return (int)(readl(pci_doorbell) & 0xff); |
02f1175c8 [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 [PATCH] Char: cyc... |
903 |
return 0; |
02f1175c8 [PATCH] Char: cyc... |
904 |
} /* cyz_issue_cmd */ |
1da177e4c Linux-2.6.12-rc2 |
905 |
|
f0eefdc30 cyclades: avoid a... |
906 |
static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
907 |
{ |
f0eefdc30 cyclades: avoid a... |
908 |
struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; |
875b206b5 Char: cyclades, m... |
909 |
struct cyclades_card *cinfo = info->card; |
65f76a82e Char: cyclades, f... |
910 |
unsigned int char_count; |
02f1175c8 [PATCH] Char: cyc... |
911 |
int len; |
1da177e4c Linux-2.6.12-rc2 |
912 |
#ifdef BLOCKMOVE |
ce71b0ffd Char: cyclades, f... |
913 |
unsigned char *buf; |
1da177e4c Linux-2.6.12-rc2 |
914 |
#else |
02f1175c8 [PATCH] Char: cyc... |
915 |
char data; |
1da177e4c Linux-2.6.12-rc2 |
916 |
#endif |
ad39c3004 Char: cyclades, r... |
917 |
__u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; |
1da177e4c Linux-2.6.12-rc2 |
918 |
|
db05c3b1d 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 [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 Linux-2.6.12-rc2 |
927 |
|
02f1175c8 [PATCH] Char: cyc... |
928 |
if (char_count) { |
1da177e4c Linux-2.6.12-rc2 |
929 |
#ifdef CY_ENABLE_MONITORING |
02f1175c8 [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 Linux-2.6.12-rc2 |
935 |
#endif |
f74290342 Char: cyclades, c... |
936 |
if (tty == NULL) { |
02f1175c8 [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 Linux-2.6.12-rc2 |
942 |
#ifdef BLOCKMOVE |
02f1175c8 [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 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 [PATCH] Char: cyc... |
959 |
(rx_bufsize - 1); |
ce71b0ffd Char: cyclades, f... |
960 961 962 |
char_count -= len; info->icount.rx += len; info->idle_stats.recv_bytes += len; |
02f1175c8 [PATCH] Char: cyc... |
963 |
} |
1da177e4c Linux-2.6.12-rc2 |
964 |
#else |
02f1175c8 [PATCH] Char: cyc... |
965 966 |
len = tty_buffer_request_room(tty, char_count); while (len--) { |
db05c3b1d Char: cyclades, c... |
967 |
data = readb(cinfo->base_addr + rx_bufaddr + |
02f1175c8 [PATCH] Char: cyc... |
968 |
new_rx_get); |
15ed6cc0b cyclades: coding ... |
969 970 |
new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1); |
02f1175c8 [PATCH] Char: cyc... |
971 972 973 974 |
tty_insert_flip_char(tty, data, TTY_NORMAL); info->idle_stats.recv_bytes++; info->icount.rx++; } |
1da177e4c Linux-2.6.12-rc2 |
975 976 |
#endif #ifdef CONFIG_CYZ_INTR |
02f1175c8 [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 Char: cyclades, c... |
979 |
rx_put = readl(&buf_ctrl->rx_put); |
02f1175c8 [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 Char: cyclades, f... |
984 |
if (char_count >= readl(&buf_ctrl->rx_threshold) && |
ebafeeff0 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 Linux-2.6.12-rc2 |
989 |
#endif |
02f1175c8 [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 Linux-2.6.12-rc2 |
995 |
} |
1da177e4c Linux-2.6.12-rc2 |
996 |
} |
f0eefdc30 cyclades: avoid a... |
997 |
static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
998 |
{ |
f0eefdc30 cyclades: avoid a... |
999 |
struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; |
875b206b5 Char: cyclades, m... |
1000 |
struct cyclades_card *cinfo = info->card; |
65f76a82e Char: cyclades, f... |
1001 1002 |
u8 data; unsigned int char_count; |
1da177e4c Linux-2.6.12-rc2 |
1003 |
#ifdef BLOCKMOVE |
02f1175c8 [PATCH] Char: cyc... |
1004 |
int small_count; |
1da177e4c Linux-2.6.12-rc2 |
1005 |
#endif |
ad39c3004 Char: cyclades, r... |
1006 |
__u32 tx_put, tx_get, tx_bufsize, tx_bufaddr; |
1da177e4c Linux-2.6.12-rc2 |
1007 |
|
02f1175c8 [PATCH] Char: cyc... |
1008 1009 |
if (info->xmit_cnt <= 0) /* Nothing to transmit */ return; |
1da177e4c Linux-2.6.12-rc2 |
1010 |
|
db05c3b1d 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 [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 Linux-2.6.12-rc2 |
1019 |
|
02f1175c8 [PATCH] Char: cyc... |
1020 |
if (char_count) { |
1da177e4c Linux-2.6.12-rc2 |
1021 |
|
f74290342 Char: cyclades, c... |
1022 |
if (tty == NULL) |
02f1175c8 [PATCH] Char: cyc... |
1023 |
goto ztxdone; |
1da177e4c Linux-2.6.12-rc2 |
1024 |
|
02f1175c8 [PATCH] Char: cyc... |
1025 1026 |
if (info->x_char) { /* send special char */ data = info->x_char; |
1da177e4c Linux-2.6.12-rc2 |
1027 |
|
02f1175c8 [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 [PATCH] Char: cyc... |
1033 |
} |
1da177e4c Linux-2.6.12-rc2 |
1034 |
#ifdef BLOCKMOVE |
02f1175c8 [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 cyclades: use tty... |
1043 |
&info->port.xmit_buf[info->xmit_tail], |
02f1175c8 [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 [PATCH] Char: cyc... |
1052 |
} |
1da177e4c Linux-2.6.12-rc2 |
1053 |
#else |
02f1175c8 [PATCH] Char: cyc... |
1054 |
while (info->xmit_cnt && char_count) { |
77451e53e cyclades: use tty... |
1055 |
data = info->port.xmit_buf[info->xmit_tail]; |
02f1175c8 [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 [PATCH] Char: cyc... |
1064 |
} |
1da177e4c Linux-2.6.12-rc2 |
1065 |
#endif |
ebafeeff0 Char: cyclades, r... |
1066 |
tty_wakeup(tty); |
7fa57a0cd Char: cyclades, f... |
1067 |
ztxdone: |
02f1175c8 [PATCH] Char: cyc... |
1068 1069 |
/* Update tx_put */ cy_writel(&buf_ctrl->tx_put, tx_put); |
1da177e4c Linux-2.6.12-rc2 |
1070 |
} |
1da177e4c Linux-2.6.12-rc2 |
1071 |
} |
02f1175c8 [PATCH] Char: cyc... |
1072 |
static void cyz_handle_cmd(struct cyclades_card *cinfo) |
1da177e4c Linux-2.6.12-rc2 |
1073 |
{ |
f0eefdc30 cyclades: avoid a... |
1074 |
struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; |
02f1175c8 [PATCH] Char: cyc... |
1075 1076 |
struct tty_struct *tty; struct cyclades_port *info; |
101b81590 tty: cyclades, ca... |
1077 |
__u32 channel, param, fw_ver; |
1a86b5e34 cyclades: remove ... |
1078 |
__u8 cmd; |
02f1175c8 [PATCH] Char: cyc... |
1079 1080 |
int special_count; int delta_count; |
db05c3b1d Char: cyclades, c... |
1081 |
fw_ver = readl(&board_ctrl->fw_version); |
02f1175c8 [PATCH] Char: cyc... |
1082 1083 1084 1085 |
while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { special_count = 0; delta_count = 0; |
dd025c0c7 Char: cyclades, d... |
1086 |
info = &cinfo->ports[channel]; |
d13549f80 cyclades: add tty... |
1087 |
tty = tty_port_tty_get(&info->port); |
15ed6cc0b cyclades: coding ... |
1088 |
if (tty == NULL) |
02f1175c8 [PATCH] Char: cyc... |
1089 |
continue; |
f74290342 Char: cyclades, c... |
1090 |
|
02f1175c8 [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 cyclades: use tty... |
1110 |
if (info->port.flags & ASYNC_CHECK_CD) { |
f0eefdc30 cyclades: avoid a... |
1111 1112 |
u32 dcd = fw_ver > 241 ? param : readl(&info->u.cyz.ch_ctrl->rs_status); |
174e6fe01 cyclades: switch ... |
1113 |
if (dcd & C_RS_DCD) |
77451e53e cyclades: use tty... |
1114 |
wake_up_interruptible(&info->port.open_wait); |
174e6fe01 cyclades: switch ... |
1115 |
else |
d13549f80 cyclades: add tty... |
1116 |
tty_hangup(tty); |
02f1175c8 [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 Linux-2.6.12-rc2 |
1131 |
#ifdef Z_WAKE |
02f1175c8 [PATCH] Char: cyc... |
1132 |
case C_CM_IOCTLW: |
ebafeeff0 Char: cyclades, r... |
1133 |
complete(&info->shutdown_wait); |
02f1175c8 [PATCH] Char: cyc... |
1134 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1135 1136 |
#endif #ifdef CONFIG_CYZ_INTR |
02f1175c8 [PATCH] Char: cyc... |
1137 1138 1139 1140 |
case C_CM_RXHIWM: case C_CM_RXNNDT: case C_CM_INTBACK2: /* Reception Interrupt */ |
1da177e4c Linux-2.6.12-rc2 |
1141 |
#ifdef CY_DEBUG_INTERRUPTS |
217191910 Char: cyclades, p... |
1142 1143 1144 |
printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, " "port %ld ", info->card, channel); |
1da177e4c Linux-2.6.12-rc2 |
1145 |
#endif |
f0eefdc30 cyclades: avoid a... |
1146 |
cyz_handle_rx(info, tty); |
02f1175c8 [PATCH] Char: cyc... |
1147 1148 1149 1150 1151 |
break; case C_CM_TXBEMPTY: case C_CM_TXLOWWM: case C_CM_INTBACK: /* Transmission Interrupt */ |
1da177e4c Linux-2.6.12-rc2 |
1152 |
#ifdef CY_DEBUG_INTERRUPTS |
217191910 Char: cyclades, p... |
1153 1154 1155 |
printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, " "port %ld ", info->card, channel); |
1da177e4c Linux-2.6.12-rc2 |
1156 |
#endif |
f0eefdc30 cyclades: avoid a... |
1157 |
cyz_handle_tx(info, tty); |
02f1175c8 [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 serial: move delt... |
1167 |
wake_up_interruptible(&info->port.delta_msr_wait); |
02f1175c8 [PATCH] Char: cyc... |
1168 1169 |
if (special_count) tty_schedule_flip(tty); |
d13549f80 cyclades: add tty... |
1170 |
tty_kref_put(tty); |
1da177e4c Linux-2.6.12-rc2 |
1171 |
} |
1da177e4c Linux-2.6.12-rc2 |
1172 1173 1174 |
} #ifdef CONFIG_CYZ_INTR |
02f1175c8 [PATCH] Char: cyc... |
1175 |
static irqreturn_t cyz_interrupt(int irq, void *dev_id) |
1da177e4c Linux-2.6.12-rc2 |
1176 |
{ |
f74290342 Char: cyclades, c... |
1177 |
struct cyclades_card *cinfo = dev_id; |
1da177e4c Linux-2.6.12-rc2 |
1178 |
|
2693f485c tty: cyclades, co... |
1179 |
if (unlikely(!cyz_is_loaded(cinfo))) { |
1da177e4c Linux-2.6.12-rc2 |
1180 |
#ifdef CY_DEBUG_INTERRUPTS |
217191910 Char: cyclades, p... |
1181 1182 1183 |
printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " "(IRQ%d). ", irq); |
1da177e4c Linux-2.6.12-rc2 |
1184 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
1185 1186 |
return IRQ_NONE; } |
1da177e4c Linux-2.6.12-rc2 |
1187 |
|
02f1175c8 [PATCH] Char: cyc... |
1188 1189 |
/* Handle the interrupts */ cyz_handle_cmd(cinfo); |
1da177e4c Linux-2.6.12-rc2 |
1190 |
|
02f1175c8 [PATCH] Char: cyc... |
1191 1192 |
return IRQ_HANDLED; } /* cyz_interrupt */ |
1da177e4c Linux-2.6.12-rc2 |
1193 |
|
02f1175c8 [PATCH] Char: cyc... |
1194 |
static void cyz_rx_restart(unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
1195 |
{ |
02f1175c8 [PATCH] Char: cyc... |
1196 |
struct cyclades_port *info = (struct cyclades_port *)arg; |
875b206b5 Char: cyclades, m... |
1197 |
struct cyclades_card *card = info->card; |
02f1175c8 [PATCH] Char: cyc... |
1198 |
int retval; |
875b206b5 Char: cyclades, m... |
1199 |
__u32 channel = info->line - card->first_line; |
02f1175c8 [PATCH] Char: cyc... |
1200 |
unsigned long flags; |
9fa1b3b18 Char: cyclades, r... |
1201 |
spin_lock_irqsave(&card->card_lock, flags); |
875b206b5 Char: cyclades, m... |
1202 |
retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L); |
02f1175c8 [PATCH] Char: cyc... |
1203 |
if (retval != 0) { |
217191910 Char: cyclades, p... |
1204 1205 |
printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x ", |
02f1175c8 [PATCH] Char: cyc... |
1206 1207 |
info->line, retval); } |
9fa1b3b18 Char: cyclades, r... |
1208 |
spin_unlock_irqrestore(&card->card_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
1209 |
} |
02f1175c8 [PATCH] Char: cyc... |
1210 |
#else /* CONFIG_CYZ_INTR */ |
1da177e4c Linux-2.6.12-rc2 |
1211 |
|
02f1175c8 [PATCH] Char: cyc... |
1212 |
static void cyz_poll(unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
1213 |
{ |
02f1175c8 [PATCH] Char: cyc... |
1214 1215 |
struct cyclades_card *cinfo; struct cyclades_port *info; |
b70509066 Char: cyclades, t... |
1216 |
unsigned long expires = jiffies + HZ; |
65f76a82e Char: cyclades, f... |
1217 |
unsigned int port, card; |
1da177e4c Linux-2.6.12-rc2 |
1218 |
|
02f1175c8 [PATCH] Char: cyc... |
1219 1220 |
for (card = 0; card < NR_CARDS; card++) { cinfo = &cy_card[card]; |
2693f485c tty: cyclades, co... |
1221 |
if (!cy_is_Z(cinfo)) |
02f1175c8 [PATCH] Char: cyc... |
1222 |
continue; |
2693f485c tty: cyclades, co... |
1223 |
if (!cyz_is_loaded(cinfo)) |
02f1175c8 [PATCH] Char: cyc... |
1224 |
continue; |
1da177e4c Linux-2.6.12-rc2 |
1225 |
/* Skip first polling cycle to avoid racing conditions with the FW */ |
02f1175c8 [PATCH] Char: cyc... |
1226 |
if (!cinfo->intr_enabled) { |
02f1175c8 [PATCH] Char: cyc... |
1227 1228 1229 |
cinfo->intr_enabled = 1; continue; } |
1da177e4c Linux-2.6.12-rc2 |
1230 |
|
02f1175c8 [PATCH] Char: cyc... |
1231 |
cyz_handle_cmd(cinfo); |
1da177e4c Linux-2.6.12-rc2 |
1232 |
|
02f1175c8 [PATCH] Char: cyc... |
1233 |
for (port = 0; port < cinfo->nports; port++) { |
d13549f80 cyclades: add tty... |
1234 |
struct tty_struct *tty; |
dd025c0c7 Char: cyclades, d... |
1235 |
info = &cinfo->ports[port]; |
d13549f80 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 [PATCH] Char: cyc... |
1239 |
if (!info->throttle) |
f0eefdc30 cyclades: avoid a... |
1240 1241 |
cyz_handle_rx(info, tty); cyz_handle_tx(info, tty); |
d13549f80 cyclades: add tty... |
1242 |
tty_kref_put(tty); |
02f1175c8 [PATCH] Char: cyc... |
1243 1244 |
} /* poll every 'cyz_polling_cycle' period */ |
b70509066 Char: cyclades, t... |
1245 |
expires = jiffies + cyz_polling_cycle; |
1da177e4c Linux-2.6.12-rc2 |
1246 |
} |
b70509066 Char: cyclades, t... |
1247 |
mod_timer(&cyz_timerlist, expires); |
02f1175c8 [PATCH] Char: cyc... |
1248 |
} /* cyz_poll */ |
1da177e4c Linux-2.6.12-rc2 |
1249 |
|
02f1175c8 [PATCH] Char: cyc... |
1250 |
#endif /* CONFIG_CYZ_INTR */ |
1da177e4c Linux-2.6.12-rc2 |
1251 1252 1253 |
/********** End of block of Cyclades-Z specific code *********/ /***********************************************************/ |
1da177e4c 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 cyclades: add tty... |
1257 |
static int cy_startup(struct cyclades_port *info, struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1258 |
{ |
875b206b5 Char: cyclades, m... |
1259 |
struct cyclades_card *card; |
02f1175c8 [PATCH] Char: cyc... |
1260 1261 |
unsigned long flags; int retval = 0; |
cc7fdf49d cyclades: merge c... |
1262 |
int channel; |
02f1175c8 [PATCH] Char: cyc... |
1263 |
unsigned long page; |
1da177e4c Linux-2.6.12-rc2 |
1264 |
|
02f1175c8 [PATCH] Char: cyc... |
1265 |
card = info->card; |
875b206b5 Char: cyclades, m... |
1266 |
channel = info->line - card->first_line; |
1da177e4c Linux-2.6.12-rc2 |
1267 |
|
02f1175c8 [PATCH] Char: cyc... |
1268 1269 1270 |
page = get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
1271 |
|
9fa1b3b18 Char: cyclades, r... |
1272 |
spin_lock_irqsave(&card->card_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
1273 |
|
cc7fdf49d cyclades: merge c... |
1274 |
if (info->port.flags & ASYNC_INITIALIZED) |
02f1175c8 [PATCH] Char: cyc... |
1275 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
1276 |
|
02f1175c8 [PATCH] Char: cyc... |
1277 |
if (!info->type) { |
d13549f80 cyclades: add tty... |
1278 |
set_bit(TTY_IO_ERROR, &tty->flags); |
02f1175c8 [PATCH] Char: cyc... |
1279 1280 |
goto errout; } |
1da177e4c Linux-2.6.12-rc2 |
1281 |
|
77451e53e cyclades: use tty... |
1282 |
if (info->port.xmit_buf) |
02f1175c8 [PATCH] Char: cyc... |
1283 1284 |
free_page(page); else |
77451e53e cyclades: use tty... |
1285 |
info->port.xmit_buf = (unsigned char *)page; |
1da177e4c Linux-2.6.12-rc2 |
1286 |
|
9fa1b3b18 Char: cyclades, r... |
1287 |
spin_unlock_irqrestore(&card->card_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
1288 |
|
d13549f80 cyclades: add tty... |
1289 |
cy_set_line_char(info, tty); |
1da177e4c Linux-2.6.12-rc2 |
1290 |
|
2693f485c tty: cyclades, co... |
1291 |
if (!cy_is_Z(card)) { |
02f1175c8 [PATCH] Char: cyc... |
1292 |
channel &= 0x03; |
1da177e4c Linux-2.6.12-rc2 |
1293 |
|
9fa1b3b18 Char: cyclades, r... |
1294 |
spin_lock_irqsave(&card->card_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
1295 |
|
3aeea5b92 cyclades: introdu... |
1296 |
cyy_writeb(info, CyCAR, channel); |
1da177e4c Linux-2.6.12-rc2 |
1297 |
|
3aeea5b92 cyclades: introdu... |
1298 |
cyy_writeb(info, CyRTPR, |
02f1175c8 [PATCH] Char: cyc... |
1299 1300 |
(info->default_timeout ? info->default_timeout : 0x02)); /* 10ms rx timeout */ |
1da177e4c Linux-2.6.12-rc2 |
1301 |
|
3aeea5b92 cyclades: introdu... |
1302 |
cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR); |
1da177e4c Linux-2.6.12-rc2 |
1303 |
|
4d7682005 cyclades: use dtr... |
1304 |
cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0); |
1da177e4c Linux-2.6.12-rc2 |
1305 |
|
3aeea5b92 cyclades: introdu... |
1306 |
cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData); |
02f1175c8 [PATCH] Char: cyc... |
1307 |
} else { |
f0eefdc30 cyclades: avoid a... |
1308 |
struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; |
1da177e4c Linux-2.6.12-rc2 |
1309 |
|
2693f485c tty: cyclades, co... |
1310 |
if (!cyz_is_loaded(card)) |
02f1175c8 [PATCH] Char: cyc... |
1311 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
1312 |
|
1da177e4c Linux-2.6.12-rc2 |
1313 |
#ifdef CY_DEBUG_OPEN |
217191910 Char: cyclades, p... |
1314 |
printk(KERN_DEBUG "cyc startup Z card %d, channel %d, " |
f0eefdc30 cyclades: avoid a... |
1315 1316 |
"base_addr %p ", card, channel, card->base_addr); |
1da177e4c Linux-2.6.12-rc2 |
1317 |
#endif |
9fa1b3b18 Char: cyclades, r... |
1318 |
spin_lock_irqsave(&card->card_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
1319 |
|
f0eefdc30 cyclades: avoid a... |
1320 |
cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE); |
1da177e4c Linux-2.6.12-rc2 |
1321 1322 |
#ifdef Z_WAKE #ifdef CONFIG_CYZ_INTR |
f0eefdc30 cyclades: avoid a... |
1323 |
cy_writel(&ch_ctrl->intr_enable, |
02f1175c8 [PATCH] Char: cyc... |
1324 1325 |
C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD); |
1da177e4c Linux-2.6.12-rc2 |
1326 |
#else |
f0eefdc30 cyclades: avoid a... |
1327 |
cy_writel(&ch_ctrl->intr_enable, |
02f1175c8 [PATCH] Char: cyc... |
1328 1329 |
C_IN_IOCTLW | C_IN_MDCD); #endif /* CONFIG_CYZ_INTR */ |
1da177e4c Linux-2.6.12-rc2 |
1330 1331 |
#else #ifdef CONFIG_CYZ_INTR |
f0eefdc30 cyclades: avoid a... |
1332 |
cy_writel(&ch_ctrl->intr_enable, |
02f1175c8 [PATCH] Char: cyc... |
1333 1334 |
C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | C_IN_RXNNDT | C_IN_MDCD); |
1da177e4c Linux-2.6.12-rc2 |
1335 |
#else |
f0eefdc30 cyclades: avoid a... |
1336 |
cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD); |
02f1175c8 [PATCH] Char: cyc... |
1337 1338 |
#endif /* CONFIG_CYZ_INTR */ #endif /* Z_WAKE */ |
875b206b5 Char: cyclades, m... |
1339 |
retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); |
02f1175c8 [PATCH] Char: cyc... |
1340 |
if (retval != 0) { |
217191910 Char: cyclades, p... |
1341 1342 1343 |
printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was " "%x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
1344 |
} |
1da177e4c Linux-2.6.12-rc2 |
1345 |
|
02f1175c8 [PATCH] Char: cyc... |
1346 |
/* Flush RX buffers before raising DTR and RTS */ |
875b206b5 Char: cyclades, m... |
1347 |
retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L); |
02f1175c8 [PATCH] Char: cyc... |
1348 |
if (retval != 0) { |
217191910 Char: cyclades, p... |
1349 1350 1351 |
printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was " "%x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
1352 |
} |
1da177e4c Linux-2.6.12-rc2 |
1353 |
|
02f1175c8 [PATCH] Char: cyc... |
1354 1355 |
/* set timeout !!! */ /* set RTS and DTR !!! */ |
4d7682005 cyclades: use dtr... |
1356 |
tty_port_raise_dtr_rts(&info->port); |
1da177e4c Linux-2.6.12-rc2 |
1357 |
|
02f1175c8 [PATCH] Char: cyc... |
1358 |
/* enable send, recv, modem !!! */ |
cc7fdf49d cyclades: merge c... |
1359 |
} |
02f1175c8 [PATCH] Char: cyc... |
1360 |
|
cc7fdf49d cyclades: merge c... |
1361 |
info->port.flags |= ASYNC_INITIALIZED; |
1da177e4c Linux-2.6.12-rc2 |
1362 |
|
cc7fdf49d 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 Linux-2.6.12-rc2 |
1372 1373 |
#ifdef CY_DEBUG_OPEN |
217191910 Char: cyclades, p... |
1374 1375 |
printk(KERN_DEBUG "cyc startup done "); |
1da177e4c Linux-2.6.12-rc2 |
1376 1377 1378 1379 |
#endif return 0; errout: |
9fa1b3b18 Char: cyclades, r... |
1380 |
spin_unlock_irqrestore(&card->card_lock, flags); |
cc7fdf49d cyclades: merge c... |
1381 |
free_page(page); |
1da177e4c Linux-2.6.12-rc2 |
1382 |
return retval; |
02f1175c8 [PATCH] Char: cyc... |
1383 |
} /* startup */ |
1da177e4c Linux-2.6.12-rc2 |
1384 |
|
02f1175c8 [PATCH] Char: cyc... |
1385 |
static void start_xmit(struct cyclades_port *info) |
1da177e4c Linux-2.6.12-rc2 |
1386 |
{ |
3aeea5b92 cyclades: introdu... |
1387 |
struct cyclades_card *card = info->card; |
02f1175c8 [PATCH] Char: cyc... |
1388 |
unsigned long flags; |
3aeea5b92 cyclades: introdu... |
1389 |
int channel = info->line - card->first_line; |
1da177e4c Linux-2.6.12-rc2 |
1390 |
|
2693f485c tty: cyclades, co... |
1391 |
if (!cy_is_Z(card)) { |
9fa1b3b18 Char: cyclades, r... |
1392 |
spin_lock_irqsave(&card->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
1393 1394 |
cyy_writeb(info, CyCAR, channel & 0x03); cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); |
9fa1b3b18 Char: cyclades, r... |
1395 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1396 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
1397 |
#ifdef CONFIG_CYZ_INTR |
02f1175c8 [PATCH] Char: cyc... |
1398 |
int retval; |
1da177e4c Linux-2.6.12-rc2 |
1399 |
|
9fa1b3b18 Char: cyclades, r... |
1400 |
spin_lock_irqsave(&card->card_lock, flags); |
875b206b5 Char: cyclades, m... |
1401 |
retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L); |
02f1175c8 [PATCH] Char: cyc... |
1402 |
if (retval != 0) { |
217191910 Char: cyclades, p... |
1403 1404 1405 |
printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was " "%x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
1406 |
} |
9fa1b3b18 Char: cyclades, r... |
1407 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [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 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 cyclades: add tty... |
1418 |
static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1419 |
{ |
875b206b5 Char: cyclades, m... |
1420 |
struct cyclades_card *card; |
02f1175c8 [PATCH] Char: cyc... |
1421 |
unsigned long flags; |
02f1175c8 [PATCH] Char: cyc... |
1422 |
|
77451e53e cyclades: use tty... |
1423 |
if (!(info->port.flags & ASYNC_INITIALIZED)) |
02f1175c8 [PATCH] Char: cyc... |
1424 |
return; |
02f1175c8 [PATCH] Char: cyc... |
1425 1426 |
card = info->card; |
2693f485c tty: cyclades, co... |
1427 |
if (!cy_is_Z(card)) { |
9fa1b3b18 Char: cyclades, r... |
1428 |
spin_lock_irqsave(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1429 1430 |
/* Clear delta_msr_wait queue to avoid mem leaks. */ |
bdc04e317 serial: move delt... |
1431 |
wake_up_interruptible(&info->port.delta_msr_wait); |
1da177e4c Linux-2.6.12-rc2 |
1432 |
|
77451e53e cyclades: use tty... |
1433 |
if (info->port.xmit_buf) { |
02f1175c8 [PATCH] Char: cyc... |
1434 |
unsigned char *temp; |
77451e53e cyclades: use tty... |
1435 1436 |
temp = info->port.xmit_buf; info->port.xmit_buf = NULL; |
02f1175c8 [PATCH] Char: cyc... |
1437 1438 |
free_page((unsigned long)temp); } |
4d7682005 cyclades: use dtr... |
1439 1440 |
if (tty->termios->c_cflag & HUPCL) cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR); |
3aeea5b92 cyclades: introdu... |
1441 |
cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR); |
02f1175c8 [PATCH] Char: cyc... |
1442 1443 |
/* it may be appropriate to clear _XMIT at some later date (after testing)!!! */ |
d13549f80 cyclades: add tty... |
1444 |
set_bit(TTY_IO_ERROR, &tty->flags); |
77451e53e cyclades: use tty... |
1445 |
info->port.flags &= ~ASYNC_INITIALIZED; |
9fa1b3b18 Char: cyclades, r... |
1446 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1447 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
1448 |
#ifdef CY_DEBUG_OPEN |
0e7f4194a Char: cyclades, f... |
1449 |
int channel = info->line - card->first_line; |
217191910 Char: cyclades, p... |
1450 |
printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " |
f0eefdc30 cyclades: avoid a... |
1451 1452 |
"base_addr %p ", card, channel, card->base_addr); |
1da177e4c Linux-2.6.12-rc2 |
1453 |
#endif |
2693f485c tty: cyclades, co... |
1454 |
if (!cyz_is_loaded(card)) |
02f1175c8 [PATCH] Char: cyc... |
1455 |
return; |
1da177e4c Linux-2.6.12-rc2 |
1456 |
|
9fa1b3b18 Char: cyclades, r... |
1457 |
spin_lock_irqsave(&card->card_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
1458 |
|
77451e53e cyclades: use tty... |
1459 |
if (info->port.xmit_buf) { |
02f1175c8 [PATCH] Char: cyc... |
1460 |
unsigned char *temp; |
77451e53e cyclades: use tty... |
1461 1462 |
temp = info->port.xmit_buf; info->port.xmit_buf = NULL; |
02f1175c8 [PATCH] Char: cyc... |
1463 |
free_page((unsigned long)temp); |
1da177e4c Linux-2.6.12-rc2 |
1464 |
} |
02f1175c8 [PATCH] Char: cyc... |
1465 |
|
4d7682005 cyclades: use dtr... |
1466 1467 |
if (tty->termios->c_cflag & HUPCL) tty_port_lower_dtr_rts(&info->port); |
1da177e4c Linux-2.6.12-rc2 |
1468 |
|
d13549f80 cyclades: add tty... |
1469 |
set_bit(TTY_IO_ERROR, &tty->flags); |
77451e53e cyclades: use tty... |
1470 |
info->port.flags &= ~ASYNC_INITIALIZED; |
02f1175c8 [PATCH] Char: cyc... |
1471 |
|
9fa1b3b18 Char: cyclades, r... |
1472 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1473 |
} |
1da177e4c Linux-2.6.12-rc2 |
1474 1475 |
#ifdef CY_DEBUG_OPEN |
217191910 Char: cyclades, p... |
1476 1477 |
printk(KERN_DEBUG "cyc shutdown done "); |
1da177e4c Linux-2.6.12-rc2 |
1478 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
1479 |
} /* shutdown */ |
1da177e4c Linux-2.6.12-rc2 |
1480 1481 1482 1483 1484 1485 |
/* * ------------------------------------------------------------ * cy_open() and friends * ------------------------------------------------------------ */ |
1da177e4c 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 [PATCH] Char: cyc... |
1490 |
static int cy_open(struct tty_struct *tty, struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
1491 |
{ |
02f1175c8 [PATCH] Char: cyc... |
1492 |
struct cyclades_port *info; |
65f76a82e Char: cyclades, f... |
1493 1494 |
unsigned int i, line; int retval; |
1da177e4c Linux-2.6.12-rc2 |
1495 |
|
02f1175c8 [PATCH] Char: cyc... |
1496 |
line = tty->index; |
15ed6cc0b cyclades: coding ... |
1497 |
if (tty->index < 0 || NR_PORTS <= line) |
02f1175c8 [PATCH] Char: cyc... |
1498 |
return -ENODEV; |
15ed6cc0b cyclades: coding ... |
1499 |
|
dd025c0c7 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 cyclades: coding ... |
1507 |
if (info->line < 0) |
02f1175c8 [PATCH] Char: cyc... |
1508 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
1509 |
|
02f1175c8 [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 tty: cyclades, co... |
1514 |
if (cy_is_Z(info->card)) { |
875b206b5 Char: cyclades, m... |
1515 |
struct cyclades_card *cinfo = info->card; |
02f1175c8 [PATCH] Char: cyc... |
1516 |
struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; |
2693f485c tty: cyclades, co... |
1517 1518 |
if (!cyz_is_loaded(cinfo)) { if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) && |
101b81590 tty: cyclades, ca... |
1519 1520 |
readl(&firm_id->signature) == ZFIRM_HLT) { |
217191910 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 [PATCH] Char: cyc... |
1527 |
} else { |
217191910 Char: cyclades, p... |
1528 1529 1530 |
printk(KERN_ERR "cyc:Cyclades-Z firmware not " "yet loaded "); |
02f1175c8 [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 tty: cyclades, pl... |
1540 |
u16 intr; |
02f1175c8 [PATCH] Char: cyc... |
1541 |
|
02f1175c8 [PATCH] Char: cyc... |
1542 |
/* Enable interrupts on the PLX chip */ |
97e87f8eb 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 [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 Char: cyclades, p... |
1551 1552 1553 |
printk(KERN_ERR "cyc:IRQ enable retval " "was %x ", retval); |
02f1175c8 [PATCH] Char: cyc... |
1554 |
} |
02f1175c8 [PATCH] Char: cyc... |
1555 1556 |
cinfo->intr_enabled = 1; } |
1da177e4c Linux-2.6.12-rc2 |
1557 |
} |
02f1175c8 [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 Linux-2.6.12-rc2 |
1562 |
} |
1da177e4c Linux-2.6.12-rc2 |
1563 |
#ifdef CY_DEBUG_OTHER |
217191910 Char: cyclades, p... |
1564 1565 |
printk(KERN_DEBUG "cyc:cy_open ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
1566 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
1567 |
tty->driver_data = info; |
15ed6cc0b cyclades: coding ... |
1568 |
if (serial_paranoia_check(info, tty->name, "cy_open")) |
02f1175c8 [PATCH] Char: cyc... |
1569 |
return -ENODEV; |
15ed6cc0b cyclades: coding ... |
1570 |
|
1da177e4c Linux-2.6.12-rc2 |
1571 |
#ifdef CY_DEBUG_OPEN |
217191910 Char: cyclades, p... |
1572 1573 |
printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d ", info->line, |
77451e53e cyclades: use tty... |
1574 |
info->port.count); |
1da177e4c Linux-2.6.12-rc2 |
1575 |
#endif |
77451e53e cyclades: use tty... |
1576 |
info->port.count++; |
1da177e4c Linux-2.6.12-rc2 |
1577 |
#ifdef CY_DEBUG_COUNT |
217191910 Char: cyclades, p... |
1578 1579 |
printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d ", |
77451e53e cyclades: use tty... |
1580 |
current->pid, info->port.count); |
1da177e4c Linux-2.6.12-rc2 |
1581 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
1582 |
|
02f1175c8 [PATCH] Char: cyc... |
1583 1584 1585 |
/* * If the port is the middle of closing, bail out now */ |
77451e53e cyclades: use tty... |
1586 |
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { |
be1bc2889 tty: introduce wa... |
1587 |
wait_event_interruptible_tty(info->port.close_wait, |
77451e53e cyclades: use tty... |
1588 1589 |
!(info->port.flags & ASYNC_CLOSING)); return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; |
02f1175c8 [PATCH] Char: cyc... |
1590 |
} |
1da177e4c Linux-2.6.12-rc2 |
1591 |
|
02f1175c8 [PATCH] Char: cyc... |
1592 1593 1594 |
/* * Start up serial port */ |
d13549f80 cyclades: add tty... |
1595 |
retval = cy_startup(info, tty); |
15ed6cc0b cyclades: coding ... |
1596 |
if (retval) |
02f1175c8 [PATCH] Char: cyc... |
1597 |
return retval; |
1da177e4c Linux-2.6.12-rc2 |
1598 |
|
f07375794 cyclades: remove ... |
1599 |
retval = tty_port_block_til_ready(&info->port, tty, filp); |
02f1175c8 [PATCH] Char: cyc... |
1600 |
if (retval) { |
1da177e4c Linux-2.6.12-rc2 |
1601 |
#ifdef CY_DEBUG_OPEN |
217191910 Char: cyclades, p... |
1602 1603 1604 |
printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " "with %d ", retval); |
1da177e4c Linux-2.6.12-rc2 |
1605 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
1606 1607 |
return retval; } |
1da177e4c Linux-2.6.12-rc2 |
1608 |
|
02f1175c8 [PATCH] Char: cyc... |
1609 |
info->throttle = 0; |
d13549f80 cyclades: add tty... |
1610 |
tty_port_tty_set(&info->port, tty); |
1da177e4c Linux-2.6.12-rc2 |
1611 |
|
02f1175c8 [PATCH] Char: cyc... |
1612 |
#ifdef CY_DEBUG_OPEN |
217191910 Char: cyclades, p... |
1613 1614 |
printk(KERN_DEBUG "cyc:cy_open done "); |
02f1175c8 [PATCH] Char: cyc... |
1615 1616 1617 |
#endif return 0; } /* cy_open */ |
1da177e4c Linux-2.6.12-rc2 |
1618 1619 1620 1621 |
/* * cy_wait_until_sent() --- wait until the transmitter is empty */ |
02f1175c8 [PATCH] Char: cyc... |
1622 |
static void cy_wait_until_sent(struct tty_struct *tty, int timeout) |
1da177e4c Linux-2.6.12-rc2 |
1623 |
{ |
875b206b5 Char: cyclades, m... |
1624 |
struct cyclades_card *card; |
cab9bdd14 Char: cyclades, r... |
1625 |
struct cyclades_port *info = tty->driver_data; |
02f1175c8 [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 Linux-2.6.12-rc2 |
1634 |
|
02f1175c8 [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 TTY: mxser+cyclad... |
1663 |
|
02f1175c8 [PATCH] Char: cyc... |
1664 |
card = info->card; |
2693f485c tty: cyclades, co... |
1665 |
if (!cy_is_Z(card)) { |
3aeea5b92 cyclades: introdu... |
1666 |
while (cyy_readb(info, CySRER) & CyTxRdy) { |
02f1175c8 [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 Linux-2.6.12-rc2 |
1673 |
} |
02f1175c8 [PATCH] Char: cyc... |
1674 1675 |
/* Run one more char cycle */ msleep_interruptible(jiffies_to_msecs(char_time * 5)); |
1da177e4c Linux-2.6.12-rc2 |
1676 |
} |
978e595f8 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 tty: cyclades, co... |
1698 |
if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board |
978e595f8 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 cyclades: use the... |
1711 |
static void cy_do_close(struct tty_port *port) |
1da177e4c Linux-2.6.12-rc2 |
1712 |
{ |
e936ffd5c cyclades: use the... |
1713 1714 |
struct cyclades_port *info = container_of(port, struct cyclades_port, port); |
9fa1b3b18 Char: cyclades, r... |
1715 |
struct cyclades_card *card; |
02f1175c8 [PATCH] Char: cyc... |
1716 |
unsigned long flags; |
3aeea5b92 cyclades: introdu... |
1717 |
int channel; |
1da177e4c Linux-2.6.12-rc2 |
1718 |
|
9fa1b3b18 Char: cyclades, r... |
1719 |
card = info->card; |
3aeea5b92 cyclades: introdu... |
1720 |
channel = info->line - card->first_line; |
9fa1b3b18 Char: cyclades, r... |
1721 |
spin_lock_irqsave(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1722 |
|
2693f485c tty: cyclades, co... |
1723 |
if (!cy_is_Z(card)) { |
02f1175c8 [PATCH] Char: cyc... |
1724 |
/* Stop accepting input */ |
3aeea5b92 cyclades: introdu... |
1725 1726 |
cyy_writeb(info, CyCAR, channel & 0x03); cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData); |
77451e53e cyclades: use tty... |
1727 |
if (info->port.flags & ASYNC_INITIALIZED) { |
15ed6cc0b cyclades: coding ... |
1728 1729 |
/* Waiting for on-board buffers to be empty before closing the port */ |
9fa1b3b18 Char: cyclades, r... |
1730 |
spin_unlock_irqrestore(&card->card_lock, flags); |
e936ffd5c cyclades: use the... |
1731 |
cy_wait_until_sent(port->tty, info->timeout); |
9fa1b3b18 Char: cyclades, r... |
1732 |
spin_lock_irqsave(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1733 1734 1735 |
} } else { #ifdef Z_WAKE |
15ed6cc0b cyclades: coding ... |
1736 1737 |
/* Waiting for on-board buffers to be empty before closing the port */ |
f0eefdc30 cyclades: avoid a... |
1738 |
struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; |
02f1175c8 [PATCH] Char: cyc... |
1739 |
int retval; |
f0eefdc30 cyclades: avoid a... |
1740 |
if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) { |
9fa1b3b18 Char: cyclades, r... |
1741 |
retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L); |
02f1175c8 [PATCH] Char: cyc... |
1742 |
if (retval != 0) { |
217191910 Char: cyclades, p... |
1743 1744 1745 |
printk(KERN_DEBUG "cyc:cy_close retval on " "ttyC%d was %x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
1746 |
} |
9fa1b3b18 Char: cyclades, r... |
1747 |
spin_unlock_irqrestore(&card->card_lock, flags); |
2c7fea992 Char: cyclades, r... |
1748 |
wait_for_completion_interruptible(&info->shutdown_wait); |
9fa1b3b18 Char: cyclades, r... |
1749 |
spin_lock_irqsave(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1750 |
} |
1da177e4c Linux-2.6.12-rc2 |
1751 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
1752 |
} |
9fa1b3b18 Char: cyclades, r... |
1753 |
spin_unlock_irqrestore(&card->card_lock, flags); |
e936ffd5c cyclades: use the... |
1754 1755 |
cy_shutdown(info, port->tty); } |
1da177e4c Linux-2.6.12-rc2 |
1756 |
|
e936ffd5c 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 [PATCH] Char: cyc... |
1766 |
} /* cy_close */ |
1da177e4c 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 [PATCH] Char: cyc... |
1781 |
static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) |
1da177e4c Linux-2.6.12-rc2 |
1782 |
{ |
cab9bdd14 Char: cyclades, r... |
1783 |
struct cyclades_port *info = tty->driver_data; |
02f1175c8 [PATCH] Char: cyc... |
1784 1785 |
unsigned long flags; int c, ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
1786 1787 |
#ifdef CY_DEBUG_IO |
217191910 Char: cyclades, p... |
1788 1789 |
printk(KERN_DEBUG "cyc:cy_write ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
1790 |
#endif |
15ed6cc0b cyclades: coding ... |
1791 |
if (serial_paranoia_check(info, tty->name, "cy_write")) |
02f1175c8 [PATCH] Char: cyc... |
1792 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1793 |
|
77451e53e cyclades: use tty... |
1794 |
if (!info->port.xmit_buf) |
02f1175c8 [PATCH] Char: cyc... |
1795 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1796 |
|
9fa1b3b18 Char: cyclades, r... |
1797 |
spin_lock_irqsave(&info->card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1798 |
while (1) { |
1a4e2351e 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 [PATCH] Char: cyc... |
1801 1802 1803 |
if (c <= 0) break; |
77451e53e cyclades: use tty... |
1804 |
memcpy(info->port.xmit_buf + info->xmit_head, buf, c); |
02f1175c8 [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 Char: cyclades, r... |
1812 |
spin_unlock_irqrestore(&info->card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
1813 1814 1815 |
info->idle_stats.xmit_bytes += ret; info->idle_stats.xmit_idle = jiffies; |
15ed6cc0b cyclades: coding ... |
1816 |
if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) |
02f1175c8 [PATCH] Char: cyc... |
1817 |
start_xmit(info); |
15ed6cc0b cyclades: coding ... |
1818 |
|
02f1175c8 [PATCH] Char: cyc... |
1819 1820 |
return ret; } /* cy_write */ |
1da177e4c 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 char: switch gs, ... |
1829 |
static int cy_put_char(struct tty_struct *tty, unsigned char ch) |
1da177e4c Linux-2.6.12-rc2 |
1830 |
{ |
cab9bdd14 Char: cyclades, r... |
1831 |
struct cyclades_port *info = tty->driver_data; |
02f1175c8 [PATCH] Char: cyc... |
1832 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
1833 1834 |
#ifdef CY_DEBUG_IO |
217191910 Char: cyclades, p... |
1835 1836 |
printk(KERN_DEBUG "cyc:cy_put_char ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
1837 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
1838 |
if (serial_paranoia_check(info, tty->name, "cy_put_char")) |
76b25a550 char: switch gs, ... |
1839 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1840 |
|
77451e53e cyclades: use tty... |
1841 |
if (!info->port.xmit_buf) |
76b25a550 char: switch gs, ... |
1842 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1843 |
|
9fa1b3b18 Char: cyclades, r... |
1844 |
spin_lock_irqsave(&info->card->card_lock, flags); |
90cc30185 [PATCH] Char: cyc... |
1845 |
if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { |
9fa1b3b18 Char: cyclades, r... |
1846 |
spin_unlock_irqrestore(&info->card->card_lock, flags); |
76b25a550 char: switch gs, ... |
1847 |
return 0; |
02f1175c8 [PATCH] Char: cyc... |
1848 |
} |
1da177e4c Linux-2.6.12-rc2 |
1849 |
|
77451e53e cyclades: use tty... |
1850 |
info->port.xmit_buf[info->xmit_head++] = ch; |
02f1175c8 [PATCH] Char: cyc... |
1851 1852 |
info->xmit_head &= SERIAL_XMIT_SIZE - 1; info->xmit_cnt++; |
1da177e4c Linux-2.6.12-rc2 |
1853 1854 |
info->idle_stats.xmit_bytes++; info->idle_stats.xmit_idle = jiffies; |
9fa1b3b18 Char: cyclades, r... |
1855 |
spin_unlock_irqrestore(&info->card->card_lock, flags); |
76b25a550 char: switch gs, ... |
1856 |
return 1; |
02f1175c8 [PATCH] Char: cyc... |
1857 |
} /* cy_put_char */ |
1da177e4c Linux-2.6.12-rc2 |
1858 1859 1860 |
/* * This routine is called by the kernel after it has written a |
15ed6cc0b cyclades: coding ... |
1861 |
* series of characters to the tty device using put_char(). |
1da177e4c Linux-2.6.12-rc2 |
1862 |
*/ |
02f1175c8 [PATCH] Char: cyc... |
1863 |
static void cy_flush_chars(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1864 |
{ |
cab9bdd14 Char: cyclades, r... |
1865 |
struct cyclades_port *info = tty->driver_data; |
02f1175c8 [PATCH] Char: cyc... |
1866 |
|
1da177e4c Linux-2.6.12-rc2 |
1867 |
#ifdef CY_DEBUG_IO |
217191910 Char: cyclades, p... |
1868 1869 |
printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
1870 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
1871 1872 |
if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) return; |
1da177e4c Linux-2.6.12-rc2 |
1873 |
|
02f1175c8 [PATCH] Char: cyc... |
1874 |
if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || |
77451e53e cyclades: use tty... |
1875 |
!info->port.xmit_buf) |
02f1175c8 [PATCH] Char: cyc... |
1876 |
return; |
1da177e4c Linux-2.6.12-rc2 |
1877 |
|
02f1175c8 [PATCH] Char: cyc... |
1878 1879 |
start_xmit(info); } /* cy_flush_chars */ |
1da177e4c 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 [PATCH] Char: cyc... |
1887 |
static int cy_write_room(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1888 |
{ |
cab9bdd14 Char: cyclades, r... |
1889 |
struct cyclades_port *info = tty->driver_data; |
02f1175c8 [PATCH] Char: cyc... |
1890 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
1891 |
#ifdef CY_DEBUG_IO |
217191910 Char: cyclades, p... |
1892 1893 |
printk(KERN_DEBUG "cyc:cy_write_room ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
1894 |
#endif |
02f1175c8 [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 Linux-2.6.12-rc2 |
1902 |
|
02f1175c8 [PATCH] Char: cyc... |
1903 |
static int cy_chars_in_buffer(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1904 |
{ |
cab9bdd14 Char: cyclades, r... |
1905 |
struct cyclades_port *info = tty->driver_data; |
1da177e4c Linux-2.6.12-rc2 |
1906 |
|
02f1175c8 [PATCH] Char: cyc... |
1907 1908 |
if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) return 0; |
1da177e4c Linux-2.6.12-rc2 |
1909 |
#ifdef Z_EXT_CHARS_IN_BUFFER |
f0eefdc30 cyclades: avoid a... |
1910 |
if (!cy_is_Z(info->card)) { |
02f1175c8 [PATCH] Char: cyc... |
1911 |
#endif /* Z_EXT_CHARS_IN_BUFFER */ |
1da177e4c Linux-2.6.12-rc2 |
1912 |
#ifdef CY_DEBUG_IO |
217191910 Char: cyclades, p... |
1913 1914 1915 |
printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d ", info->line, info->xmit_cnt); |
1da177e4c Linux-2.6.12-rc2 |
1916 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
1917 |
return info->xmit_cnt; |
1da177e4c Linux-2.6.12-rc2 |
1918 |
#ifdef Z_EXT_CHARS_IN_BUFFER |
02f1175c8 [PATCH] Char: cyc... |
1919 |
} else { |
f0eefdc30 cyclades: avoid a... |
1920 |
struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; |
02f1175c8 [PATCH] Char: cyc... |
1921 |
int char_count; |
ad39c3004 Char: cyclades, r... |
1922 |
__u32 tx_put, tx_get, tx_bufsize; |
02f1175c8 [PATCH] Char: cyc... |
1923 |
|
db05c3b1d 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 [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 Linux-2.6.12-rc2 |
1931 |
#ifdef CY_DEBUG_IO |
217191910 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 Linux-2.6.12-rc2 |
1935 |
#endif |
096dcfce3 [PATCH] Char: cyc... |
1936 |
return info->xmit_cnt + char_count; |
02f1175c8 [PATCH] Char: cyc... |
1937 1938 1939 |
} #endif /* Z_EXT_CHARS_IN_BUFFER */ } /* cy_chars_in_buffer */ |
1da177e4c Linux-2.6.12-rc2 |
1940 1941 1942 1943 1944 1945 |
/* * ------------------------------------------------------------ * cy_ioctl() and friends * ------------------------------------------------------------ */ |
1a86b5e34 cyclades: remove ... |
1946 |
static void cyy_baud_calc(struct cyclades_port *info, __u32 baud) |
1da177e4c Linux-2.6.12-rc2 |
1947 |
{ |
02f1175c8 [PATCH] Char: cyc... |
1948 |
int co, co_val, bpr; |
1a86b5e34 cyclades: remove ... |
1949 |
__u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : |
02f1175c8 [PATCH] Char: cyc... |
1950 |
25000000); |
1da177e4c Linux-2.6.12-rc2 |
1951 |
|
02f1175c8 [PATCH] Char: cyc... |
1952 1953 1954 1955 |
if (baud == 0) { info->tbpr = info->tco = info->rbpr = info->rco = 0; return; } |
1da177e4c Linux-2.6.12-rc2 |
1956 |
|
02f1175c8 [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 Linux-2.6.12-rc2 |
1962 |
|
02f1175c8 [PATCH] Char: cyc... |
1963 1964 1965 |
bpr = (cy_clock / co_val * 2 / baud + 1) / 2; if (bpr > 255) bpr = 255; |
1da177e4c Linux-2.6.12-rc2 |
1966 |
|
02f1175c8 [PATCH] Char: cyc... |
1967 1968 |
info->tbpr = info->rbpr = bpr; info->tco = info->rco = co; |
1da177e4c 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 cyclades: add tty... |
1975 |
static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1976 |
{ |
875b206b5 Char: cyclades, m... |
1977 |
struct cyclades_card *card; |
02f1175c8 [PATCH] Char: cyc... |
1978 |
unsigned long flags; |
3aeea5b92 cyclades: introdu... |
1979 |
int channel; |
02f1175c8 [PATCH] Char: cyc... |
1980 |
unsigned cflag, iflag; |
02f1175c8 [PATCH] Char: cyc... |
1981 1982 |
int baud, baud_rate = 0; int i; |
d13549f80 cyclades: add tty... |
1983 |
if (!tty->termios) /* XXX can this happen at all? */ |
02f1175c8 [PATCH] Char: cyc... |
1984 |
return; |
15ed6cc0b cyclades: coding ... |
1985 1986 |
if (info->line == -1) |
02f1175c8 [PATCH] Char: cyc... |
1987 |
return; |
15ed6cc0b cyclades: coding ... |
1988 |
|
d13549f80 cyclades: add tty... |
1989 1990 |
cflag = tty->termios->c_cflag; iflag = tty->termios->c_iflag; |
1da177e4c Linux-2.6.12-rc2 |
1991 |
|
02f1175c8 [PATCH] Char: cyc... |
1992 1993 1994 |
/* * Set up the tty->alt_speed kludge */ |
d13549f80 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 [PATCH] Char: cyc... |
2003 2004 |
card = info->card; |
875b206b5 Char: cyclades, m... |
2005 |
channel = info->line - card->first_line; |
02f1175c8 [PATCH] Char: cyc... |
2006 |
|
2693f485c tty: cyclades, co... |
2007 |
if (!cy_is_Z(card)) { |
46fb78252 cyclades: remove ... |
2008 |
u32 cflags; |
02f1175c8 [PATCH] Char: cyc... |
2009 |
/* baud rate */ |
d13549f80 cyclades: add tty... |
2010 |
baud = tty_get_baud_rate(tty); |
77451e53e cyclades: use tty... |
2011 |
if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == |
02f1175c8 [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 cyclades: coding ... |
2022 |
if (baud == baud_table[i]) |
02f1175c8 [PATCH] Char: cyc... |
2023 |
break; |
02f1175c8 [PATCH] Char: cyc... |
2024 |
} |
15ed6cc0b cyclades: coding ... |
2025 |
if (i == 20) |
02f1175c8 [PATCH] Char: cyc... |
2026 |
i = 19; /* CD1400_MAX_SPEED */ |
02f1175c8 [PATCH] Char: cyc... |
2027 |
|
77451e53e cyclades: use tty... |
2028 |
if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == |
02f1175c8 [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 cyclades: use tty... |
2049 |
} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == |
02f1175c8 [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 cyclades: coding ... |
2085 |
if (cflag & CSTOPB) |
02f1175c8 [PATCH] Char: cyc... |
2086 |
info->cor1 |= Cy_2_STOP; |
15ed6cc0b cyclades: coding ... |
2087 |
|
02f1175c8 [PATCH] Char: cyc... |
2088 |
if (cflag & PARENB) { |
15ed6cc0b cyclades: coding ... |
2089 |
if (cflag & PARODD) |
02f1175c8 [PATCH] Char: cyc... |
2090 |
info->cor1 |= CyPARITY_O; |
15ed6cc0b cyclades: coding ... |
2091 |
else |
02f1175c8 [PATCH] Char: cyc... |
2092 |
info->cor1 |= CyPARITY_E; |
15ed6cc0b cyclades: coding ... |
2093 |
} else |
02f1175c8 [PATCH] Char: cyc... |
2094 |
info->cor1 |= CyPARITY_NONE; |
02f1175c8 [PATCH] Char: cyc... |
2095 2096 2097 |
/* CTS flow control flag */ if (cflag & CRTSCTS) { |
77451e53e cyclades: use tty... |
2098 |
info->port.flags |= ASYNC_CTS_FLOW; |
02f1175c8 [PATCH] Char: cyc... |
2099 2100 |
info->cor2 |= CyCtsAE; } else { |
77451e53e cyclades: use tty... |
2101 |
info->port.flags &= ~ASYNC_CTS_FLOW; |
02f1175c8 [PATCH] Char: cyc... |
2102 2103 2104 |
info->cor2 &= ~CyCtsAE; } if (cflag & CLOCAL) |
77451e53e cyclades: use tty... |
2105 |
info->port.flags &= ~ASYNC_CHECK_CD; |
02f1175c8 [PATCH] Char: cyc... |
2106 |
else |
77451e53e cyclades: use tty... |
2107 |
info->port.flags |= ASYNC_CHECK_CD; |
1da177e4c 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 [PATCH] Char: cyc... |
2118 |
channel &= 0x03; |
1da177e4c Linux-2.6.12-rc2 |
2119 |
|
9fa1b3b18 Char: cyclades, r... |
2120 |
spin_lock_irqsave(&card->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
2121 |
cyy_writeb(info, CyCAR, channel); |
02f1175c8 [PATCH] Char: cyc... |
2122 2123 |
/* tx and rx baud rate */ |
3aeea5b92 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 [PATCH] Char: cyc... |
2128 2129 |
/* set line characteristics according configuration */ |
3aeea5b92 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 [PATCH] Char: cyc... |
2137 |
|
3aeea5b92 cyclades: introdu... |
2138 2139 |
cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch | CyCOR3ch); |
02f1175c8 [PATCH] Char: cyc... |
2140 |
|
15ed6cc0b cyclades: coding ... |
2141 |
/* !!! Is this needed? */ |
3aeea5b92 cyclades: introdu... |
2142 2143 |
cyy_writeb(info, CyCAR, channel); cyy_writeb(info, CyRTPR, |
02f1175c8 [PATCH] Char: cyc... |
2144 2145 |
(info->default_timeout ? info->default_timeout : 0x02)); /* 10ms rx timeout */ |
46fb78252 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 [PATCH] Char: cyc... |
2158 |
|
4d7682005 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 Linux-2.6.12-rc2 |
2163 |
|
d13549f80 cyclades: add tty... |
2164 |
clear_bit(TTY_IO_ERROR, &tty->flags); |
9fa1b3b18 Char: cyclades, r... |
2165 |
spin_unlock_irqrestore(&card->card_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
2166 |
|
1da177e4c Linux-2.6.12-rc2 |
2167 |
} else { |
f0eefdc30 cyclades: avoid a... |
2168 |
struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; |
1a86b5e34 cyclades: remove ... |
2169 |
__u32 sw_flow; |
02f1175c8 [PATCH] Char: cyc... |
2170 |
int retval; |
1da177e4c Linux-2.6.12-rc2 |
2171 |
|
2693f485c tty: cyclades, co... |
2172 |
if (!cyz_is_loaded(card)) |
02f1175c8 [PATCH] Char: cyc... |
2173 |
return; |
1da177e4c Linux-2.6.12-rc2 |
2174 |
|
02f1175c8 [PATCH] Char: cyc... |
2175 |
/* baud rate */ |
d13549f80 cyclades: add tty... |
2176 |
baud = tty_get_baud_rate(tty); |
77451e53e cyclades: use tty... |
2177 |
if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == |
02f1175c8 [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 cyclades: use tty... |
2192 |
} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == |
02f1175c8 [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 Linux-2.6.12-rc2 |
2203 |
|
02f1175c8 [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 Char: cyclades, c... |
2221 |
readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); |
02f1175c8 [PATCH] Char: cyc... |
2222 2223 |
} else { cy_writel(&ch_ctrl->comm_data_l, |
db05c3b1d Char: cyclades, c... |
2224 |
readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); |
02f1175c8 [PATCH] Char: cyc... |
2225 2226 |
} if (cflag & PARENB) { |
15ed6cc0b cyclades: coding ... |
2227 |
if (cflag & PARODD) |
02f1175c8 [PATCH] Char: cyc... |
2228 |
cy_writel(&ch_ctrl->comm_parity, C_PR_ODD); |
15ed6cc0b cyclades: coding ... |
2229 |
else |
02f1175c8 [PATCH] Char: cyc... |
2230 |
cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN); |
15ed6cc0b cyclades: coding ... |
2231 |
} else |
02f1175c8 [PATCH] Char: cyc... |
2232 |
cy_writel(&ch_ctrl->comm_parity, C_PR_NONE); |
1da177e4c Linux-2.6.12-rc2 |
2233 |
|
02f1175c8 [PATCH] Char: cyc... |
2234 2235 2236 |
/* CTS flow control flag */ if (cflag & CRTSCTS) { cy_writel(&ch_ctrl->hw_flow, |
db05c3b1d Char: cyclades, c... |
2237 |
readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); |
02f1175c8 [PATCH] Char: cyc... |
2238 |
} else { |
db05c3b1d Char: cyclades, c... |
2239 2240 |
cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) & ~(C_RS_CTS | C_RS_RTS)); |
02f1175c8 [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 cyclades: use tty... |
2244 |
info->port.flags &= ~ASYNC_CTS_FLOW; |
02f1175c8 [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 Char: cyclades, m... |
2254 |
retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); |
02f1175c8 [PATCH] Char: cyc... |
2255 |
if (retval != 0) { |
217191910 Char: cyclades, p... |
2256 2257 2258 |
printk(KERN_ERR "cyc:set_line_char retval on ttyC%d " "was %x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
2259 2260 2261 |
} /* CD sensitivity */ |
15ed6cc0b cyclades: coding ... |
2262 |
if (cflag & CLOCAL) |
77451e53e cyclades: use tty... |
2263 |
info->port.flags &= ~ASYNC_CHECK_CD; |
15ed6cc0b cyclades: coding ... |
2264 |
else |
77451e53e cyclades: use tty... |
2265 |
info->port.flags |= ASYNC_CHECK_CD; |
1da177e4c Linux-2.6.12-rc2 |
2266 |
|
02f1175c8 [PATCH] Char: cyc... |
2267 2268 |
if (baud == 0) { /* baud rate is zero, turn off line */ cy_writel(&ch_ctrl->rs_control, |
db05c3b1d Char: cyclades, c... |
2269 |
readl(&ch_ctrl->rs_control) & ~C_RS_DTR); |
1da177e4c Linux-2.6.12-rc2 |
2270 |
#ifdef CY_DEBUG_DTR |
217191910 Char: cyclades, p... |
2271 2272 |
printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR "); |
1da177e4c Linux-2.6.12-rc2 |
2273 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2274 2275 |
} else { cy_writel(&ch_ctrl->rs_control, |
db05c3b1d Char: cyclades, c... |
2276 |
readl(&ch_ctrl->rs_control) | C_RS_DTR); |
1da177e4c Linux-2.6.12-rc2 |
2277 |
#ifdef CY_DEBUG_DTR |
217191910 Char: cyclades, p... |
2278 2279 |
printk(KERN_DEBUG "cyc:set_line_char raising Z DTR "); |
1da177e4c Linux-2.6.12-rc2 |
2280 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2281 |
} |
1da177e4c Linux-2.6.12-rc2 |
2282 |
|
15ed6cc0b cyclades: coding ... |
2283 |
retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); |
02f1175c8 [PATCH] Char: cyc... |
2284 |
if (retval != 0) { |
217191910 Char: cyclades, p... |
2285 2286 2287 |
printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d " "was %x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
2288 |
} |
1da177e4c Linux-2.6.12-rc2 |
2289 |
|
d13549f80 cyclades: add tty... |
2290 |
clear_bit(TTY_IO_ERROR, &tty->flags); |
1da177e4c Linux-2.6.12-rc2 |
2291 |
} |
02f1175c8 [PATCH] Char: cyc... |
2292 |
} /* set_line_char */ |
1da177e4c Linux-2.6.12-rc2 |
2293 |
|
6c28181cf cyclades: ioctls ... |
2294 |
static int cy_get_serial_info(struct cyclades_port *info, |
15ed6cc0b cyclades: coding ... |
2295 |
struct serial_struct __user *retinfo) |
1da177e4c Linux-2.6.12-rc2 |
2296 |
{ |
875b206b5 Char: cyclades, m... |
2297 |
struct cyclades_card *cinfo = info->card; |
6c28181cf 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 [PATCH] Char: cyc... |
2311 |
return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; |
6c28181cf cyclades: ioctls ... |
2312 |
} |
1da177e4c Linux-2.6.12-rc2 |
2313 2314 |
static int |
d13549f80 cyclades: add tty... |
2315 |
cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, |
15ed6cc0b cyclades: coding ... |
2316 |
struct serial_struct __user *new_info) |
1da177e4c Linux-2.6.12-rc2 |
2317 |
{ |
02f1175c8 [PATCH] Char: cyc... |
2318 |
struct serial_struct new_serial; |
25c3cdf80 cyclades: Kill of... |
2319 |
int ret; |
02f1175c8 [PATCH] Char: cyc... |
2320 2321 2322 |
if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) return -EFAULT; |
02f1175c8 [PATCH] Char: cyc... |
2323 |
|
25c3cdf80 cyclades: Kill of... |
2324 |
mutex_lock(&info->port.mutex); |
02f1175c8 [PATCH] Char: cyc... |
2325 |
if (!capable(CAP_SYS_ADMIN)) { |
44b7d1b37 tty: add more tty... |
2326 |
if (new_serial.close_delay != info->port.close_delay || |
02f1175c8 [PATCH] Char: cyc... |
2327 2328 2329 |
new_serial.baud_base != info->baud || (new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != |
77451e53e cyclades: use tty... |
2330 |
(info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) |
25c3cdf80 cyclades: Kill of... |
2331 2332 |
{ mutex_unlock(&info->port.mutex); |
02f1175c8 [PATCH] Char: cyc... |
2333 |
return -EPERM; |
25c3cdf80 cyclades: Kill of... |
2334 |
} |
77451e53e cyclades: use tty... |
2335 |
info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | |
02f1175c8 [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 cyclades: use tty... |
2349 |
info->port.flags = (info->port.flags & ~ASYNC_FLAGS) | |
02f1175c8 [PATCH] Char: cyc... |
2350 |
(new_serial.flags & ASYNC_FLAGS); |
44b7d1b37 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 Linux-2.6.12-rc2 |
2353 2354 |
check_and_exit: |
77451e53e cyclades: use tty... |
2355 |
if (info->port.flags & ASYNC_INITIALIZED) { |
d13549f80 cyclades: add tty... |
2356 |
cy_set_line_char(info, tty); |
25c3cdf80 cyclades: Kill of... |
2357 |
ret = 0; |
02f1175c8 [PATCH] Char: cyc... |
2358 |
} else { |
25c3cdf80 cyclades: Kill of... |
2359 |
ret = cy_startup(info, tty); |
02f1175c8 [PATCH] Char: cyc... |
2360 |
} |
25c3cdf80 cyclades: Kill of... |
2361 2362 |
mutex_unlock(&info->port.mutex); return ret; |
02f1175c8 [PATCH] Char: cyc... |
2363 |
} /* set_serial_info */ |
1da177e4c 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 cyclades: coding ... |
2375 |
static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) |
1da177e4c Linux-2.6.12-rc2 |
2376 |
{ |
3aeea5b92 cyclades: introdu... |
2377 |
struct cyclades_card *card = info->card; |
02f1175c8 [PATCH] Char: cyc... |
2378 2379 |
unsigned int result; unsigned long flags; |
3aeea5b92 cyclades: introdu... |
2380 |
u8 status; |
1da177e4c Linux-2.6.12-rc2 |
2381 |
|
2693f485c tty: cyclades, co... |
2382 |
if (!cy_is_Z(card)) { |
9fa1b3b18 Char: cyclades, r... |
2383 |
spin_lock_irqsave(&card->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
2384 |
status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty); |
9fa1b3b18 Char: cyclades, r... |
2385 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [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 Linux-2.6.12-rc2 |
2392 |
} |
60b33c133 tiocmget: kill of... |
2393 |
static int cy_tiocmget(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
2394 |
{ |
cab9bdd14 Char: cyclades, r... |
2395 |
struct cyclades_port *info = tty->driver_data; |
875b206b5 Char: cyclades, m... |
2396 |
struct cyclades_card *card; |
3aeea5b92 cyclades: introdu... |
2397 |
int result; |
02f1175c8 [PATCH] Char: cyc... |
2398 |
|
bf9d89295 drivers/char: rep... |
2399 |
if (serial_paranoia_check(info, tty->name, __func__)) |
02f1175c8 [PATCH] Char: cyc... |
2400 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
2401 |
|
02f1175c8 [PATCH] Char: cyc... |
2402 |
card = info->card; |
0d3487294 cyclades: tiocm c... |
2403 |
|
2693f485c tty: cyclades, co... |
2404 |
if (!cy_is_Z(card)) { |
0d3487294 cyclades: tiocm c... |
2405 |
unsigned long flags; |
3aeea5b92 cyclades: introdu... |
2406 2407 |
int channel = info->line - card->first_line; u8 status; |
1da177e4c Linux-2.6.12-rc2 |
2408 |
|
9fa1b3b18 Char: cyclades, r... |
2409 |
spin_lock_irqsave(&card->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
2410 2411 2412 |
cyy_writeb(info, CyCAR, channel & 0x03); status = cyy_readb(info, CyMSVR1); status |= cyy_readb(info, CyMSVR2); |
9fa1b3b18 Char: cyclades, r... |
2413 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [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 Linux-2.6.12-rc2 |
2426 |
} else { |
0d3487294 cyclades: tiocm c... |
2427 2428 2429 2430 2431 |
u32 lstatus; if (!cyz_is_loaded(card)) { result = -ENODEV; goto end; |
02f1175c8 [PATCH] Char: cyc... |
2432 |
} |
1da177e4c Linux-2.6.12-rc2 |
2433 |
|
0d3487294 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 [PATCH] Char: cyc... |
2441 |
} |
0d3487294 cyclades: tiocm c... |
2442 |
end: |
02f1175c8 [PATCH] Char: cyc... |
2443 2444 |
return result; } /* cy_tiomget */ |
1da177e4c Linux-2.6.12-rc2 |
2445 2446 |
static int |
20b9d1771 tiocmset: kill th... |
2447 |
cy_tiocmset(struct tty_struct *tty, |
02f1175c8 [PATCH] Char: cyc... |
2448 |
unsigned int set, unsigned int clear) |
1da177e4c Linux-2.6.12-rc2 |
2449 |
{ |
cab9bdd14 Char: cyclades, r... |
2450 |
struct cyclades_port *info = tty->driver_data; |
875b206b5 Char: cyclades, m... |
2451 |
struct cyclades_card *card; |
02f1175c8 [PATCH] Char: cyc... |
2452 |
unsigned long flags; |
02f1175c8 [PATCH] Char: cyc... |
2453 |
|
bf9d89295 drivers/char: rep... |
2454 |
if (serial_paranoia_check(info, tty->name, __func__)) |
02f1175c8 [PATCH] Char: cyc... |
2455 2456 2457 |
return -ENODEV; card = info->card; |
2693f485c tty: cyclades, co... |
2458 |
if (!cy_is_Z(card)) { |
4d7682005 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 [PATCH] Char: cyc... |
2462 |
} else { |
0d3487294 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 Linux-2.6.12-rc2 |
2478 |
#ifdef CY_DEBUG_DTR |
0d3487294 cyclades: tiocm c... |
2479 2480 |
printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR "); |
1da177e4c Linux-2.6.12-rc2 |
2481 |
#endif |
0d3487294 cyclades: tiocm c... |
2482 2483 2484 |
} if (clear & TIOCM_DTR) { rs &= ~C_RS_DTR; |
1da177e4c Linux-2.6.12-rc2 |
2485 |
#ifdef CY_DEBUG_DTR |
0d3487294 cyclades: tiocm c... |
2486 2487 2488 |
printk(KERN_DEBUG "cyc:set_modem_info clearing " "Z DTR "); |
1da177e4c Linux-2.6.12-rc2 |
2489 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2490 |
} |
0d3487294 cyclades: tiocm c... |
2491 |
cy_writel(&ch_ctrl->rs_control, rs); |
9fa1b3b18 Char: cyclades, r... |
2492 |
retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); |
0d3487294 cyclades: tiocm c... |
2493 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2494 |
if (retval != 0) { |
217191910 Char: cyclades, p... |
2495 2496 2497 |
printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " "was %x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
2498 |
} |
1da177e4c Linux-2.6.12-rc2 |
2499 |
} |
02f1175c8 [PATCH] Char: cyc... |
2500 |
return 0; |
0d3487294 cyclades: tiocm c... |
2501 |
} |
1da177e4c Linux-2.6.12-rc2 |
2502 2503 2504 2505 |
/* * cy_break() --- routine which turns the break handling on or off */ |
9e98966c7 tty: rework break... |
2506 |
static int cy_break(struct tty_struct *tty, int break_state) |
1da177e4c Linux-2.6.12-rc2 |
2507 |
{ |
cab9bdd14 Char: cyclades, r... |
2508 |
struct cyclades_port *info = tty->driver_data; |
9fa1b3b18 Char: cyclades, r... |
2509 |
struct cyclades_card *card; |
02f1175c8 [PATCH] Char: cyc... |
2510 |
unsigned long flags; |
9e98966c7 tty: rework break... |
2511 |
int retval = 0; |
1da177e4c Linux-2.6.12-rc2 |
2512 |
|
02f1175c8 [PATCH] Char: cyc... |
2513 |
if (serial_paranoia_check(info, tty->name, "cy_break")) |
9e98966c7 tty: rework break... |
2514 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
2515 |
|
9fa1b3b18 Char: cyclades, r... |
2516 2517 2518 |
card = info->card; spin_lock_irqsave(&card->card_lock, flags); |
2693f485c tty: cyclades, co... |
2519 |
if (!cy_is_Z(card)) { |
02f1175c8 [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 Char: cyclades, r... |
2527 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2528 |
start_xmit(info); |
9fa1b3b18 Char: cyclades, r... |
2529 |
spin_lock_irqsave(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2530 2531 2532 2533 2534 2535 |
} } } else { if (!info->breakoff) { info->breakoff = 1; if (!info->xmit_cnt) { |
9fa1b3b18 Char: cyclades, r... |
2536 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2537 |
start_xmit(info); |
9fa1b3b18 Char: cyclades, r... |
2538 |
spin_lock_irqsave(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2539 2540 |
} } |
1da177e4c Linux-2.6.12-rc2 |
2541 |
} |
1da177e4c Linux-2.6.12-rc2 |
2542 |
} else { |
02f1175c8 [PATCH] Char: cyc... |
2543 |
if (break_state == -1) { |
9fa1b3b18 Char: cyclades, r... |
2544 2545 |
retval = cyz_issue_cmd(card, info->line - card->first_line, |
02f1175c8 [PATCH] Char: cyc... |
2546 2547 |
C_CM_SET_BREAK, 0L); if (retval != 0) { |
217191910 Char: cyclades, p... |
2548 2549 2550 |
printk(KERN_ERR "cyc:cy_break (set) retval on " "ttyC%d was %x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
2551 2552 |
} } else { |
9fa1b3b18 Char: cyclades, r... |
2553 2554 |
retval = cyz_issue_cmd(card, info->line - card->first_line, |
02f1175c8 [PATCH] Char: cyc... |
2555 2556 |
C_CM_CLR_BREAK, 0L); if (retval != 0) { |
217191910 Char: cyclades, p... |
2557 2558 2559 2560 |
printk(KERN_DEBUG "cyc:cy_break (clr) retval " "on ttyC%d was %x ", info->line, retval); |
02f1175c8 [PATCH] Char: cyc... |
2561 |
} |
1da177e4c Linux-2.6.12-rc2 |
2562 |
} |
1da177e4c Linux-2.6.12-rc2 |
2563 |
} |
9fa1b3b18 Char: cyclades, r... |
2564 |
spin_unlock_irqrestore(&card->card_lock, flags); |
9e98966c7 tty: rework break... |
2565 |
return retval; |
02f1175c8 [PATCH] Char: cyc... |
2566 |
} /* cy_break */ |
1da177e4c Linux-2.6.12-rc2 |
2567 |
|
02f1175c8 [PATCH] Char: cyc... |
2568 |
static int set_threshold(struct cyclades_port *info, unsigned long value) |
1da177e4c Linux-2.6.12-rc2 |
2569 |
{ |
3aeea5b92 cyclades: introdu... |
2570 |
struct cyclades_card *card = info->card; |
02f1175c8 [PATCH] Char: cyc... |
2571 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
2572 |
|
2693f485c tty: cyclades, co... |
2573 |
if (!cy_is_Z(card)) { |
02f1175c8 [PATCH] Char: cyc... |
2574 2575 |
info->cor3 &= ~CyREC_FIFO; info->cor3 |= value & CyREC_FIFO; |
1da177e4c Linux-2.6.12-rc2 |
2576 |
|
9fa1b3b18 Char: cyclades, r... |
2577 |
spin_lock_irqsave(&card->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
2578 2579 |
cyy_writeb(info, CyCOR3, info->cor3); cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch); |
9fa1b3b18 Char: cyclades, r... |
2580 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2581 2582 2583 |
} return 0; } /* set_threshold */ |
1da177e4c Linux-2.6.12-rc2 |
2584 |
|
15ed6cc0b cyclades: coding ... |
2585 2586 |
static int get_threshold(struct cyclades_port *info, unsigned long __user *value) |
1da177e4c Linux-2.6.12-rc2 |
2587 |
{ |
3aeea5b92 cyclades: introdu... |
2588 |
struct cyclades_card *card = info->card; |
1da177e4c Linux-2.6.12-rc2 |
2589 |
|
2693f485c tty: cyclades, co... |
2590 |
if (!cy_is_Z(card)) { |
3aeea5b92 cyclades: introdu... |
2591 |
u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO; |
02f1175c8 [PATCH] Char: cyc... |
2592 |
return put_user(tmp, value); |
02f1175c8 [PATCH] Char: cyc... |
2593 |
} |
f74290342 Char: cyclades, c... |
2594 |
return 0; |
02f1175c8 [PATCH] Char: cyc... |
2595 |
} /* get_threshold */ |
1da177e4c Linux-2.6.12-rc2 |
2596 |
|
02f1175c8 [PATCH] Char: cyc... |
2597 |
static int set_timeout(struct cyclades_port *info, unsigned long value) |
1da177e4c Linux-2.6.12-rc2 |
2598 |
{ |
3aeea5b92 cyclades: introdu... |
2599 |
struct cyclades_card *card = info->card; |
02f1175c8 [PATCH] Char: cyc... |
2600 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
2601 |
|
2693f485c tty: cyclades, co... |
2602 |
if (!cy_is_Z(card)) { |
9fa1b3b18 Char: cyclades, r... |
2603 |
spin_lock_irqsave(&card->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
2604 |
cyy_writeb(info, CyRTPR, value & 0xff); |
9fa1b3b18 Char: cyclades, r... |
2605 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2606 2607 2608 |
} return 0; } /* set_timeout */ |
1da177e4c Linux-2.6.12-rc2 |
2609 |
|
15ed6cc0b cyclades: coding ... |
2610 2611 |
static int get_timeout(struct cyclades_port *info, unsigned long __user *value) |
1da177e4c Linux-2.6.12-rc2 |
2612 |
{ |
3aeea5b92 cyclades: introdu... |
2613 |
struct cyclades_card *card = info->card; |
1da177e4c Linux-2.6.12-rc2 |
2614 |
|
2693f485c tty: cyclades, co... |
2615 |
if (!cy_is_Z(card)) { |
3aeea5b92 cyclades: introdu... |
2616 |
u8 tmp = cyy_readb(info, CyRTPR); |
02f1175c8 [PATCH] Char: cyc... |
2617 |
return put_user(tmp, value); |
02f1175c8 [PATCH] Char: cyc... |
2618 |
} |
f74290342 Char: cyclades, c... |
2619 |
return 0; |
02f1175c8 [PATCH] Char: cyc... |
2620 |
} /* get_timeout */ |
1da177e4c Linux-2.6.12-rc2 |
2621 |
|
6c28181cf cyclades: ioctls ... |
2622 2623 |
static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg, struct cyclades_icount *cprev) |
1da177e4c Linux-2.6.12-rc2 |
2624 |
{ |
6c28181cf cyclades: ioctls ... |
2625 2626 2627 |
struct cyclades_icount cnow; unsigned long flags; int ret; |
1da177e4c Linux-2.6.12-rc2 |
2628 |
|
6c28181cf 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 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 tty: now phase ou... |
2649 |
cy_ioctl(struct tty_struct *tty, |
02f1175c8 [PATCH] Char: cyc... |
2650 |
unsigned int cmd, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
2651 |
{ |
cab9bdd14 Char: cyclades, r... |
2652 |
struct cyclades_port *info = tty->driver_data; |
6c28181cf cyclades: ioctls ... |
2653 |
struct cyclades_icount cnow; /* kernel counter temps */ |
02f1175c8 [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 Linux-2.6.12-rc2 |
2660 2661 |
#ifdef CY_DEBUG_OTHER |
217191910 Char: cyclades, p... |
2662 2663 2664 |
printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx ", info->line, cmd, arg); |
1da177e4c Linux-2.6.12-rc2 |
2665 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2666 2667 |
switch (cmd) { case CYGETMON: |
6c28181cf 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 [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 cyclades: ioctls ... |
2681 2682 |
ret_val = put_user(info->default_threshold, (unsigned long __user *)argp); |
02f1175c8 [PATCH] Char: cyc... |
2683 2684 |
break; case CYSETDEFTHRESH: |
6c28181cf cyclades: ioctls ... |
2685 |
info->default_threshold = arg & 0x0f; |
02f1175c8 [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 cyclades: ioctls ... |
2694 2695 |
ret_val = put_user(info->default_timeout, (unsigned long __user *)argp); |
02f1175c8 [PATCH] Char: cyc... |
2696 2697 |
break; case CYSETDEFTIMEOUT: |
6c28181cf cyclades: ioctls ... |
2698 |
info->default_timeout = arg & 0xff; |
02f1175c8 [PATCH] Char: cyc... |
2699 |
break; |
1da177e4c Linux-2.6.12-rc2 |
2700 |
case CYSETRFLOW: |
02f1175c8 [PATCH] Char: cyc... |
2701 |
info->rflow = (int)arg; |
02f1175c8 [PATCH] Char: cyc... |
2702 |
break; |
1da177e4c Linux-2.6.12-rc2 |
2703 |
case CYGETRFLOW: |
02f1175c8 [PATCH] Char: cyc... |
2704 2705 |
ret_val = info->rflow; break; |
1da177e4c Linux-2.6.12-rc2 |
2706 |
case CYSETRTSDTR_INV: |
02f1175c8 [PATCH] Char: cyc... |
2707 |
info->rtsdtr_inv = (int)arg; |
02f1175c8 [PATCH] Char: cyc... |
2708 |
break; |
1da177e4c Linux-2.6.12-rc2 |
2709 |
case CYGETRTSDTR_INV: |
02f1175c8 [PATCH] Char: cyc... |
2710 2711 |
ret_val = info->rtsdtr_inv; break; |
1da177e4c Linux-2.6.12-rc2 |
2712 |
case CYGETCD1400VER: |
02f1175c8 [PATCH] Char: cyc... |
2713 2714 |
ret_val = info->chip_rev; break; |
1da177e4c Linux-2.6.12-rc2 |
2715 2716 |
#ifndef CONFIG_CYZ_INTR case CYZSETPOLLCYCLE: |
02f1175c8 [PATCH] Char: cyc... |
2717 |
cyz_polling_cycle = (arg * HZ) / 1000; |
02f1175c8 [PATCH] Char: cyc... |
2718 |
break; |
1da177e4c Linux-2.6.12-rc2 |
2719 |
case CYZGETPOLLCYCLE: |
02f1175c8 [PATCH] Char: cyc... |
2720 2721 2722 |
ret_val = (cyz_polling_cycle * 1000) / HZ; break; #endif /* CONFIG_CYZ_INTR */ |
1da177e4c Linux-2.6.12-rc2 |
2723 |
case CYSETWAIT: |
44b7d1b37 tty: add more tty... |
2724 |
info->port.closing_wait = (unsigned short)arg * HZ / 100; |
02f1175c8 [PATCH] Char: cyc... |
2725 |
break; |
1da177e4c Linux-2.6.12-rc2 |
2726 |
case CYGETWAIT: |
44b7d1b37 tty: add more tty... |
2727 |
ret_val = info->port.closing_wait / (HZ / 100); |
02f1175c8 [PATCH] Char: cyc... |
2728 2729 |
break; case TIOCGSERIAL: |
6c28181cf cyclades: ioctls ... |
2730 |
ret_val = cy_get_serial_info(info, argp); |
02f1175c8 [PATCH] Char: cyc... |
2731 2732 |
break; case TIOCSSERIAL: |
d13549f80 cyclades: add tty... |
2733 |
ret_val = cy_set_serial_info(info, tty, argp); |
02f1175c8 [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 Linux-2.6.12-rc2 |
2744 |
case TIOCMIWAIT: |
9fa1b3b18 Char: cyclades, r... |
2745 |
spin_lock_irqsave(&info->card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2746 |
/* note the counters on entry */ |
2c7fea992 Char: cyclades, r... |
2747 |
cnow = info->icount; |
9fa1b3b18 Char: cyclades, r... |
2748 |
spin_unlock_irqrestore(&info->card->card_lock, flags); |
bdc04e317 serial: move delt... |
2749 |
ret_val = wait_event_interruptible(info->port.delta_msr_wait, |
6c28181cf cyclades: ioctls ... |
2750 |
cy_cflags_changed(info, arg, &cnow)); |
2c7fea992 Char: cyclades, r... |
2751 |
break; |
1da177e4c Linux-2.6.12-rc2 |
2752 |
|
02f1175c8 [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 [PATCH] Char: cyc... |
2759 2760 2761 |
default: ret_val = -ENOIOCTLCMD; } |
1da177e4c Linux-2.6.12-rc2 |
2762 2763 |
#ifdef CY_DEBUG_OTHER |
217191910 Char: cyclades, p... |
2764 2765 |
printk(KERN_DEBUG "cyc:cy_ioctl done "); |
1da177e4c Linux-2.6.12-rc2 |
2766 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2767 2768 |
return ret_val; } /* cy_ioctl */ |
1da177e4c Linux-2.6.12-rc2 |
2769 |
|
0587102cf 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 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 [PATCH] Char: cyc... |
2800 |
static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) |
1da177e4c Linux-2.6.12-rc2 |
2801 |
{ |
cab9bdd14 Char: cyclades, r... |
2802 |
struct cyclades_port *info = tty->driver_data; |
1da177e4c Linux-2.6.12-rc2 |
2803 2804 |
#ifdef CY_DEBUG_OTHER |
217191910 Char: cyclades, p... |
2805 2806 |
printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
2807 |
#endif |
d13549f80 cyclades: add tty... |
2808 |
cy_set_line_char(info, tty); |
02f1175c8 [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 Linux-2.6.12-rc2 |
2815 |
#if 0 |
02f1175c8 [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 cyclades: use tty... |
2824 |
wake_up_interruptible(&info->port.open_wait); |
1da177e4c Linux-2.6.12-rc2 |
2825 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2826 |
} /* cy_set_termios */ |
1da177e4c 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 [PATCH] Char: cyc... |
2831 |
static void cy_send_xchar(struct tty_struct *tty, char ch) |
1da177e4c Linux-2.6.12-rc2 |
2832 |
{ |
cab9bdd14 Char: cyclades, r... |
2833 |
struct cyclades_port *info = tty->driver_data; |
875b206b5 Char: cyclades, m... |
2834 2835 |
struct cyclades_card *card; int channel; |
1da177e4c Linux-2.6.12-rc2 |
2836 |
|
02f1175c8 [PATCH] Char: cyc... |
2837 |
if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) |
1da177e4c Linux-2.6.12-rc2 |
2838 |
return; |
02f1175c8 [PATCH] Char: cyc... |
2839 |
info->x_char = ch; |
1da177e4c Linux-2.6.12-rc2 |
2840 2841 |
if (ch) |
02f1175c8 [PATCH] Char: cyc... |
2842 |
cy_start(tty); |
1da177e4c Linux-2.6.12-rc2 |
2843 2844 |
card = info->card; |
875b206b5 Char: cyclades, m... |
2845 |
channel = info->line - card->first_line; |
1da177e4c Linux-2.6.12-rc2 |
2846 |
|
2693f485c tty: cyclades, co... |
2847 |
if (cy_is_Z(card)) { |
02f1175c8 [PATCH] Char: cyc... |
2848 |
if (ch == STOP_CHAR(tty)) |
875b206b5 Char: cyclades, m... |
2849 |
cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); |
02f1175c8 [PATCH] Char: cyc... |
2850 |
else if (ch == START_CHAR(tty)) |
875b206b5 Char: cyclades, m... |
2851 |
cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L); |
1da177e4c 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 [PATCH] Char: cyc... |
2859 |
static void cy_throttle(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
2860 |
{ |
cab9bdd14 Char: cyclades, r... |
2861 |
struct cyclades_port *info = tty->driver_data; |
875b206b5 Char: cyclades, m... |
2862 |
struct cyclades_card *card; |
02f1175c8 [PATCH] Char: cyc... |
2863 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
2864 2865 |
#ifdef CY_DEBUG_THROTTLE |
02f1175c8 [PATCH] Char: cyc... |
2866 |
char buf[64]; |
1da177e4c Linux-2.6.12-rc2 |
2867 |
|
217191910 Char: cyclades, p... |
2868 2869 |
printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d ", tty_name(tty, buf), |
02f1175c8 [PATCH] Char: cyc... |
2870 |
tty->ldisc.chars_in_buffer(tty), info->line); |
1da177e4c Linux-2.6.12-rc2 |
2871 |
#endif |
15ed6cc0b cyclades: coding ... |
2872 |
if (serial_paranoia_check(info, tty->name, "cy_throttle")) |
02f1175c8 [PATCH] Char: cyc... |
2873 |
return; |
02f1175c8 [PATCH] Char: cyc... |
2874 2875 2876 2877 |
card = info->card; if (I_IXOFF(tty)) { |
2693f485c tty: cyclades, co... |
2878 |
if (!cy_is_Z(card)) |
02f1175c8 [PATCH] Char: cyc... |
2879 2880 2881 2882 |
cy_send_xchar(tty, STOP_CHAR(tty)); else info->throttle = 1; } |
1da177e4c Linux-2.6.12-rc2 |
2883 |
|
02f1175c8 [PATCH] Char: cyc... |
2884 |
if (tty->termios->c_cflag & CRTSCTS) { |
2693f485c tty: cyclades, co... |
2885 |
if (!cy_is_Z(card)) { |
9fa1b3b18 Char: cyclades, r... |
2886 |
spin_lock_irqsave(&card->card_lock, flags); |
4d7682005 cyclades: use dtr... |
2887 |
cyy_change_rts_dtr(info, 0, TIOCM_RTS); |
9fa1b3b18 Char: cyclades, r... |
2888 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2889 2890 2891 2892 |
} else { info->throttle = 1; } } |
02f1175c8 [PATCH] Char: cyc... |
2893 |
} /* cy_throttle */ |
1da177e4c 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 [PATCH] Char: cyc... |
2900 |
static void cy_unthrottle(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
2901 |
{ |
cab9bdd14 Char: cyclades, r... |
2902 |
struct cyclades_port *info = tty->driver_data; |
875b206b5 Char: cyclades, m... |
2903 |
struct cyclades_card *card; |
02f1175c8 [PATCH] Char: cyc... |
2904 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
2905 2906 |
#ifdef CY_DEBUG_THROTTLE |
02f1175c8 [PATCH] Char: cyc... |
2907 |
char buf[64]; |
217191910 Char: cyclades, p... |
2908 2909 |
printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d ", |
15ed6cc0b cyclades: coding ... |
2910 |
tty_name(tty, buf), tty_chars_in_buffer(tty), info->line); |
1da177e4c Linux-2.6.12-rc2 |
2911 |
#endif |
15ed6cc0b cyclades: coding ... |
2912 |
if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) |
02f1175c8 [PATCH] Char: cyc... |
2913 |
return; |
1da177e4c Linux-2.6.12-rc2 |
2914 |
|
02f1175c8 [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 Linux-2.6.12-rc2 |
2920 |
} |
1da177e4c Linux-2.6.12-rc2 |
2921 |
|
02f1175c8 [PATCH] Char: cyc... |
2922 2923 |
if (tty->termios->c_cflag & CRTSCTS) { card = info->card; |
2693f485c tty: cyclades, co... |
2924 |
if (!cy_is_Z(card)) { |
9fa1b3b18 Char: cyclades, r... |
2925 |
spin_lock_irqsave(&card->card_lock, flags); |
4d7682005 cyclades: use dtr... |
2926 |
cyy_change_rts_dtr(info, TIOCM_RTS, 0); |
9fa1b3b18 Char: cyclades, r... |
2927 |
spin_unlock_irqrestore(&card->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2928 2929 2930 2931 |
} else { info->throttle = 0; } } |
02f1175c8 [PATCH] Char: cyc... |
2932 |
} /* cy_unthrottle */ |
1da177e4c 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 [PATCH] Char: cyc... |
2937 |
static void cy_stop(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
2938 |
{ |
02f1175c8 [PATCH] Char: cyc... |
2939 |
struct cyclades_card *cinfo; |
cab9bdd14 Char: cyclades, r... |
2940 |
struct cyclades_port *info = tty->driver_data; |
3aeea5b92 cyclades: introdu... |
2941 |
int channel; |
02f1175c8 [PATCH] Char: cyc... |
2942 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
2943 2944 |
#ifdef CY_DEBUG_OTHER |
217191910 Char: cyclades, p... |
2945 2946 |
printk(KERN_DEBUG "cyc:cy_stop ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
2947 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2948 2949 |
if (serial_paranoia_check(info, tty->name, "cy_stop")) return; |
1da177e4c Linux-2.6.12-rc2 |
2950 |
|
875b206b5 Char: cyclades, m... |
2951 |
cinfo = info->card; |
02f1175c8 [PATCH] Char: cyc... |
2952 |
channel = info->line - cinfo->first_line; |
2693f485c tty: cyclades, co... |
2953 |
if (!cy_is_Z(cinfo)) { |
9fa1b3b18 Char: cyclades, r... |
2954 |
spin_lock_irqsave(&cinfo->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
2955 2956 |
cyy_writeb(info, CyCAR, channel & 0x03); cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); |
9fa1b3b18 Char: cyclades, r... |
2957 |
spin_unlock_irqrestore(&cinfo->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2958 |
} |
02f1175c8 [PATCH] Char: cyc... |
2959 |
} /* cy_stop */ |
1da177e4c Linux-2.6.12-rc2 |
2960 |
|
02f1175c8 [PATCH] Char: cyc... |
2961 |
static void cy_start(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
2962 |
{ |
02f1175c8 [PATCH] Char: cyc... |
2963 |
struct cyclades_card *cinfo; |
cab9bdd14 Char: cyclades, r... |
2964 |
struct cyclades_port *info = tty->driver_data; |
3aeea5b92 cyclades: introdu... |
2965 |
int channel; |
02f1175c8 [PATCH] Char: cyc... |
2966 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
2967 2968 |
#ifdef CY_DEBUG_OTHER |
217191910 Char: cyclades, p... |
2969 2970 |
printk(KERN_DEBUG "cyc:cy_start ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
2971 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2972 2973 |
if (serial_paranoia_check(info, tty->name, "cy_start")) return; |
1da177e4c Linux-2.6.12-rc2 |
2974 |
|
875b206b5 Char: cyclades, m... |
2975 |
cinfo = info->card; |
02f1175c8 [PATCH] Char: cyc... |
2976 |
channel = info->line - cinfo->first_line; |
2693f485c tty: cyclades, co... |
2977 |
if (!cy_is_Z(cinfo)) { |
9fa1b3b18 Char: cyclades, r... |
2978 |
spin_lock_irqsave(&cinfo->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
2979 2980 |
cyy_writeb(info, CyCAR, channel & 0x03); cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); |
9fa1b3b18 Char: cyclades, r... |
2981 |
spin_unlock_irqrestore(&cinfo->card_lock, flags); |
02f1175c8 [PATCH] Char: cyc... |
2982 |
} |
02f1175c8 [PATCH] Char: cyc... |
2983 |
} /* cy_start */ |
1da177e4c Linux-2.6.12-rc2 |
2984 |
|
1da177e4c Linux-2.6.12-rc2 |
2985 2986 2987 |
/* * cy_hangup() --- called by tty_hangup() when a hangup is signaled. */ |
02f1175c8 [PATCH] Char: cyc... |
2988 |
static void cy_hangup(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
2989 |
{ |
cab9bdd14 Char: cyclades, r... |
2990 |
struct cyclades_port *info = tty->driver_data; |
02f1175c8 [PATCH] Char: cyc... |
2991 |
|
1da177e4c Linux-2.6.12-rc2 |
2992 |
#ifdef CY_DEBUG_OTHER |
217191910 Char: cyclades, p... |
2993 2994 |
printk(KERN_DEBUG "cyc:cy_hangup ttyC%d ", info->line); |
1da177e4c Linux-2.6.12-rc2 |
2995 |
#endif |
02f1175c8 [PATCH] Char: cyc... |
2996 2997 |
if (serial_paranoia_check(info, tty->name, "cy_hangup")) return; |
1da177e4c Linux-2.6.12-rc2 |
2998 |
|
02f1175c8 [PATCH] Char: cyc... |
2999 |
cy_flush_buffer(tty); |
d13549f80 cyclades: add tty... |
3000 |
cy_shutdown(info, tty); |
174e6fe01 cyclades: switch ... |
3001 |
tty_port_hangup(&info->port); |
02f1175c8 [PATCH] Char: cyc... |
3002 |
} /* cy_hangup */ |
1da177e4c Linux-2.6.12-rc2 |
3003 |
|
f07375794 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 cyclades: remove ... |
3009 3010 |
unsigned long flags; int channel = info->line - cinfo->first_line; |
f07375794 cyclades: remove ... |
3011 |
u32 cd; |
f07375794 cyclades: remove ... |
3012 |
spin_lock_irqsave(&cinfo->card_lock, flags); |
3aeea5b92 cyclades: introdu... |
3013 3014 |
cyy_writeb(info, CyCAR, channel & 0x03); cd = cyy_readb(info, CyMSVR1) & CyDCD; |
f07375794 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 cyclades: remove ... |
3025 |
unsigned long flags; |
f07375794 cyclades: remove ... |
3026 3027 |
spin_lock_irqsave(&cinfo->card_lock, flags); |
4d7682005 cyclades: use dtr... |
3028 3029 |
cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0, raise ? 0 : TIOCM_RTS | TIOCM_DTR); |
f07375794 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 cyclades: remove ... |
3037 |
|
f0eefdc30 cyclades: avoid a... |
3038 |
return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD; |
f07375794 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 cyclades: avoid a... |
3046 |
struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; |
f07375794 cyclades: remove ... |
3047 3048 |
int ret, channel = info->line - cinfo->first_line; u32 rs; |
f0eefdc30 cyclades: avoid a... |
3049 |
rs = readl(&ch_ctrl->rs_control); |
f07375794 cyclades: remove ... |
3050 3051 3052 3053 |
if (raise) rs |= C_RS_RTS | C_RS_DTR; else rs &= ~(C_RS_RTS | C_RS_DTR); |
f0eefdc30 cyclades: avoid a... |
3054 |
cy_writel(&ch_ctrl->rs_control, rs); |
f07375794 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 cyclades: use the... |
3069 |
.shutdown = cy_do_close, |
f07375794 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 cyclades: use the... |
3075 |
.shutdown = cy_do_close, |
f07375794 cyclades: remove ... |
3076 |
}; |
1da177e4c 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 Char: cyclades, d... |
3084 |
static int __devinit cy_init_card(struct cyclades_card *cinfo) |
0809e2671 Char: cyclades, m... |
3085 3086 |
{ struct cyclades_port *info; |
f0eefdc30 cyclades: avoid a... |
3087 |
unsigned int channel, port; |
0809e2671 Char: cyclades, m... |
3088 |
|
3046d50ea Char: cyclades, s... |
3089 |
spin_lock_init(&cinfo->card_lock); |
963118eef tty: cyclades, fi... |
3090 |
cinfo->intr_enabled = 0; |
3046d50ea Char: cyclades, s... |
3091 |
|
963118eef tty: cyclades, fi... |
3092 3093 |
cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports), GFP_KERNEL); |
dd025c0c7 Char: cyclades, d... |
3094 3095 3096 3097 3098 |
if (cinfo->ports == NULL) { printk(KERN_ERR "Cyclades: cannot allocate ports "); return -ENOMEM; } |
f0eefdc30 cyclades: avoid a... |
3099 3100 3101 |
for (channel = 0, port = cinfo->first_line; channel < cinfo->nports; channel++, port++) { info = &cinfo->ports[channel]; |
44b7d1b37 tty: add more tty... |
3102 |
tty_port_init(&info->port); |
3046d50ea Char: cyclades, s... |
3103 |
info->magic = CYCLADES_MAGIC; |
875b206b5 Char: cyclades, m... |
3104 |
info->card = cinfo; |
3046d50ea Char: cyclades, s... |
3105 |
info->line = port; |
3046d50ea Char: cyclades, s... |
3106 |
|
44b7d1b37 tty: add more tty... |
3107 3108 |
info->port.closing_wait = CLOSING_WAIT_DELAY; info->port.close_delay = 5 * HZ / 10; |
77451e53e cyclades: use tty... |
3109 |
info->port.flags = STD_COM_FLAGS; |
2c7fea992 Char: cyclades, r... |
3110 |
init_completion(&info->shutdown_wait); |
3046d50ea Char: cyclades, s... |
3111 |
|
2693f485c tty: cyclades, co... |
3112 |
if (cy_is_Z(cinfo)) { |
f0eefdc30 cyclades: avoid a... |
3113 3114 |
struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS; struct ZFW_CTRL *zfw_ctrl; |
f07375794 cyclades: remove ... |
3115 |
info->port.ops = &cyz_port_ops; |
0809e2671 Char: cyclades, m... |
3116 |
info->type = PORT_STARTECH; |
f0eefdc30 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 tty: cyclades, ca... |
3122 |
if (cinfo->hw_ver == ZO_V1) |
0809e2671 Char: cyclades, m... |
3123 3124 |
info->xmit_fifo_size = CYZ_FIFO_SIZE; else |
3046d50ea Char: cyclades, s... |
3125 |
info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; |
0809e2671 Char: cyclades, m... |
3126 |
#ifdef CONFIG_CYZ_INTR |
3991428d9 Char: cyclades, t... |
3127 3128 |
setup_timer(&cyz_rx_full_timer[port], cyz_rx_restart, (unsigned long)info); |
0809e2671 Char: cyclades, m... |
3129 |
#endif |
3046d50ea Char: cyclades, s... |
3130 |
} else { |
f0eefdc30 cyclades: avoid a... |
3131 |
unsigned short chip_number; |
963118eef tty: cyclades, fi... |
3132 |
int index = cinfo->bus_index; |
f0eefdc30 cyclades: avoid a... |
3133 |
|
f07375794 cyclades: remove ... |
3134 |
info->port.ops = &cyy_port_ops; |
0809e2671 Char: cyclades, m... |
3135 |
info->type = PORT_CIRRUS; |
0809e2671 Char: cyclades, m... |
3136 |
info->xmit_fifo_size = CyMAX_CHAR_FIFO; |
3046d50ea Char: cyclades, s... |
3137 |
info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; |
0809e2671 Char: cyclades, m... |
3138 3139 |
info->cor2 = CyETC; info->cor3 = 0x08; /* _very_ small rcv threshold */ |
3046d50ea Char: cyclades, s... |
3140 |
|
f0eefdc30 cyclades: avoid a... |
3141 |
chip_number = channel / CyPORTS_PER_CHIP; |
3aeea5b92 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 cyclades: coding ... |
3145 3146 |
if (info->chip_rev >= CD1400_REV_J) { |
0809e2671 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 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 Char: cyclades, m... |
3158 3159 |
info->rtsdtr_inv = 0; } |
3046d50ea Char: cyclades, s... |
3160 3161 |
info->read_status_mask = CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY | CyFRAME | CyOVERRUN; |
0809e2671 Char: cyclades, m... |
3162 |
} |
3046d50ea Char: cyclades, s... |
3163 |
|
0809e2671 Char: cyclades, m... |
3164 |
} |
3046d50ea Char: cyclades, s... |
3165 3166 |
#ifndef CONFIG_CYZ_INTR |
2693f485c tty: cyclades, co... |
3167 |
if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) { |
3046d50ea 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 Char: cyclades, d... |
3175 |
return 0; |
0809e2671 Char: cyclades, m... |
3176 |
} |
1da177e4c 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 Char: cyclades, m... |
3179 3180 |
static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, int index) |
1da177e4c Linux-2.6.12-rc2 |
3181 |
{ |
02f1175c8 [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 cyclades: coding ... |
3190 3191 |
for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; chip_number++) { |
02f1175c8 [PATCH] Char: cyc... |
3192 3193 3194 |
base_addr = true_base_addr + (cy_chip_offset[chip_number] << index); mdelay(1); |
db05c3b1d Char: cyclades, c... |
3195 |
if (readb(base_addr + (CyCCR << index)) != 0x00) { |
02f1175c8 [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 Char: cyclades, c... |
3213 |
if (chip_number == 4 && readb(true_base_addr + |
02f1175c8 [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 Char: cyclades, c... |
3221 |
if (readb(base_addr + (CyGFRCR << index)) == 0x00) { |
02f1175c8 [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 Char: cyclades, c... |
3230 |
if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) != |
02f1175c8 [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 Char: cyclades, c... |
3242 |
if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) { |
02f1175c8 [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 Linux-2.6.12-rc2 |
3251 |
|
02f1175c8 [PATCH] Char: cyc... |
3252 3253 3254 3255 |
/* printk(" chip #%d at %#6lx is rev 0x%2x ", chip_number, (unsigned long)base_addr, |
db05c3b1d Char: cyclades, c... |
3256 |
readb(base_addr+(CyGFRCR<<index))); |
02f1175c8 [PATCH] Char: cyc... |
3257 3258 3259 3260 |
*/ } return chip_number; } /* cyy_init_card */ |
1da177e4c 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 [PATCH] Char: cyc... |
3268 |
static int __init cy_detect_isa(void) |
1da177e4c Linux-2.6.12-rc2 |
3269 3270 |
{ #ifdef CONFIG_ISA |
02f1175c8 [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 [PATCH] Char: cyc... |
3274 |
int isparam = 0; |
1da177e4c Linux-2.6.12-rc2 |
3275 |
|
02f1175c8 [PATCH] Char: cyc... |
3276 |
nboard = 0; |
1da177e4c Linux-2.6.12-rc2 |
3277 |
|
1da177e4c Linux-2.6.12-rc2 |
3278 |
/* Check for module parameters */ |
02f1175c8 [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 Linux-2.6.12-rc2 |
3286 |
} |
1da177e4c Linux-2.6.12-rc2 |
3287 |
|
02f1175c8 [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 cyclades: coding ... |
3291 |
if (isa_address == 0x0000) |
096dcfce3 [PATCH] Char: cyc... |
3292 |
return nboard; |
1da177e4c Linux-2.6.12-rc2 |
3293 |
|
02f1175c8 [PATCH] Char: cyc... |
3294 |
/* probe for CD1400... */ |
cd989b3a8 cyclades: use ior... |
3295 |
cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin); |
3137553d3 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 [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 Char: cyclades, p... |
3305 |
iounmap(cy_isa_address); |
02f1175c8 [PATCH] Char: cyc... |
3306 3307 |
continue; } |
209043635 serial: cyclades:... |
3308 |
|
196b3167e cyclades: fix rea... |
3309 |
if (isparam && i < NR_CARDS && irq[i]) |
02f1175c8 [PATCH] Char: cyc... |
3310 |
cy_isa_irq = irq[i]; |
1da177e4c Linux-2.6.12-rc2 |
3311 |
else |
02f1175c8 [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 Char: cyclades, p... |
3315 3316 3317 |
printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the " "IRQ could not be detected. ", |
02f1175c8 [PATCH] Char: cyc... |
3318 |
(unsigned long)cy_isa_address); |
3137553d3 Char: cyclades, p... |
3319 |
iounmap(cy_isa_address); |
02f1175c8 [PATCH] Char: cyc... |
3320 3321 3322 3323 |
continue; } if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) { |
217191910 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 [PATCH] Char: cyc... |
3328 |
(unsigned long)cy_isa_address); |
3137553d3 Char: cyclades, p... |
3329 |
iounmap(cy_isa_address); |
096dcfce3 [PATCH] Char: cyc... |
3330 |
return nboard; |
02f1175c8 [PATCH] Char: cyc... |
3331 3332 3333 |
} /* fill the next cy_card structure available */ for (j = 0; j < NR_CARDS; j++) { |
f74290342 Char: cyclades, c... |
3334 |
if (cy_card[j].base_addr == NULL) |
02f1175c8 [PATCH] Char: cyc... |
3335 3336 3337 |
break; } if (j == NR_CARDS) { /* no more cy_cards available */ |
217191910 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 [PATCH] Char: cyc... |
3342 |
(unsigned long)cy_isa_address); |
3137553d3 Char: cyclades, p... |
3343 |
iounmap(cy_isa_address); |
096dcfce3 [PATCH] Char: cyc... |
3344 |
return nboard; |
02f1175c8 [PATCH] Char: cyc... |
3345 3346 3347 3348 |
} /* allocate IRQ */ if (request_irq(cy_isa_irq, cyy_interrupt, |
9cfb5c05f TTY: irq: Remove ... |
3349 |
0, "Cyclom-Y", &cy_card[j])) { |
217191910 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 Char: cyclades, p... |
3354 |
iounmap(cy_isa_address); |
096dcfce3 [PATCH] Char: cyc... |
3355 |
return nboard; |
02f1175c8 [PATCH] Char: cyc... |
3356 3357 3358 3359 |
} /* set cy_card */ cy_card[j].base_addr = cy_isa_address; |
97e87f8eb tty: cyclades, pl... |
3360 |
cy_card[j].ctl_addr.p9050 = NULL; |
02f1175c8 [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 tty: cyclades, fi... |
3364 3365 |
cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; cy_card[j].nports = cy_isa_nchan; |
3137553d3 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 [PATCH] Char: cyc... |
3372 |
nboard++; |
217191910 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 [PATCH] Char: cyc... |
3376 3377 |
j + 1, (unsigned long)cy_isa_address, (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), |
217191910 Char: cyclades, p... |
3378 |
cy_isa_irq, cy_isa_nchan, cy_next_channel); |
6ad1ccc19 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 [PATCH] Char: cyc... |
3382 3383 |
cy_next_channel += cy_isa_nchan; } |
096dcfce3 [PATCH] Char: cyc... |
3384 |
return nboard; |
1da177e4c Linux-2.6.12-rc2 |
3385 |
#else |
096dcfce3 [PATCH] Char: cyc... |
3386 |
return 0; |
02f1175c8 [PATCH] Char: cyc... |
3387 3388 |
#endif /* CONFIG_ISA */ } /* cy_detect_isa */ |
1da177e4c Linux-2.6.12-rc2 |
3389 |
|
58936d8d9 Char: cyclades, c... |
3390 |
#ifdef CONFIG_PCI |
054f5b0aa 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 cyclades: treat f... |
3405 |
static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data, |
054f5b0aa 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 Linux-2.6.12-rc2 |
3416 |
{ |
02f1175c8 [PATCH] Char: cyc... |
3417 |
/* Reset PLX */ |
054f5b0aa Char: cyclades, a... |
3418 |
cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000); |
02f1175c8 [PATCH] Char: cyc... |
3419 |
udelay(100L); |
054f5b0aa Char: cyclades, a... |
3420 |
cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000); |
02f1175c8 [PATCH] Char: cyc... |
3421 3422 |
/* Reload Config. Registers from EEPROM */ |
054f5b0aa Char: cyclades, a... |
3423 |
cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000); |
02f1175c8 [PATCH] Char: cyc... |
3424 |
udelay(100L); |
054f5b0aa 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 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 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 Char: cyclades, f... |
3524 |
void __iomem *tmp; |
963118eef tty: cyclades, fi... |
3525 |
u32 mailbox, status, nchan; |
054f5b0aa 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 tty: cyclades, co... |
3538 |
if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { |
054f5b0aa 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 tty: cyclades, co... |
3557 |
if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) { |
054f5b0aa 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 tty: cyclades, co... |
3573 |
if (!__cyz_fpga_loaded(ctl_addr)) { |
054f5b0aa 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 Char: cyclades, f... |
3588 |
for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) |
054f5b0aa 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 Char: cyclades, f... |
3593 |
for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) |
054f5b0aa 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 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 tty: cyclades, co... |
3636 |
if (__cyz_fpga_loaded(ctl_addr)) |
054f5b0aa 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 tty: cyclades, fi... |
3652 |
nchan = readl(&pt_zfwctrl->board_ctrl.n_channel); |
054f5b0aa Char: cyclades, a... |
3653 3654 |
dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u ", |
963118eef tty: cyclades, fi... |
3655 |
readl(&pt_zfwctrl->board_ctrl.fw_version), nchan); |
054f5b0aa Char: cyclades, a... |
3656 |
|
963118eef tty: cyclades, fi... |
3657 |
if (nchan == 0) { |
054f5b0aa 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 tty: cyclades, co... |
3662 |
if (__cyz_fpga_loaded(ctl_addr)) |
054f5b0aa 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 tty: cyclades, fi... |
3683 |
return nchan; |
054f5b0aa Char: cyclades, a... |
3684 3685 3686 3687 |
err_rel: release_firmware(fw); err: return retval; |
1da177e4c Linux-2.6.12-rc2 |
3688 |
} |
58936d8d9 Char: cyclades, c... |
3689 3690 |
static int __devinit cy_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
1da177e4c Linux-2.6.12-rc2 |
3691 |
{ |
3137553d3 Char: cyclades, p... |
3692 3693 |
void __iomem *addr0 = NULL, *addr2 = NULL; char *card_name = NULL; |
101b81590 tty: cyclades, ca... |
3694 |
u32 uninitialized_var(mailbox); |
3137553d3 Char: cyclades, p... |
3695 3696 3697 |
unsigned int device_id, nchan = 0, card_no, i; unsigned char plx_ver; int retval, irq; |
02f1175c8 [PATCH] Char: cyc... |
3698 |
|
58936d8d9 Char: cyclades, c... |
3699 3700 3701 3702 |
retval = pci_enable_device(pdev); if (retval) { dev_err(&pdev->dev, "cannot enable device "); |
3137553d3 Char: cyclades, p... |
3703 |
goto err; |
58936d8d9 Char: cyclades, c... |
3704 |
} |
1da177e4c Linux-2.6.12-rc2 |
3705 |
|
58936d8d9 Char: cyclades, c... |
3706 |
/* read PCI configuration area */ |
3137553d3 Char: cyclades, p... |
3707 |
irq = pdev->irq; |
58936d8d9 Char: cyclades, c... |
3708 |
device_id = pdev->device & ~PCI_DEVICE_ID_MASK; |
1da177e4c Linux-2.6.12-rc2 |
3709 |
|
3137553d3 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 Char: cyclades, c... |
3742 3743 |
if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { |
3137553d3 Char: cyclades, p... |
3744 |
card_name = "Cyclom-Y"; |
1da177e4c Linux-2.6.12-rc2 |
3745 |
|
24e6fd4cd Char: cyclades. r... |
3746 3747 |
addr0 = ioremap_nocache(pci_resource_start(pdev, 0), CyPCI_Yctl); |
3137553d3 Char: cyclades, p... |
3748 3749 3750 3751 |
if (addr0 == NULL) { dev_err(&pdev->dev, "can't remap ctl region "); goto err_reg; |
58936d8d9 Char: cyclades, c... |
3752 |
} |
24e6fd4cd Char: cyclades. r... |
3753 3754 |
addr2 = ioremap_nocache(pci_resource_start(pdev, 2), CyPCI_Ywin); |
3137553d3 Char: cyclades, p... |
3755 3756 3757 3758 |
if (addr2 == NULL) { dev_err(&pdev->dev, "can't remap base region "); goto err_unmap; |
58936d8d9 Char: cyclades, c... |
3759 |
} |
1da177e4c Linux-2.6.12-rc2 |
3760 |
|
3137553d3 Char: cyclades, p... |
3761 3762 |
nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1); if (nchan == 0) { |
217191910 Char: cyclades, p... |
3763 3764 3765 |
dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " "Serial-Modules "); |
c847d47cb drivers/char/cycl... |
3766 |
goto err_unmap; |
58936d8d9 Char: cyclades, c... |
3767 |
} |
58936d8d9 Char: cyclades, c... |
3768 |
} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { |
3137553d3 Char: cyclades, p... |
3769 |
struct RUNTIME_9060 __iomem *ctl_addr; |
217191910 Char: cyclades, p... |
3770 |
|
24e6fd4cd Char: cyclades. r... |
3771 3772 |
ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0), CyPCI_Zctl); |
3137553d3 Char: cyclades, p... |
3773 3774 3775 3776 3777 |
if (addr0 == NULL) { dev_err(&pdev->dev, "can't remap ctl region "); goto err_reg; } |
58936d8d9 Char: cyclades, c... |
3778 3779 |
/* Disable interrupts on the PLX before resetting it */ |
97e87f8eb tty: cyclades, pl... |
3780 3781 |
cy_writew(&ctl_addr->intr_ctrl_stat, readw(&ctl_addr->intr_ctrl_stat) & ~0x0900); |
58936d8d9 Char: cyclades, c... |
3782 |
|
054f5b0aa Char: cyclades, a... |
3783 |
plx_init(pdev, irq, addr0); |
02f1175c8 [PATCH] Char: cyc... |
3784 |
|
101b81590 tty: cyclades, ca... |
3785 |
mailbox = readl(&ctl_addr->mail_box_0); |
58936d8d9 Char: cyclades, c... |
3786 |
|
24e6fd4cd Char: cyclades. r... |
3787 3788 |
addr2 = ioremap_nocache(pci_resource_start(pdev, 2), mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); |
3137553d3 Char: cyclades, p... |
3789 3790 3791 3792 |
if (addr2 == NULL) { dev_err(&pdev->dev, "can't remap base region "); goto err_unmap; |
58936d8d9 Char: cyclades, c... |
3793 3794 3795 |
} if (mailbox == ZE_V1) { |
3137553d3 Char: cyclades, p... |
3796 |
card_name = "Cyclades-Ze"; |
58936d8d9 Char: cyclades, c... |
3797 |
} else { |
3137553d3 Char: cyclades, p... |
3798 |
card_name = "Cyclades-8Zo"; |
1da177e4c Linux-2.6.12-rc2 |
3799 |
#ifdef CY_PCI_DEBUG |
3137553d3 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 Linux-2.6.12-rc2 |
3815 |
#endif |
3137553d3 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 Char: cyclades, c... |
3822 |
} |
ace08c3c4 tty:cyclades, loa... |
3823 3824 |
retval = cyz_load_fw(pdev, addr2, addr0, irq); |
963118eef tty: cyclades, fi... |
3825 |
if (retval <= 0) |
ace08c3c4 tty:cyclades, loa... |
3826 |
goto err_unmap; |
963118eef tty: cyclades, fi... |
3827 |
nchan = retval; |
3137553d3 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 Char: cyclades, c... |
3859 |
} |
963118eef tty: cyclades, fi... |
3860 |
cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; |
3137553d3 Char: cyclades, p... |
3861 |
} else { |
f0eefdc30 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 tty: cyclades, ca... |
3866 3867 |
cy_card[card_no].hw_ver = mailbox; cy_card[card_no].num_chips = (unsigned int)-1; |
f0eefdc30 cyclades: avoid a... |
3868 |
cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl; |
02f1175c8 [PATCH] Char: cyc... |
3869 |
#ifdef CONFIG_CYZ_INTR |
58936d8d9 Char: cyclades, c... |
3870 |
/* allocate IRQ only if board has an IRQ */ |
3137553d3 Char: cyclades, p... |
3871 3872 |
if (irq != 0 && irq != 255) { retval = request_irq(irq, cyz_interrupt, |
58936d8d9 Char: cyclades, c... |
3873 |
IRQF_SHARED, "Cyclades-Z", |
3137553d3 Char: cyclades, p... |
3874 |
&cy_card[card_no]); |
58936d8d9 Char: cyclades, c... |
3875 |
if (retval) { |
217191910 Char: cyclades, p... |
3876 3877 |
dev_err(&pdev->dev, "could not allocate IRQ "); |
3137553d3 Char: cyclades, p... |
3878 |
goto err_unmap; |
02f1175c8 [PATCH] Char: cyc... |
3879 |
} |
58936d8d9 Char: cyclades, c... |
3880 |
} |
02f1175c8 [PATCH] Char: cyc... |
3881 |
#endif /* CONFIG_CYZ_INTR */ |
3137553d3 Char: cyclades, p... |
3882 |
} |
02f1175c8 [PATCH] Char: cyc... |
3883 |
|
3137553d3 Char: cyclades, p... |
3884 3885 |
/* set cy_card */ cy_card[card_no].base_addr = addr2; |
97e87f8eb tty: cyclades, pl... |
3886 |
cy_card[card_no].ctl_addr.p9050 = addr0; |
3137553d3 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 tty: cyclades, fi... |
3890 |
cy_card[card_no].nports = nchan; |
3137553d3 Char: cyclades, p... |
3891 3892 3893 |
retval = cy_init_card(&cy_card[card_no]); if (retval) goto err_null; |
58936d8d9 Char: cyclades, c... |
3894 |
|
3137553d3 Char: cyclades, p... |
3895 |
pci_set_drvdata(pdev, &cy_card[card_no]); |
58936d8d9 Char: cyclades, c... |
3896 |
|
3137553d3 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 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 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 Char: cyclades, p... |
3914 3915 |
break; } |
97e87f8eb tty: cyclades, pl... |
3916 |
} |
58936d8d9 Char: cyclades, c... |
3917 |
} |
3137553d3 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 Char: cyclades, c... |
3924 |
return 0; |
3137553d3 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 Char: cyclades. r... |
3929 |
iounmap(addr0); |
3137553d3 Char: cyclades, p... |
3930 |
if (addr2) |
24e6fd4cd Char: cyclades. r... |
3931 |
iounmap(addr2); |
3137553d3 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 Char: cyclades, c... |
3938 |
} |
58936d8d9 Char: cyclades, c... |
3939 |
|
6747cd93f Char: cyclades, s... |
3940 |
static void __devexit cy_pci_remove(struct pci_dev *pdev) |
58936d8d9 Char: cyclades, c... |
3941 |
{ |
38d090932 Char: cyclades, u... |
3942 |
struct cyclades_card *cinfo = pci_get_drvdata(pdev); |
f3851e73e Char: cyclades, i... |
3943 |
unsigned int i; |
38d090932 Char: cyclades, u... |
3944 |
|
85c93fa95 Char: cyclades, c... |
3945 |
/* non-Z with old PLX */ |
2693f485c tty: cyclades, co... |
3946 |
if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == |
c2ad4c751 Char: cyclades, u... |
3947 |
PLX_9050) |
97e87f8eb tty: cyclades, pl... |
3948 |
cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0); |
85c93fa95 Char: cyclades, c... |
3949 3950 |
else #ifndef CONFIG_CYZ_INTR |
2693f485c tty: cyclades, co... |
3951 |
if (!cy_is_Z(cinfo)) |
85c93fa95 Char: cyclades, c... |
3952 |
#endif |
97e87f8eb 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 Char: cyclades, c... |
3956 |
|
24e6fd4cd Char: cyclades. r... |
3957 |
iounmap(cinfo->base_addr); |
97e87f8eb tty: cyclades, pl... |
3958 3959 |
if (cinfo->ctl_addr.p9050) iounmap(cinfo->ctl_addr.p9050); |
38d090932 Char: cyclades, u... |
3960 3961 |
if (cinfo->irq #ifndef CONFIG_CYZ_INTR |
2693f485c tty: cyclades, co... |
3962 |
&& !cy_is_Z(cinfo) |
38d090932 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 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 Char: cyclades, d... |
3972 3973 |
cinfo->nports = 0; kfree(cinfo->ports); |
38d090932 Char: cyclades, u... |
3974 |
} |
6747cd93f 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 proc tty: switch ... |
3982 |
static int cyclades_proc_show(struct seq_file *m, void *v) |
1da177e4c Linux-2.6.12-rc2 |
3983 |
{ |
02f1175c8 [PATCH] Char: cyc... |
3984 |
struct cyclades_port *info; |
dd025c0c7 Char: cyclades, d... |
3985 |
unsigned int i, j; |
02f1175c8 [PATCH] Char: cyc... |
3986 |
__u32 cur_jifs = jiffies; |
444697d61 proc tty: switch ... |
3987 |
seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn " |
02f1175c8 [PATCH] Char: cyc... |
3988 3989 |
"IdleIn Overruns Ldisc "); |
02f1175c8 [PATCH] Char: cyc... |
3990 |
/* Output one line for each known port */ |
dd025c0c7 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 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 proc tty: switch ... |
4008 |
seq_printf(m, "%3d %8lu %10lu %8lu " |
d13549f80 cyclades: add tty... |
4009 4010 |
"%10lu %8lu %9lu %6d ", info->line, |
dd025c0c7 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 cyclades: add tty... |
4017 4018 |
num); } else |
444697d61 proc tty: switch ... |
4019 |
seq_printf(m, "%3d %8lu %10lu %8lu " |
dd025c0c7 Char: cyclades, d... |
4020 4021 4022 |
"%10lu %8lu %9lu %6ld ", info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); |
02f1175c8 [PATCH] Char: cyc... |
4023 |
} |
444697d61 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 Linux-2.6.12-rc2 |
4030 |
} |
444697d61 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 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 [PATCH] const str... |
4055 |
static const struct tty_operations cy_ops = { |
02f1175c8 [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 [PATCH] Char: cyc... |
4073 4074 |
.tiocmget = cy_tiocmget, .tiocmset = cy_tiocmset, |
0587102cf tty: icount chang... |
4075 |
.get_icount = cy_get_icount, |
444697d61 proc tty: switch ... |
4076 |
.proc_fops = &cyclades_proc_fops, |
1da177e4c Linux-2.6.12-rc2 |
4077 |
}; |
02f1175c8 [PATCH] Char: cyc... |
4078 |
static int __init cy_init(void) |
1da177e4c Linux-2.6.12-rc2 |
4079 |
{ |
dd025c0c7 Char: cyclades, d... |
4080 |
unsigned int nboards; |
9dacf3b2f Char: cyclades, c... |
4081 |
int retval = -ENOMEM; |
02f1175c8 [PATCH] Char: cyc... |
4082 4083 4084 |
cy_serial_driver = alloc_tty_driver(NR_PORTS); if (!cy_serial_driver) |
9dacf3b2f Char: cyclades, c... |
4085 |
goto err; |
217191910 Char: cyclades, p... |
4086 |
|
64a14b51b cyclades: Drop __... |
4087 4088 |
printk(KERN_INFO "Cyclades driver " CY_VERSION " "); |
02f1175c8 [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 Char: cyclades, t... |
4102 |
cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
02f1175c8 [PATCH] Char: cyc... |
4103 |
tty_set_operations(cy_serial_driver, &cy_ops); |
9dacf3b2f 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 [PATCH] Char: cyc... |
4110 |
|
02f1175c8 [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 Char: cyclades, r... |
4119 |
nboards = cy_detect_isa(); |
02f1175c8 [PATCH] Char: cyc... |
4120 |
|
6747cd93f Char: cyclades, s... |
4121 |
#ifdef CONFIG_PCI |
02f1175c8 [PATCH] Char: cyc... |
4122 |
/* look for pci boards */ |
6747cd93f Char: cyclades, s... |
4123 |
retval = pci_register_driver(&cy_pci_driver); |
d941ea7d4 Cyclades: Avoid l... |
4124 4125 4126 4127 |
if (retval && !nboards) { tty_unregister_driver(cy_serial_driver); goto err_frtty; } |
6747cd93f Char: cyclades, s... |
4128 |
#endif |
9dacf3b2f Char: cyclades, c... |
4129 4130 |
return 0; |
9dacf3b2f Char: cyclades, c... |
4131 4132 4133 4134 |
err_frtty: put_tty_driver(cy_serial_driver); err: return retval; |
02f1175c8 [PATCH] Char: cyc... |
4135 |
} /* cy_init */ |
1da177e4c Linux-2.6.12-rc2 |
4136 |
|
02f1175c8 [PATCH] Char: cyc... |
4137 |
static void __exit cy_cleanup_module(void) |
1da177e4c Linux-2.6.12-rc2 |
4138 |
{ |
dd025c0c7 Char: cyclades, d... |
4139 |
struct cyclades_card *card; |
65f76a82e Char: cyclades, f... |
4140 |
unsigned int i, e1; |
1da177e4c Linux-2.6.12-rc2 |
4141 4142 |
#ifndef CONFIG_CYZ_INTR |
b70509066 Char: cyclades, t... |
4143 |
del_timer_sync(&cyz_timerlist); |
1da177e4c Linux-2.6.12-rc2 |
4144 |
#endif /* CONFIG_CYZ_INTR */ |
15ed6cc0b cyclades: coding ... |
4145 4146 |
e1 = tty_unregister_driver(cy_serial_driver); if (e1) |
217191910 Char: cyclades, p... |
4147 4148 4149 |
printk(KERN_ERR "failed to unregister Cyclades serial " "driver(%d) ", e1); |
1da177e4c Linux-2.6.12-rc2 |
4150 |
|
6747cd93f Char: cyclades, s... |
4151 4152 4153 |
#ifdef CONFIG_PCI pci_unregister_driver(&cy_pci_driver); #endif |
02f1175c8 [PATCH] Char: cyc... |
4154 |
for (i = 0; i < NR_CARDS; i++) { |
dd025c0c7 Char: cyclades, d... |
4155 4156 |
card = &cy_card[i]; if (card->base_addr) { |
85c93fa95 Char: cyclades, c... |
4157 |
/* clear interrupt */ |
dd025c0c7 Char: cyclades, d... |
4158 4159 |
cy_writeb(card->base_addr + Cy_ClrIntr, 0); iounmap(card->base_addr); |
97e87f8eb tty: cyclades, pl... |
4160 4161 |
if (card->ctl_addr.p9050) iounmap(card->ctl_addr.p9050); |
dd025c0c7 Char: cyclades, d... |
4162 |
if (card->irq |
1da177e4c Linux-2.6.12-rc2 |
4163 |
#ifndef CONFIG_CYZ_INTR |
2693f485c tty: cyclades, co... |
4164 |
&& !cy_is_Z(card) |
1da177e4c Linux-2.6.12-rc2 |
4165 |
#endif /* CONFIG_CYZ_INTR */ |
02f1175c8 [PATCH] Char: cyc... |
4166 |
) |
dd025c0c7 Char: cyclades, d... |
4167 |
free_irq(card->irq, card); |
65f76a82e Char: cyclades, f... |
4168 |
for (e1 = card->first_line; e1 < card->first_line + |
dd025c0c7 Char: cyclades, d... |
4169 |
card->nports; e1++) |
6ad1ccc19 Char: cyclades, t... |
4170 |
tty_unregister_device(cy_serial_driver, e1); |
dd025c0c7 Char: cyclades, d... |
4171 |
kfree(card->ports); |
02f1175c8 [PATCH] Char: cyc... |
4172 4173 |
} } |
f2462bfe5 Char: cyclades, f... |
4174 4175 |
put_tty_driver(cy_serial_driver); |
1da177e4c 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 Char: cyclades, c... |
4182 |
MODULE_VERSION(CY_VERSION); |
9f56fad74 cyclades: Auto-lo... |
4183 |
MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); |
e6c4ef984 tty: declare MODU... |
4184 |
MODULE_FIRMWARE("cyzfirm.bin"); |