1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69#define VERSION "1.11"
70
71
72
73
74
75
76
77
78#include <linux/module.h>
79
80#include <linux/io.h>
81#include <linux/kernel.h>
82#include <linux/sched.h>
83#include <linux/ioport.h>
84#include <linux/interrupt.h>
85#include <linux/errno.h>
86#include <linux/tty.h>
87#include <linux/tty_flip.h>
88#include <linux/mm.h>
89#include <linux/serial.h>
90#include <linux/fcntl.h>
91#include <linux/major.h>
92#include <linux/delay.h>
93#include <linux/pci.h>
94#include <linux/init.h>
95#include <linux/uaccess.h>
96
97#include "specialix_io8.h"
98#include "cd1865.h"
99
100
101
102
103
104
105
106
107
108
109#define DEBUG
110
111static int sx_debug;
112static int sx_rxfifo = SPECIALIX_RXFIFO;
113static int sx_rtscts;
114
115#ifdef DEBUG
116#define dprintk(f, str...) if (sx_debug & f) printk(str)
117#else
118#define dprintk(f, str...)
119#endif
120
121#define SX_DEBUG_FLOW 0x0001
122#define SX_DEBUG_DATA 0x0002
123#define SX_DEBUG_PROBE 0x0004
124#define SX_DEBUG_CHAN 0x0008
125#define SX_DEBUG_INIT 0x0010
126#define SX_DEBUG_RX 0x0020
127#define SX_DEBUG_TX 0x0040
128#define SX_DEBUG_IRQ 0x0080
129#define SX_DEBUG_OPEN 0x0100
130#define SX_DEBUG_TERMIOS 0x0200
131#define SX_DEBUG_SIGNALS 0x0400
132#define SX_DEBUG_FIFO 0x0800
133
134
135#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__)
136#define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__)
137
138
139
140
141
142#define SPECIALIX_PARANOIA_CHECK
143
144
145
146
147
148#undef SX_REPORT_FIFO
149#undef SX_REPORT_OVERRUN
150
151
152
153
154#define SPECIALIX_LEGAL_FLAGS \
155 (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \
156 ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \
157 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
158
159static struct tty_driver *specialix_driver;
160
161static struct specialix_board sx_board[SX_NBOARD] = {
162 { 0, SX_IOBASE1, 9, },
163 { 0, SX_IOBASE2, 11, },
164 { 0, SX_IOBASE3, 12, },
165 { 0, SX_IOBASE4, 15, },
166};
167
168static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
169
170
171static int sx_paranoia_check(struct specialix_port const *port,
172 char *name, const char *routine)
173{
174#ifdef SPECIALIX_PARANOIA_CHECK
175 static const char *badmagic = KERN_ERR
176 "sx: Warning: bad specialix port magic number for device %s in %s\n";
177 static const char *badinfo = KERN_ERR
178 "sx: Warning: null specialix port for device %s in %s\n";
179
180 if (!port) {
181 printk(badinfo, name, routine);
182 return 1;
183 }
184 if (port->magic != SPECIALIX_MAGIC) {
185 printk(badmagic, name, routine);
186 return 1;
187 }
188#endif
189 return 0;
190}
191
192
193
194
195
196
197
198
199
200static inline int board_No(struct specialix_board *bp)
201{
202 return bp - sx_board;
203}
204
205
206
207static inline int port_No(struct specialix_port const *port)
208{
209 return SX_PORT(port - sx_port);
210}
211
212
213
214static inline struct specialix_board *port_Board(
215 struct specialix_port const *port)
216{
217 return &sx_board[SX_BOARD(port - sx_port)];
218}
219
220
221
222static inline unsigned char sx_in(struct specialix_board *bp,
223 unsigned short reg)
224{
225 bp->reg = reg | 0x80;
226 outb(reg | 0x80, bp->base + SX_ADDR_REG);
227 return inb(bp->base + SX_DATA_REG);
228}
229
230
231
232static inline void sx_out(struct specialix_board *bp, unsigned short reg,
233 unsigned char val)
234{
235 bp->reg = reg | 0x80;
236 outb(reg | 0x80, bp->base + SX_ADDR_REG);
237 outb(val, bp->base + SX_DATA_REG);
238}
239
240
241
242static inline unsigned char sx_in_off(struct specialix_board *bp,
243 unsigned short reg)
244{
245 bp->reg = reg;
246 outb(reg, bp->base + SX_ADDR_REG);
247 return inb(bp->base + SX_DATA_REG);
248}
249
250
251
252static inline void sx_out_off(struct specialix_board *bp,
253 unsigned short reg, unsigned char val)
254{
255 bp->reg = reg;
256 outb(reg, bp->base + SX_ADDR_REG);
257 outb(val, bp->base + SX_DATA_REG);
258}
259
260
261
262static void sx_wait_CCR(struct specialix_board *bp)
263{
264 unsigned long delay, flags;
265 unsigned char ccr;
266
267 for (delay = SX_CCR_TIMEOUT; delay; delay--) {
268 spin_lock_irqsave(&bp->lock, flags);
269 ccr = sx_in(bp, CD186x_CCR);
270 spin_unlock_irqrestore(&bp->lock, flags);
271 if (!ccr)
272 return;
273 udelay(1);
274 }
275
276 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
277}
278
279
280
281static void sx_wait_CCR_off(struct specialix_board *bp)
282{
283 unsigned long delay;
284 unsigned char crr;
285 unsigned long flags;
286
287 for (delay = SX_CCR_TIMEOUT; delay; delay--) {
288 spin_lock_irqsave(&bp->lock, flags);
289 crr = sx_in_off(bp, CD186x_CCR);
290 spin_unlock_irqrestore(&bp->lock, flags);
291 if (!crr)
292 return;
293 udelay(1);
294 }
295
296 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
297}
298
299
300
301
302
303
304static int sx_request_io_range(struct specialix_board *bp)
305{
306 return request_region(bp->base,
307 bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
308 "specialix IO8+") == NULL;
309}
310
311
312static void sx_release_io_range(struct specialix_board *bp)
313{
314 release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ?
315 SX_PCI_IO_SPACE : SX_IO_SPACE);
316}
317
318
319
320static int sx_set_irq(struct specialix_board *bp)
321{
322 int virq;
323 int i;
324 unsigned long flags;
325
326 if (bp->flags & SX_BOARD_IS_PCI)
327 return 1;
328 switch (bp->irq) {
329
330 case 15:
331 virq = 0;
332 break;
333 case 12:
334 virq = 1;
335 break;
336 case 11:
337 virq = 2;
338 break;
339 case 9:
340 virq = 3;
341 break;
342 default:printk(KERN_ERR
343 "Speclialix: cannot set irq to %d.\n", bp->irq);
344 return 0;
345 }
346 spin_lock_irqsave(&bp->lock, flags);
347 for (i = 0; i < 2; i++) {
348 sx_out(bp, CD186x_CAR, i);
349 sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
350 }
351 spin_unlock_irqrestore(&bp->lock, flags);
352 return 1;
353}
354
355
356
357static int sx_init_CD186x(struct specialix_board *bp)
358{
359 unsigned long flags;
360 int scaler;
361 int rv = 1;
362
363 func_enter();
364 sx_wait_CCR_off(bp);
365 spin_lock_irqsave(&bp->lock, flags);
366 sx_out_off(bp, CD186x_CCR, CCR_HARDRESET);
367 spin_unlock_irqrestore(&bp->lock, flags);
368 msleep(50);
369 spin_lock_irqsave(&bp->lock, flags);
370 sx_out_off(bp, CD186x_GIVR, SX_ID);
371 sx_out_off(bp, CD186x_GICR, 0);
372 sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT);
373 sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT);
374 sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT);
375
376 sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN);
377
378
379 scaler = SX_OSCFREQ/SPECIALIX_TPS;
380
381 sx_out_off(bp, CD186x_PPRH, scaler >> 8);
382 sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
383 spin_unlock_irqrestore(&bp->lock, flags);
384
385 if (!sx_set_irq(bp)) {
386
387 printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq);
388 rv = 0;
389 }
390
391 func_exit();
392 return rv;
393}
394
395
396static int read_cross_byte(struct specialix_board *bp, int reg, int bit)
397{
398 int i;
399 int t;
400 unsigned long flags;
401
402 spin_lock_irqsave(&bp->lock, flags);
403 for (i = 0, t = 0; i < 8; i++) {
404 sx_out_off(bp, CD186x_CAR, i);
405 if (sx_in_off(bp, reg) & bit)
406 t |= 1 << i;
407 }
408 spin_unlock_irqrestore(&bp->lock, flags);
409
410 return t;
411}
412
413
414
415static int sx_probe(struct specialix_board *bp)
416{
417 unsigned char val1, val2;
418 int rev;
419 int chip;
420
421 func_enter();
422
423 if (sx_request_io_range(bp)) {
424 func_exit();
425 return 1;
426 }
427
428
429 sx_out_off(bp, CD186x_PPRL, 0x5a);
430 udelay(1);
431 val1 = sx_in_off(bp, CD186x_PPRL);
432
433 sx_out_off(bp, CD186x_PPRL, 0xa5);
434 udelay(1);
435 val2 = sx_in_off(bp, CD186x_PPRL);
436
437
438 if (val1 != 0x5a || val2 != 0xa5) {
439 printk(KERN_INFO
440 "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
441 board_No(bp), bp->base);
442 sx_release_io_range(bp);
443 func_exit();
444 return 1;
445 }
446
447
448
449 val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR);
450 val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS);
451 dprintk(SX_DEBUG_INIT,
452 "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
453 board_No(bp), val1, val2);
454
455
456
457
458
459 val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
460 if (val1 != val2) {
461 printk(KERN_INFO
462 "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
463 board_No(bp), val2, bp->base, val1);
464 sx_release_io_range(bp);
465 func_exit();
466 return 1;
467 }
468
469
470
471 if (!sx_init_CD186x(bp)) {
472 sx_release_io_range(bp);
473 func_exit();
474 return 1;
475 }
476
477 sx_request_io_range(bp);
478 bp->flags |= SX_BOARD_PRESENT;
479
480
481
482
483
484
485
486
487
488
489
490 switch (sx_in_off(bp, CD186x_GFRCR)) {
491 case 0x82:
492 chip = 1864;
493 rev = 'A';
494 break;
495 case 0x83:
496 chip = 1865;
497 rev = 'A';
498 break;
499 case 0x84:
500 chip = 1865;
501 rev = 'B';
502 break;
503 case 0x85:
504 chip = 1865;
505 rev = 'C';
506 break;
507 default:
508 chip = -1;
509 rev = 'x';
510 }
511
512 dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR));
513
514 printk(KERN_INFO
515 "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
516 board_No(bp), bp->base, bp->irq, chip, rev);
517
518 func_exit();
519 return 0;
520}
521
522
523
524
525
526
527static struct specialix_port *sx_get_port(struct specialix_board *bp,
528 unsigned char const *what)
529{
530 unsigned char channel;
531 struct specialix_port *port = NULL;
532
533 channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
534 dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel);
535 if (channel < CD186x_NCH) {
536 port = &sx_port[board_No(bp) * SX_NPORT + channel];
537 dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",
538 board_No(bp) * SX_NPORT + channel, port,
539 port->port.flags & ASYNC_INITIALIZED);
540
541 if (port->port.flags & ASYNC_INITIALIZED) {
542 dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
543 func_exit();
544 return port;
545 }
546 }
547 printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
548 board_No(bp), what, channel);
549 return NULL;
550}
551
552
553static void sx_receive_exc(struct specialix_board *bp)
554{
555 struct specialix_port *port;
556 struct tty_struct *tty;
557 unsigned char status;
558 unsigned char ch, flag;
559
560 func_enter();
561
562 port = sx_get_port(bp, "Receive");
563 if (!port) {
564 dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
565 func_exit();
566 return;
567 }
568 tty = port->port.tty;
569
570 status = sx_in(bp, CD186x_RCSR);
571
572 dprintk(SX_DEBUG_RX, "status: 0x%x\n", status);
573 if (status & RCSR_OE) {
574 port->overrun++;
575 dprintk(SX_DEBUG_FIFO,
576 "sx%d: port %d: Overrun. Total %ld overruns.\n",
577 board_No(bp), port_No(port), port->overrun);
578 }
579 status &= port->mark_mask;
580
581
582
583 if (tty_buffer_request_room(tty, 1) == 0) {
584 dprintk(SX_DEBUG_FIFO,
585 "sx%d: port %d: Working around flip buffer overflow.\n",
586 board_No(bp), port_No(port));
587 func_exit();
588 return;
589 }
590
591 ch = sx_in(bp, CD186x_RDR);
592 if (!status) {
593 func_exit();
594 return;
595 }
596 if (status & RCSR_TOUT) {
597 printk(KERN_INFO
598 "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
599 board_No(bp), port_No(port));
600 func_exit();
601 return;
602
603 } else if (status & RCSR_BREAK) {
604 dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
605 board_No(bp), port_No(port));
606 flag = TTY_BREAK;
607 if (port->port.flags & ASYNC_SAK)
608 do_SAK(tty);
609
610 } else if (status & RCSR_PE)
611 flag = TTY_PARITY;
612
613 else if (status & RCSR_FE)
614 flag = TTY_FRAME;
615
616 else if (status & RCSR_OE)
617 flag = TTY_OVERRUN;
618
619 else
620 flag = TTY_NORMAL;
621
622 if (tty_insert_flip_char(tty, ch, flag))
623 tty_flip_buffer_push(tty);
624 func_exit();
625}
626
627
628static void sx_receive(struct specialix_board *bp)
629{
630 struct specialix_port *port;
631 struct tty_struct *tty;
632 unsigned char count;
633
634 func_enter();
635
636 port = sx_get_port(bp, "Receive");
637 if (port == NULL) {
638 dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
639 func_exit();
640 return;
641 }
642 tty = port->port.tty;
643
644 count = sx_in(bp, CD186x_RDCR);
645 dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
646 port->hits[count > 8 ? 9 : count]++;
647
648 tty_buffer_request_room(tty, count);
649
650 while (count--)
651 tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
652 tty_flip_buffer_push(tty);
653 func_exit();
654}
655
656
657static void sx_transmit(struct specialix_board *bp)
658{
659 struct specialix_port *port;
660 struct tty_struct *tty;
661 unsigned char count;
662
663 func_enter();
664 port = sx_get_port(bp, "Transmit");
665 if (port == NULL) {
666 func_exit();
667 return;
668 }
669 dprintk(SX_DEBUG_TX, "port: %p\n", port);
670 tty = port->port.tty;
671
672 if (port->IER & IER_TXEMPTY) {
673
674 sx_out(bp, CD186x_CAR, port_No(port));
675 port->IER &= ~IER_TXEMPTY;
676 sx_out(bp, CD186x_IER, port->IER);
677 func_exit();
678 return;
679 }
680
681 if ((port->xmit_cnt <= 0 && !port->break_length)
682 || tty->stopped || tty->hw_stopped) {
683 sx_out(bp, CD186x_CAR, port_No(port));
684 port->IER &= ~IER_TXRDY;
685 sx_out(bp, CD186x_IER, port->IER);
686 func_exit();
687 return;
688 }
689
690 if (port->break_length) {
691 if (port->break_length > 0) {
692 if (port->COR2 & COR2_ETC) {
693 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
694 sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
695 port->COR2 &= ~COR2_ETC;
696 }
697 count = min_t(int, port->break_length, 0xff);
698 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
699 sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
700 sx_out(bp, CD186x_TDR, count);
701 port->break_length -= count;
702 if (port->break_length == 0)
703 port->break_length--;
704 } else {
705 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
706 sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
707 sx_out(bp, CD186x_COR2, port->COR2);
708 sx_wait_CCR(bp);
709 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
710 port->break_length = 0;
711 }
712
713 func_exit();
714 return;
715 }
716
717 count = CD186x_NFIFO;
718 do {
719 sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
720 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
721 if (--port->xmit_cnt <= 0)
722 break;
723 } while (--count > 0);
724
725 if (port->xmit_cnt <= 0) {
726 sx_out(bp, CD186x_CAR, port_No(port));
727 port->IER &= ~IER_TXRDY;
728 sx_out(bp, CD186x_IER, port->IER);
729 }
730 if (port->xmit_cnt <= port->wakeup_chars)
731 tty_wakeup(tty);
732
733 func_exit();
734}
735
736
737static void sx_check_modem(struct specialix_board *bp)
738{
739 struct specialix_port *port;
740 struct tty_struct *tty;
741 unsigned char mcr;
742 int msvr_cd;
743
744 dprintk(SX_DEBUG_SIGNALS, "Modem intr. ");
745 port = sx_get_port(bp, "Modem");
746 if (port == NULL)
747 return;
748
749 tty = port->port.tty;
750
751 mcr = sx_in(bp, CD186x_MCR);
752
753 if ((mcr & MCR_CDCHG)) {
754 dprintk(SX_DEBUG_SIGNALS, "CD just changed... ");
755 msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
756 if (msvr_cd) {
757 dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
758 wake_up_interruptible(&port->port.open_wait);
759 } else {
760 dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n");
761 tty_hangup(tty);
762 }
763 }
764
765#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
766 if (mcr & MCR_CTSCHG) {
767 if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
768 tty->hw_stopped = 0;
769 port->IER |= IER_TXRDY;
770 if (port->xmit_cnt <= port->wakeup_chars)
771 tty_wakeup(tty);
772 } else {
773 tty->hw_stopped = 1;
774 port->IER &= ~IER_TXRDY;
775 }
776 sx_out(bp, CD186x_IER, port->IER);
777 }
778 if (mcr & MCR_DSSXHG) {
779 if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
780 tty->hw_stopped = 0;
781 port->IER |= IER_TXRDY;
782 if (port->xmit_cnt <= port->wakeup_chars)
783 tty_wakeup(tty);
784 } else {
785 tty->hw_stopped = 1;
786 port->IER &= ~IER_TXRDY;
787 }
788 sx_out(bp, CD186x_IER, port->IER);
789 }
790#endif
791
792
793 sx_out(bp, CD186x_MCR, 0);
794}
795
796
797
798static irqreturn_t sx_interrupt(int dummy, void *dev_id)
799{
800 unsigned char status;
801 unsigned char ack;
802 struct specialix_board *bp = dev_id;
803 unsigned long loop = 0;
804 int saved_reg;
805 unsigned long flags;
806
807 func_enter();
808
809 spin_lock_irqsave(&bp->lock, flags);
810
811 dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__,
812 port_No(sx_get_port(bp, "INT")),
813 SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
814 if (!(bp->flags & SX_BOARD_ACTIVE)) {
815 dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n",
816 bp->irq);
817 spin_unlock_irqrestore(&bp->lock, flags);
818 func_exit();
819 return IRQ_NONE;
820 }
821
822 saved_reg = bp->reg;
823
824 while (++loop < 16) {
825 status = sx_in(bp, CD186x_SRSR) &
826 (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint);
827 if (status == 0)
828 break;
829 if (status & SRSR_RREQint) {
830 ack = sx_in(bp, CD186x_RRAR);
831
832 if (ack == (SX_ID | GIVR_IT_RCV))
833 sx_receive(bp);
834 else if (ack == (SX_ID | GIVR_IT_REXC))
835 sx_receive_exc(bp);
836 else
837 printk(KERN_ERR
838 "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
839 board_No(bp), status, ack);
840
841 } else if (status & SRSR_TREQint) {
842 ack = sx_in(bp, CD186x_TRAR);
843
844 if (ack == (SX_ID | GIVR_IT_TX))
845 sx_transmit(bp);
846 else
847 printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
848 board_No(bp), status, ack,
849 port_No(sx_get_port(bp, "Int")));
850 } else if (status & SRSR_MREQint) {
851 ack = sx_in(bp, CD186x_MRAR);
852
853 if (ack == (SX_ID | GIVR_IT_MODEM))
854 sx_check_modem(bp);
855 else
856 printk(KERN_ERR
857 "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
858 board_No(bp), status, ack);
859
860 }
861
862 sx_out(bp, CD186x_EOIR, 0);
863 }
864 bp->reg = saved_reg;
865 outb(bp->reg, bp->base + SX_ADDR_REG);
866 spin_unlock_irqrestore(&bp->lock, flags);
867 func_exit();
868 return IRQ_HANDLED;
869}
870
871
872
873
874
875
876static void turn_ints_off(struct specialix_board *bp)
877{
878 unsigned long flags;
879
880 func_enter();
881 spin_lock_irqsave(&bp->lock, flags);
882 (void) sx_in_off(bp, 0);
883 spin_unlock_irqrestore(&bp->lock, flags);
884
885 func_exit();
886}
887
888static void turn_ints_on(struct specialix_board *bp)
889{
890 unsigned long flags;
891
892 func_enter();
893
894 spin_lock_irqsave(&bp->lock, flags);
895 (void) sx_in(bp, 0);
896 spin_unlock_irqrestore(&bp->lock, flags);
897
898 func_exit();
899}
900
901
902
903static int sx_setup_board(struct specialix_board *bp)
904{
905 int error;
906
907 if (bp->flags & SX_BOARD_ACTIVE)
908 return 0;
909
910 if (bp->flags & SX_BOARD_IS_PCI)
911 error = request_irq(bp->irq, sx_interrupt,
912 IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
913 else
914 error = request_irq(bp->irq, sx_interrupt,
915 IRQF_DISABLED, "specialix IO8+", bp);
916
917 if (error)
918 return error;
919
920 turn_ints_on(bp);
921 bp->flags |= SX_BOARD_ACTIVE;
922
923 return 0;
924}
925
926
927
928static void sx_shutdown_board(struct specialix_board *bp)
929{
930 func_enter();
931
932 if (!(bp->flags & SX_BOARD_ACTIVE)) {
933 func_exit();
934 return;
935 }
936
937 bp->flags &= ~SX_BOARD_ACTIVE;
938
939 dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
940 bp->irq, board_No(bp));
941 free_irq(bp->irq, bp);
942 turn_ints_off(bp);
943 func_exit();
944}
945
946static unsigned int sx_crtscts(struct tty_struct *tty)
947{
948 if (sx_rtscts)
949 return C_CRTSCTS(tty);
950 return 1;
951}
952
953
954
955
956
957static void sx_change_speed(struct specialix_board *bp,
958 struct specialix_port *port)
959{
960 struct tty_struct *tty;
961 unsigned long baud;
962 long tmp;
963 unsigned char cor1 = 0, cor3 = 0;
964 unsigned char mcor1 = 0, mcor2 = 0;
965 static unsigned long again;
966 unsigned long flags;
967
968 func_enter();
969
970 tty = port->port.tty;
971 if (!tty || !tty->termios) {
972 func_exit();
973 return;
974 }
975
976 port->IER = 0;
977 port->COR2 = 0;
978
979 spin_lock_irqsave(&bp->lock, flags);
980 sx_out(bp, CD186x_CAR, port_No(port));
981
982
983
984 if (sx_crtscts(tty))
985 port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
986 else
987 port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
988 spin_unlock_irqrestore(&bp->lock, flags);
989 dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
990 baud = tty_get_baud_rate(tty);
991
992 if (baud == 38400) {
993 if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
994 baud = 57600;
995 if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
996 baud = 115200;
997 }
998
999 if (!baud) {
1000
1001 dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
1002 if (!sx_crtscts(tty)) {
1003 port->MSVR &= ~MSVR_DTR;
1004 spin_lock_irqsave(&bp->lock, flags);
1005 sx_out(bp, CD186x_MSVR, port->MSVR);
1006 spin_unlock_irqrestore(&bp->lock, flags);
1007 } else
1008 dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
1009 return;
1010 } else {
1011
1012 if (!sx_crtscts(tty))
1013 port->MSVR |= MSVR_DTR;
1014 }
1015
1016
1017
1018
1019
1020
1021 tmp = port->custom_divisor ;
1022 if (tmp)
1023 printk(KERN_INFO
1024 "sx%d: Using custom baud rate divisor %ld. \n"
1025 "This is an untested option, please be careful.\n",
1026 port_No(port), tmp);
1027 else
1028 tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) /
1029 CD186x_TPC);
1030
1031 if (tmp < 0x10 && time_before(again, jiffies)) {
1032 again = jiffies + HZ * 60;
1033
1034 if (tmp >= 12) {
1035 printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1036 "Performance degradation is possible.\n"
1037 "Read specialix.txt for more info.\n",
1038 port_No(port), tmp);
1039 } else {
1040 printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1041 "Warning: overstressing Cirrus chip. This might not work.\n"
1042 "Read specialix.txt for more info.\n", port_No(port), tmp);
1043 }
1044 }
1045 spin_lock_irqsave(&bp->lock, flags);
1046 sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
1047 sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
1048 sx_out(bp, CD186x_RBPRL, tmp & 0xff);
1049 sx_out(bp, CD186x_TBPRL, tmp & 0xff);
1050 spin_unlock_irqrestore(&bp->lock, flags);
1051 if (port->custom_divisor)
1052 baud = (SX_OSCFREQ + port->custom_divisor/2) /
1053 port->custom_divisor;
1054 baud = (baud + 5) / 10;
1055
1056
1057 tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
1058 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
1059 SERIAL_XMIT_SIZE - 1 : tmp);
1060
1061
1062 tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
1063 tmp = (tmp > 0xff) ? 0xff : tmp;
1064 spin_lock_irqsave(&bp->lock, flags);
1065 sx_out(bp, CD186x_RTPR, tmp);
1066 spin_unlock_irqrestore(&bp->lock, flags);
1067 switch (C_CSIZE(tty)) {
1068 case CS5:
1069 cor1 |= COR1_5BITS;
1070 break;
1071 case CS6:
1072 cor1 |= COR1_6BITS;
1073 break;
1074 case CS7:
1075 cor1 |= COR1_7BITS;
1076 break;
1077 case CS8:
1078 cor1 |= COR1_8BITS;
1079 break;
1080 }
1081
1082 if (C_CSTOPB(tty))
1083 cor1 |= COR1_2SB;
1084
1085 cor1 |= COR1_IGNORE;
1086 if (C_PARENB(tty)) {
1087 cor1 |= COR1_NORMPAR;
1088 if (C_PARODD(tty))
1089 cor1 |= COR1_ODDP;
1090 if (I_INPCK(tty))
1091 cor1 &= ~COR1_IGNORE;
1092 }
1093
1094 port->mark_mask = RCSR_OE | RCSR_TOUT;
1095 if (I_INPCK(tty))
1096 port->mark_mask |= RCSR_FE | RCSR_PE;
1097 if (I_BRKINT(tty) || I_PARMRK(tty))
1098 port->mark_mask |= RCSR_BREAK;
1099 if (I_IGNPAR(tty))
1100 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
1101 if (I_IGNBRK(tty)) {
1102 port->mark_mask &= ~RCSR_BREAK;
1103 if (I_IGNPAR(tty))
1104
1105 port->mark_mask &= ~RCSR_OE;
1106 }
1107
1108 if (C_CRTSCTS(tty)) {
1109#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
1110 port->IER |= IER_DSR | IER_CTS;
1111 mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
1112 mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
1113 spin_lock_irqsave(&bp->lock, flags);
1114 tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) &
1115 (MSVR_CTS|MSVR_DSR));
1116 spin_unlock_irqrestore(&bp->lock, flags);
1117#else
1118 port->COR2 |= COR2_CTSAE;
1119#endif
1120 }
1121
1122
1123 if (I_IXON(tty)) {
1124 port->COR2 |= COR2_TXIBE;
1125 cor3 |= (COR3_FCT | COR3_SCDE);
1126 if (I_IXANY(tty))
1127 port->COR2 |= COR2_IXM;
1128 spin_lock_irqsave(&bp->lock, flags);
1129 sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
1130 sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
1131 sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
1132 sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
1133 spin_unlock_irqrestore(&bp->lock, flags);
1134 }
1135 if (!C_CLOCAL(tty)) {
1136
1137 port->IER |= IER_CD;
1138 mcor1 |= MCOR1_CDZD;
1139 mcor2 |= MCOR2_CDOD;
1140 }
1141
1142 if (C_CREAD(tty))
1143
1144 port->IER |= IER_RXD;
1145
1146
1147 cor3 |= sx_rxfifo;
1148
1149 spin_lock_irqsave(&bp->lock, flags);
1150 sx_out(bp, CD186x_COR1, cor1);
1151 sx_out(bp, CD186x_COR2, port->COR2);
1152 sx_out(bp, CD186x_COR3, cor3);
1153 spin_unlock_irqrestore(&bp->lock, flags);
1154
1155 sx_wait_CCR(bp);
1156 spin_lock_irqsave(&bp->lock, flags);
1157 sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1158
1159 dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n",
1160 mcor1, mcor2);
1161 sx_out(bp, CD186x_MCOR1, mcor1);
1162 sx_out(bp, CD186x_MCOR2, mcor2);
1163 spin_unlock_irqrestore(&bp->lock, flags);
1164
1165 sx_wait_CCR(bp);
1166 spin_lock_irqsave(&bp->lock, flags);
1167 sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
1168
1169 sx_out(bp, CD186x_IER, port->IER);
1170
1171 sx_out(bp, CD186x_MSVR, port->MSVR);
1172 spin_unlock_irqrestore(&bp->lock, flags);
1173
1174 func_exit();
1175}
1176
1177
1178
1179static int sx_setup_port(struct specialix_board *bp,
1180 struct specialix_port *port)
1181{
1182 unsigned long flags;
1183
1184 func_enter();
1185
1186 if (port->port.flags & ASYNC_INITIALIZED) {
1187 func_exit();
1188 return 0;
1189 }
1190
1191 if (!port->xmit_buf) {
1192
1193 unsigned long tmp;
1194
1195 tmp = get_zeroed_page(GFP_KERNEL);
1196 if (tmp == 0L) {
1197 func_exit();
1198 return -ENOMEM;
1199 }
1200
1201 if (port->xmit_buf) {
1202 free_page(tmp);
1203 func_exit();
1204 return -ERESTARTSYS;
1205 }
1206 port->xmit_buf = (unsigned char *) tmp;
1207 }
1208
1209 spin_lock_irqsave(&port->lock, flags);
1210
1211 if (port->port.tty)
1212 clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
1213
1214 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1215 sx_change_speed(bp, port);
1216 port->port.flags |= ASYNC_INITIALIZED;
1217
1218 spin_unlock_irqrestore(&port->lock, flags);
1219
1220
1221 func_exit();
1222 return 0;
1223}
1224
1225
1226
1227static void sx_shutdown_port(struct specialix_board *bp,
1228 struct specialix_port *port)
1229{
1230 struct tty_struct *tty;
1231 int i;
1232 unsigned long flags;
1233
1234 func_enter();
1235
1236 if (!(port->port.flags & ASYNC_INITIALIZED)) {
1237 func_exit();
1238 return;
1239 }
1240
1241 if (sx_debug & SX_DEBUG_FIFO) {
1242 dprintk(SX_DEBUG_FIFO,
1243 "sx%d: port %d: %ld overruns, FIFO hits [ ",
1244 board_No(bp), port_No(port), port->overrun);
1245 for (i = 0; i < 10; i++)
1246 dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
1247 dprintk(SX_DEBUG_FIFO, "].\n");
1248 }
1249
1250 if (port->xmit_buf) {
1251 free_page((unsigned long) port->xmit_buf);
1252 port->xmit_buf = NULL;
1253 }
1254
1255
1256 spin_lock_irqsave(&bp->lock, flags);
1257 sx_out(bp, CD186x_CAR, port_No(port));
1258
1259 tty = port->port.tty;
1260 if (tty == NULL || C_HUPCL(tty)) {
1261
1262 sx_out(bp, CD186x_MSVDTR, 0);
1263 }
1264 spin_unlock_irqrestore(&bp->lock, flags);
1265
1266 sx_wait_CCR(bp);
1267 spin_lock_irqsave(&bp->lock, flags);
1268 sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
1269
1270 port->IER = 0;
1271 sx_out(bp, CD186x_IER, port->IER);
1272 spin_unlock_irqrestore(&bp->lock, flags);
1273 if (tty)
1274 set_bit(TTY_IO_ERROR, &tty->flags);
1275 port->port.flags &= ~ASYNC_INITIALIZED;
1276
1277 if (!bp->count)
1278 sx_shutdown_board(bp);
1279 func_exit();
1280}
1281
1282
1283static int block_til_ready(struct tty_struct *tty, struct file *filp,
1284 struct specialix_port *port)
1285{
1286 DECLARE_WAITQUEUE(wait, current);
1287 struct specialix_board *bp = port_Board(port);
1288 int retval;
1289 int do_clocal = 0;
1290 int CD;
1291 unsigned long flags;
1292
1293 func_enter();
1294
1295
1296
1297
1298
1299 if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
1300 interruptible_sleep_on(&port->port.close_wait);
1301 if (port->port.flags & ASYNC_HUP_NOTIFY) {
1302 func_exit();
1303 return -EAGAIN;
1304 } else {
1305 func_exit();
1306 return -ERESTARTSYS;
1307 }
1308 }
1309
1310
1311
1312
1313
1314 if ((filp->f_flags & O_NONBLOCK) ||
1315 (tty->flags & (1 << TTY_IO_ERROR))) {
1316 port->port.flags |= ASYNC_NORMAL_ACTIVE;
1317 func_exit();
1318 return 0;
1319 }
1320
1321 if (C_CLOCAL(tty))
1322 do_clocal = 1;
1323
1324
1325
1326
1327
1328
1329
1330
1331 retval = 0;
1332 add_wait_queue(&port->port.open_wait, &wait);
1333 spin_lock_irqsave(&port->lock, flags);
1334 if (!tty_hung_up_p(filp))
1335 port->port.count--;
1336 spin_unlock_irqrestore(&port->lock, flags);
1337 port->port.blocked_open++;
1338 while (1) {
1339 spin_lock_irqsave(&bp->lock, flags);
1340 sx_out(bp, CD186x_CAR, port_No(port));
1341 CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
1342 if (sx_crtscts(tty)) {
1343
1344 port->MSVR |= MSVR_DTR;
1345 sx_out(bp, CD186x_MSVR, port->MSVR);
1346 } else {
1347
1348 port->MSVR |= MSVR_DTR;
1349 sx_out(bp, CD186x_MSVR, port->MSVR);
1350 }
1351 spin_unlock_irqrestore(&bp->lock, flags);
1352 set_current_state(TASK_INTERRUPTIBLE);
1353 if (tty_hung_up_p(filp) ||
1354 !(port->port.flags & ASYNC_INITIALIZED)) {
1355 if (port->port.flags & ASYNC_HUP_NOTIFY)
1356 retval = -EAGAIN;
1357 else
1358 retval = -ERESTARTSYS;
1359 break;
1360 }
1361 if (!(port->port.flags & ASYNC_CLOSING) &&
1362 (do_clocal || CD))
1363 break;
1364 if (signal_pending(current)) {
1365 retval = -ERESTARTSYS;
1366 break;
1367 }
1368 schedule();
1369 }
1370
1371 set_current_state(TASK_RUNNING);
1372 remove_wait_queue(&port->port.open_wait, &wait);
1373 spin_lock_irqsave(&port->lock, flags);
1374 if (!tty_hung_up_p(filp))
1375 port->port.count++;
1376 port->port.blocked_open--;
1377 spin_unlock_irqrestore(&port->lock, flags);
1378 if (retval) {
1379 func_exit();
1380 return retval;
1381 }
1382
1383 port->port.flags |= ASYNC_NORMAL_ACTIVE;
1384 func_exit();
1385 return 0;
1386}
1387
1388
1389static int sx_open(struct tty_struct *tty, struct file *filp)
1390{
1391 int board;
1392 int error;
1393 struct specialix_port *port;
1394 struct specialix_board *bp;
1395 int i;
1396 unsigned long flags;
1397
1398 func_enter();
1399
1400 board = SX_BOARD(tty->index);
1401
1402 if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
1403 func_exit();
1404 return -ENODEV;
1405 }
1406
1407 bp = &sx_board[board];
1408 port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
1409 port->overrun = 0;
1410 for (i = 0; i < 10; i++)
1411 port->hits[i] = 0;
1412
1413 dprintk(SX_DEBUG_OPEN,
1414 "Board = %d, bp = %p, port = %p, portno = %d.\n",
1415 board, bp, port, SX_PORT(tty->index));
1416
1417 if (sx_paranoia_check(port, tty->name, "sx_open")) {
1418 func_enter();
1419 return -ENODEV;
1420 }
1421
1422 error = sx_setup_board(bp);
1423 if (error) {
1424 func_exit();
1425 return error;
1426 }
1427
1428 spin_lock_irqsave(&bp->lock, flags);
1429 port->port.count++;
1430 bp->count++;
1431 tty->driver_data = port;
1432 port->port.tty = tty;
1433 spin_unlock_irqrestore(&bp->lock, flags);
1434
1435 error = sx_setup_port(bp, port);
1436 if (error) {
1437 func_enter();
1438 return error;
1439 }
1440
1441 error = block_til_ready(tty, filp, port);
1442 if (error) {
1443 func_enter();
1444 return error;
1445 }
1446
1447 func_exit();
1448 return 0;
1449}
1450
1451static void sx_flush_buffer(struct tty_struct *tty)
1452{
1453 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1454 unsigned long flags;
1455 struct specialix_board *bp;
1456
1457 func_enter();
1458
1459 if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
1460 func_exit();
1461 return;
1462 }
1463
1464 bp = port_Board(port);
1465 spin_lock_irqsave(&port->lock, flags);
1466 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1467 spin_unlock_irqrestore(&port->lock, flags);
1468 tty_wakeup(tty);
1469
1470 func_exit();
1471}
1472
1473static void sx_close(struct tty_struct *tty, struct file *filp)
1474{
1475 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1476 struct specialix_board *bp;
1477 unsigned long flags;
1478 unsigned long timeout;
1479
1480 func_enter();
1481 if (!port || sx_paranoia_check(port, tty->name, "close")) {
1482 func_exit();
1483 return;
1484 }
1485 spin_lock_irqsave(&port->lock, flags);
1486
1487 if (tty_hung_up_p(filp)) {
1488 spin_unlock_irqrestore(&port->lock, flags);
1489 func_exit();
1490 return;
1491 }
1492
1493 bp = port_Board(port);
1494 if (tty->count == 1 && port->port.count != 1) {
1495 printk(KERN_ERR "sx%d: sx_close: bad port count;"
1496 " tty->count is 1, port count is %d\n",
1497 board_No(bp), port->port.count);
1498 port->port.count = 1;
1499 }
1500
1501 if (port->port.count > 1) {
1502 port->port.count--;
1503 bp->count--;
1504
1505 spin_unlock_irqrestore(&port->lock, flags);
1506
1507 func_exit();
1508 return;
1509 }
1510 port->port.flags |= ASYNC_CLOSING;
1511
1512
1513
1514
1515 tty->closing = 1;
1516 spin_unlock_irqrestore(&port->lock, flags);
1517 dprintk(SX_DEBUG_OPEN, "Closing\n");
1518 if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
1519 tty_wait_until_sent(tty, port->port.closing_wait);
1520
1521
1522
1523
1524
1525
1526 dprintk(SX_DEBUG_OPEN, "Closed\n");
1527 port->IER &= ~IER_RXD;
1528 if (port->port.flags & ASYNC_INITIALIZED) {
1529 port->IER &= ~IER_TXRDY;
1530 port->IER |= IER_TXEMPTY;
1531 spin_lock_irqsave(&bp->lock, flags);
1532 sx_out(bp, CD186x_CAR, port_No(port));
1533 sx_out(bp, CD186x_IER, port->IER);
1534 spin_unlock_irqrestore(&bp->lock, flags);
1535
1536
1537
1538
1539
1540 timeout = jiffies+HZ;
1541 while (port->IER & IER_TXEMPTY) {
1542 set_current_state(TASK_INTERRUPTIBLE);
1543 msleep_interruptible(jiffies_to_msecs(port->timeout));
1544 if (time_after(jiffies, timeout)) {
1545 printk(KERN_INFO "Timeout waiting for close\n");
1546 break;
1547 }
1548 }
1549
1550 }
1551
1552 if (--bp->count < 0) {
1553 printk(KERN_ERR
1554 "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
1555 board_No(bp), bp->count, tty->index);
1556 bp->count = 0;
1557 }
1558 if (--port->port.count < 0) {
1559 printk(KERN_ERR
1560 "sx%d: sx_close: bad port count for tty%d: %d\n",
1561 board_No(bp), port_No(port), port->port.count);
1562 port->port.count = 0;
1563 }
1564
1565 sx_shutdown_port(bp, port);
1566 sx_flush_buffer(tty);
1567 tty_ldisc_flush(tty);
1568 spin_lock_irqsave(&port->lock, flags);
1569 tty->closing = 0;
1570 port->port.tty = NULL;
1571 spin_unlock_irqrestore(&port->lock, flags);
1572 if (port->port.blocked_open) {
1573 if (port->port.close_delay)
1574 msleep_interruptible(
1575 jiffies_to_msecs(port->port.close_delay));
1576 wake_up_interruptible(&port->port.open_wait);
1577 }
1578 port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1579 wake_up_interruptible(&port->port.close_wait);
1580
1581 func_exit();
1582}
1583
1584
1585static int sx_write(struct tty_struct *tty,
1586 const unsigned char *buf, int count)
1587{
1588 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1589 struct specialix_board *bp;
1590 int c, total = 0;
1591 unsigned long flags;
1592
1593 func_enter();
1594 if (sx_paranoia_check(port, tty->name, "sx_write")) {
1595 func_exit();
1596 return 0;
1597 }
1598
1599 bp = port_Board(port);
1600
1601 if (!port->xmit_buf) {
1602 func_exit();
1603 return 0;
1604 }
1605
1606 while (1) {
1607 spin_lock_irqsave(&port->lock, flags);
1608 c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1609 SERIAL_XMIT_SIZE - port->xmit_head));
1610 if (c <= 0) {
1611 spin_unlock_irqrestore(&port->lock, flags);
1612 break;
1613 }
1614 memcpy(port->xmit_buf + port->xmit_head, buf, c);
1615 port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1616 port->xmit_cnt += c;
1617 spin_unlock_irqrestore(&port->lock, flags);
1618
1619 buf += c;
1620 count -= c;
1621 total += c;
1622 }
1623
1624 spin_lock_irqsave(&bp->lock, flags);
1625 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1626 !(port->IER & IER_TXRDY)) {
1627 port->IER |= IER_TXRDY;
1628 sx_out(bp, CD186x_CAR, port_No(port));
1629 sx_out(bp, CD186x_IER, port->IER);
1630 }
1631 spin_unlock_irqrestore(&bp->lock, flags);
1632 func_exit();
1633
1634 return total;
1635}
1636
1637
1638static int sx_put_char(struct tty_struct *tty, unsigned char ch)
1639{
1640 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1641 unsigned long flags;
1642 struct specialix_board *bp;
1643
1644 func_enter();
1645
1646 if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
1647 func_exit();
1648 return 0;
1649 }
1650 dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
1651 if (!port->xmit_buf) {
1652 func_exit();
1653 return 0;
1654 }
1655 bp = port_Board(port);
1656 spin_lock_irqsave(&port->lock, flags);
1657
1658 dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n",
1659 port->xmit_cnt, port->xmit_buf);
1660 if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) {
1661 spin_unlock_irqrestore(&port->lock, flags);
1662 dprintk(SX_DEBUG_TX, "Exit size\n");
1663 func_exit();
1664 return 0;
1665 }
1666 dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
1667 port->xmit_buf[port->xmit_head++] = ch;
1668 port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1669 port->xmit_cnt++;
1670 spin_unlock_irqrestore(&port->lock, flags);
1671
1672 func_exit();
1673 return 1;
1674}
1675
1676
1677static void sx_flush_chars(struct tty_struct *tty)
1678{
1679 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1680 unsigned long flags;
1681 struct specialix_board *bp = port_Board(port);
1682
1683 func_enter();
1684
1685 if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
1686 func_exit();
1687 return;
1688 }
1689 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1690 !port->xmit_buf) {
1691 func_exit();
1692 return;
1693 }
1694 spin_lock_irqsave(&bp->lock, flags);
1695 port->IER |= IER_TXRDY;
1696 sx_out(port_Board(port), CD186x_CAR, port_No(port));
1697 sx_out(port_Board(port), CD186x_IER, port->IER);
1698 spin_unlock_irqrestore(&bp->lock, flags);
1699
1700 func_exit();
1701}
1702
1703
1704static int sx_write_room(struct tty_struct *tty)
1705{
1706 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1707 int ret;
1708
1709 func_enter();
1710
1711 if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
1712 func_exit();
1713 return 0;
1714 }
1715
1716 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1717 if (ret < 0)
1718 ret = 0;
1719
1720 func_exit();
1721 return ret;
1722}
1723
1724
1725static int sx_chars_in_buffer(struct tty_struct *tty)
1726{
1727 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1728
1729 func_enter();
1730
1731 if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
1732 func_exit();
1733 return 0;
1734 }
1735 func_exit();
1736 return port->xmit_cnt;
1737}
1738
1739static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1740{
1741 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1742 struct specialix_board *bp;
1743 unsigned char status;
1744 unsigned int result;
1745 unsigned long flags;
1746
1747 func_enter();
1748
1749 if (sx_paranoia_check(port, tty->name, __func__)) {
1750 func_exit();
1751 return -ENODEV;
1752 }
1753
1754 bp = port_Board(port);
1755 spin_lock_irqsave(&bp->lock, flags);
1756 sx_out(bp, CD186x_CAR, port_No(port));
1757 status = sx_in(bp, CD186x_MSVR);
1758 spin_unlock_irqrestore(&bp->lock, flags);
1759 dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
1760 port_No(port), status, sx_in(bp, CD186x_CAR));
1761 dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
1762 if (sx_crtscts(port->port.tty)) {
1763 result = TIOCM_DTR | TIOCM_DSR
1764 | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
1765 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1766 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1767 } else {
1768 result = TIOCM_RTS | TIOCM_DSR
1769 | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1770 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1771 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1772 }
1773
1774 func_exit();
1775
1776 return result;
1777}
1778
1779
1780static int sx_tiocmset(struct tty_struct *tty, struct file *file,
1781 unsigned int set, unsigned int clear)
1782{
1783 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1784 unsigned long flags;
1785 struct specialix_board *bp;
1786
1787 func_enter();
1788
1789 if (sx_paranoia_check(port, tty->name, __func__)) {
1790 func_exit();
1791 return -ENODEV;
1792 }
1793
1794 bp = port_Board(port);
1795
1796 spin_lock_irqsave(&port->lock, flags);
1797 if (sx_crtscts(port->port.tty)) {
1798 if (set & TIOCM_RTS)
1799 port->MSVR |= MSVR_DTR;
1800 } else {
1801 if (set & TIOCM_DTR)
1802 port->MSVR |= MSVR_DTR;
1803 }
1804 if (sx_crtscts(port->port.tty)) {
1805 if (clear & TIOCM_RTS)
1806 port->MSVR &= ~MSVR_DTR;
1807 } else {
1808 if (clear & TIOCM_DTR)
1809 port->MSVR &= ~MSVR_DTR;
1810 }
1811 spin_lock_irqsave(&bp->lock, flags);
1812 sx_out(bp, CD186x_CAR, port_No(port));
1813 sx_out(bp, CD186x_MSVR, port->MSVR);
1814 spin_unlock_irqrestore(&bp->lock, flags);
1815 spin_unlock_irqrestore(&port->lock, flags);
1816 func_exit();
1817 return 0;
1818}
1819
1820
1821static int sx_send_break(struct tty_struct *tty, int length)
1822{
1823 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1824 struct specialix_board *bp = port_Board(port);
1825 unsigned long flags;
1826
1827 func_enter();
1828 if (length == 0 || length == -1)
1829 return -EOPNOTSUPP;
1830
1831 spin_lock_irqsave(&port->lock, flags);
1832 port->break_length = SPECIALIX_TPS / HZ * length;
1833 port->COR2 |= COR2_ETC;
1834 port->IER |= IER_TXRDY;
1835 spin_lock_irqsave(&bp->lock, flags);
1836 sx_out(bp, CD186x_CAR, port_No(port));
1837 sx_out(bp, CD186x_COR2, port->COR2);
1838 sx_out(bp, CD186x_IER, port->IER);
1839 spin_unlock_irqrestore(&bp->lock, flags);
1840 spin_unlock_irqrestore(&port->lock, flags);
1841 sx_wait_CCR(bp);
1842 spin_lock_irqsave(&bp->lock, flags);
1843 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
1844 spin_unlock_irqrestore(&bp->lock, flags);
1845 sx_wait_CCR(bp);
1846
1847 func_exit();
1848 return 0;
1849}
1850
1851
1852static int sx_set_serial_info(struct specialix_port *port,
1853 struct serial_struct __user *newinfo)
1854{
1855 struct serial_struct tmp;
1856 struct specialix_board *bp = port_Board(port);
1857 int change_speed;
1858
1859 func_enter();
1860
1861 if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
1862 func_enter();
1863 return -EFAULT;
1864 }
1865
1866 lock_kernel();
1867
1868 change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
1869 (tmp.flags & ASYNC_SPD_MASK));
1870 change_speed |= (tmp.custom_divisor != port->custom_divisor);
1871
1872 if (!capable(CAP_SYS_ADMIN)) {
1873 if ((tmp.close_delay != port->port.close_delay) ||
1874 (tmp.closing_wait != port->port.closing_wait) ||
1875 ((tmp.flags & ~ASYNC_USR_MASK) !=
1876 (port->port.flags & ~ASYNC_USR_MASK))) {
1877 func_exit();
1878 unlock_kernel();
1879 return -EPERM;
1880 }
1881 port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
1882 (tmp.flags & ASYNC_USR_MASK));
1883 port->custom_divisor = tmp.custom_divisor;
1884 } else {
1885 port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
1886 (tmp.flags & ASYNC_FLAGS));
1887 port->port.close_delay = tmp.close_delay;
1888 port->port.closing_wait = tmp.closing_wait;
1889 port->custom_divisor = tmp.custom_divisor;
1890 }
1891 if (change_speed)
1892 sx_change_speed(bp, port);
1893
1894 func_exit();
1895 unlock_kernel();
1896 return 0;
1897}
1898
1899
1900static int sx_get_serial_info(struct specialix_port *port,
1901 struct serial_struct __user *retinfo)
1902{
1903 struct serial_struct tmp;
1904 struct specialix_board *bp = port_Board(port);
1905
1906 func_enter();
1907
1908 memset(&tmp, 0, sizeof(tmp));
1909 lock_kernel();
1910 tmp.type = PORT_CIRRUS;
1911 tmp.line = port - sx_port;
1912 tmp.port = bp->base;
1913 tmp.irq = bp->irq;
1914 tmp.flags = port->port.flags;
1915 tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
1916 tmp.close_delay = port->port.close_delay * HZ/100;
1917 tmp.closing_wait = port->port.closing_wait * HZ/100;
1918 tmp.custom_divisor = port->custom_divisor;
1919 tmp.xmit_fifo_size = CD186x_NFIFO;
1920 unlock_kernel();
1921 if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
1922 func_exit();
1923 return -EFAULT;
1924 }
1925
1926 func_exit();
1927 return 0;
1928}
1929
1930
1931static int sx_ioctl(struct tty_struct *tty, struct file *filp,
1932 unsigned int cmd, unsigned long arg)
1933{
1934 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1935 void __user *argp = (void __user *)arg;
1936
1937 func_enter();
1938
1939 if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
1940 func_exit();
1941 return -ENODEV;
1942 }
1943
1944 switch (cmd) {
1945 case TIOCGSERIAL:
1946 func_exit();
1947 return sx_get_serial_info(port, argp);
1948 case TIOCSSERIAL:
1949 func_exit();
1950 return sx_set_serial_info(port, argp);
1951 default:
1952 func_exit();
1953 return -ENOIOCTLCMD;
1954 }
1955 func_exit();
1956 return 0;
1957}
1958
1959
1960static void sx_throttle(struct tty_struct *tty)
1961{
1962 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1963 struct specialix_board *bp;
1964 unsigned long flags;
1965
1966 func_enter();
1967
1968 if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
1969 func_exit();
1970 return;
1971 }
1972
1973 bp = port_Board(port);
1974
1975
1976 if (sx_crtscts(tty))
1977 port->MSVR &= ~MSVR_DTR;
1978 else {
1979
1980
1981
1982
1983 printk(KERN_ERR
1984 "sx%d: Need to throttle, but can't (hardware hs is off)\n",
1985 port_No(port));
1986 }
1987 spin_lock_irqsave(&bp->lock, flags);
1988 sx_out(bp, CD186x_CAR, port_No(port));
1989 spin_unlock_irqrestore(&bp->lock, flags);
1990 if (I_IXOFF(tty)) {
1991 sx_wait_CCR(bp);
1992 spin_lock_irqsave(&bp->lock, flags);
1993 sx_out(bp, CD186x_CCR, CCR_SSCH2);
1994 spin_unlock_irqrestore(&bp->lock, flags);
1995 sx_wait_CCR(bp);
1996 }
1997 spin_lock_irqsave(&bp->lock, flags);
1998 sx_out(bp, CD186x_MSVR, port->MSVR);
1999 spin_unlock_irqrestore(&bp->lock, flags);
2000
2001 func_exit();
2002}
2003
2004
2005static void sx_unthrottle(struct tty_struct *tty)
2006{
2007 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2008 struct specialix_board *bp;
2009 unsigned long flags;
2010
2011 func_enter();
2012
2013 if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
2014 func_exit();
2015 return;
2016 }
2017
2018 bp = port_Board(port);
2019
2020 spin_lock_irqsave(&port->lock, flags);
2021
2022 if (sx_crtscts(tty))
2023 port->MSVR |= MSVR_DTR;
2024
2025 spin_lock_irqsave(&bp->lock, flags);
2026 sx_out(bp, CD186x_CAR, port_No(port));
2027 spin_unlock_irqrestore(&bp->lock, flags);
2028 if (I_IXOFF(tty)) {
2029 spin_unlock_irqrestore(&port->lock, flags);
2030 sx_wait_CCR(bp);
2031 spin_lock_irqsave(&bp->lock, flags);
2032 sx_out(bp, CD186x_CCR, CCR_SSCH1);
2033 spin_unlock_irqrestore(&bp->lock, flags);
2034 sx_wait_CCR(bp);
2035 spin_lock_irqsave(&port->lock, flags);
2036 }
2037 spin_lock_irqsave(&bp->lock, flags);
2038 sx_out(bp, CD186x_MSVR, port->MSVR);
2039 spin_unlock_irqrestore(&bp->lock, flags);
2040 spin_unlock_irqrestore(&port->lock, flags);
2041
2042 func_exit();
2043}
2044
2045
2046static void sx_stop(struct tty_struct *tty)
2047{
2048 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2049 struct specialix_board *bp;
2050 unsigned long flags;
2051
2052 func_enter();
2053
2054 if (sx_paranoia_check(port, tty->name, "sx_stop")) {
2055 func_exit();
2056 return;
2057 }
2058
2059 bp = port_Board(port);
2060
2061 spin_lock_irqsave(&port->lock, flags);
2062 port->IER &= ~IER_TXRDY;
2063 spin_lock_irqsave(&bp->lock, flags);
2064 sx_out(bp, CD186x_CAR, port_No(port));
2065 sx_out(bp, CD186x_IER, port->IER);
2066 spin_unlock_irqrestore(&bp->lock, flags);
2067 spin_unlock_irqrestore(&port->lock, flags);
2068
2069 func_exit();
2070}
2071
2072
2073static void sx_start(struct tty_struct *tty)
2074{
2075 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2076 struct specialix_board *bp;
2077 unsigned long flags;
2078
2079 func_enter();
2080
2081 if (sx_paranoia_check(port, tty->name, "sx_start")) {
2082 func_exit();
2083 return;
2084 }
2085
2086 bp = port_Board(port);
2087
2088 spin_lock_irqsave(&port->lock, flags);
2089 if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
2090 port->IER |= IER_TXRDY;
2091 spin_lock_irqsave(&bp->lock, flags);
2092 sx_out(bp, CD186x_CAR, port_No(port));
2093 sx_out(bp, CD186x_IER, port->IER);
2094 spin_unlock_irqrestore(&bp->lock, flags);
2095 }
2096 spin_unlock_irqrestore(&port->lock, flags);
2097
2098 func_exit();
2099}
2100
2101static void sx_hangup(struct tty_struct *tty)
2102{
2103 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2104 struct specialix_board *bp;
2105 unsigned long flags;
2106
2107 func_enter();
2108
2109 if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
2110 func_exit();
2111 return;
2112 }
2113
2114 bp = port_Board(port);
2115
2116 sx_shutdown_port(bp, port);
2117 spin_lock_irqsave(&port->lock, flags);
2118 bp->count -= port->port.count;
2119 if (bp->count < 0) {
2120 printk(KERN_ERR
2121 "sx%d: sx_hangup: bad board count: %d port: %d\n",
2122 board_No(bp), bp->count, tty->index);
2123 bp->count = 0;
2124 }
2125 port->port.count = 0;
2126 port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
2127 port->port.tty = NULL;
2128 spin_unlock_irqrestore(&port->lock, flags);
2129 wake_up_interruptible(&port->port.open_wait);
2130
2131 func_exit();
2132}
2133
2134
2135static void sx_set_termios(struct tty_struct *tty,
2136 struct ktermios *old_termios)
2137{
2138 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2139 unsigned long flags;
2140 struct specialix_board *bp;
2141
2142 if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
2143 return;
2144
2145 bp = port_Board(port);
2146 spin_lock_irqsave(&port->lock, flags);
2147 sx_change_speed(port_Board(port), port);
2148 spin_unlock_irqrestore(&port->lock, flags);
2149
2150 if ((old_termios->c_cflag & CRTSCTS) &&
2151 !(tty->termios->c_cflag & CRTSCTS)) {
2152 tty->hw_stopped = 0;
2153 sx_start(tty);
2154 }
2155}
2156
2157static const struct tty_operations sx_ops = {
2158 .open = sx_open,
2159 .close = sx_close,
2160 .write = sx_write,
2161 .put_char = sx_put_char,
2162 .flush_chars = sx_flush_chars,
2163 .write_room = sx_write_room,
2164 .chars_in_buffer = sx_chars_in_buffer,
2165 .flush_buffer = sx_flush_buffer,
2166 .ioctl = sx_ioctl,
2167 .throttle = sx_throttle,
2168 .unthrottle = sx_unthrottle,
2169 .set_termios = sx_set_termios,
2170 .stop = sx_stop,
2171 .start = sx_start,
2172 .hangup = sx_hangup,
2173 .tiocmget = sx_tiocmget,
2174 .tiocmset = sx_tiocmset,
2175 .break_ctl = sx_send_break,
2176};
2177
2178static int sx_init_drivers(void)
2179{
2180 int error;
2181 int i;
2182
2183 func_enter();
2184
2185 specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
2186 if (!specialix_driver) {
2187 printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
2188 func_exit();
2189 return 1;
2190 }
2191
2192 specialix_driver->owner = THIS_MODULE;
2193 specialix_driver->name = "ttyW";
2194 specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
2195 specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
2196 specialix_driver->subtype = SERIAL_TYPE_NORMAL;
2197 specialix_driver->init_termios = tty_std_termios;
2198 specialix_driver->init_termios.c_cflag =
2199 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2200 specialix_driver->init_termios.c_ispeed = 9600;
2201 specialix_driver->init_termios.c_ospeed = 9600;
2202 specialix_driver->flags = TTY_DRIVER_REAL_RAW |
2203 TTY_DRIVER_HARDWARE_BREAK;
2204 tty_set_operations(specialix_driver, &sx_ops);
2205
2206 error = tty_register_driver(specialix_driver);
2207 if (error) {
2208 put_tty_driver(specialix_driver);
2209 printk(KERN_ERR
2210 "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2211 error);
2212 func_exit();
2213 return 1;
2214 }
2215 memset(sx_port, 0, sizeof(sx_port));
2216 for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
2217 sx_port[i].magic = SPECIALIX_MAGIC;
2218 tty_port_init(&sx_port[i].port);
2219 spin_lock_init(&sx_port[i].lock);
2220 }
2221
2222 func_exit();
2223 return 0;
2224}
2225
2226static void sx_release_drivers(void)
2227{
2228 func_enter();
2229
2230 tty_unregister_driver(specialix_driver);
2231 put_tty_driver(specialix_driver);
2232 func_exit();
2233}
2234
2235
2236
2237
2238static int __init specialix_init(void)
2239{
2240 int i;
2241 int found = 0;
2242
2243 func_enter();
2244
2245 printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
2246 printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2247 if (sx_rtscts)
2248 printk(KERN_INFO
2249 "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2250 else
2251 printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
2252
2253 for (i = 0; i < SX_NBOARD; i++)
2254 spin_lock_init(&sx_board[i].lock);
2255
2256 if (sx_init_drivers()) {
2257 func_exit();
2258 return -EIO;
2259 }
2260
2261 for (i = 0; i < SX_NBOARD; i++)
2262 if (sx_board[i].base && !sx_probe(&sx_board[i]))
2263 found++;
2264
2265#ifdef CONFIG_PCI
2266 {
2267 struct pci_dev *pdev = NULL;
2268
2269 i = 0;
2270 while (i < SX_NBOARD) {
2271 if (sx_board[i].flags & SX_BOARD_PRESENT) {
2272 i++;
2273 continue;
2274 }
2275 pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX,
2276 PCI_DEVICE_ID_SPECIALIX_IO8, pdev);
2277 if (!pdev)
2278 break;
2279
2280 if (pci_enable_device(pdev))
2281 continue;
2282
2283 sx_board[i].irq = pdev->irq;
2284
2285 sx_board[i].base = pci_resource_start(pdev, 2);
2286
2287 sx_board[i].flags |= SX_BOARD_IS_PCI;
2288 if (!sx_probe(&sx_board[i]))
2289 found++;
2290 }
2291
2292 if (pdev != NULL)
2293 pci_dev_put(pdev);
2294 }
2295#endif
2296
2297 if (!found) {
2298 sx_release_drivers();
2299 printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
2300 func_exit();
2301 return -EIO;
2302 }
2303
2304 func_exit();
2305 return 0;
2306}
2307
2308static int iobase[SX_NBOARD] = {0,};
2309static int irq[SX_NBOARD] = {0,};
2310
2311module_param_array(iobase, int, NULL, 0);
2312module_param_array(irq, int, NULL, 0);
2313module_param(sx_debug, int, 0);
2314module_param(sx_rtscts, int, 0);
2315module_param(sx_rxfifo, int, 0);
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326static int __init specialix_init_module(void)
2327{
2328 int i;
2329
2330 func_enter();
2331
2332 if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
2333 for (i = 0; i < SX_NBOARD; i++) {
2334 sx_board[i].base = iobase[i];
2335 sx_board[i].irq = irq[i];
2336 sx_board[i].count = 0;
2337 }
2338 }
2339
2340 func_exit();
2341
2342 return specialix_init();
2343}
2344
2345static void __exit specialix_exit_module(void)
2346{
2347 int i;
2348
2349 func_enter();
2350
2351 sx_release_drivers();
2352 for (i = 0; i < SX_NBOARD; i++)
2353 if (sx_board[i].flags & SX_BOARD_PRESENT)
2354 sx_release_io_range(&sx_board[i]);
2355 func_exit();
2356}
2357
2358static struct pci_device_id specialx_pci_tbl[] __devinitdata = {
2359 { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
2360 { }
2361};
2362MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
2363
2364module_init(specialix_init_module);
2365module_exit(specialix_exit_module);
2366
2367MODULE_LICENSE("GPL");