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