aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/ctctty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net/ctctty.c')
-rw-r--r--drivers/s390/net/ctctty.c1276
1 files changed, 1276 insertions, 0 deletions
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
new file mode 100644
index 000000000000..9257d60c7833
--- /dev/null
+++ b/drivers/s390/net/ctctty.c
@@ -0,0 +1,1276 @@
1/*
2 * $Id: ctctty.c,v 1.26 2004/08/04 11:06:55 mschwide Exp $
3 *
4 * CTC / ESCON network driver, tty interface.
5 *
6 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include <linux/config.h>
26#include <linux/module.h>
27#include <linux/tty.h>
28#include <linux/serial_reg.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <asm/uaccess.h>
32#include <linux/devfs_fs_kernel.h>
33#include "ctctty.h"
34#include "ctcdbug.h"
35
36#define CTC_TTY_MAJOR 43
37#define CTC_TTY_MAX_DEVICES 64
38
39#define CTC_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */
40#define CTC_ASYNC_INITIALIZED 0x80000000 /* port was initialized */
41#define CTC_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device active */
42#define CTC_ASYNC_CLOSING 0x08000000 /* Serial port is closing */
43#define CTC_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */
44#define CTC_ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */
45#define CTC_ASYNC_HUP_NOTIFY 0x0001 /* Notify tty on hangups/closes */
46#define CTC_ASYNC_NETDEV_OPEN 0x0002 /* Underlying netdev is open */
47#define CTC_ASYNC_TX_LINESTAT 0x0004 /* Must send line status */
48#define CTC_ASYNC_SPLIT_TERMIOS 0x0008 /* Sep. termios for dialin/out */
49#define CTC_TTY_XMIT_SIZE 1024 /* Default bufsize for write */
50#define CTC_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */
51
52/* Private data (similar to async_struct in <linux/serial.h>) */
53typedef struct {
54 int magic;
55 int flags; /* defined in tty.h */
56 int mcr; /* Modem control register */
57 int msr; /* Modem status register */
58 int lsr; /* Line status register */
59 int line;
60 int count; /* # of fd on device */
61 int blocked_open; /* # of blocked opens */
62 struct net_device *netdev;
63 struct sk_buff_head tx_queue; /* transmit queue */
64 struct sk_buff_head rx_queue; /* receive queue */
65 struct tty_struct *tty; /* Pointer to corresponding tty */
66 wait_queue_head_t open_wait;
67 wait_queue_head_t close_wait;
68 struct semaphore write_sem;
69 struct tasklet_struct tasklet;
70 struct timer_list stoptimer;
71} ctc_tty_info;
72
73/* Description of one CTC-tty */
74typedef struct {
75 struct tty_driver *ctc_tty_device; /* tty-device */
76 ctc_tty_info info[CTC_TTY_MAX_DEVICES]; /* Private data */
77} ctc_tty_driver;
78
79static ctc_tty_driver *driver;
80
81/* Leave this unchanged unless you know what you do! */
82#define MODEM_PARANOIA_CHECK
83#define MODEM_DO_RESTART
84
85#define CTC_TTY_NAME "ctctty"
86
87static __u32 ctc_tty_magic = CTC_ASYNC_MAGIC;
88static int ctc_tty_shuttingdown = 0;
89
90static spinlock_t ctc_tty_lock;
91
92/* ctc_tty_try_read() is called from within ctc_tty_rcv_skb()
93 * to stuff incoming data directly into a tty's flip-buffer. If the
94 * flip buffer is full, the packet gets queued up.
95 *
96 * Return:
97 * 1 = Success
98 * 0 = Failure, data has to be buffered and later processed by
99 * ctc_tty_readmodem().
100 */
101static int
102ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
103{
104 int c;
105 int len;
106 struct tty_struct *tty;
107
108 DBF_TEXT(trace, 5, __FUNCTION__);
109 if ((tty = info->tty)) {
110 if (info->mcr & UART_MCR_RTS) {
111 c = TTY_FLIPBUF_SIZE - tty->flip.count;
112 len = skb->len;
113 if (c >= len) {
114 memcpy(tty->flip.char_buf_ptr, skb->data, len);
115 memset(tty->flip.flag_buf_ptr, 0, len);
116 tty->flip.count += len;
117 tty->flip.char_buf_ptr += len;
118 tty->flip.flag_buf_ptr += len;
119 tty_flip_buffer_push(tty);
120 kfree_skb(skb);
121 return 1;
122 }
123 }
124 }
125 return 0;
126}
127
128/* ctc_tty_readmodem() is called periodically from within timer-interrupt.
129 * It tries getting received data from the receive queue an stuff it into
130 * the tty's flip-buffer.
131 */
132static int
133ctc_tty_readmodem(ctc_tty_info *info)
134{
135 int ret = 1;
136 struct tty_struct *tty;
137
138 DBF_TEXT(trace, 5, __FUNCTION__);
139 if ((tty = info->tty)) {
140 if (info->mcr & UART_MCR_RTS) {
141 int c = TTY_FLIPBUF_SIZE - tty->flip.count;
142 struct sk_buff *skb;
143
144 if ((c > 0) && (skb = skb_dequeue(&info->rx_queue))) {
145 int len = skb->len;
146 if (len > c)
147 len = c;
148 memcpy(tty->flip.char_buf_ptr, skb->data, len);
149 skb_pull(skb, len);
150 memset(tty->flip.flag_buf_ptr, 0, len);
151 tty->flip.count += len;
152 tty->flip.char_buf_ptr += len;
153 tty->flip.flag_buf_ptr += len;
154 tty_flip_buffer_push(tty);
155 if (skb->len > 0)
156 skb_queue_head(&info->rx_queue, skb);
157 else {
158 kfree_skb(skb);
159 ret = skb_queue_len(&info->rx_queue);
160 }
161 }
162 }
163 }
164 return ret;
165}
166
167void
168ctc_tty_setcarrier(struct net_device *netdev, int on)
169{
170 int i;
171
172 DBF_TEXT(trace, 4, __FUNCTION__);
173 if ((!driver) || ctc_tty_shuttingdown)
174 return;
175 for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
176 if (driver->info[i].netdev == netdev) {
177 ctc_tty_info *info = &driver->info[i];
178 if (on)
179 info->msr |= UART_MSR_DCD;
180 else
181 info->msr &= ~UART_MSR_DCD;
182 if ((info->flags & CTC_ASYNC_CHECK_CD) && (!on))
183 tty_hangup(info->tty);
184 }
185}
186
187void
188ctc_tty_netif_rx(struct sk_buff *skb)
189{
190 int i;
191 ctc_tty_info *info = NULL;
192
193 DBF_TEXT(trace, 5, __FUNCTION__);
194 if (!skb)
195 return;
196 if ((!skb->dev) || (!driver) || ctc_tty_shuttingdown) {
197 dev_kfree_skb(skb);
198 return;
199 }
200 for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
201 if (driver->info[i].netdev == skb->dev) {
202 info = &driver->info[i];
203 break;
204 }
205 if (!info) {
206 dev_kfree_skb(skb);
207 return;
208 }
209 if (skb->len < 6) {
210 dev_kfree_skb(skb);
211 return;
212 }
213 if (memcmp(skb->data, &ctc_tty_magic, sizeof(__u32))) {
214 dev_kfree_skb(skb);
215 return;
216 }
217 skb_pull(skb, sizeof(__u32));
218
219 i = *((int *)skb->data);
220 skb_pull(skb, sizeof(info->mcr));
221 if (i & UART_MCR_RTS) {
222 info->msr |= UART_MSR_CTS;
223 if (info->flags & CTC_ASYNC_CTS_FLOW)
224 info->tty->hw_stopped = 0;
225 } else {
226 info->msr &= ~UART_MSR_CTS;
227 if (info->flags & CTC_ASYNC_CTS_FLOW)
228 info->tty->hw_stopped = 1;
229 }
230 if (i & UART_MCR_DTR)
231 info->msr |= UART_MSR_DSR;
232 else
233 info->msr &= ~UART_MSR_DSR;
234 if (skb->len <= 0) {
235 kfree_skb(skb);
236 return;
237 }
238 /* Try to deliver directly via tty-flip-buf if queue is empty */
239 if (skb_queue_empty(&info->rx_queue))
240 if (ctc_tty_try_read(info, skb))
241 return;
242 /* Direct deliver failed or queue wasn't empty.
243 * Queue up for later dequeueing via timer-irq.
244 */
245 skb_queue_tail(&info->rx_queue, skb);
246 /* Schedule dequeuing */
247 tasklet_schedule(&info->tasklet);
248}
249
250static int
251ctc_tty_tint(ctc_tty_info * info)
252{
253 struct sk_buff *skb = skb_dequeue(&info->tx_queue);
254 int stopped = (info->tty->hw_stopped || info->tty->stopped);
255 int wake = 1;
256 int rc;
257
258 DBF_TEXT(trace, 4, __FUNCTION__);
259 if (!info->netdev) {
260 if (skb)
261 kfree_skb(skb);
262 return 0;
263 }
264 if (info->flags & CTC_ASYNC_TX_LINESTAT) {
265 int skb_res = info->netdev->hard_header_len +
266 sizeof(info->mcr) + sizeof(__u32);
267 /* If we must update line status,
268 * create an empty dummy skb and insert it.
269 */
270 if (skb)
271 skb_queue_head(&info->tx_queue, skb);
272
273 skb = dev_alloc_skb(skb_res);
274 if (!skb) {
275 printk(KERN_WARNING
276 "ctc_tty: Out of memory in %s%d tint\n",
277 CTC_TTY_NAME, info->line);
278 return 1;
279 }
280 skb_reserve(skb, skb_res);
281 stopped = 0;
282 wake = 0;
283 }
284 if (!skb)
285 return 0;
286 if (stopped) {
287 skb_queue_head(&info->tx_queue, skb);
288 return 1;
289 }
290#if 0
291 if (skb->len > 0)
292 printk(KERN_DEBUG "tint: %d %02x\n", skb->len, *(skb->data));
293 else
294 printk(KERN_DEBUG "tint: %d STAT\n", skb->len);
295#endif
296 memcpy(skb_push(skb, sizeof(info->mcr)), &info->mcr, sizeof(info->mcr));
297 memcpy(skb_push(skb, sizeof(__u32)), &ctc_tty_magic, sizeof(__u32));
298 rc = info->netdev->hard_start_xmit(skb, info->netdev);
299 if (rc) {
300 skb_pull(skb, sizeof(info->mcr) + sizeof(__u32));
301 if (skb->len > 0)
302 skb_queue_head(&info->tx_queue, skb);
303 else
304 kfree_skb(skb);
305 } else {
306 struct tty_struct *tty = info->tty;
307
308 info->flags &= ~CTC_ASYNC_TX_LINESTAT;
309 if (tty) {
310 tty_wakeup(tty);
311 }
312 }
313 return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
314}
315
316/************************************************************
317 *
318 * Modem-functions
319 *
320 * mostly "stolen" from original Linux-serial.c and friends.
321 *
322 ************************************************************/
323
324static inline int
325ctc_tty_paranoia_check(ctc_tty_info * info, char *name, const char *routine)
326{
327#ifdef MODEM_PARANOIA_CHECK
328 if (!info) {
329 printk(KERN_WARNING "ctc_tty: null info_struct for %s in %s\n",
330 name, routine);
331 return 1;
332 }
333 if (info->magic != CTC_ASYNC_MAGIC) {
334 printk(KERN_WARNING "ctc_tty: bad magic for info struct %s in %s\n",
335 name, routine);
336 return 1;
337 }
338#endif
339 return 0;
340}
341
342static void
343ctc_tty_inject(ctc_tty_info *info, char c)
344{
345 int skb_res;
346 struct sk_buff *skb;
347
348 DBF_TEXT(trace, 4, __FUNCTION__);
349 if (ctc_tty_shuttingdown)
350 return;
351 skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
352 sizeof(__u32) + 1;
353 skb = dev_alloc_skb(skb_res);
354 if (!skb) {
355 printk(KERN_WARNING
356 "ctc_tty: Out of memory in %s%d tx_inject\n",
357 CTC_TTY_NAME, info->line);
358 return;
359 }
360 skb_reserve(skb, skb_res);
361 *(skb_put(skb, 1)) = c;
362 skb_queue_head(&info->tx_queue, skb);
363 tasklet_schedule(&info->tasklet);
364}
365
366static void
367ctc_tty_transmit_status(ctc_tty_info *info)
368{
369 DBF_TEXT(trace, 5, __FUNCTION__);
370 if (ctc_tty_shuttingdown)
371 return;
372 info->flags |= CTC_ASYNC_TX_LINESTAT;
373 tasklet_schedule(&info->tasklet);
374}
375
376static void
377ctc_tty_change_speed(ctc_tty_info * info)
378{
379 unsigned int cflag;
380 unsigned int quot;
381 int i;
382
383 DBF_TEXT(trace, 3, __FUNCTION__);
384 if (!info->tty || !info->tty->termios)
385 return;
386 cflag = info->tty->termios->c_cflag;
387
388 quot = i = cflag & CBAUD;
389 if (i & CBAUDEX) {
390 i &= ~CBAUDEX;
391 if (i < 1 || i > 2)
392 info->tty->termios->c_cflag &= ~CBAUDEX;
393 else
394 i += 15;
395 }
396 if (quot) {
397 info->mcr |= UART_MCR_DTR;
398 info->mcr |= UART_MCR_RTS;
399 ctc_tty_transmit_status(info);
400 } else {
401 info->mcr &= ~UART_MCR_DTR;
402 info->mcr &= ~UART_MCR_RTS;
403 ctc_tty_transmit_status(info);
404 return;
405 }
406
407 /* CTS flow control flag and modem status interrupts */
408 if (cflag & CRTSCTS) {
409 info->flags |= CTC_ASYNC_CTS_FLOW;
410 } else
411 info->flags &= ~CTC_ASYNC_CTS_FLOW;
412 if (cflag & CLOCAL)
413 info->flags &= ~CTC_ASYNC_CHECK_CD;
414 else {
415 info->flags |= CTC_ASYNC_CHECK_CD;
416 }
417}
418
419static int
420ctc_tty_startup(ctc_tty_info * info)
421{
422 DBF_TEXT(trace, 3, __FUNCTION__);
423 if (info->flags & CTC_ASYNC_INITIALIZED)
424 return 0;
425#ifdef CTC_DEBUG_MODEM_OPEN
426 printk(KERN_DEBUG "starting up %s%d ...\n", CTC_TTY_NAME, info->line);
427#endif
428 /*
429 * Now, initialize the UART
430 */
431 info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
432 if (info->tty)
433 clear_bit(TTY_IO_ERROR, &info->tty->flags);
434 /*
435 * and set the speed of the serial port
436 */
437 ctc_tty_change_speed(info);
438
439 info->flags |= CTC_ASYNC_INITIALIZED;
440 if (!(info->flags & CTC_ASYNC_NETDEV_OPEN))
441 info->netdev->open(info->netdev);
442 info->flags |= CTC_ASYNC_NETDEV_OPEN;
443 return 0;
444}
445
446static void
447ctc_tty_stopdev(unsigned long data)
448{
449 ctc_tty_info *info = (ctc_tty_info *)data;
450
451 if ((!info) || (!info->netdev) ||
452 (info->flags & CTC_ASYNC_INITIALIZED))
453 return;
454 info->netdev->stop(info->netdev);
455 info->flags &= ~CTC_ASYNC_NETDEV_OPEN;
456}
457
458/*
459 * This routine will shutdown a serial port; interrupts are disabled, and
460 * DTR is dropped if the hangup on close termio flag is on.
461 */
462static void
463ctc_tty_shutdown(ctc_tty_info * info)
464{
465 DBF_TEXT(trace, 3, __FUNCTION__);
466 if (!(info->flags & CTC_ASYNC_INITIALIZED))
467 return;
468#ifdef CTC_DEBUG_MODEM_OPEN
469 printk(KERN_DEBUG "Shutting down %s%d ....\n", CTC_TTY_NAME, info->line);
470#endif
471 info->msr &= ~UART_MSR_RI;
472 if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
473 info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
474 if (info->tty)
475 set_bit(TTY_IO_ERROR, &info->tty->flags);
476 mod_timer(&info->stoptimer, jiffies + (10 * HZ));
477 skb_queue_purge(&info->tx_queue);
478 skb_queue_purge(&info->rx_queue);
479 info->flags &= ~CTC_ASYNC_INITIALIZED;
480}
481
482/* ctc_tty_write() is the main send-routine. It is called from the upper
483 * levels within the kernel to perform sending data. Depending on the
484 * online-flag it either directs output to the at-command-interpreter or
485 * to the lower level. Additional tasks done here:
486 * - If online, check for escape-sequence (+++)
487 * - If sending audio-data, call ctc_tty_DLEdown() to parse DLE-codes.
488 * - If receiving audio-data, call ctc_tty_end_vrx() to abort if needed.
489 * - If dialing, abort dial.
490 */
491static int
492ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count)
493{
494 int c;
495 int total = 0;
496 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
497
498 DBF_TEXT(trace, 5, __FUNCTION__);
499 if (ctc_tty_shuttingdown)
500 goto ex;
501 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write"))
502 goto ex;
503 if (!tty)
504 goto ex;
505 if (!info->netdev) {
506 total = -ENODEV;
507 goto ex;
508 }
509 while (1) {
510 struct sk_buff *skb;
511 int skb_res;
512
513 c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE;
514 if (c <= 0)
515 break;
516
517 skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
518 + sizeof(__u32);
519 skb = dev_alloc_skb(skb_res + c);
520 if (!skb) {
521 printk(KERN_WARNING
522 "ctc_tty: Out of memory in %s%d write\n",
523 CTC_TTY_NAME, info->line);
524 break;
525 }
526 skb_reserve(skb, skb_res);
527 memcpy(skb_put(skb, c), buf, c);
528 skb_queue_tail(&info->tx_queue, skb);
529 buf += c;
530 total += c;
531 count -= c;
532 }
533 if (skb_queue_len(&info->tx_queue)) {
534 info->lsr &= ~UART_LSR_TEMT;
535 tasklet_schedule(&info->tasklet);
536 }
537ex:
538 DBF_TEXT(trace, 6, __FUNCTION__);
539 return total;
540}
541
542static int
543ctc_tty_write_room(struct tty_struct *tty)
544{
545 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
546
547 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write_room"))
548 return 0;
549 return CTC_TTY_XMIT_SIZE;
550}
551
552static int
553ctc_tty_chars_in_buffer(struct tty_struct *tty)
554{
555 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
556
557 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_chars_in_buffer"))
558 return 0;
559 return 0;
560}
561
562static void
563ctc_tty_flush_buffer(struct tty_struct *tty)
564{
565 ctc_tty_info *info;
566 unsigned long flags;
567
568 DBF_TEXT(trace, 4, __FUNCTION__);
569 if (!tty)
570 goto ex;
571 spin_lock_irqsave(&ctc_tty_lock, flags);
572 info = (ctc_tty_info *) tty->driver_data;
573 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_buffer")) {
574 spin_unlock_irqrestore(&ctc_tty_lock, flags);
575 goto ex;
576 }
577 skb_queue_purge(&info->tx_queue);
578 info->lsr |= UART_LSR_TEMT;
579 spin_unlock_irqrestore(&ctc_tty_lock, flags);
580 wake_up_interruptible(&tty->write_wait);
581 tty_wakeup(tty);
582ex:
583 DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__);
584 return;
585}
586
587static void
588ctc_tty_flush_chars(struct tty_struct *tty)
589{
590 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
591
592 DBF_TEXT(trace, 4, __FUNCTION__);
593 if (ctc_tty_shuttingdown)
594 return;
595 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars"))
596 return;
597 if (tty->stopped || tty->hw_stopped || (!skb_queue_len(&info->tx_queue)))
598 return;
599 tasklet_schedule(&info->tasklet);
600}
601
602/*
603 * ------------------------------------------------------------
604 * ctc_tty_throttle()
605 *
606 * This routine is called by the upper-layer tty layer to signal that
607 * incoming characters should be throttled.
608 * ------------------------------------------------------------
609 */
610static void
611ctc_tty_throttle(struct tty_struct *tty)
612{
613 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
614
615 DBF_TEXT(trace, 4, __FUNCTION__);
616 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_throttle"))
617 return;
618 info->mcr &= ~UART_MCR_RTS;
619 if (I_IXOFF(tty))
620 ctc_tty_inject(info, STOP_CHAR(tty));
621 ctc_tty_transmit_status(info);
622}
623
624static void
625ctc_tty_unthrottle(struct tty_struct *tty)
626{
627 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
628
629 DBF_TEXT(trace, 4, __FUNCTION__);
630 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_unthrottle"))
631 return;
632 info->mcr |= UART_MCR_RTS;
633 if (I_IXOFF(tty))
634 ctc_tty_inject(info, START_CHAR(tty));
635 ctc_tty_transmit_status(info);
636}
637
638/*
639 * ------------------------------------------------------------
640 * ctc_tty_ioctl() and friends
641 * ------------------------------------------------------------
642 */
643
644/*
645 * ctc_tty_get_lsr_info - get line status register info
646 *
647 * Purpose: Let user call ioctl() to get info when the UART physically
648 * is emptied. On bus types like RS485, the transmitter must
649 * release the bus after transmitting. This must be done when
650 * the transmit shift register is empty, not be done when the
651 * transmit holding register is empty. This functionality
652 * allows RS485 driver to be written in user space.
653 */
654static int
655ctc_tty_get_lsr_info(ctc_tty_info * info, uint __user *value)
656{
657 u_char status;
658 uint result;
659 ulong flags;
660
661 DBF_TEXT(trace, 4, __FUNCTION__);
662 spin_lock_irqsave(&ctc_tty_lock, flags);
663 status = info->lsr;
664 spin_unlock_irqrestore(&ctc_tty_lock, flags);
665 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
666 put_user(result, value);
667 return 0;
668}
669
670
671static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
672{
673 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
674 u_char control,
675 status;
676 uint result;
677 ulong flags;
678
679 DBF_TEXT(trace, 4, __FUNCTION__);
680 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
681 return -ENODEV;
682 if (tty->flags & (1 << TTY_IO_ERROR))
683 return -EIO;
684
685 control = info->mcr;
686 spin_lock_irqsave(&ctc_tty_lock, flags);
687 status = info->msr;
688 spin_unlock_irqrestore(&ctc_tty_lock, flags);
689 result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
690 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
691 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
692 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
693 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
694 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
695 return result;
696}
697
698static int
699ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
700 unsigned int set, unsigned int clear)
701{
702 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
703
704 DBF_TEXT(trace, 4, __FUNCTION__);
705 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
706 return -ENODEV;
707 if (tty->flags & (1 << TTY_IO_ERROR))
708 return -EIO;
709
710 if (set & TIOCM_RTS)
711 info->mcr |= UART_MCR_RTS;
712 if (set & TIOCM_DTR)
713 info->mcr |= UART_MCR_DTR;
714
715 if (clear & TIOCM_RTS)
716 info->mcr &= ~UART_MCR_RTS;
717 if (clear & TIOCM_DTR)
718 info->mcr &= ~UART_MCR_DTR;
719
720 if ((set | clear) & (TIOCM_RTS|TIOCM_DTR))
721 ctc_tty_transmit_status(info);
722 return 0;
723}
724
725static int
726ctc_tty_ioctl(struct tty_struct *tty, struct file *file,
727 uint cmd, ulong arg)
728{
729 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
730 int error;
731 int retval;
732
733 DBF_TEXT(trace, 4, __FUNCTION__);
734 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
735 return -ENODEV;
736 if (tty->flags & (1 << TTY_IO_ERROR))
737 return -EIO;
738 switch (cmd) {
739 case TCSBRK: /* SVID version: non-zero arg --> no break */
740#ifdef CTC_DEBUG_MODEM_IOCTL
741 printk(KERN_DEBUG "%s%d ioctl TCSBRK\n", CTC_TTY_NAME, info->line);
742#endif
743 retval = tty_check_change(tty);
744 if (retval)
745 return retval;
746 tty_wait_until_sent(tty, 0);
747 return 0;
748 case TCSBRKP: /* support for POSIX tcsendbreak() */
749#ifdef CTC_DEBUG_MODEM_IOCTL
750 printk(KERN_DEBUG "%s%d ioctl TCSBRKP\n", CTC_TTY_NAME, info->line);
751#endif
752 retval = tty_check_change(tty);
753 if (retval)
754 return retval;
755 tty_wait_until_sent(tty, 0);
756 return 0;
757 case TIOCGSOFTCAR:
758#ifdef CTC_DEBUG_MODEM_IOCTL
759 printk(KERN_DEBUG "%s%d ioctl TIOCGSOFTCAR\n", CTC_TTY_NAME,
760 info->line);
761#endif
762 error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
763 return error;
764 case TIOCSSOFTCAR:
765#ifdef CTC_DEBUG_MODEM_IOCTL
766 printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME,
767 info->line);
768#endif
769 error = get_user(arg, (ulong __user *) arg);
770 if (error)
771 return error;
772 tty->termios->c_cflag =
773 ((tty->termios->c_cflag & ~CLOCAL) |
774 (arg ? CLOCAL : 0));
775 return 0;
776 case TIOCSERGETLSR: /* Get line status register */
777#ifdef CTC_DEBUG_MODEM_IOCTL
778 printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
779 info->line);
780#endif
781 if (access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(uint)))
782 return ctc_tty_get_lsr_info(info, (uint __user *) arg);
783 else
784 return -EFAULT;
785 default:
786#ifdef CTC_DEBUG_MODEM_IOCTL
787 printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd,
788 CTC_TTY_NAME, info->line);
789#endif
790 return -ENOIOCTLCMD;
791 }
792 return 0;
793}
794
795static void
796ctc_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
797{
798 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
799 unsigned int cflag = tty->termios->c_cflag;
800
801 DBF_TEXT(trace, 4, __FUNCTION__);
802 ctc_tty_change_speed(info);
803
804 /* Handle transition to B0 */
805 if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) {
806 info->mcr &= ~(UART_MCR_DTR|UART_MCR_RTS);
807 ctc_tty_transmit_status(info);
808 }
809
810 /* Handle transition from B0 to other */
811 if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
812 info->mcr |= UART_MCR_DTR;
813 if (!(tty->termios->c_cflag & CRTSCTS) ||
814 !test_bit(TTY_THROTTLED, &tty->flags)) {
815 info->mcr |= UART_MCR_RTS;
816 }
817 ctc_tty_transmit_status(info);
818 }
819
820 /* Handle turning off CRTSCTS */
821 if ((old_termios->c_cflag & CRTSCTS) &&
822 !(tty->termios->c_cflag & CRTSCTS))
823 tty->hw_stopped = 0;
824}
825
826/*
827 * ------------------------------------------------------------
828 * ctc_tty_open() and friends
829 * ------------------------------------------------------------
830 */
831static int
832ctc_tty_block_til_ready(struct tty_struct *tty, struct file *filp, ctc_tty_info *info)
833{
834 DECLARE_WAITQUEUE(wait, NULL);
835 int do_clocal = 0;
836 unsigned long flags;
837 int retval;
838
839 DBF_TEXT(trace, 4, __FUNCTION__);
840 /*
841 * If the device is in the middle of being closed, then block
842 * until it's done, and then try again.
843 */
844 if (tty_hung_up_p(filp) ||
845 (info->flags & CTC_ASYNC_CLOSING)) {
846 if (info->flags & CTC_ASYNC_CLOSING)
847 wait_event(info->close_wait,
848 !(info->flags & CTC_ASYNC_CLOSING));
849#ifdef MODEM_DO_RESTART
850 if (info->flags & CTC_ASYNC_HUP_NOTIFY)
851 return -EAGAIN;
852 else
853 return -ERESTARTSYS;
854#else
855 return -EAGAIN;
856#endif
857 }
858 /*
859 * If non-blocking mode is set, then make the check up front
860 * and then exit.
861 */
862 if ((filp->f_flags & O_NONBLOCK) ||
863 (tty->flags & (1 << TTY_IO_ERROR))) {
864 info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
865 return 0;
866 }
867 if (tty->termios->c_cflag & CLOCAL)
868 do_clocal = 1;
869 /*
870 * Block waiting for the carrier detect and the line to become
871 * free (i.e., not in use by the callout). While we are in
872 * this loop, info->count is dropped by one, so that
873 * ctc_tty_close() knows when to free things. We restore it upon
874 * exit, either normal or abnormal.
875 */
876 retval = 0;
877 add_wait_queue(&info->open_wait, &wait);
878#ifdef CTC_DEBUG_MODEM_OPEN
879 printk(KERN_DEBUG "ctc_tty_block_til_ready before block: %s%d, count = %d\n",
880 CTC_TTY_NAME, info->line, info->count);
881#endif
882 spin_lock_irqsave(&ctc_tty_lock, flags);
883 if (!(tty_hung_up_p(filp)))
884 info->count--;
885 spin_unlock_irqrestore(&ctc_tty_lock, flags);
886 info->blocked_open++;
887 while (1) {
888 set_current_state(TASK_INTERRUPTIBLE);
889 if (tty_hung_up_p(filp) ||
890 !(info->flags & CTC_ASYNC_INITIALIZED)) {
891#ifdef MODEM_DO_RESTART
892 if (info->flags & CTC_ASYNC_HUP_NOTIFY)
893 retval = -EAGAIN;
894 else
895 retval = -ERESTARTSYS;
896#else
897 retval = -EAGAIN;
898#endif
899 break;
900 }
901 if (!(info->flags & CTC_ASYNC_CLOSING) &&
902 (do_clocal || (info->msr & UART_MSR_DCD))) {
903 break;
904 }
905 if (signal_pending(current)) {
906 retval = -ERESTARTSYS;
907 break;
908 }
909#ifdef CTC_DEBUG_MODEM_OPEN
910 printk(KERN_DEBUG "ctc_tty_block_til_ready blocking: %s%d, count = %d\n",
911 CTC_TTY_NAME, info->line, info->count);
912#endif
913 schedule();
914 }
915 current->state = TASK_RUNNING;
916 remove_wait_queue(&info->open_wait, &wait);
917 if (!tty_hung_up_p(filp))
918 info->count++;
919 info->blocked_open--;
920#ifdef CTC_DEBUG_MODEM_OPEN
921 printk(KERN_DEBUG "ctc_tty_block_til_ready after blocking: %s%d, count = %d\n",
922 CTC_TTY_NAME, info->line, info->count);
923#endif
924 if (retval)
925 return retval;
926 info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
927 return 0;
928}
929
930/*
931 * This routine is called whenever a serial port is opened. It
932 * enables interrupts for a serial port, linking in its async structure into
933 * the IRQ chain. It also performs the serial-specific
934 * initialization for the tty structure.
935 */
936static int
937ctc_tty_open(struct tty_struct *tty, struct file *filp)
938{
939 ctc_tty_info *info;
940 unsigned long saveflags;
941 int retval,
942 line;
943
944 DBF_TEXT(trace, 3, __FUNCTION__);
945 line = tty->index;
946 if (line < 0 || line > CTC_TTY_MAX_DEVICES)
947 return -ENODEV;
948 info = &driver->info[line];
949 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_open"))
950 return -ENODEV;
951 if (!info->netdev)
952 return -ENODEV;
953#ifdef CTC_DEBUG_MODEM_OPEN
954 printk(KERN_DEBUG "ctc_tty_open %s, count = %d\n", tty->name,
955 info->count);
956#endif
957 spin_lock_irqsave(&ctc_tty_lock, saveflags);
958 info->count++;
959 tty->driver_data = info;
960 info->tty = tty;
961 spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
962 /*
963 * Start up serial port
964 */
965 retval = ctc_tty_startup(info);
966 if (retval) {
967#ifdef CTC_DEBUG_MODEM_OPEN
968 printk(KERN_DEBUG "ctc_tty_open return after startup\n");
969#endif
970 return retval;
971 }
972 retval = ctc_tty_block_til_ready(tty, filp, info);
973 if (retval) {
974#ifdef CTC_DEBUG_MODEM_OPEN
975 printk(KERN_DEBUG "ctc_tty_open return after ctc_tty_block_til_ready \n");
976#endif
977 return retval;
978 }
979#ifdef CTC_DEBUG_MODEM_OPEN
980 printk(KERN_DEBUG "ctc_tty_open %s successful...\n", tty->name);
981#endif
982 return 0;
983}
984
985static void
986ctc_tty_close(struct tty_struct *tty, struct file *filp)
987{
988 ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
989 ulong flags;
990 ulong timeout;
991 DBF_TEXT(trace, 3, __FUNCTION__);
992 if (!info || ctc_tty_paranoia_check(info, tty->name, "ctc_tty_close"))
993 return;
994 spin_lock_irqsave(&ctc_tty_lock, flags);
995 if (tty_hung_up_p(filp)) {
996 spin_unlock_irqrestore(&ctc_tty_lock, flags);
997#ifdef CTC_DEBUG_MODEM_OPEN
998 printk(KERN_DEBUG "ctc_tty_close return after tty_hung_up_p\n");
999#endif
1000 return;
1001 }
1002 if ((tty->count == 1) && (info->count != 1)) {
1003 /*
1004 * Uh, oh. tty->count is 1, which means that the tty
1005 * structure will be freed. Info->count should always
1006 * be one in these conditions. If it's greater than
1007 * one, we've got real problems, since it means the
1008 * serial port won't be shutdown.
1009 */
1010 printk(KERN_ERR "ctc_tty_close: bad port count; tty->count is 1, "
1011 "info->count is %d\n", info->count);
1012 info->count = 1;
1013 }
1014 if (--info->count < 0) {
1015 printk(KERN_ERR "ctc_tty_close: bad port count for %s%d: %d\n",
1016 CTC_TTY_NAME, info->line, info->count);
1017 info->count = 0;
1018 }
1019 if (info->count) {
1020 local_irq_restore(flags);
1021#ifdef CTC_DEBUG_MODEM_OPEN
1022 printk(KERN_DEBUG "ctc_tty_close after info->count != 0\n");
1023#endif
1024 return;
1025 }
1026 info->flags |= CTC_ASYNC_CLOSING;
1027 tty->closing = 1;
1028 /*
1029 * At this point we stop accepting input. To do this, we
1030 * disable the receive line status interrupts, and tell the
1031 * interrupt driver to stop checking the data ready bit in the
1032 * line status register.
1033 */
1034 if (info->flags & CTC_ASYNC_INITIALIZED) {
1035 tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */
1036 /*
1037 * Before we drop DTR, make sure the UART transmitter
1038 * has completely drained; this is especially
1039 * important if there is a transmit FIFO!
1040 */
1041 timeout = jiffies + HZ;
1042 while (!(info->lsr & UART_LSR_TEMT)) {
1043 spin_unlock_irqrestore(&ctc_tty_lock, flags);
1044 msleep(500);
1045 spin_lock_irqsave(&ctc_tty_lock, flags);
1046 if (time_after(jiffies,timeout))
1047 break;
1048 }
1049 }
1050 ctc_tty_shutdown(info);
1051 if (tty->driver->flush_buffer) {
1052 skb_queue_purge(&info->tx_queue);
1053 info->lsr |= UART_LSR_TEMT;
1054 }
1055 tty_ldisc_flush(tty);
1056 info->tty = 0;
1057 tty->closing = 0;
1058 if (info->blocked_open) {
1059 set_current_state(TASK_INTERRUPTIBLE);
1060 schedule_timeout(HZ/2);
1061 wake_up_interruptible(&info->open_wait);
1062 }
1063 info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING);
1064 wake_up_interruptible(&info->close_wait);
1065 spin_unlock_irqrestore(&ctc_tty_lock, flags);
1066#ifdef CTC_DEBUG_MODEM_OPEN
1067 printk(KERN_DEBUG "ctc_tty_close normal exit\n");
1068#endif
1069}
1070
1071/*
1072 * ctc_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
1073 */
1074static void
1075ctc_tty_hangup(struct tty_struct *tty)
1076{
1077 ctc_tty_info *info = (ctc_tty_info *)tty->driver_data;
1078 unsigned long saveflags;
1079 DBF_TEXT(trace, 3, __FUNCTION__);
1080 if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_hangup"))
1081 return;
1082 ctc_tty_shutdown(info);
1083 info->count = 0;
1084 info->flags &= ~CTC_ASYNC_NORMAL_ACTIVE;
1085 spin_lock_irqsave(&ctc_tty_lock, saveflags);
1086 info->tty = 0;
1087 spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
1088 wake_up_interruptible(&info->open_wait);
1089}
1090
1091
1092/*
1093 * For all online tty's, try sending data to
1094 * the lower levels.
1095 */
1096static void
1097ctc_tty_task(unsigned long arg)
1098{
1099 ctc_tty_info *info = (void *)arg;
1100 unsigned long saveflags;
1101 int again;
1102
1103 DBF_TEXT(trace, 3, __FUNCTION__);
1104 spin_lock_irqsave(&ctc_tty_lock, saveflags);
1105 if ((!ctc_tty_shuttingdown) && info) {
1106 again = ctc_tty_tint(info);
1107 if (!again)
1108 info->lsr |= UART_LSR_TEMT;
1109 again |= ctc_tty_readmodem(info);
1110 if (again) {
1111 tasklet_schedule(&info->tasklet);
1112 }
1113 }
1114 spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
1115}
1116
1117static struct tty_operations ctc_ops = {
1118 .open = ctc_tty_open,
1119 .close = ctc_tty_close,
1120 .write = ctc_tty_write,
1121 .flush_chars = ctc_tty_flush_chars,
1122 .write_room = ctc_tty_write_room,
1123 .chars_in_buffer = ctc_tty_chars_in_buffer,
1124 .flush_buffer = ctc_tty_flush_buffer,
1125 .ioctl = ctc_tty_ioctl,
1126 .throttle = ctc_tty_throttle,
1127 .unthrottle = ctc_tty_unthrottle,
1128 .set_termios = ctc_tty_set_termios,
1129 .hangup = ctc_tty_hangup,
1130 .tiocmget = ctc_tty_tiocmget,
1131 .tiocmset = ctc_tty_tiocmset,
1132};
1133
1134int
1135ctc_tty_init(void)
1136{
1137 int i;
1138 ctc_tty_info *info;
1139 struct tty_driver *device;
1140
1141 DBF_TEXT(trace, 2, __FUNCTION__);
1142 driver = kmalloc(sizeof(ctc_tty_driver), GFP_KERNEL);
1143 if (driver == NULL) {
1144 printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
1145 return -ENOMEM;
1146 }
1147 memset(driver, 0, sizeof(ctc_tty_driver));
1148 device = alloc_tty_driver(CTC_TTY_MAX_DEVICES);
1149 if (!device) {
1150 kfree(driver);
1151 printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
1152 return -ENOMEM;
1153 }
1154
1155 device->devfs_name = "ctc/" CTC_TTY_NAME;
1156 device->name = CTC_TTY_NAME;
1157 device->major = CTC_TTY_MAJOR;
1158 device->minor_start = 0;
1159 device->type = TTY_DRIVER_TYPE_SERIAL;
1160 device->subtype = SERIAL_TYPE_NORMAL;
1161 device->init_termios = tty_std_termios;
1162 device->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1163 device->flags = TTY_DRIVER_REAL_RAW;
1164 device->driver_name = "ctc_tty",
1165 tty_set_operations(device, &ctc_ops);
1166 if (tty_register_driver(device)) {
1167 printk(KERN_WARNING "ctc_tty: Couldn't register serial-device\n");
1168 put_tty_driver(device);
1169 kfree(driver);
1170 return -1;
1171 }
1172 driver->ctc_tty_device = device;
1173 for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) {
1174 info = &driver->info[i];
1175 init_MUTEX(&info->write_sem);
1176 tasklet_init(&info->tasklet, ctc_tty_task,
1177 (unsigned long) info);
1178 info->magic = CTC_ASYNC_MAGIC;
1179 info->line = i;
1180 info->tty = 0;
1181 info->count = 0;
1182 info->blocked_open = 0;
1183 init_waitqueue_head(&info->open_wait);
1184 init_waitqueue_head(&info->close_wait);
1185 skb_queue_head_init(&info->tx_queue);
1186 skb_queue_head_init(&info->rx_queue);
1187 init_timer(&info->stoptimer);
1188 info->stoptimer.function = ctc_tty_stopdev;
1189 info->stoptimer.data = (unsigned long)info;
1190 info->mcr = UART_MCR_RTS;
1191 }
1192 return 0;
1193}
1194
1195int
1196ctc_tty_register_netdev(struct net_device *dev) {
1197 int ttynum;
1198 char *err;
1199 char *p;
1200
1201 DBF_TEXT(trace, 2, __FUNCTION__);
1202 if ((!dev) || (!dev->name)) {
1203 printk(KERN_WARNING
1204 "ctc_tty_register_netdev called "
1205 "with NULL dev or NULL dev-name\n");
1206 return -1;
1207 }
1208
1209 /*
1210 * If the name is a format string the caller wants us to
1211 * do a name allocation : format string must end with %d
1212 */
1213 if (strchr(dev->name, '%'))
1214 {
1215 int err = dev_alloc_name(dev, dev->name); // dev->name is changed by this
1216 if (err < 0) {
1217 printk(KERN_DEBUG "dev_alloc returned error %d\n", err);
1218 return err;
1219 }
1220
1221 }
1222
1223 for (p = dev->name; p && ((*p < '0') || (*p > '9')); p++);
1224 ttynum = simple_strtoul(p, &err, 0);
1225 if ((ttynum < 0) || (ttynum >= CTC_TTY_MAX_DEVICES) ||
1226 (err && *err)) {
1227 printk(KERN_WARNING
1228 "ctc_tty_register_netdev called "
1229 "with number in name '%s'\n", dev->name);
1230 return -1;
1231 }
1232 if (driver->info[ttynum].netdev) {
1233 printk(KERN_WARNING
1234 "ctc_tty_register_netdev called "
1235 "for already registered device '%s'\n",
1236 dev->name);
1237 return -1;
1238 }
1239 driver->info[ttynum].netdev = dev;
1240 return 0;
1241}
1242
1243void
1244ctc_tty_unregister_netdev(struct net_device *dev) {
1245 int i;
1246 unsigned long saveflags;
1247 ctc_tty_info *info = NULL;
1248
1249 DBF_TEXT(trace, 2, __FUNCTION__);
1250 spin_lock_irqsave(&ctc_tty_lock, saveflags);
1251 for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
1252 if (driver->info[i].netdev == dev) {
1253 info = &driver->info[i];
1254 break;
1255 }
1256 if (info) {
1257 info->netdev = NULL;
1258 skb_queue_purge(&info->tx_queue);
1259 skb_queue_purge(&info->rx_queue);
1260 }
1261 spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
1262}
1263
1264void
1265ctc_tty_cleanup(void) {
1266 unsigned long saveflags;
1267
1268 DBF_TEXT(trace, 2, __FUNCTION__);
1269 spin_lock_irqsave(&ctc_tty_lock, saveflags);
1270 ctc_tty_shuttingdown = 1;
1271 spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
1272 tty_unregister_driver(driver->ctc_tty_device);
1273 put_tty_driver(driver->ctc_tty_device);
1274 kfree(driver);
1275 driver = NULL;
1276}