1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
2 | /* |
3 | * nozomi.c -- HSDPA driver Broadband Wireless Data Card - Globe Trotter |
4 | * |
5 | * Written by: Ulf Jakobsson, |
6 | * Jan Ã…kerfeldt, |
7 | * Stefan Thomasson, |
8 | * |
9 | * Maintained by: Paul Hardwick (p.hardwick@option.com) |
10 | * |
11 | * Patches: |
12 | * Locking code changes for Vodafone by Sphere Systems Ltd, |
13 | * Andrew Bird (ajb@spheresystems.co.uk ) |
14 | * & Phil Sanderson |
15 | * |
16 | * Source has been ported from an implementation made by Filip Aben @ Option |
17 | * |
18 | * -------------------------------------------------------------------------- |
19 | * |
20 | * Copyright (c) 2005,2006 Option Wireless Sweden AB |
21 | * Copyright (c) 2006 Sphere Systems Ltd |
22 | * Copyright (c) 2006 Option Wireless n/v |
23 | * All rights Reserved. |
24 | * |
25 | * -------------------------------------------------------------------------- |
26 | */ |
27 | |
28 | /* Enable this to have a lot of debug printouts */ |
29 | #define DEBUG |
30 | |
31 | #include <linux/kernel.h> |
32 | #include <linux/module.h> |
33 | #include <linux/pci.h> |
34 | #include <linux/ioport.h> |
35 | #include <linux/tty.h> |
36 | #include <linux/tty_driver.h> |
37 | #include <linux/tty_flip.h> |
38 | #include <linux/sched.h> |
39 | #include <linux/serial.h> |
40 | #include <linux/interrupt.h> |
41 | #include <linux/kmod.h> |
42 | #include <linux/init.h> |
43 | #include <linux/kfifo.h> |
44 | #include <linux/uaccess.h> |
45 | #include <linux/slab.h> |
46 | #include <asm/byteorder.h> |
47 | |
48 | #include <linux/delay.h> |
49 | |
50 | /* Default debug printout level */ |
51 | #define NOZOMI_DEBUG_LEVEL 0x00 |
52 | static int debug = NOZOMI_DEBUG_LEVEL; |
53 | module_param(debug, int, S_IRUGO | S_IWUSR); |
54 | |
55 | /* Macros definitions */ |
56 | #define DBG_(lvl, fmt, args...) \ |
57 | do { \ |
58 | if (lvl & debug) \ |
59 | pr_debug("[%d] %s(): " fmt "\n", \ |
60 | __LINE__, __func__, ##args); \ |
61 | } while (0) |
62 | |
63 | #define DBG1(args...) DBG_(0x01, ##args) |
64 | #define DBG2(args...) DBG_(0x02, ##args) |
65 | #define DBG3(args...) DBG_(0x04, ##args) |
66 | #define DBG4(args...) DBG_(0x08, ##args) |
67 | |
68 | #define TMP_BUF_MAX 256 |
69 | |
70 | /* Defines */ |
71 | #define NOZOMI_NAME "nozomi" |
72 | #define NOZOMI_NAME_TTY "nozomi_tty" |
73 | |
74 | #define NTTY_TTY_MAXMINORS 256 |
75 | #define NTTY_FIFO_BUFFER_SIZE 8192 |
76 | |
77 | /* Must be power of 2 */ |
78 | #define FIFO_BUFFER_SIZE_UL 8192 |
79 | |
80 | /* Size of tmp send buffer to card */ |
81 | #define SEND_BUF_MAX 1024 |
82 | #define RECEIVE_BUF_MAX 4 |
83 | |
84 | |
85 | #define R_IIR 0x0000 /* Interrupt Identity Register */ |
86 | #define R_FCR 0x0000 /* Flow Control Register */ |
87 | #define R_IER 0x0004 /* Interrupt Enable Register */ |
88 | |
89 | #define NOZOMI_CONFIG_MAGIC 0xEFEFFEFE |
90 | #define TOGGLE_VALID 0x0000 |
91 | |
92 | /* Definition of interrupt tokens */ |
93 | #define MDM_DL1 0x0001 |
94 | #define MDM_UL1 0x0002 |
95 | #define MDM_DL2 0x0004 |
96 | #define MDM_UL2 0x0008 |
97 | #define DIAG_DL1 0x0010 |
98 | #define DIAG_DL2 0x0020 |
99 | #define DIAG_UL 0x0040 |
100 | #define APP1_DL 0x0080 |
101 | #define APP1_UL 0x0100 |
102 | #define APP2_DL 0x0200 |
103 | #define APP2_UL 0x0400 |
104 | #define CTRL_DL 0x0800 |
105 | #define CTRL_UL 0x1000 |
106 | #define RESET 0x8000 |
107 | |
108 | #define MDM_DL (MDM_DL1 | MDM_DL2) |
109 | #define MDM_UL (MDM_UL1 | MDM_UL2) |
110 | #define DIAG_DL (DIAG_DL1 | DIAG_DL2) |
111 | |
112 | /* modem signal definition */ |
113 | #define CTRL_DSR 0x0001 |
114 | #define CTRL_DCD 0x0002 |
115 | #define CTRL_RI 0x0004 |
116 | #define CTRL_CTS 0x0008 |
117 | |
118 | #define CTRL_DTR 0x0001 |
119 | #define CTRL_RTS 0x0002 |
120 | |
121 | #define MAX_PORT 4 |
122 | #define NOZOMI_MAX_PORTS 5 |
123 | #define NOZOMI_MAX_CARDS (NTTY_TTY_MAXMINORS / MAX_PORT) |
124 | |
125 | /* Type definitions */ |
126 | |
127 | /* |
128 | * There are two types of nozomi cards, |
129 | * one with 2048 memory and with 8192 memory |
130 | */ |
131 | enum card_type { |
132 | F32_2 = 2048, /* 512 bytes downlink + uplink * 2 -> 2048 */ |
133 | F32_8 = 8192, /* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */ |
134 | }; |
135 | |
136 | /* Initialization states a card can be in */ |
137 | enum card_state { |
138 | NOZOMI_STATE_UNKNOWN = 0, |
139 | NOZOMI_STATE_ENABLED = 1, /* pci device enabled */ |
140 | NOZOMI_STATE_ALLOCATED = 2, /* config setup done */ |
141 | NOZOMI_STATE_READY = 3, /* flowcontrols received */ |
142 | }; |
143 | |
144 | /* Two different toggle channels exist */ |
145 | enum channel_type { |
146 | CH_A = 0, |
147 | CH_B = 1, |
148 | }; |
149 | |
150 | /* Port definition for the card regarding flow control */ |
151 | enum ctrl_port_type { |
152 | CTRL_CMD = 0, |
153 | CTRL_MDM = 1, |
154 | CTRL_DIAG = 2, |
155 | CTRL_APP1 = 3, |
156 | CTRL_APP2 = 4, |
157 | CTRL_ERROR = -1, |
158 | }; |
159 | |
160 | /* Ports that the nozomi has */ |
161 | enum port_type { |
162 | PORT_MDM = 0, |
163 | PORT_DIAG = 1, |
164 | PORT_APP1 = 2, |
165 | PORT_APP2 = 3, |
166 | PORT_CTRL = 4, |
167 | PORT_ERROR = -1, |
168 | }; |
169 | |
170 | #ifdef __BIG_ENDIAN |
171 | /* Big endian */ |
172 | |
173 | struct toggles { |
174 | unsigned int enabled:5; /* |
175 | * Toggle fields are valid if enabled is 0, |
176 | * else A-channels must always be used. |
177 | */ |
178 | unsigned int diag_dl:1; |
179 | unsigned int mdm_dl:1; |
180 | unsigned int mdm_ul:1; |
181 | } __attribute__ ((packed)); |
182 | |
183 | /* Configuration table to read at startup of card */ |
184 | /* Is for now only needed during initialization phase */ |
185 | struct config_table { |
186 | u32 signature; |
187 | u16 product_information; |
188 | u16 version; |
189 | u8 pad3[3]; |
190 | struct toggles toggle; |
191 | u8 pad1[4]; |
192 | u16 dl_mdm_len1; /* |
193 | * If this is 64, it can hold |
194 | * 60 bytes + 4 that is length field |
195 | */ |
196 | u16 dl_start; |
197 | |
198 | u16 dl_diag_len1; |
199 | u16 dl_mdm_len2; /* |
200 | * If this is 64, it can hold |
201 | * 60 bytes + 4 that is length field |
202 | */ |
203 | u16 dl_app1_len; |
204 | |
205 | u16 dl_diag_len2; |
206 | u16 dl_ctrl_len; |
207 | u16 dl_app2_len; |
208 | u8 pad2[16]; |
209 | u16 ul_mdm_len1; |
210 | u16 ul_start; |
211 | u16 ul_diag_len; |
212 | u16 ul_mdm_len2; |
213 | u16 ul_app1_len; |
214 | u16 ul_app2_len; |
215 | u16 ul_ctrl_len; |
216 | } __attribute__ ((packed)); |
217 | |
218 | /* This stores all control downlink flags */ |
219 | struct ctrl_dl { |
220 | u8 port; |
221 | unsigned int reserved:4; |
222 | unsigned int CTS:1; |
223 | unsigned int RI:1; |
224 | unsigned int DCD:1; |
225 | unsigned int DSR:1; |
226 | } __attribute__ ((packed)); |
227 | |
228 | /* This stores all control uplink flags */ |
229 | struct ctrl_ul { |
230 | u8 port; |
231 | unsigned int reserved:6; |
232 | unsigned int RTS:1; |
233 | unsigned int DTR:1; |
234 | } __attribute__ ((packed)); |
235 | |
236 | #else |
237 | /* Little endian */ |
238 | |
239 | /* This represents the toggle information */ |
240 | struct toggles { |
241 | unsigned int mdm_ul:1; |
242 | unsigned int mdm_dl:1; |
243 | unsigned int diag_dl:1; |
244 | unsigned int enabled:5; /* |
245 | * Toggle fields are valid if enabled is 0, |
246 | * else A-channels must always be used. |
247 | */ |
248 | } __attribute__ ((packed)); |
249 | |
250 | /* Configuration table to read at startup of card */ |
251 | struct config_table { |
252 | u32 signature; |
253 | u16 version; |
254 | u16 product_information; |
255 | struct toggles toggle; |
256 | u8 pad1[7]; |
257 | u16 dl_start; |
258 | u16 dl_mdm_len1; /* |
259 | * If this is 64, it can hold |
260 | * 60 bytes + 4 that is length field |
261 | */ |
262 | u16 dl_mdm_len2; |
263 | u16 dl_diag_len1; |
264 | u16 dl_diag_len2; |
265 | u16 dl_app1_len; |
266 | u16 dl_app2_len; |
267 | u16 dl_ctrl_len; |
268 | u8 pad2[16]; |
269 | u16 ul_start; |
270 | u16 ul_mdm_len2; |
271 | u16 ul_mdm_len1; |
272 | u16 ul_diag_len; |
273 | u16 ul_app1_len; |
274 | u16 ul_app2_len; |
275 | u16 ul_ctrl_len; |
276 | } __attribute__ ((packed)); |
277 | |
278 | /* This stores all control downlink flags */ |
279 | struct ctrl_dl { |
280 | unsigned int DSR:1; |
281 | unsigned int DCD:1; |
282 | unsigned int RI:1; |
283 | unsigned int CTS:1; |
284 | unsigned int reserved:4; |
285 | u8 port; |
286 | } __attribute__ ((packed)); |
287 | |
288 | /* This stores all control uplink flags */ |
289 | struct ctrl_ul { |
290 | unsigned int DTR:1; |
291 | unsigned int RTS:1; |
292 | unsigned int reserved:6; |
293 | u8 port; |
294 | } __attribute__ ((packed)); |
295 | #endif |
296 | |
297 | /* This holds all information that is needed regarding a port */ |
298 | struct port { |
299 | struct tty_port port; |
300 | u8 update_flow_control; |
301 | struct ctrl_ul ctrl_ul; |
302 | struct ctrl_dl ctrl_dl; |
303 | struct kfifo fifo_ul; |
304 | void __iomem *dl_addr[2]; |
305 | u32 dl_size[2]; |
306 | u8 toggle_dl; |
307 | void __iomem *ul_addr[2]; |
308 | u32 ul_size[2]; |
309 | u8 toggle_ul; |
310 | u16 token_dl; |
311 | |
312 | wait_queue_head_t tty_wait; |
313 | struct async_icount tty_icount; |
314 | |
315 | struct nozomi *dc; |
316 | }; |
317 | |
318 | /* Private data one for each card in the system */ |
319 | struct nozomi { |
320 | void __iomem *base_addr; |
321 | unsigned long flip; |
322 | |
323 | /* Pointers to registers */ |
324 | void __iomem *reg_iir; |
325 | void __iomem *reg_fcr; |
326 | void __iomem *reg_ier; |
327 | |
328 | u16 last_ier; |
329 | enum card_type card_type; |
330 | struct config_table config_table; /* Configuration table */ |
331 | struct pci_dev *pdev; |
332 | struct port port[NOZOMI_MAX_PORTS]; |
333 | u8 *send_buf; |
334 | |
335 | spinlock_t spin_mutex; /* secures access to registers and tty */ |
336 | |
337 | unsigned int index_start; |
338 | enum card_state state; |
339 | u32 open_ttys; |
340 | }; |
341 | |
342 | /* Global variables */ |
343 | static const struct pci_device_id nozomi_pci_tbl[] = { |
344 | {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */ |
345 | {}, |
346 | }; |
347 | |
348 | MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl); |
349 | |
350 | static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; |
351 | static struct tty_driver *ntty_driver; |
352 | |
353 | static const struct tty_port_operations noz_tty_port_ops; |
354 | |
355 | /* |
356 | * find card by tty_index |
357 | */ |
358 | static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty) |
359 | { |
360 | return tty ? ndevs[tty->index / MAX_PORT] : NULL; |
361 | } |
362 | |
363 | static inline struct port *get_port_by_tty(const struct tty_struct *tty) |
364 | { |
365 | struct nozomi *ndev = get_dc_by_tty(tty); |
366 | return ndev ? &ndev->port[tty->index % MAX_PORT] : NULL; |
367 | } |
368 | |
369 | /* |
370 | * TODO: |
371 | * -Optimize |
372 | * -Rewrite cleaner |
373 | */ |
374 | |
375 | static void read_mem32(u32 *buf, const void __iomem *mem_addr_start, |
376 | u32 size_bytes) |
377 | { |
378 | u32 i = 0; |
379 | const u32 __iomem *ptr = mem_addr_start; |
380 | u16 *buf16; |
381 | |
382 | if (unlikely(!ptr || !buf)) |
383 | goto out; |
384 | |
385 | /* shortcut for extremely often used cases */ |
386 | switch (size_bytes) { |
387 | case 2: /* 2 bytes */ |
388 | buf16 = (u16 *) buf; |
389 | *buf16 = __le16_to_cpu(readw(ptr)); |
390 | goto out; |
391 | case 4: /* 4 bytes */ |
392 | *(buf) = __le32_to_cpu(readl(ptr)); |
393 | goto out; |
394 | } |
395 | |
396 | while (i < size_bytes) { |
397 | if (size_bytes - i == 2) { |
398 | /* Handle 2 bytes in the end */ |
399 | buf16 = (u16 *) buf; |
400 | *(buf16) = __le16_to_cpu(readw(ptr)); |
401 | i += 2; |
402 | } else { |
403 | /* Read 4 bytes */ |
404 | *(buf) = __le32_to_cpu(readl(ptr)); |
405 | i += 4; |
406 | } |
407 | buf++; |
408 | ptr++; |
409 | } |
410 | out: |
411 | return; |
412 | } |
413 | |
414 | /* |
415 | * TODO: |
416 | * -Optimize |
417 | * -Rewrite cleaner |
418 | */ |
419 | static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf, |
420 | u32 size_bytes) |
421 | { |
422 | u32 i = 0; |
423 | u32 __iomem *ptr = mem_addr_start; |
424 | const u16 *buf16; |
425 | |
426 | if (unlikely(!ptr || !buf)) |
427 | return 0; |
428 | |
429 | /* shortcut for extremely often used cases */ |
430 | switch (size_bytes) { |
431 | case 2: /* 2 bytes */ |
432 | buf16 = (const u16 *)buf; |
433 | writew(__cpu_to_le16(*buf16), addr: ptr); |
434 | return 2; |
435 | case 1: /* |
436 | * also needs to write 4 bytes in this case |
437 | * so falling through.. |
438 | */ |
439 | fallthrough; |
440 | case 4: /* 4 bytes */ |
441 | writel(__cpu_to_le32(*buf), addr: ptr); |
442 | return 4; |
443 | } |
444 | |
445 | while (i < size_bytes) { |
446 | if (size_bytes - i == 2) { |
447 | /* 2 bytes */ |
448 | buf16 = (const u16 *)buf; |
449 | writew(__cpu_to_le16(*buf16), addr: ptr); |
450 | i += 2; |
451 | } else { |
452 | /* 4 bytes */ |
453 | writel(__cpu_to_le32(*buf), addr: ptr); |
454 | i += 4; |
455 | } |
456 | buf++; |
457 | ptr++; |
458 | } |
459 | return i; |
460 | } |
461 | |
462 | /* Setup pointers to different channels and also setup buffer sizes. */ |
463 | static void nozomi_setup_memory(struct nozomi *dc) |
464 | { |
465 | void __iomem *offset = dc->base_addr + dc->config_table.dl_start; |
466 | /* The length reported is including the length field of 4 bytes, |
467 | * hence subtract with 4. |
468 | */ |
469 | const u16 buff_offset = 4; |
470 | |
471 | /* Modem port dl configuration */ |
472 | dc->port[PORT_MDM].dl_addr[CH_A] = offset; |
473 | dc->port[PORT_MDM].dl_addr[CH_B] = |
474 | (offset += dc->config_table.dl_mdm_len1); |
475 | dc->port[PORT_MDM].dl_size[CH_A] = |
476 | dc->config_table.dl_mdm_len1 - buff_offset; |
477 | dc->port[PORT_MDM].dl_size[CH_B] = |
478 | dc->config_table.dl_mdm_len2 - buff_offset; |
479 | |
480 | /* Diag port dl configuration */ |
481 | dc->port[PORT_DIAG].dl_addr[CH_A] = |
482 | (offset += dc->config_table.dl_mdm_len2); |
483 | dc->port[PORT_DIAG].dl_size[CH_A] = |
484 | dc->config_table.dl_diag_len1 - buff_offset; |
485 | dc->port[PORT_DIAG].dl_addr[CH_B] = |
486 | (offset += dc->config_table.dl_diag_len1); |
487 | dc->port[PORT_DIAG].dl_size[CH_B] = |
488 | dc->config_table.dl_diag_len2 - buff_offset; |
489 | |
490 | /* App1 port dl configuration */ |
491 | dc->port[PORT_APP1].dl_addr[CH_A] = |
492 | (offset += dc->config_table.dl_diag_len2); |
493 | dc->port[PORT_APP1].dl_size[CH_A] = |
494 | dc->config_table.dl_app1_len - buff_offset; |
495 | |
496 | /* App2 port dl configuration */ |
497 | dc->port[PORT_APP2].dl_addr[CH_A] = |
498 | (offset += dc->config_table.dl_app1_len); |
499 | dc->port[PORT_APP2].dl_size[CH_A] = |
500 | dc->config_table.dl_app2_len - buff_offset; |
501 | |
502 | /* Ctrl dl configuration */ |
503 | dc->port[PORT_CTRL].dl_addr[CH_A] = |
504 | (offset += dc->config_table.dl_app2_len); |
505 | dc->port[PORT_CTRL].dl_size[CH_A] = |
506 | dc->config_table.dl_ctrl_len - buff_offset; |
507 | |
508 | offset = dc->base_addr + dc->config_table.ul_start; |
509 | |
510 | /* Modem Port ul configuration */ |
511 | dc->port[PORT_MDM].ul_addr[CH_A] = offset; |
512 | dc->port[PORT_MDM].ul_size[CH_A] = |
513 | dc->config_table.ul_mdm_len1 - buff_offset; |
514 | dc->port[PORT_MDM].ul_addr[CH_B] = |
515 | (offset += dc->config_table.ul_mdm_len1); |
516 | dc->port[PORT_MDM].ul_size[CH_B] = |
517 | dc->config_table.ul_mdm_len2 - buff_offset; |
518 | |
519 | /* Diag port ul configuration */ |
520 | dc->port[PORT_DIAG].ul_addr[CH_A] = |
521 | (offset += dc->config_table.ul_mdm_len2); |
522 | dc->port[PORT_DIAG].ul_size[CH_A] = |
523 | dc->config_table.ul_diag_len - buff_offset; |
524 | |
525 | /* App1 port ul configuration */ |
526 | dc->port[PORT_APP1].ul_addr[CH_A] = |
527 | (offset += dc->config_table.ul_diag_len); |
528 | dc->port[PORT_APP1].ul_size[CH_A] = |
529 | dc->config_table.ul_app1_len - buff_offset; |
530 | |
531 | /* App2 port ul configuration */ |
532 | dc->port[PORT_APP2].ul_addr[CH_A] = |
533 | (offset += dc->config_table.ul_app1_len); |
534 | dc->port[PORT_APP2].ul_size[CH_A] = |
535 | dc->config_table.ul_app2_len - buff_offset; |
536 | |
537 | /* Ctrl ul configuration */ |
538 | dc->port[PORT_CTRL].ul_addr[CH_A] = |
539 | (offset += dc->config_table.ul_app2_len); |
540 | dc->port[PORT_CTRL].ul_size[CH_A] = |
541 | dc->config_table.ul_ctrl_len - buff_offset; |
542 | } |
543 | |
544 | /* Dump config table under initalization phase */ |
545 | #ifdef DEBUG |
546 | static void dump_table(const struct nozomi *dc) |
547 | { |
548 | DBG3("signature: 0x%08X" , dc->config_table.signature); |
549 | DBG3("version: 0x%04X" , dc->config_table.version); |
550 | DBG3("product_information: 0x%04X" , \ |
551 | dc->config_table.product_information); |
552 | DBG3("toggle enabled: %d" , dc->config_table.toggle.enabled); |
553 | DBG3("toggle up_mdm: %d" , dc->config_table.toggle.mdm_ul); |
554 | DBG3("toggle dl_mdm: %d" , dc->config_table.toggle.mdm_dl); |
555 | DBG3("toggle dl_dbg: %d" , dc->config_table.toggle.diag_dl); |
556 | |
557 | DBG3("dl_start: 0x%04X" , dc->config_table.dl_start); |
558 | DBG3("dl_mdm_len0: 0x%04X, %d" , dc->config_table.dl_mdm_len1, |
559 | dc->config_table.dl_mdm_len1); |
560 | DBG3("dl_mdm_len1: 0x%04X, %d" , dc->config_table.dl_mdm_len2, |
561 | dc->config_table.dl_mdm_len2); |
562 | DBG3("dl_diag_len0: 0x%04X, %d" , dc->config_table.dl_diag_len1, |
563 | dc->config_table.dl_diag_len1); |
564 | DBG3("dl_diag_len1: 0x%04X, %d" , dc->config_table.dl_diag_len2, |
565 | dc->config_table.dl_diag_len2); |
566 | DBG3("dl_app1_len: 0x%04X, %d" , dc->config_table.dl_app1_len, |
567 | dc->config_table.dl_app1_len); |
568 | DBG3("dl_app2_len: 0x%04X, %d" , dc->config_table.dl_app2_len, |
569 | dc->config_table.dl_app2_len); |
570 | DBG3("dl_ctrl_len: 0x%04X, %d" , dc->config_table.dl_ctrl_len, |
571 | dc->config_table.dl_ctrl_len); |
572 | DBG3("ul_start: 0x%04X, %d" , dc->config_table.ul_start, |
573 | dc->config_table.ul_start); |
574 | DBG3("ul_mdm_len[0]: 0x%04X, %d" , dc->config_table.ul_mdm_len1, |
575 | dc->config_table.ul_mdm_len1); |
576 | DBG3("ul_mdm_len[1]: 0x%04X, %d" , dc->config_table.ul_mdm_len2, |
577 | dc->config_table.ul_mdm_len2); |
578 | DBG3("ul_diag_len: 0x%04X, %d" , dc->config_table.ul_diag_len, |
579 | dc->config_table.ul_diag_len); |
580 | DBG3("ul_app1_len: 0x%04X, %d" , dc->config_table.ul_app1_len, |
581 | dc->config_table.ul_app1_len); |
582 | DBG3("ul_app2_len: 0x%04X, %d" , dc->config_table.ul_app2_len, |
583 | dc->config_table.ul_app2_len); |
584 | DBG3("ul_ctrl_len: 0x%04X, %d" , dc->config_table.ul_ctrl_len, |
585 | dc->config_table.ul_ctrl_len); |
586 | } |
587 | #else |
588 | static inline void dump_table(const struct nozomi *dc) { } |
589 | #endif |
590 | |
591 | /* |
592 | * Read configuration table from card under intalization phase |
593 | * Returns 1 if ok, else 0 |
594 | */ |
595 | static int nozomi_read_config_table(struct nozomi *dc) |
596 | { |
597 | read_mem32(buf: (u32 *) &dc->config_table, mem_addr_start: dc->base_addr + 0, |
598 | size_bytes: sizeof(struct config_table)); |
599 | |
600 | if (dc->config_table.signature != NOZOMI_CONFIG_MAGIC) { |
601 | dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n" , |
602 | dc->config_table.signature, NOZOMI_CONFIG_MAGIC); |
603 | return 0; |
604 | } |
605 | |
606 | if ((dc->config_table.version == 0) |
607 | || (dc->config_table.toggle.enabled == TOGGLE_VALID)) { |
608 | int i; |
609 | DBG1("Second phase, configuring card" ); |
610 | |
611 | nozomi_setup_memory(dc); |
612 | |
613 | dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul; |
614 | dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl; |
615 | dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl; |
616 | DBG1("toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d" , |
617 | dc->port[PORT_MDM].toggle_ul, |
618 | dc->port[PORT_MDM].toggle_dl, dc->port[PORT_DIAG].toggle_dl); |
619 | |
620 | dump_table(dc); |
621 | |
622 | for (i = PORT_MDM; i < MAX_PORT; i++) { |
623 | memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl)); |
624 | memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul)); |
625 | } |
626 | |
627 | /* Enable control channel */ |
628 | dc->last_ier = dc->last_ier | CTRL_DL; |
629 | writew(val: dc->last_ier, addr: dc->reg_ier); |
630 | |
631 | dc->state = NOZOMI_STATE_ALLOCATED; |
632 | dev_info(&dc->pdev->dev, "Initialization OK!\n" ); |
633 | return 1; |
634 | } |
635 | |
636 | if ((dc->config_table.version > 0) |
637 | && (dc->config_table.toggle.enabled != TOGGLE_VALID)) { |
638 | u32 offset = 0; |
639 | DBG1("First phase: pushing upload buffers, clearing download" ); |
640 | |
641 | dev_info(&dc->pdev->dev, "Version of card: %d\n" , |
642 | dc->config_table.version); |
643 | |
644 | /* Here we should disable all I/O over F32. */ |
645 | nozomi_setup_memory(dc); |
646 | |
647 | /* |
648 | * We should send ALL channel pair tokens back along |
649 | * with reset token |
650 | */ |
651 | |
652 | /* push upload modem buffers */ |
653 | write_mem32(mem_addr_start: dc->port[PORT_MDM].ul_addr[CH_A], |
654 | buf: (u32 *) &offset, size_bytes: 4); |
655 | write_mem32(mem_addr_start: dc->port[PORT_MDM].ul_addr[CH_B], |
656 | buf: (u32 *) &offset, size_bytes: 4); |
657 | |
658 | writew(MDM_UL | DIAG_DL | MDM_DL, addr: dc->reg_fcr); |
659 | |
660 | DBG1("First phase done" ); |
661 | } |
662 | |
663 | return 1; |
664 | } |
665 | |
666 | /* Enable uplink interrupts */ |
667 | static void enable_transmit_ul(enum port_type port, struct nozomi *dc) |
668 | { |
669 | static const u16 mask[] = {MDM_UL, DIAG_UL, APP1_UL, APP2_UL, CTRL_UL}; |
670 | |
671 | if (port < NOZOMI_MAX_PORTS) { |
672 | dc->last_ier |= mask[port]; |
673 | writew(val: dc->last_ier, addr: dc->reg_ier); |
674 | } else { |
675 | dev_err(&dc->pdev->dev, "Called with wrong port?\n" ); |
676 | } |
677 | } |
678 | |
679 | /* Disable uplink interrupts */ |
680 | static void disable_transmit_ul(enum port_type port, struct nozomi *dc) |
681 | { |
682 | static const u16 mask[] = |
683 | {~MDM_UL, ~DIAG_UL, ~APP1_UL, ~APP2_UL, ~CTRL_UL}; |
684 | |
685 | if (port < NOZOMI_MAX_PORTS) { |
686 | dc->last_ier &= mask[port]; |
687 | writew(val: dc->last_ier, addr: dc->reg_ier); |
688 | } else { |
689 | dev_err(&dc->pdev->dev, "Called with wrong port?\n" ); |
690 | } |
691 | } |
692 | |
693 | /* Enable downlink interrupts */ |
694 | static void enable_transmit_dl(enum port_type port, struct nozomi *dc) |
695 | { |
696 | static const u16 mask[] = {MDM_DL, DIAG_DL, APP1_DL, APP2_DL, CTRL_DL}; |
697 | |
698 | if (port < NOZOMI_MAX_PORTS) { |
699 | dc->last_ier |= mask[port]; |
700 | writew(val: dc->last_ier, addr: dc->reg_ier); |
701 | } else { |
702 | dev_err(&dc->pdev->dev, "Called with wrong port?\n" ); |
703 | } |
704 | } |
705 | |
706 | /* Disable downlink interrupts */ |
707 | static void disable_transmit_dl(enum port_type port, struct nozomi *dc) |
708 | { |
709 | static const u16 mask[] = |
710 | {~MDM_DL, ~DIAG_DL, ~APP1_DL, ~APP2_DL, ~CTRL_DL}; |
711 | |
712 | if (port < NOZOMI_MAX_PORTS) { |
713 | dc->last_ier &= mask[port]; |
714 | writew(val: dc->last_ier, addr: dc->reg_ier); |
715 | } else { |
716 | dev_err(&dc->pdev->dev, "Called with wrong port?\n" ); |
717 | } |
718 | } |
719 | |
720 | /* |
721 | * Return 1 - send buffer to card and ack. |
722 | * Return 0 - don't ack, don't send buffer to card. |
723 | */ |
724 | static int send_data(enum port_type index, struct nozomi *dc) |
725 | { |
726 | u32 size = 0; |
727 | struct port *port = &dc->port[index]; |
728 | const u8 toggle = port->toggle_ul; |
729 | void __iomem *addr = port->ul_addr[toggle]; |
730 | const u32 ul_size = port->ul_size[toggle]; |
731 | |
732 | /* Get data from tty and place in buf for now */ |
733 | size = kfifo_out(&port->fifo_ul, dc->send_buf, |
734 | ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX); |
735 | |
736 | if (size == 0) { |
737 | DBG4("No more data to send, disable link:" ); |
738 | return 0; |
739 | } |
740 | |
741 | /* Write length + data */ |
742 | write_mem32(mem_addr_start: addr, buf: (u32 *) &size, size_bytes: 4); |
743 | write_mem32(mem_addr_start: addr + 4, buf: (u32 *) dc->send_buf, size_bytes: size); |
744 | |
745 | tty_port_tty_wakeup(port: &port->port); |
746 | |
747 | return 1; |
748 | } |
749 | |
750 | /* If all data has been read, return 1, else 0 */ |
751 | static int receive_data(enum port_type index, struct nozomi *dc) |
752 | { |
753 | u8 buf[RECEIVE_BUF_MAX] = { 0 }; |
754 | int size; |
755 | u32 offset = 4; |
756 | struct port *port = &dc->port[index]; |
757 | void __iomem *addr = port->dl_addr[port->toggle_dl]; |
758 | struct tty_struct *tty = tty_port_tty_get(port: &port->port); |
759 | int i, ret; |
760 | |
761 | size = __le32_to_cpu(readl(addr)); |
762 | |
763 | if (tty && tty_throttled(tty)) { |
764 | DBG1("No room in tty, don't read data, don't ack interrupt, " |
765 | "disable interrupt" ); |
766 | |
767 | /* disable interrupt in downlink... */ |
768 | disable_transmit_dl(port: index, dc); |
769 | ret = 0; |
770 | goto put; |
771 | } |
772 | |
773 | if (unlikely(size == 0)) { |
774 | dev_err(&dc->pdev->dev, "size == 0?\n" ); |
775 | ret = 1; |
776 | goto put; |
777 | } |
778 | |
779 | while (size > 0) { |
780 | read_mem32(buf: (u32 *) buf, mem_addr_start: addr + offset, RECEIVE_BUF_MAX); |
781 | |
782 | if (size == 1) { |
783 | tty_insert_flip_char(port: &port->port, ch: buf[0], TTY_NORMAL); |
784 | size = 0; |
785 | } else if (size < RECEIVE_BUF_MAX) { |
786 | size -= tty_insert_flip_string(port: &port->port, chars: buf, size); |
787 | } else { |
788 | i = tty_insert_flip_string(port: &port->port, chars: buf, |
789 | RECEIVE_BUF_MAX); |
790 | size -= i; |
791 | offset += i; |
792 | } |
793 | } |
794 | |
795 | set_bit(nr: index, addr: &dc->flip); |
796 | ret = 1; |
797 | put: |
798 | tty_kref_put(tty); |
799 | return ret; |
800 | } |
801 | |
802 | /* Debug for interrupts */ |
803 | #ifdef DEBUG |
804 | static char *interrupt2str(u16 interrupt) |
805 | { |
806 | static char buf[TMP_BUF_MAX]; |
807 | char *p = buf; |
808 | |
809 | if (interrupt & MDM_DL1) |
810 | p += scnprintf(buf: p, TMP_BUF_MAX, fmt: "MDM_DL1 " ); |
811 | if (interrupt & MDM_DL2) |
812 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "MDM_DL2 " ); |
813 | if (interrupt & MDM_UL1) |
814 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "MDM_UL1 " ); |
815 | if (interrupt & MDM_UL2) |
816 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "MDM_UL2 " ); |
817 | if (interrupt & DIAG_DL1) |
818 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "DIAG_DL1 " ); |
819 | if (interrupt & DIAG_DL2) |
820 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "DIAG_DL2 " ); |
821 | |
822 | if (interrupt & DIAG_UL) |
823 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "DIAG_UL " ); |
824 | |
825 | if (interrupt & APP1_DL) |
826 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "APP1_DL " ); |
827 | if (interrupt & APP2_DL) |
828 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "APP2_DL " ); |
829 | |
830 | if (interrupt & APP1_UL) |
831 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "APP1_UL " ); |
832 | if (interrupt & APP2_UL) |
833 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "APP2_UL " ); |
834 | |
835 | if (interrupt & CTRL_DL) |
836 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "CTRL_DL " ); |
837 | if (interrupt & CTRL_UL) |
838 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "CTRL_UL " ); |
839 | |
840 | if (interrupt & RESET) |
841 | p += scnprintf(buf: p, TMP_BUF_MAX - (p - buf), fmt: "RESET " ); |
842 | |
843 | return buf; |
844 | } |
845 | #endif |
846 | |
847 | /* |
848 | * Receive flow control |
849 | * Return 1 - If ok, else 0 |
850 | */ |
851 | static int receive_flow_control(struct nozomi *dc) |
852 | { |
853 | enum port_type port = PORT_MDM; |
854 | struct ctrl_dl ctrl_dl; |
855 | struct ctrl_dl old_ctrl; |
856 | u16 enable_ier = 0; |
857 | |
858 | read_mem32(buf: (u32 *) &ctrl_dl, mem_addr_start: dc->port[PORT_CTRL].dl_addr[CH_A], size_bytes: 2); |
859 | |
860 | switch (ctrl_dl.port) { |
861 | case CTRL_CMD: |
862 | DBG1("The Base Band sends this value as a response to a " |
863 | "request for IMSI detach sent over the control " |
864 | "channel uplink (see section 7.6.1)." ); |
865 | break; |
866 | case CTRL_MDM: |
867 | port = PORT_MDM; |
868 | enable_ier = MDM_DL; |
869 | break; |
870 | case CTRL_DIAG: |
871 | port = PORT_DIAG; |
872 | enable_ier = DIAG_DL; |
873 | break; |
874 | case CTRL_APP1: |
875 | port = PORT_APP1; |
876 | enable_ier = APP1_DL; |
877 | break; |
878 | case CTRL_APP2: |
879 | port = PORT_APP2; |
880 | enable_ier = APP2_DL; |
881 | if (dc->state == NOZOMI_STATE_ALLOCATED) { |
882 | /* |
883 | * After card initialization the flow control |
884 | * received for APP2 is always the last |
885 | */ |
886 | dc->state = NOZOMI_STATE_READY; |
887 | dev_info(&dc->pdev->dev, "Device READY!\n" ); |
888 | } |
889 | break; |
890 | default: |
891 | dev_err(&dc->pdev->dev, |
892 | "ERROR: flow control received for non-existing port\n" ); |
893 | return 0; |
894 | } |
895 | |
896 | DBG1("0x%04X->0x%04X" , *((u16 *)&dc->port[port].ctrl_dl), |
897 | *((u16 *)&ctrl_dl)); |
898 | |
899 | old_ctrl = dc->port[port].ctrl_dl; |
900 | dc->port[port].ctrl_dl = ctrl_dl; |
901 | |
902 | if (old_ctrl.CTS == 1 && ctrl_dl.CTS == 0) { |
903 | DBG1("Disable interrupt (0x%04X) on port: %d" , |
904 | enable_ier, port); |
905 | disable_transmit_ul(port, dc); |
906 | |
907 | } else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) { |
908 | |
909 | if (kfifo_len(&dc->port[port].fifo_ul)) { |
910 | DBG1("Enable interrupt (0x%04X) on port: %d" , |
911 | enable_ier, port); |
912 | DBG1("Data in buffer [%d], enable transmit! " , |
913 | kfifo_len(&dc->port[port].fifo_ul)); |
914 | enable_transmit_ul(port, dc); |
915 | } else { |
916 | DBG1("No data in buffer..." ); |
917 | } |
918 | } |
919 | |
920 | if (*(u16 *)&old_ctrl == *(u16 *)&ctrl_dl) { |
921 | DBG1(" No change in mctrl" ); |
922 | return 1; |
923 | } |
924 | /* Update statistics */ |
925 | if (old_ctrl.CTS != ctrl_dl.CTS) |
926 | dc->port[port].tty_icount.cts++; |
927 | if (old_ctrl.DSR != ctrl_dl.DSR) |
928 | dc->port[port].tty_icount.dsr++; |
929 | if (old_ctrl.RI != ctrl_dl.RI) |
930 | dc->port[port].tty_icount.rng++; |
931 | if (old_ctrl.DCD != ctrl_dl.DCD) |
932 | dc->port[port].tty_icount.dcd++; |
933 | |
934 | wake_up_interruptible(&dc->port[port].tty_wait); |
935 | |
936 | DBG1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)" , |
937 | port, |
938 | dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts, |
939 | dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr); |
940 | |
941 | return 1; |
942 | } |
943 | |
944 | static enum ctrl_port_type port2ctrl(enum port_type port, |
945 | const struct nozomi *dc) |
946 | { |
947 | switch (port) { |
948 | case PORT_MDM: |
949 | return CTRL_MDM; |
950 | case PORT_DIAG: |
951 | return CTRL_DIAG; |
952 | case PORT_APP1: |
953 | return CTRL_APP1; |
954 | case PORT_APP2: |
955 | return CTRL_APP2; |
956 | default: |
957 | dev_err(&dc->pdev->dev, |
958 | "ERROR: send flow control " \ |
959 | "received for non-existing port\n" ); |
960 | } |
961 | return CTRL_ERROR; |
962 | } |
963 | |
964 | /* |
965 | * Send flow control, can only update one channel at a time |
966 | * Return 0 - If we have updated all flow control |
967 | * Return 1 - If we need to update more flow control, ack current enable more |
968 | */ |
969 | static int send_flow_control(struct nozomi *dc) |
970 | { |
971 | u32 i, more_flow_control_to_be_updated = 0; |
972 | u16 *ctrl; |
973 | |
974 | for (i = PORT_MDM; i < MAX_PORT; i++) { |
975 | if (dc->port[i].update_flow_control) { |
976 | if (more_flow_control_to_be_updated) { |
977 | /* We have more flow control to be updated */ |
978 | return 1; |
979 | } |
980 | dc->port[i].ctrl_ul.port = port2ctrl(port: i, dc); |
981 | ctrl = (u16 *)&dc->port[i].ctrl_ul; |
982 | write_mem32(mem_addr_start: dc->port[PORT_CTRL].ul_addr[0], \ |
983 | buf: (u32 *) ctrl, size_bytes: 2); |
984 | dc->port[i].update_flow_control = 0; |
985 | more_flow_control_to_be_updated = 1; |
986 | } |
987 | } |
988 | return 0; |
989 | } |
990 | |
991 | /* |
992 | * Handle downlink data, ports that are handled are modem and diagnostics |
993 | * Return 1 - ok |
994 | * Return 0 - toggle fields are out of sync |
995 | */ |
996 | static int handle_data_dl(struct nozomi *dc, enum port_type port, u8 *toggle, |
997 | u16 read_iir, u16 mask1, u16 mask2) |
998 | { |
999 | if (*toggle == 0 && read_iir & mask1) { |
1000 | if (receive_data(index: port, dc)) { |
1001 | writew(val: mask1, addr: dc->reg_fcr); |
1002 | *toggle = !(*toggle); |
1003 | } |
1004 | |
1005 | if (read_iir & mask2) { |
1006 | if (receive_data(index: port, dc)) { |
1007 | writew(val: mask2, addr: dc->reg_fcr); |
1008 | *toggle = !(*toggle); |
1009 | } |
1010 | } |
1011 | } else if (*toggle == 1 && read_iir & mask2) { |
1012 | if (receive_data(index: port, dc)) { |
1013 | writew(val: mask2, addr: dc->reg_fcr); |
1014 | *toggle = !(*toggle); |
1015 | } |
1016 | |
1017 | if (read_iir & mask1) { |
1018 | if (receive_data(index: port, dc)) { |
1019 | writew(val: mask1, addr: dc->reg_fcr); |
1020 | *toggle = !(*toggle); |
1021 | } |
1022 | } |
1023 | } else { |
1024 | dev_err(&dc->pdev->dev, "port out of sync!, toggle:%d\n" , |
1025 | *toggle); |
1026 | return 0; |
1027 | } |
1028 | return 1; |
1029 | } |
1030 | |
1031 | /* |
1032 | * Handle uplink data, this is currently for the modem port |
1033 | * Return 1 - ok |
1034 | * Return 0 - toggle field are out of sync |
1035 | */ |
1036 | static int handle_data_ul(struct nozomi *dc, enum port_type port, u16 read_iir) |
1037 | { |
1038 | u8 *toggle = &(dc->port[port].toggle_ul); |
1039 | |
1040 | if (*toggle == 0 && read_iir & MDM_UL1) { |
1041 | dc->last_ier &= ~MDM_UL; |
1042 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1043 | if (send_data(index: port, dc)) { |
1044 | writew(MDM_UL1, addr: dc->reg_fcr); |
1045 | dc->last_ier = dc->last_ier | MDM_UL; |
1046 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1047 | *toggle = !*toggle; |
1048 | } |
1049 | |
1050 | if (read_iir & MDM_UL2) { |
1051 | dc->last_ier &= ~MDM_UL; |
1052 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1053 | if (send_data(index: port, dc)) { |
1054 | writew(MDM_UL2, addr: dc->reg_fcr); |
1055 | dc->last_ier = dc->last_ier | MDM_UL; |
1056 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1057 | *toggle = !*toggle; |
1058 | } |
1059 | } |
1060 | |
1061 | } else if (*toggle == 1 && read_iir & MDM_UL2) { |
1062 | dc->last_ier &= ~MDM_UL; |
1063 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1064 | if (send_data(index: port, dc)) { |
1065 | writew(MDM_UL2, addr: dc->reg_fcr); |
1066 | dc->last_ier = dc->last_ier | MDM_UL; |
1067 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1068 | *toggle = !*toggle; |
1069 | } |
1070 | |
1071 | if (read_iir & MDM_UL1) { |
1072 | dc->last_ier &= ~MDM_UL; |
1073 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1074 | if (send_data(index: port, dc)) { |
1075 | writew(MDM_UL1, addr: dc->reg_fcr); |
1076 | dc->last_ier = dc->last_ier | MDM_UL; |
1077 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1078 | *toggle = !*toggle; |
1079 | } |
1080 | } |
1081 | } else { |
1082 | writew(val: read_iir & MDM_UL, addr: dc->reg_fcr); |
1083 | dev_err(&dc->pdev->dev, "port out of sync!\n" ); |
1084 | return 0; |
1085 | } |
1086 | return 1; |
1087 | } |
1088 | |
1089 | static irqreturn_t interrupt_handler(int irq, void *dev_id) |
1090 | { |
1091 | struct nozomi *dc = dev_id; |
1092 | unsigned int a; |
1093 | u16 read_iir; |
1094 | |
1095 | if (!dc) |
1096 | return IRQ_NONE; |
1097 | |
1098 | spin_lock(lock: &dc->spin_mutex); |
1099 | read_iir = readw(addr: dc->reg_iir); |
1100 | |
1101 | /* Card removed */ |
1102 | if (read_iir == (u16)-1) |
1103 | goto none; |
1104 | /* |
1105 | * Just handle interrupt enabled in IER |
1106 | * (by masking with dc->last_ier) |
1107 | */ |
1108 | read_iir &= dc->last_ier; |
1109 | |
1110 | if (read_iir == 0) |
1111 | goto none; |
1112 | |
1113 | |
1114 | DBG4("%s irq:0x%04X, prev:0x%04X" , interrupt2str(read_iir), read_iir, |
1115 | dc->last_ier); |
1116 | |
1117 | if (read_iir & RESET) { |
1118 | if (unlikely(!nozomi_read_config_table(dc))) { |
1119 | dc->last_ier = 0x0; |
1120 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1121 | dev_err(&dc->pdev->dev, "Could not read status from " |
1122 | "card, we should disable interface\n" ); |
1123 | } else { |
1124 | writew(RESET, addr: dc->reg_fcr); |
1125 | } |
1126 | /* No more useful info if this was the reset interrupt. */ |
1127 | goto exit_handler; |
1128 | } |
1129 | if (read_iir & CTRL_UL) { |
1130 | DBG1("CTRL_UL" ); |
1131 | dc->last_ier &= ~CTRL_UL; |
1132 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1133 | if (send_flow_control(dc)) { |
1134 | writew(CTRL_UL, addr: dc->reg_fcr); |
1135 | dc->last_ier = dc->last_ier | CTRL_UL; |
1136 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1137 | } |
1138 | } |
1139 | if (read_iir & CTRL_DL) { |
1140 | receive_flow_control(dc); |
1141 | writew(CTRL_DL, addr: dc->reg_fcr); |
1142 | } |
1143 | if (read_iir & MDM_DL) { |
1144 | if (!handle_data_dl(dc, port: PORT_MDM, |
1145 | toggle: &(dc->port[PORT_MDM].toggle_dl), read_iir, |
1146 | MDM_DL1, MDM_DL2)) { |
1147 | dev_err(&dc->pdev->dev, "MDM_DL out of sync!\n" ); |
1148 | goto exit_handler; |
1149 | } |
1150 | } |
1151 | if (read_iir & MDM_UL) { |
1152 | if (!handle_data_ul(dc, port: PORT_MDM, read_iir)) { |
1153 | dev_err(&dc->pdev->dev, "MDM_UL out of sync!\n" ); |
1154 | goto exit_handler; |
1155 | } |
1156 | } |
1157 | if (read_iir & DIAG_DL) { |
1158 | if (!handle_data_dl(dc, port: PORT_DIAG, |
1159 | toggle: &(dc->port[PORT_DIAG].toggle_dl), read_iir, |
1160 | DIAG_DL1, DIAG_DL2)) { |
1161 | dev_err(&dc->pdev->dev, "DIAG_DL out of sync!\n" ); |
1162 | goto exit_handler; |
1163 | } |
1164 | } |
1165 | if (read_iir & DIAG_UL) { |
1166 | dc->last_ier &= ~DIAG_UL; |
1167 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1168 | if (send_data(index: PORT_DIAG, dc)) { |
1169 | writew(DIAG_UL, addr: dc->reg_fcr); |
1170 | dc->last_ier = dc->last_ier | DIAG_UL; |
1171 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1172 | } |
1173 | } |
1174 | if (read_iir & APP1_DL) { |
1175 | if (receive_data(index: PORT_APP1, dc)) |
1176 | writew(APP1_DL, addr: dc->reg_fcr); |
1177 | } |
1178 | if (read_iir & APP1_UL) { |
1179 | dc->last_ier &= ~APP1_UL; |
1180 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1181 | if (send_data(index: PORT_APP1, dc)) { |
1182 | writew(APP1_UL, addr: dc->reg_fcr); |
1183 | dc->last_ier = dc->last_ier | APP1_UL; |
1184 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1185 | } |
1186 | } |
1187 | if (read_iir & APP2_DL) { |
1188 | if (receive_data(index: PORT_APP2, dc)) |
1189 | writew(APP2_DL, addr: dc->reg_fcr); |
1190 | } |
1191 | if (read_iir & APP2_UL) { |
1192 | dc->last_ier &= ~APP2_UL; |
1193 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1194 | if (send_data(index: PORT_APP2, dc)) { |
1195 | writew(APP2_UL, addr: dc->reg_fcr); |
1196 | dc->last_ier = dc->last_ier | APP2_UL; |
1197 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1198 | } |
1199 | } |
1200 | |
1201 | exit_handler: |
1202 | spin_unlock(lock: &dc->spin_mutex); |
1203 | |
1204 | for (a = 0; a < NOZOMI_MAX_PORTS; a++) |
1205 | if (test_and_clear_bit(nr: a, addr: &dc->flip)) |
1206 | tty_flip_buffer_push(port: &dc->port[a].port); |
1207 | |
1208 | return IRQ_HANDLED; |
1209 | none: |
1210 | spin_unlock(lock: &dc->spin_mutex); |
1211 | return IRQ_NONE; |
1212 | } |
1213 | |
1214 | static void nozomi_get_card_type(struct nozomi *dc) |
1215 | { |
1216 | int i; |
1217 | u32 size = 0; |
1218 | |
1219 | for (i = 0; i < 6; i++) |
1220 | size += pci_resource_len(dc->pdev, i); |
1221 | |
1222 | /* Assume card type F32_8 if no match */ |
1223 | dc->card_type = size == 2048 ? F32_2 : F32_8; |
1224 | |
1225 | dev_info(&dc->pdev->dev, "Card type is: %d\n" , dc->card_type); |
1226 | } |
1227 | |
1228 | static void nozomi_setup_private_data(struct nozomi *dc) |
1229 | { |
1230 | void __iomem *offset = dc->base_addr + dc->card_type / 2; |
1231 | unsigned int i; |
1232 | |
1233 | dc->reg_fcr = (void __iomem *)(offset + R_FCR); |
1234 | dc->reg_iir = (void __iomem *)(offset + R_IIR); |
1235 | dc->reg_ier = (void __iomem *)(offset + R_IER); |
1236 | dc->last_ier = 0; |
1237 | dc->flip = 0; |
1238 | |
1239 | dc->port[PORT_MDM].token_dl = MDM_DL; |
1240 | dc->port[PORT_DIAG].token_dl = DIAG_DL; |
1241 | dc->port[PORT_APP1].token_dl = APP1_DL; |
1242 | dc->port[PORT_APP2].token_dl = APP2_DL; |
1243 | |
1244 | for (i = 0; i < MAX_PORT; i++) |
1245 | init_waitqueue_head(&dc->port[i].tty_wait); |
1246 | } |
1247 | |
1248 | static ssize_t card_type_show(struct device *dev, struct device_attribute *attr, |
1249 | char *buf) |
1250 | { |
1251 | const struct nozomi *dc = dev_get_drvdata(dev); |
1252 | |
1253 | return sprintf(buf, fmt: "%d\n" , dc->card_type); |
1254 | } |
1255 | static DEVICE_ATTR_RO(card_type); |
1256 | |
1257 | static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr, |
1258 | char *buf) |
1259 | { |
1260 | const struct nozomi *dc = dev_get_drvdata(dev); |
1261 | |
1262 | return sprintf(buf, fmt: "%u\n" , dc->open_ttys); |
1263 | } |
1264 | static DEVICE_ATTR_RO(open_ttys); |
1265 | |
1266 | static void make_sysfs_files(struct nozomi *dc) |
1267 | { |
1268 | if (device_create_file(device: &dc->pdev->dev, entry: &dev_attr_card_type)) |
1269 | dev_err(&dc->pdev->dev, |
1270 | "Could not create sysfs file for card_type\n" ); |
1271 | if (device_create_file(device: &dc->pdev->dev, entry: &dev_attr_open_ttys)) |
1272 | dev_err(&dc->pdev->dev, |
1273 | "Could not create sysfs file for open_ttys\n" ); |
1274 | } |
1275 | |
1276 | static void remove_sysfs_files(struct nozomi *dc) |
1277 | { |
1278 | device_remove_file(dev: &dc->pdev->dev, attr: &dev_attr_card_type); |
1279 | device_remove_file(dev: &dc->pdev->dev, attr: &dev_attr_open_ttys); |
1280 | } |
1281 | |
1282 | /* Allocate memory for one device */ |
1283 | static int nozomi_card_init(struct pci_dev *pdev, |
1284 | const struct pci_device_id *ent) |
1285 | { |
1286 | int ret; |
1287 | struct nozomi *dc = NULL; |
1288 | int ndev_idx; |
1289 | int i; |
1290 | |
1291 | for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++) |
1292 | if (!ndevs[ndev_idx]) |
1293 | break; |
1294 | |
1295 | if (ndev_idx >= ARRAY_SIZE(ndevs)) { |
1296 | dev_err(&pdev->dev, "no free tty range for this card left\n" ); |
1297 | ret = -EIO; |
1298 | goto err; |
1299 | } |
1300 | |
1301 | dc = kzalloc(size: sizeof(struct nozomi), GFP_KERNEL); |
1302 | if (unlikely(!dc)) { |
1303 | dev_err(&pdev->dev, "Could not allocate memory\n" ); |
1304 | ret = -ENOMEM; |
1305 | goto err_free; |
1306 | } |
1307 | |
1308 | dc->pdev = pdev; |
1309 | |
1310 | ret = pci_enable_device(dev: dc->pdev); |
1311 | if (ret) { |
1312 | dev_err(&pdev->dev, "Failed to enable PCI Device\n" ); |
1313 | goto err_free; |
1314 | } |
1315 | |
1316 | ret = pci_request_regions(dc->pdev, NOZOMI_NAME); |
1317 | if (ret) { |
1318 | dev_err(&pdev->dev, "I/O address 0x%04x already in use\n" , |
1319 | (int) /* nozomi_private.io_addr */ 0); |
1320 | goto err_disable_device; |
1321 | } |
1322 | |
1323 | /* Find out what card type it is */ |
1324 | nozomi_get_card_type(dc); |
1325 | |
1326 | dc->base_addr = pci_iomap(dev: dc->pdev, bar: 0, max: dc->card_type); |
1327 | if (!dc->base_addr) { |
1328 | dev_err(&pdev->dev, "Unable to map card MMIO\n" ); |
1329 | ret = -ENODEV; |
1330 | goto err_rel_regs; |
1331 | } |
1332 | |
1333 | dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL); |
1334 | if (!dc->send_buf) { |
1335 | dev_err(&pdev->dev, "Could not allocate send buffer?\n" ); |
1336 | ret = -ENOMEM; |
1337 | goto err_free_sbuf; |
1338 | } |
1339 | |
1340 | for (i = PORT_MDM; i < MAX_PORT; i++) { |
1341 | if (kfifo_alloc(&dc->port[i].fifo_ul, FIFO_BUFFER_SIZE_UL, |
1342 | GFP_KERNEL)) { |
1343 | dev_err(&pdev->dev, |
1344 | "Could not allocate kfifo buffer\n" ); |
1345 | ret = -ENOMEM; |
1346 | goto err_free_kfifo; |
1347 | } |
1348 | } |
1349 | |
1350 | spin_lock_init(&dc->spin_mutex); |
1351 | |
1352 | nozomi_setup_private_data(dc); |
1353 | |
1354 | /* Disable all interrupts */ |
1355 | dc->last_ier = 0; |
1356 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1357 | |
1358 | ret = request_irq(irq: pdev->irq, handler: &interrupt_handler, IRQF_SHARED, |
1359 | NOZOMI_NAME, dev: dc); |
1360 | if (unlikely(ret)) { |
1361 | dev_err(&pdev->dev, "can't request irq %d\n" , pdev->irq); |
1362 | goto err_free_all_kfifo; |
1363 | } |
1364 | |
1365 | DBG1("base_addr: %p" , dc->base_addr); |
1366 | |
1367 | make_sysfs_files(dc); |
1368 | |
1369 | dc->index_start = ndev_idx * MAX_PORT; |
1370 | ndevs[ndev_idx] = dc; |
1371 | |
1372 | pci_set_drvdata(pdev, data: dc); |
1373 | |
1374 | /* Enable RESET interrupt */ |
1375 | dc->last_ier = RESET; |
1376 | iowrite16(dc->last_ier, dc->reg_ier); |
1377 | |
1378 | dc->state = NOZOMI_STATE_ENABLED; |
1379 | |
1380 | for (i = 0; i < MAX_PORT; i++) { |
1381 | struct device *tty_dev; |
1382 | struct port *port = &dc->port[i]; |
1383 | port->dc = dc; |
1384 | tty_port_init(port: &port->port); |
1385 | port->port.ops = &noz_tty_port_ops; |
1386 | tty_dev = tty_port_register_device(port: &port->port, driver: ntty_driver, |
1387 | index: dc->index_start + i, device: &pdev->dev); |
1388 | |
1389 | if (IS_ERR(ptr: tty_dev)) { |
1390 | ret = PTR_ERR(ptr: tty_dev); |
1391 | dev_err(&pdev->dev, "Could not allocate tty?\n" ); |
1392 | tty_port_destroy(port: &port->port); |
1393 | goto err_free_tty; |
1394 | } |
1395 | } |
1396 | |
1397 | return 0; |
1398 | |
1399 | err_free_tty: |
1400 | for (i--; i >= 0; i--) { |
1401 | tty_unregister_device(driver: ntty_driver, index: dc->index_start + i); |
1402 | tty_port_destroy(port: &dc->port[i].port); |
1403 | } |
1404 | free_irq(pdev->irq, dc); |
1405 | err_free_all_kfifo: |
1406 | i = MAX_PORT; |
1407 | err_free_kfifo: |
1408 | for (i--; i >= PORT_MDM; i--) |
1409 | kfifo_free(&dc->port[i].fifo_ul); |
1410 | err_free_sbuf: |
1411 | kfree(objp: dc->send_buf); |
1412 | iounmap(addr: dc->base_addr); |
1413 | err_rel_regs: |
1414 | pci_release_regions(pdev); |
1415 | err_disable_device: |
1416 | pci_disable_device(dev: pdev); |
1417 | err_free: |
1418 | kfree(objp: dc); |
1419 | err: |
1420 | return ret; |
1421 | } |
1422 | |
1423 | static void tty_exit(struct nozomi *dc) |
1424 | { |
1425 | unsigned int i; |
1426 | |
1427 | for (i = 0; i < MAX_PORT; ++i) |
1428 | tty_port_tty_hangup(port: &dc->port[i].port, check_clocal: false); |
1429 | |
1430 | /* Racy below - surely should wait for scheduled work to be done or |
1431 | complete off a hangup method ? */ |
1432 | while (dc->open_ttys) |
1433 | msleep(msecs: 1); |
1434 | for (i = 0; i < MAX_PORT; ++i) { |
1435 | tty_unregister_device(driver: ntty_driver, index: dc->index_start + i); |
1436 | tty_port_destroy(port: &dc->port[i].port); |
1437 | } |
1438 | } |
1439 | |
1440 | /* Deallocate memory for one device */ |
1441 | static void nozomi_card_exit(struct pci_dev *pdev) |
1442 | { |
1443 | int i; |
1444 | struct ctrl_ul ctrl; |
1445 | struct nozomi *dc = pci_get_drvdata(pdev); |
1446 | |
1447 | /* Disable all interrupts */ |
1448 | dc->last_ier = 0; |
1449 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1450 | |
1451 | tty_exit(dc); |
1452 | |
1453 | /* Send 0x0001, command card to resend the reset token. */ |
1454 | /* This is to get the reset when the module is reloaded. */ |
1455 | ctrl.port = 0x00; |
1456 | ctrl.reserved = 0; |
1457 | ctrl.RTS = 0; |
1458 | ctrl.DTR = 1; |
1459 | DBG1("sending flow control 0x%04X" , *((u16 *)&ctrl)); |
1460 | |
1461 | /* Setup dc->reg addresses to we can use defines here */ |
1462 | write_mem32(mem_addr_start: dc->port[PORT_CTRL].ul_addr[0], buf: (u32 *)&ctrl, size_bytes: 2); |
1463 | writew(CTRL_UL, addr: dc->reg_fcr); /* push the token to the card. */ |
1464 | |
1465 | remove_sysfs_files(dc); |
1466 | |
1467 | free_irq(pdev->irq, dc); |
1468 | |
1469 | for (i = 0; i < MAX_PORT; i++) |
1470 | kfifo_free(&dc->port[i].fifo_ul); |
1471 | |
1472 | kfree(objp: dc->send_buf); |
1473 | |
1474 | iounmap(addr: dc->base_addr); |
1475 | |
1476 | pci_release_regions(pdev); |
1477 | |
1478 | pci_disable_device(dev: pdev); |
1479 | |
1480 | ndevs[dc->index_start / MAX_PORT] = NULL; |
1481 | |
1482 | kfree(objp: dc); |
1483 | } |
1484 | |
1485 | static void set_rts(const struct tty_struct *tty, int rts) |
1486 | { |
1487 | struct port *port = get_port_by_tty(tty); |
1488 | |
1489 | port->ctrl_ul.RTS = rts; |
1490 | port->update_flow_control = 1; |
1491 | enable_transmit_ul(port: PORT_CTRL, dc: get_dc_by_tty(tty)); |
1492 | } |
1493 | |
1494 | static void set_dtr(const struct tty_struct *tty, int dtr) |
1495 | { |
1496 | struct port *port = get_port_by_tty(tty); |
1497 | |
1498 | DBG1("SETTING DTR index: %d, dtr: %d" , tty->index, dtr); |
1499 | |
1500 | port->ctrl_ul.DTR = dtr; |
1501 | port->update_flow_control = 1; |
1502 | enable_transmit_ul(port: PORT_CTRL, dc: get_dc_by_tty(tty)); |
1503 | } |
1504 | |
1505 | /* |
1506 | * ---------------------------------------------------------------------------- |
1507 | * TTY code |
1508 | * ---------------------------------------------------------------------------- |
1509 | */ |
1510 | |
1511 | static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) |
1512 | { |
1513 | struct port *port = get_port_by_tty(tty); |
1514 | struct nozomi *dc = get_dc_by_tty(tty); |
1515 | int ret; |
1516 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) |
1517 | return -ENODEV; |
1518 | ret = tty_standard_install(driver, tty); |
1519 | if (ret == 0) |
1520 | tty->driver_data = port; |
1521 | return ret; |
1522 | } |
1523 | |
1524 | static void ntty_cleanup(struct tty_struct *tty) |
1525 | { |
1526 | tty->driver_data = NULL; |
1527 | } |
1528 | |
1529 | static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) |
1530 | { |
1531 | struct port *port = container_of(tport, struct port, port); |
1532 | struct nozomi *dc = port->dc; |
1533 | unsigned long flags; |
1534 | |
1535 | DBG1("open: %d" , port->token_dl); |
1536 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1537 | dc->last_ier = dc->last_ier | port->token_dl; |
1538 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1539 | dc->open_ttys++; |
1540 | spin_unlock_irqrestore(lock: &dc->spin_mutex, flags); |
1541 | printk("noz: activated %d: %p\n" , tty->index, tport); |
1542 | return 0; |
1543 | } |
1544 | |
1545 | static int ntty_open(struct tty_struct *tty, struct file *filp) |
1546 | { |
1547 | struct port *port = tty->driver_data; |
1548 | return tty_port_open(port: &port->port, tty, filp); |
1549 | } |
1550 | |
1551 | static void ntty_shutdown(struct tty_port *tport) |
1552 | { |
1553 | struct port *port = container_of(tport, struct port, port); |
1554 | struct nozomi *dc = port->dc; |
1555 | unsigned long flags; |
1556 | |
1557 | DBG1("close: %d" , port->token_dl); |
1558 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1559 | dc->last_ier &= ~(port->token_dl); |
1560 | writew(val: dc->last_ier, addr: dc->reg_ier); |
1561 | dc->open_ttys--; |
1562 | spin_unlock_irqrestore(lock: &dc->spin_mutex, flags); |
1563 | printk("noz: shutdown %p\n" , tport); |
1564 | } |
1565 | |
1566 | static void ntty_close(struct tty_struct *tty, struct file *filp) |
1567 | { |
1568 | struct port *port = tty->driver_data; |
1569 | if (port) |
1570 | tty_port_close(port: &port->port, tty, filp); |
1571 | } |
1572 | |
1573 | static void ntty_hangup(struct tty_struct *tty) |
1574 | { |
1575 | struct port *port = tty->driver_data; |
1576 | tty_port_hangup(port: &port->port); |
1577 | } |
1578 | |
1579 | /* |
1580 | * called when the userspace process writes to the tty (/dev/noz*). |
1581 | * Data is inserted into a fifo, which is then read and transferred to the modem. |
1582 | */ |
1583 | static ssize_t ntty_write(struct tty_struct *tty, const u8 *buffer, |
1584 | size_t count) |
1585 | { |
1586 | struct nozomi *dc = get_dc_by_tty(tty); |
1587 | struct port *port = tty->driver_data; |
1588 | unsigned long flags; |
1589 | size_t rval; |
1590 | |
1591 | if (!dc || !port) |
1592 | return -ENODEV; |
1593 | |
1594 | rval = kfifo_in(&port->fifo_ul, buffer, count); |
1595 | |
1596 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1597 | /* CTS is only valid on the modem channel */ |
1598 | if (port == &(dc->port[PORT_MDM])) { |
1599 | if (port->ctrl_dl.CTS) { |
1600 | DBG4("Enable interrupt" ); |
1601 | enable_transmit_ul(port: tty->index % MAX_PORT, dc); |
1602 | } else { |
1603 | dev_err(&dc->pdev->dev, |
1604 | "CTS not active on modem port?\n" ); |
1605 | } |
1606 | } else { |
1607 | enable_transmit_ul(port: tty->index % MAX_PORT, dc); |
1608 | } |
1609 | spin_unlock_irqrestore(lock: &dc->spin_mutex, flags); |
1610 | |
1611 | return rval; |
1612 | } |
1613 | |
1614 | /* |
1615 | * Calculate how much is left in device |
1616 | * This method is called by the upper tty layer. |
1617 | * #according to sources N_TTY.c it expects a value >= 0 and |
1618 | * does not check for negative values. |
1619 | * |
1620 | * If the port is unplugged report lots of room and let the bits |
1621 | * dribble away so we don't block anything. |
1622 | */ |
1623 | static unsigned int ntty_write_room(struct tty_struct *tty) |
1624 | { |
1625 | struct port *port = tty->driver_data; |
1626 | unsigned int room = 4096; |
1627 | const struct nozomi *dc = get_dc_by_tty(tty); |
1628 | |
1629 | if (dc) |
1630 | room = kfifo_avail(&port->fifo_ul); |
1631 | |
1632 | return room; |
1633 | } |
1634 | |
1635 | /* Gets io control parameters */ |
1636 | static int ntty_tiocmget(struct tty_struct *tty) |
1637 | { |
1638 | const struct port *port = tty->driver_data; |
1639 | const struct ctrl_dl *ctrl_dl = &port->ctrl_dl; |
1640 | const struct ctrl_ul *ctrl_ul = &port->ctrl_ul; |
1641 | |
1642 | /* Note: these could change under us but it is not clear this |
1643 | matters if so */ |
1644 | return (ctrl_ul->RTS ? TIOCM_RTS : 0) |
1645 | | (ctrl_ul->DTR ? TIOCM_DTR : 0) |
1646 | | (ctrl_dl->DCD ? TIOCM_CAR : 0) |
1647 | | (ctrl_dl->RI ? TIOCM_RNG : 0) |
1648 | | (ctrl_dl->DSR ? TIOCM_DSR : 0) |
1649 | | (ctrl_dl->CTS ? TIOCM_CTS : 0); |
1650 | } |
1651 | |
1652 | /* Sets io controls parameters */ |
1653 | static int ntty_tiocmset(struct tty_struct *tty, |
1654 | unsigned int set, unsigned int clear) |
1655 | { |
1656 | struct nozomi *dc = get_dc_by_tty(tty); |
1657 | unsigned long flags; |
1658 | |
1659 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1660 | if (set & TIOCM_RTS) |
1661 | set_rts(tty, rts: 1); |
1662 | else if (clear & TIOCM_RTS) |
1663 | set_rts(tty, rts: 0); |
1664 | |
1665 | if (set & TIOCM_DTR) |
1666 | set_dtr(tty, dtr: 1); |
1667 | else if (clear & TIOCM_DTR) |
1668 | set_dtr(tty, dtr: 0); |
1669 | spin_unlock_irqrestore(lock: &dc->spin_mutex, flags); |
1670 | |
1671 | return 0; |
1672 | } |
1673 | |
1674 | static int ntty_cflags_changed(struct port *port, unsigned long flags, |
1675 | struct async_icount *cprev) |
1676 | { |
1677 | const struct async_icount cnow = port->tty_icount; |
1678 | int ret; |
1679 | |
1680 | ret = ((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) |
1681 | || ((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) |
1682 | || ((flags & TIOCM_CD) && (cnow.dcd != cprev->dcd)) |
1683 | || ((flags & TIOCM_CTS) && (cnow.cts != cprev->cts)); |
1684 | |
1685 | *cprev = cnow; |
1686 | |
1687 | return ret; |
1688 | } |
1689 | |
1690 | static int ntty_tiocgicount(struct tty_struct *tty, |
1691 | struct serial_icounter_struct *icount) |
1692 | { |
1693 | struct port *port = tty->driver_data; |
1694 | const struct async_icount cnow = port->tty_icount; |
1695 | |
1696 | icount->cts = cnow.cts; |
1697 | icount->dsr = cnow.dsr; |
1698 | icount->rng = cnow.rng; |
1699 | icount->dcd = cnow.dcd; |
1700 | icount->rx = cnow.rx; |
1701 | icount->tx = cnow.tx; |
1702 | icount->frame = cnow.frame; |
1703 | icount->overrun = cnow.overrun; |
1704 | icount->parity = cnow.parity; |
1705 | icount->brk = cnow.brk; |
1706 | icount->buf_overrun = cnow.buf_overrun; |
1707 | return 0; |
1708 | } |
1709 | |
1710 | static int ntty_ioctl(struct tty_struct *tty, |
1711 | unsigned int cmd, unsigned long arg) |
1712 | { |
1713 | struct port *port = tty->driver_data; |
1714 | int rval = -ENOIOCTLCMD; |
1715 | |
1716 | switch (cmd) { |
1717 | case TIOCMIWAIT: { |
1718 | struct async_icount cprev = port->tty_icount; |
1719 | |
1720 | rval = wait_event_interruptible(port->tty_wait, |
1721 | ntty_cflags_changed(port, arg, &cprev)); |
1722 | break; |
1723 | } |
1724 | default: |
1725 | DBG1("ERR: 0x%08X, %d" , cmd, cmd); |
1726 | break; |
1727 | } |
1728 | |
1729 | return rval; |
1730 | } |
1731 | |
1732 | /* |
1733 | * Called by the upper tty layer when tty buffers are ready |
1734 | * to receive data again after a call to throttle. |
1735 | */ |
1736 | static void ntty_unthrottle(struct tty_struct *tty) |
1737 | { |
1738 | struct nozomi *dc = get_dc_by_tty(tty); |
1739 | unsigned long flags; |
1740 | |
1741 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1742 | enable_transmit_dl(port: tty->index % MAX_PORT, dc); |
1743 | set_rts(tty, rts: 1); |
1744 | |
1745 | spin_unlock_irqrestore(lock: &dc->spin_mutex, flags); |
1746 | } |
1747 | |
1748 | /* |
1749 | * Called by the upper tty layer when the tty buffers are almost full. |
1750 | * The driver should stop send more data. |
1751 | */ |
1752 | static void ntty_throttle(struct tty_struct *tty) |
1753 | { |
1754 | struct nozomi *dc = get_dc_by_tty(tty); |
1755 | unsigned long flags; |
1756 | |
1757 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1758 | set_rts(tty, rts: 0); |
1759 | spin_unlock_irqrestore(lock: &dc->spin_mutex, flags); |
1760 | } |
1761 | |
1762 | /* Returns number of chars in buffer, called by tty layer */ |
1763 | static unsigned int ntty_chars_in_buffer(struct tty_struct *tty) |
1764 | { |
1765 | struct port *port = tty->driver_data; |
1766 | struct nozomi *dc = get_dc_by_tty(tty); |
1767 | |
1768 | if (unlikely(!dc || !port)) |
1769 | return 0; |
1770 | |
1771 | return kfifo_len(&port->fifo_ul); |
1772 | } |
1773 | |
1774 | static const struct tty_port_operations noz_tty_port_ops = { |
1775 | .activate = ntty_activate, |
1776 | .shutdown = ntty_shutdown, |
1777 | }; |
1778 | |
1779 | static const struct tty_operations tty_ops = { |
1780 | .ioctl = ntty_ioctl, |
1781 | .open = ntty_open, |
1782 | .close = ntty_close, |
1783 | .hangup = ntty_hangup, |
1784 | .write = ntty_write, |
1785 | .write_room = ntty_write_room, |
1786 | .unthrottle = ntty_unthrottle, |
1787 | .throttle = ntty_throttle, |
1788 | .chars_in_buffer = ntty_chars_in_buffer, |
1789 | .tiocmget = ntty_tiocmget, |
1790 | .tiocmset = ntty_tiocmset, |
1791 | .get_icount = ntty_tiocgicount, |
1792 | .install = ntty_install, |
1793 | .cleanup = ntty_cleanup, |
1794 | }; |
1795 | |
1796 | /* Module initialization */ |
1797 | static struct pci_driver nozomi_driver = { |
1798 | .name = NOZOMI_NAME, |
1799 | .id_table = nozomi_pci_tbl, |
1800 | .probe = nozomi_card_init, |
1801 | .remove = nozomi_card_exit, |
1802 | }; |
1803 | |
1804 | static __init int nozomi_init(void) |
1805 | { |
1806 | int ret; |
1807 | |
1808 | ntty_driver = tty_alloc_driver(NTTY_TTY_MAXMINORS, TTY_DRIVER_REAL_RAW | |
1809 | TTY_DRIVER_DYNAMIC_DEV); |
1810 | if (IS_ERR(ptr: ntty_driver)) |
1811 | return PTR_ERR(ptr: ntty_driver); |
1812 | |
1813 | ntty_driver->driver_name = NOZOMI_NAME_TTY; |
1814 | ntty_driver->name = "noz" ; |
1815 | ntty_driver->major = 0; |
1816 | ntty_driver->type = TTY_DRIVER_TYPE_SERIAL; |
1817 | ntty_driver->subtype = SERIAL_TYPE_NORMAL; |
1818 | ntty_driver->init_termios = tty_std_termios; |
1819 | ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \ |
1820 | HUPCL | CLOCAL; |
1821 | ntty_driver->init_termios.c_ispeed = 115200; |
1822 | ntty_driver->init_termios.c_ospeed = 115200; |
1823 | tty_set_operations(driver: ntty_driver, op: &tty_ops); |
1824 | |
1825 | ret = tty_register_driver(driver: ntty_driver); |
1826 | if (ret) { |
1827 | printk(KERN_ERR "Nozomi: failed to register ntty driver\n" ); |
1828 | goto free_tty; |
1829 | } |
1830 | |
1831 | ret = pci_register_driver(&nozomi_driver); |
1832 | if (ret) { |
1833 | printk(KERN_ERR "Nozomi: can't register pci driver\n" ); |
1834 | goto unr_tty; |
1835 | } |
1836 | |
1837 | return 0; |
1838 | unr_tty: |
1839 | tty_unregister_driver(driver: ntty_driver); |
1840 | free_tty: |
1841 | tty_driver_kref_put(driver: ntty_driver); |
1842 | return ret; |
1843 | } |
1844 | |
1845 | static __exit void nozomi_exit(void) |
1846 | { |
1847 | pci_unregister_driver(dev: &nozomi_driver); |
1848 | tty_unregister_driver(driver: ntty_driver); |
1849 | tty_driver_kref_put(driver: ntty_driver); |
1850 | } |
1851 | |
1852 | module_init(nozomi_init); |
1853 | module_exit(nozomi_exit); |
1854 | |
1855 | MODULE_LICENSE("Dual BSD/GPL" ); |
1856 | MODULE_DESCRIPTION("Nozomi driver" ); |
1857 | |