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#include <linux/sched.h>
66#include "i2lib.h"
67
68
69
70
71
72static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int);
73static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int );
74static void i2StripFifo(i2eBordStrPtr);
75static void i2StuffFifoBypass(i2eBordStrPtr);
76static void i2StuffFifoFlow(i2eBordStrPtr);
77static void i2StuffFifoInline(i2eBordStrPtr);
78static int i2RetryFlushOutput(i2ChanStrPtr);
79
80
81
82
83static void iiSendPendingMail(i2eBordStrPtr);
84static void serviceOutgoingFifo(i2eBordStrPtr);
85
86
87static void do_input(struct work_struct *);
88static void do_status(struct work_struct *);
89
90
91
92
93#ifdef DEBUG_FIFO
94
95unsigned char DBGBuf[0x4000];
96unsigned short I = 0;
97
98static void
99WriteDBGBuf(char *s, unsigned char *src, unsigned short n )
100{
101 char *p = src;
102
103
104
105 while (*s) {
106 DBGBuf[I] = *s++;
107 I = I++ & 0x3fff;
108 }
109 while (n--) {
110 DBGBuf[I] = *p++;
111 I = I++ & 0x3fff;
112 }
113}
114
115static void
116fatality(i2eBordStrPtr pB )
117{
118 int i;
119
120 for (i=0;i<sizeof(DBGBuf);i++) {
121 if ((i%16) == 0)
122 printk("\n%4x:",i);
123 printk("%02x ",DBGBuf[i]);
124 }
125 printk("\n");
126 for (i=0;i<sizeof(DBGBuf);i++) {
127 if ((i%16) == 0)
128 printk("\n%4x:",i);
129 if (DBGBuf[i] >= ' ' && DBGBuf[i] <= '~') {
130 printk(" %c ",DBGBuf[i]);
131 } else {
132 printk(" . ");
133 }
134 }
135 printk("\n");
136 printk("Last index %x\n",I);
137}
138#endif
139
140
141
142
143
144static inline int
145i2Validate ( i2ChanStrPtr pCh )
146{
147
148
149 return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT))
150 == (CHANNEL_MAGIC | CHANNEL_SUPPORT));
151}
152
153static void iiSendPendingMail_t(unsigned long data)
154{
155 i2eBordStrPtr pB = (i2eBordStrPtr)data;
156
157 iiSendPendingMail(pB);
158}
159
160
161
162
163
164
165
166
167
168
169static void
170iiSendPendingMail(i2eBordStrPtr pB)
171{
172 if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) )
173 {
174 if (iiTrySendMail(pB, pB->i2eOutMailWaiting))
175 {
176
177
178
179
180
181 pB->i2eWaitingForEmptyFifo |=
182 (pB->i2eOutMailWaiting & MB_OUT_STUFFED);
183 pB->i2eOutMailWaiting = 0;
184 pB->SendPendingRetry = 0;
185 } else {
186
187
188
189
190
191
192
193 if( ++pB->SendPendingRetry < 16 ) {
194 setup_timer(&pB->SendPendingTimer,
195 iiSendPendingMail_t, (unsigned long)pB);
196 mod_timer(&pB->SendPendingTimer, jiffies + 1);
197 } else {
198 printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" );
199 }
200 }
201 }
202}
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223static int
224i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
225{
226 int index, stuffIndex;
227 i2ChanStrPtr *ppCh;
228
229 if (pB->i2eValid != I2E_MAGIC) {
230 I2_COMPLETE(pB, I2EE_BADMAGIC);
231 }
232 if (pB->i2eState != II_STATE_STDLOADED) {
233 I2_COMPLETE(pB, I2EE_BADSTATE);
234 }
235
236 rwlock_init(&pB->read_fifo_spinlock);
237 rwlock_init(&pB->write_fifo_spinlock);
238 rwlock_init(&pB->Dbuf_spinlock);
239 rwlock_init(&pB->Bbuf_spinlock);
240 rwlock_init(&pB->Fbuf_spinlock);
241
242
243
244 pB->i2eChannelPtr = pCh;
245 pB->i2eChannelCnt = nChannels;
246
247 pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0;
248 pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0;
249 pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0;
250
251 pB->SendPendingRetry = 0;
252
253 memset ( pCh, 0, sizeof (i2ChanStr) * nChannels );
254
255 for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf);
256 nChannels && index < ABS_MOST_PORTS;
257 index++)
258 {
259 if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) {
260 continue;
261 }
262 rwlock_init(&pCh->Ibuf_spinlock);
263 rwlock_init(&pCh->Obuf_spinlock);
264 rwlock_init(&pCh->Cbuf_spinlock);
265 rwlock_init(&pCh->Pbuf_spinlock);
266
267
268 if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) {
269 pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT;
270 } else {
271 pCh->validity = CHANNEL_MAGIC;
272 }
273 pCh->pMyBord = pB;
274
275
276
277 if ( pCh->validity & CHANNEL_SUPPORT ) {
278 pCh->infl.hd.i2sChannel = index;
279 pCh->infl.hd.i2sCount = 5;
280 pCh->infl.hd.i2sType = PTYPE_BYPASS;
281 pCh->infl.fcmd = 37;
282 pCh->infl.asof = 0;
283 pCh->infl.room = IBUF_SIZE - 1;
284
285 pCh->whenSendFlow = (IBUF_SIZE/5)*4;
286
287
288
289
290 pCh->channelNeeds = NEED_FLOW;
291 pCh->sinceLastFlow = 0;
292
293 stuffIndex++;
294 *ppCh++ = pCh;
295
296 }
297
298
299
300
301 pCh->outfl.asof = 0;
302 pCh->outfl.room = 0;
303
304
305
306 pCh->Ibuf_stuff = pCh->Ibuf_strip = 0;
307 pCh->Obuf_stuff = pCh->Obuf_strip = 0;
308 pCh->Cbuf_stuff = pCh->Cbuf_strip = 0;
309
310 memset( &pCh->icount, 0, sizeof (struct async_icount) );
311 pCh->hotKeyIn = HOT_CLEAR;
312 pCh->channelOptions = 0;
313 pCh->bookMarks = 0;
314 init_waitqueue_head(&pCh->pBookmarkWait);
315
316 init_waitqueue_head(&pCh->open_wait);
317 init_waitqueue_head(&pCh->close_wait);
318 init_waitqueue_head(&pCh->delta_msr_wait);
319
320
321 pCh->BaudBase = 921600;
322 pCh->BaudDivisor = 96;
323
324 pCh->dataSetIn = 0;
325 pCh->dataSetOut = 0;
326
327 pCh->wopen = 0;
328 pCh->throttled = 0;
329
330 pCh->speed = CBR_9600;
331
332 pCh->flags = 0;
333
334 pCh->ClosingDelay = 5*HZ/10;
335 pCh->ClosingWaitTime = 30*HZ;
336
337
338 INIT_WORK(&pCh->tqueue_input, do_input);
339 INIT_WORK(&pCh->tqueue_status, do_status);
340
341#ifdef IP2DEBUG_TRACE
342 pCh->trace = ip2trace;
343#endif
344
345 ++pCh;
346 --nChannels;
347 }
348
349 pB->i2Fbuf_stuff = stuffIndex;
350 I2_COMPLETE(pB, I2EE_GOOD);
351
352}
353
354
355
356
357
358
359
360
361
362
363
364
365static i2ChanStrPtr
366i2DeQueueNeeds(i2eBordStrPtr pB, int type)
367{
368 unsigned short queueIndex;
369 unsigned long flags;
370
371 i2ChanStrPtr pCh = NULL;
372
373 switch(type) {
374
375 case NEED_INLINE:
376
377 write_lock_irqsave(&pB->Dbuf_spinlock, flags);
378 if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip)
379 {
380 queueIndex = pB->i2Dbuf_strip;
381 pCh = pB->i2Dbuf[queueIndex];
382 queueIndex++;
383 if (queueIndex >= CH_QUEUE_SIZE) {
384 queueIndex = 0;
385 }
386 pB->i2Dbuf_strip = queueIndex;
387 pCh->channelNeeds &= ~NEED_INLINE;
388 }
389 write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
390 break;
391
392 case NEED_BYPASS:
393
394 write_lock_irqsave(&pB->Bbuf_spinlock, flags);
395 if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip)
396 {
397 queueIndex = pB->i2Bbuf_strip;
398 pCh = pB->i2Bbuf[queueIndex];
399 queueIndex++;
400 if (queueIndex >= CH_QUEUE_SIZE) {
401 queueIndex = 0;
402 }
403 pB->i2Bbuf_strip = queueIndex;
404 pCh->channelNeeds &= ~NEED_BYPASS;
405 }
406 write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
407 break;
408
409 case NEED_FLOW:
410
411 write_lock_irqsave(&pB->Fbuf_spinlock, flags);
412 if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip)
413 {
414 queueIndex = pB->i2Fbuf_strip;
415 pCh = pB->i2Fbuf[queueIndex];
416 queueIndex++;
417 if (queueIndex >= CH_QUEUE_SIZE) {
418 queueIndex = 0;
419 }
420 pB->i2Fbuf_strip = queueIndex;
421 pCh->channelNeeds &= ~NEED_FLOW;
422 }
423 write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
424 break;
425 default:
426 printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type);
427 break;
428 }
429 return pCh;
430}
431
432
433
434
435
436
437
438
439
440
441
442
443static void
444i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
445{
446 unsigned short queueIndex;
447 unsigned long flags;
448
449
450
451
452 switch (type) {
453
454 case NEED_INLINE:
455
456 write_lock_irqsave(&pB->Dbuf_spinlock, flags);
457 if ( !(pCh->channelNeeds & NEED_INLINE) )
458 {
459 pCh->channelNeeds |= NEED_INLINE;
460 queueIndex = pB->i2Dbuf_stuff;
461 pB->i2Dbuf[queueIndex++] = pCh;
462 if (queueIndex >= CH_QUEUE_SIZE)
463 queueIndex = 0;
464 pB->i2Dbuf_stuff = queueIndex;
465 }
466 write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
467 break;
468
469 case NEED_BYPASS:
470
471 write_lock_irqsave(&pB->Bbuf_spinlock, flags);
472 if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS))
473 {
474 pCh->channelNeeds |= NEED_BYPASS;
475 queueIndex = pB->i2Bbuf_stuff;
476 pB->i2Bbuf[queueIndex++] = pCh;
477 if (queueIndex >= CH_QUEUE_SIZE)
478 queueIndex = 0;
479 pB->i2Bbuf_stuff = queueIndex;
480 }
481 write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
482 break;
483
484 case NEED_FLOW:
485
486 write_lock_irqsave(&pB->Fbuf_spinlock, flags);
487 if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW))
488 {
489 pCh->channelNeeds |= NEED_FLOW;
490 queueIndex = pB->i2Fbuf_stuff;
491 pB->i2Fbuf[queueIndex++] = pCh;
492 if (queueIndex >= CH_QUEUE_SIZE)
493 queueIndex = 0;
494 pB->i2Fbuf_stuff = queueIndex;
495 }
496 write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
497 break;
498
499 case NEED_CREDIT:
500 pCh->channelNeeds |= NEED_CREDIT;
501 break;
502 default:
503 printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type);
504 break;
505 }
506 return;
507}
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530static int
531i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
532 cmdSyntaxPtr pCs0,...)
533{
534 int totalsize = 0;
535 int blocksize;
536 int lastended;
537 cmdSyntaxPtr *ppCs;
538 cmdSyntaxPtr pCs;
539 int count;
540 int flag;
541 i2eBordStrPtr pB;
542
543 unsigned short maxBlock;
544 unsigned short maxBuff;
545 short bufroom;
546 unsigned short stuffIndex;
547 unsigned char *pBuf;
548 unsigned char *pInsert;
549 unsigned char *pDest, *pSource;
550 unsigned short channel;
551 int cnt;
552 unsigned long flags = 0;
553 rwlock_t *lock_var_p = NULL;
554
555
556 if ( !i2Validate ( pCh ) ) {
557 return -1;
558 }
559
560 ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 );
561
562 pB = pCh->pMyBord;
563
564
565 if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED)
566 return -2;
567
568
569 if (pB->i2eFatal) {
570 if ( pB->i2eFatalTrap ) {
571 (*(pB)->i2eFatalTrap)(pB);
572 }
573 return -3;
574 }
575
576 switch(type)
577 {
578 case PTYPE_INLINE:
579 flag = INL;
580 maxBlock = MAX_OBUF_BLOCK;
581 maxBuff = OBUF_SIZE;
582 pBuf = pCh->Obuf;
583 break;
584 case PTYPE_BYPASS:
585 flag = BYP;
586 maxBlock = MAX_CBUF_BLOCK;
587 maxBuff = CBUF_SIZE;
588 pBuf = pCh->Cbuf;
589 break;
590 default:
591 return -4;
592 }
593
594 totalsize = blocksize = sizeof(i2CmdHeader);
595 lastended = 0;
596 ppCs = &pCs0;
597 for ( count = nCommands; count; count--, ppCs++)
598 {
599 pCs = *ppCs;
600 cnt = pCs->length;
601
602
603
604 if ((blocksize + cnt > maxBlock) || lastended) {
605 blocksize = sizeof(i2CmdHeader);
606 totalsize += sizeof(i2CmdHeader);
607 }
608 totalsize += cnt;
609 blocksize += cnt;
610
611
612
613 lastended = pCs->flags & END;
614 }
615 for (;;) {
616
617 if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) {
618
619 switch(type) {
620 case PTYPE_INLINE:
621 lock_var_p = &pCh->Obuf_spinlock;
622 write_lock_irqsave(lock_var_p, flags);
623 stuffIndex = pCh->Obuf_stuff;
624 bufroom = pCh->Obuf_strip - stuffIndex;
625 break;
626 case PTYPE_BYPASS:
627 lock_var_p = &pCh->Cbuf_spinlock;
628 write_lock_irqsave(lock_var_p, flags);
629 stuffIndex = pCh->Cbuf_stuff;
630 bufroom = pCh->Cbuf_strip - stuffIndex;
631 break;
632 default:
633 return -5;
634 }
635 if (--bufroom < 0) {
636 bufroom += maxBuff;
637 }
638
639 ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom );
640
641
642 if (totalsize <= bufroom) {
643
644 break;
645 }
646 ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
647 write_unlock_irqrestore(lock_var_p, flags);
648 } else
649 ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
650
651
652 serviceOutgoingFifo(pB);
653
654 if (timeout == 0) {
655 return 0;
656 }
657 if (timeout > 0)
658 timeout--;
659
660 if (!in_interrupt()) {
661 schedule_timeout_interruptible(1);
662 } else {
663
664 return 0;
665 }
666 if (signal_pending(current)) {
667 return 0;
668 }
669
670 ip2trace (CHANN, ITRC_QUEUE, 4, 0 );
671
672 }
673
674
675 channel = pCh->infl.hd.i2sChannel;
676 pInsert = &pBuf[stuffIndex];
677 pDest = CMD_OF(pInsert);
678
679
680 for (blocksize = sizeof(i2CmdHeader), count = nCommands,
681 lastended = 0, ppCs = &pCs0;
682 count;
683 count--, ppCs++)
684 {
685 pCs = *ppCs;
686
687
688
689
690
691 if (pCs == CMD_BMARK_REQ) {
692 pCh->bookMarks++;
693
694 ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks );
695
696 }
697 cnt = pCs->length;
698
699
700
701
702 if ((blocksize + cnt > maxBlock) || lastended) {
703
704 ip2trace (CHANN, ITRC_QUEUE, 5, 0 );
705
706 PTYPE_OF(pInsert) = type;
707 CHANNEL_OF(pInsert) = channel;
708
709 CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
710 stuffIndex += blocksize;
711 if(stuffIndex >= maxBuff) {
712 stuffIndex = 0;
713 pInsert = pBuf;
714 }
715 pInsert = &pBuf[stuffIndex];
716 pDest = CMD_OF(pInsert);
717 blocksize = sizeof(i2CmdHeader);
718 }
719
720
721 blocksize += cnt;
722 pSource = pCs->cmd;
723 while (cnt--) {
724 *pDest++ = *pSource++;
725 }
726
727
728 lastended = pCs->flags & END;
729 }
730
731
732 PTYPE_OF(pInsert) = type;
733 CHANNEL_OF(pInsert) = channel;
734
735 CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
736 stuffIndex += blocksize;
737 if(stuffIndex >= maxBuff) {
738 stuffIndex = 0;
739 pInsert = pBuf;
740 }
741
742
743
744
745 switch(type)
746 {
747 case PTYPE_INLINE:
748 pCh->Obuf_stuff = stuffIndex;
749 write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
750
751 pB->debugInlineQueued++;
752
753
754 i2QueueNeeds(pB, pCh, NEED_INLINE);
755 break;
756
757 case PTYPE_BYPASS:
758 pCh->Cbuf_stuff = stuffIndex;
759 write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
760
761 pB->debugBypassQueued++;
762
763
764 i2QueueNeeds(pB, pCh, NEED_BYPASS);
765 break;
766 }
767
768 ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands );
769
770 return nCommands;
771}
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786static int
787i2GetStatus(i2ChanStrPtr pCh, int resetBits)
788{
789 unsigned short status;
790 i2eBordStrPtr pB;
791
792 ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits );
793
794
795 if ( !i2Validate ( pCh ) )
796 return -1;
797
798 pB = pCh->pMyBord;
799
800 status = pCh->dataSetIn;
801
802
803
804 if (resetBits)
805 {
806 pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR));
807 pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI);
808 }
809
810 ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn );
811
812 return status;
813}
814
815
816
817
818
819
820
821
822
823
824
825
826
827static int
828i2Input(i2ChanStrPtr pCh)
829{
830 int amountToMove;
831 unsigned short stripIndex;
832 int count;
833 unsigned long flags = 0;
834
835 ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0);
836
837
838 if ( !i2Validate( pCh ) ) {
839 count = -1;
840 goto i2Input_exit;
841 }
842 write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
843
844
845 stripIndex = pCh->Ibuf_strip;
846
847 count = pCh->Ibuf_stuff - stripIndex;
848
849
850
851 if ( count == 0 ) {
852 write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
853 goto i2Input_exit;
854 }
855
856 if ( count < 0 ) {
857 count += IBUF_SIZE;
858 }
859
860 amountToMove = pCh->pTTY->receive_room;
861 if (count > amountToMove) {
862 count = amountToMove;
863 }
864
865 amountToMove = IBUF_SIZE - stripIndex;
866
867 if (amountToMove > count) {
868 amountToMove = count;
869 }
870
871 pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
872 &(pCh->Ibuf[stripIndex]), NULL, amountToMove );
873
874 if (count > amountToMove) {
875 pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
876 pCh->Ibuf, NULL, count - amountToMove );
877 }
878
879
880 stripIndex += count;
881 if (stripIndex >= IBUF_SIZE) {
882 stripIndex -= IBUF_SIZE;
883 }
884 pCh->Ibuf_strip = stripIndex;
885
886
887
888
889 pCh->infl.asof += count;
890
891 if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) {
892 pCh->sinceLastFlow -= pCh->whenSendFlow;
893 write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
894 i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
895 } else {
896 write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
897 }
898
899i2Input_exit:
900
901 ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count);
902
903 return count;
904}
905
906
907
908
909
910
911
912
913
914
915
916static int
917i2InputFlush(i2ChanStrPtr pCh)
918{
919 int count;
920 unsigned long flags;
921
922
923 if ( !i2Validate ( pCh ) )
924 return -1;
925
926 ip2trace (CHANN, ITRC_INPUT, 10, 0);
927
928 write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
929 count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
930
931
932 if (count < 0) {
933 count += IBUF_SIZE;
934 }
935
936
937 pCh->Ibuf_strip = pCh->Ibuf_stuff;
938
939
940
941
942
943
944 pCh->infl.asof += count;
945
946 if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow )
947 {
948 pCh->sinceLastFlow -= pCh->whenSendFlow;
949 write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
950 i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
951 } else {
952 write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
953 }
954
955 ip2trace (CHANN, ITRC_INPUT, 19, 1, count);
956
957 return count;
958}
959
960
961
962
963
964
965
966
967
968
969
970#if 0
971static int
972i2InputAvailable(i2ChanStrPtr pCh)
973{
974 int count;
975
976
977 if ( !i2Validate ( pCh ) ) return -1;
978
979
980
981 read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
982 count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
983 read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
984
985
986 if (count < 0)
987 {
988 count += IBUF_SIZE;
989 }
990
991 return count;
992}
993#endif
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012static int
1013i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
1014{
1015 i2eBordStrPtr pB;
1016 unsigned char *pInsert;
1017 int amountToMove;
1018 int countOriginal = count;
1019 unsigned short channel;
1020 unsigned short stuffIndex;
1021 unsigned long flags;
1022
1023 int bailout = 10;
1024
1025 ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 );
1026
1027
1028 if ( !i2Validate ( pCh ) )
1029 return -1;
1030
1031
1032 pB = pCh->pMyBord;
1033 channel = pCh->infl.hd.i2sChannel;
1034
1035
1036
1037 if (pB->i2eFatal) {
1038 if (pB->i2eFatalTrap) {
1039 (*(pB)->i2eFatalTrap)(pB);
1040 }
1041 return -1;
1042 }
1043
1044 while ( count > 0 ) {
1045
1046
1047 read_lock_irqsave(&pCh->Obuf_spinlock, flags);
1048 amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
1049 read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
1050 if (amountToMove < 0) {
1051 amountToMove += OBUF_SIZE;
1052 }
1053
1054
1055 amountToMove -= sizeof (i2DataHeader);
1056
1057
1058 if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) {
1059 amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader);
1060 }
1061
1062 if (amountToMove > count) {
1063 amountToMove = count;
1064 }
1065
1066
1067
1068
1069
1070
1071
1072 ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove );
1073
1074 if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) )
1075 && amountToMove > 0 )
1076 {
1077 write_lock_irqsave(&pCh->Obuf_spinlock, flags);
1078 stuffIndex = pCh->Obuf_stuff;
1079
1080
1081
1082 pInsert = &(pCh->Obuf[stuffIndex]);
1083
1084
1085 CHANNEL_OF(pInsert) = channel;
1086 PTYPE_OF(pInsert) = PTYPE_DATA;
1087 TAG_OF(pInsert) = 0;
1088 ID_OF(pInsert) = ID_ORDINARY_DATA;
1089 DATA_COUNT_OF(pInsert) = amountToMove;
1090
1091
1092 memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
1093
1094 pSource += amountToMove;
1095 pCh->Obuf_char_count += amountToMove;
1096 stuffIndex += amountToMove + sizeof(i2DataHeader);
1097 count -= amountToMove;
1098
1099 if (stuffIndex >= OBUF_SIZE) {
1100 stuffIndex = 0;
1101 }
1102 pCh->Obuf_stuff = stuffIndex;
1103
1104 write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
1105
1106 ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );
1107
1108 } else {
1109
1110
1111
1112
1113
1114 ip2trace(CHANN, ITRC_OUTPUT, 14, 3,
1115 amountToMove, pB->i2eFifoRemains,
1116 pB->i2eWaitingForEmptyFifo );
1117
1118
1119
1120 i2QueueNeeds(pB, pCh, NEED_INLINE);
1121
1122 if ( pB->i2eWaitingForEmptyFifo ) {
1123
1124 ip2trace (CHANN, ITRC_OUTPUT, 16, 0 );
1125
1126
1127 if (!in_interrupt()) {
1128
1129 ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
1130
1131 schedule_timeout_interruptible(2);
1132 if (signal_pending(current)) {
1133 break;
1134 }
1135 continue;
1136 } else {
1137
1138 ip2trace (CHANN, ITRC_OUTPUT, 62, 0 );
1139
1140
1141
1142
1143 break;
1144 }
1145 break;
1146 }
1147 else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) )
1148 {
1149 ip2trace (CHANN, ITRC_OUTPUT, 19, 2,
1150 pB->i2eFifoRemains,
1151 pB->i2eTxMailEmpty );
1152
1153 break;
1154 } else if ( pCh->channelNeeds & NEED_CREDIT ) {
1155
1156 ip2trace (CHANN, ITRC_OUTPUT, 22, 0 );
1157
1158 break;
1159 } else if ( --bailout) {
1160
1161
1162
1163
1164 ip2trace (CHANN, ITRC_OUTPUT, 20, 0 );
1165
1166 serviceOutgoingFifo(pB);
1167
1168 } else {
1169 ip2trace (CHANN, ITRC_OUTPUT, 21, 3,
1170 pB->i2eFifoRemains,
1171 pB->i2eOutMailWaiting,
1172 pB->i2eWaitingForEmptyFifo );
1173
1174 break;
1175 }
1176 }
1177 }
1178
1179 i2QueueNeeds(pB, pCh, NEED_INLINE);
1180
1181
1182
1183 if (countOriginal > count) {
1184
1185 ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count );
1186
1187 serviceOutgoingFifo( pB );
1188 }
1189
1190 ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count );
1191
1192 return countOriginal - count;
1193}
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205static inline void
1206i2FlushOutput(i2ChanStrPtr pCh)
1207{
1208
1209 ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags );
1210
1211 if (pCh->flush_flags)
1212 return;
1213
1214 if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
1215 pCh->flush_flags = STARTFL_FLAG;
1216
1217 ip2trace (CHANN, ITRC_FLUSH, 2, 0 );
1218
1219 } else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) {
1220 pCh->flush_flags = STOPFL_FLAG;
1221
1222 ip2trace (CHANN, ITRC_FLUSH, 3, 0 );
1223 }
1224}
1225
1226static int
1227i2RetryFlushOutput(i2ChanStrPtr pCh)
1228{
1229 int old_flags = pCh->flush_flags;
1230
1231 ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags );
1232
1233 pCh->flush_flags = 0;
1234
1235
1236 if ( old_flags & STARTFL_FLAG ) {
1237 if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
1238 old_flags = STOPFL_FLAG;
1239 } else {
1240 old_flags = STARTFL_FLAG;
1241 }
1242
1243 ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags );
1244
1245 }
1246 if ( old_flags & STOPFL_FLAG ) {
1247 if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) {
1248 old_flags = 0;
1249 }
1250
1251 ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags );
1252 }
1253 pCh->flush_flags = old_flags;
1254
1255 ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags );
1256
1257 return old_flags;
1258}
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270static void
1271i2DrainWakeup(unsigned long d)
1272{
1273 i2ChanStrPtr pCh = (i2ChanStrPtr)d;
1274
1275 ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );
1276
1277 pCh->BookmarkTimer.expires = 0;
1278 wake_up_interruptible( &pCh->pBookmarkWait );
1279}
1280
1281static void
1282i2DrainOutput(i2ChanStrPtr pCh, int timeout)
1283{
1284 wait_queue_t wait;
1285 i2eBordStrPtr pB;
1286
1287 ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires);
1288
1289 pB = pCh->pMyBord;
1290
1291
1292 if (pB->i2eFatal) {
1293 if (pB->i2eFatalTrap) {
1294 (*(pB)->i2eFatalTrap)(pB);
1295 }
1296 return;
1297 }
1298 if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {
1299
1300 setup_timer(&pCh->BookmarkTimer, i2DrainWakeup,
1301 (unsigned long)pCh);
1302
1303 ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );
1304
1305 mod_timer(&pCh->BookmarkTimer, jiffies + timeout);
1306 }
1307
1308 i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );
1309
1310 init_waitqueue_entry(&wait, current);
1311 add_wait_queue(&(pCh->pBookmarkWait), &wait);
1312 set_current_state( TASK_INTERRUPTIBLE );
1313
1314 serviceOutgoingFifo( pB );
1315
1316 schedule();
1317
1318
1319 set_current_state( TASK_RUNNING );
1320 remove_wait_queue(&(pCh->pBookmarkWait), &wait);
1321
1322
1323 if ((timeout > 0) && pCh->BookmarkTimer.expires &&
1324 time_before(jiffies, pCh->BookmarkTimer.expires)) {
1325 del_timer( &(pCh->BookmarkTimer) );
1326 pCh->BookmarkTimer.expires = 0;
1327
1328 ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires );
1329
1330 }
1331 ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires );
1332 return;
1333}
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344static int
1345i2OutputFree(i2ChanStrPtr pCh)
1346{
1347 int amountToMove;
1348 unsigned long flags;
1349
1350
1351 if ( !i2Validate ( pCh ) ) {
1352 return -1;
1353 }
1354 read_lock_irqsave(&pCh->Obuf_spinlock, flags);
1355 amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
1356 read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
1357
1358 if (amountToMove < 0) {
1359 amountToMove += OBUF_SIZE;
1360 }
1361
1362 amountToMove -= sizeof(i2DataHeader);
1363
1364 return (amountToMove < 0) ? 0 : amountToMove;
1365}
1366static void
1367
1368ip2_owake( PTTY tp)
1369{
1370 i2ChanStrPtr pCh;
1371
1372 if (tp == NULL) return;
1373
1374 pCh = tp->driver_data;
1375
1376 ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags,
1377 (1 << TTY_DO_WRITE_WAKEUP) );
1378
1379 tty_wakeup(tp);
1380}
1381
1382static inline void
1383set_baud_params(i2eBordStrPtr pB)
1384{
1385 int i,j;
1386 i2ChanStrPtr *pCh;
1387
1388 pCh = (i2ChanStrPtr *) pB->i2eChannelPtr;
1389
1390 for (i = 0; i < ABS_MAX_BOXES; i++) {
1391 if (pB->channelBtypes.bid_value[i]) {
1392 if (BID_HAS_654(pB->channelBtypes.bid_value[i])) {
1393 for (j = 0; j < ABS_BIGGEST_BOX; j++) {
1394 if (pCh[i*16+j] == NULL)
1395 break;
1396 (pCh[i*16+j])->BaudBase = 921600;
1397 (pCh[i*16+j])->BaudDivisor = 96;
1398 }
1399 } else {
1400 for (j = 0; j < ABS_BIGGEST_BOX; j++) {
1401 if (pCh[i*16+j] == NULL)
1402 break;
1403 (pCh[i*16+j])->BaudBase = 115200;
1404 (pCh[i*16+j])->BaudDivisor = 12;
1405 }
1406 }
1407 }
1408 }
1409}
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425static unsigned char junkBuffer[IBUF_SIZE];
1426
1427
1428
1429static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4];
1430
1431
1432
1433static char xlatDss[16] = {
14340 | 0 | 0 | 0 ,
14350 | 0 | 0 | I2_CTS ,
14360 | 0 | I2_DSR | 0 ,
14370 | 0 | I2_DSR | I2_CTS ,
14380 | I2_RI | 0 | 0 ,
14390 | I2_RI | 0 | I2_CTS ,
14400 | I2_RI | I2_DSR | 0 ,
14410 | I2_RI | I2_DSR | I2_CTS ,
1442I2_DCD | 0 | 0 | 0 ,
1443I2_DCD | 0 | 0 | I2_CTS ,
1444I2_DCD | 0 | I2_DSR | 0 ,
1445I2_DCD | 0 | I2_DSR | I2_CTS ,
1446I2_DCD | I2_RI | 0 | 0 ,
1447I2_DCD | I2_RI | 0 | I2_CTS ,
1448I2_DCD | I2_RI | I2_DSR | 0 ,
1449I2_DCD | I2_RI | I2_DSR | I2_CTS };
1450
1451static inline void
1452i2StripFifo(i2eBordStrPtr pB)
1453{
1454 i2ChanStrPtr pCh;
1455 int channel;
1456 int count;
1457 unsigned short stuffIndex;
1458 int amountToRead;
1459 unsigned char *pc, *pcLimit;
1460 unsigned char uc;
1461 unsigned char dss_change;
1462 unsigned long bflags,cflags;
1463
1464
1465
1466 while (I2_HAS_INPUT(pB)) {
1467
1468
1469
1470 write_lock_irqsave(&pB->read_fifo_spinlock, bflags);
1471
1472
1473
1474 pB->i2eLeadoffWord[0] = iiReadWord(pB);
1475
1476 switch(PTYPE_OF(pB->i2eLeadoffWord))
1477 {
1478 case PTYPE_DATA:
1479 pB->got_input = 1;
1480
1481
1482
1483 channel = CHANNEL_OF(pB->i2eLeadoffWord);
1484 count = iiReadWord(pB);
1485
1486
1487
1488
1489
1490 if ( ((unsigned int)count) > IBUF_SIZE ) {
1491 pB->i2eFatal = 2;
1492 write_unlock_irqrestore(&pB->read_fifo_spinlock,
1493 bflags);
1494 return;
1495 }
1496
1497 if ((channel >= pB->i2eChannelCnt) ||
1498 (NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])))
1499 {
1500 iiReadBuf(pB, junkBuffer, count);
1501 write_unlock_irqrestore(&pB->read_fifo_spinlock,
1502 bflags);
1503 break;
1504 }
1505
1506
1507
1508
1509
1510
1511
1512
1513 if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY)
1514 {
1515 pCh->hotKeyIn = iiReadWord(pB) & 0xff;
1516 write_unlock_irqrestore(&pB->read_fifo_spinlock,
1517 bflags);
1518 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK);
1519 break;
1520 }
1521
1522
1523
1524 write_lock_irqsave(&pCh->Ibuf_spinlock, cflags);
1525
1526 stuffIndex = pCh->Ibuf_stuff;
1527 amountToRead = IBUF_SIZE - stuffIndex;
1528 if (amountToRead > count)
1529 amountToRead = count;
1530
1531
1532
1533
1534
1535 iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
1536 pCh->icount.rx += amountToRead;
1537
1538
1539
1540
1541
1542
1543
1544
1545 stuffIndex += amountToRead;
1546
1547 if (stuffIndex >= IBUF_SIZE) {
1548 if ((amountToRead & 1) && (count > amountToRead)) {
1549 pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE];
1550 amountToRead++;
1551 stuffIndex = 1;
1552 } else {
1553 stuffIndex = 0;
1554 }
1555 }
1556
1557
1558 if (count > amountToRead) {
1559 amountToRead = count - amountToRead;
1560 iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
1561 pCh->icount.rx += amountToRead;
1562 stuffIndex += amountToRead;
1563 }
1564
1565
1566 pCh->Ibuf_stuff = stuffIndex;
1567 write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags);
1568 write_unlock_irqrestore(&pB->read_fifo_spinlock,
1569 bflags);
1570
1571#ifdef USE_IQ
1572 schedule_work(&pCh->tqueue_input);
1573#else
1574 do_input(&pCh->tqueue_input);
1575#endif
1576
1577
1578
1579
1580
1581
1582 break;
1583
1584 case PTYPE_STATUS:
1585 ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 );
1586
1587 count = CMD_COUNT_OF(pB->i2eLeadoffWord);
1588
1589 iiReadBuf(pB, cmdBuffer, count);
1590
1591 write_unlock_irqrestore(&pB->read_fifo_spinlock,
1592 bflags);
1593
1594 pc = cmdBuffer;
1595 pcLimit = &(cmdBuffer[count]);
1596
1597 while (pc < pcLimit) {
1598 channel = *pc++;
1599
1600 ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc );
1601
1602
1603 if (channel < pB->i2eChannelCnt
1604 &&
1605 (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL
1606 )
1607 {
1608 dss_change = 0;
1609
1610 switch (uc = *pc++)
1611 {
1612
1613 case STAT_CTS_UP:
1614 if ( !(pCh->dataSetIn & I2_CTS) )
1615 {
1616 pCh->dataSetIn |= I2_DCTS;
1617 pCh->icount.cts++;
1618 dss_change = 1;
1619 }
1620 pCh->dataSetIn |= I2_CTS;
1621 break;
1622
1623 case STAT_CTS_DN:
1624 if ( pCh->dataSetIn & I2_CTS )
1625 {
1626 pCh->dataSetIn |= I2_DCTS;
1627 pCh->icount.cts++;
1628 dss_change = 1;
1629 }
1630 pCh->dataSetIn &= ~I2_CTS;
1631 break;
1632
1633 case STAT_DCD_UP:
1634 ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn );
1635
1636 if ( !(pCh->dataSetIn & I2_DCD) )
1637 {
1638 ip2trace (CHANN, ITRC_MODEM, 2, 0 );
1639 pCh->dataSetIn |= I2_DDCD;
1640 pCh->icount.dcd++;
1641 dss_change = 1;
1642 }
1643 pCh->dataSetIn |= I2_DCD;
1644
1645 ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn );
1646 break;
1647
1648 case STAT_DCD_DN:
1649 ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn );
1650 if ( pCh->dataSetIn & I2_DCD )
1651 {
1652 ip2trace (channel, ITRC_MODEM, 5, 0 );
1653 pCh->dataSetIn |= I2_DDCD;
1654 pCh->icount.dcd++;
1655 dss_change = 1;
1656 }
1657 pCh->dataSetIn &= ~I2_DCD;
1658
1659 ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn );
1660 break;
1661
1662 case STAT_DSR_UP:
1663 if ( !(pCh->dataSetIn & I2_DSR) )
1664 {
1665 pCh->dataSetIn |= I2_DDSR;
1666 pCh->icount.dsr++;
1667 dss_change = 1;
1668 }
1669 pCh->dataSetIn |= I2_DSR;
1670 break;
1671
1672 case STAT_DSR_DN:
1673 if ( pCh->dataSetIn & I2_DSR )
1674 {
1675 pCh->dataSetIn |= I2_DDSR;
1676 pCh->icount.dsr++;
1677 dss_change = 1;
1678 }
1679 pCh->dataSetIn &= ~I2_DSR;
1680 break;
1681
1682 case STAT_RI_UP:
1683 if ( !(pCh->dataSetIn & I2_RI) )
1684 {
1685 pCh->dataSetIn |= I2_DRI;
1686 pCh->icount.rng++;
1687 dss_change = 1;
1688 }
1689 pCh->dataSetIn |= I2_RI ;
1690 break;
1691
1692 case STAT_RI_DN:
1693
1694
1695
1696
1697
1698
1699
1700 pCh->dataSetIn &= ~I2_RI ;
1701 break;
1702
1703 case STAT_BRK_DET:
1704 pCh->dataSetIn |= I2_BRK;
1705 pCh->icount.brk++;
1706 dss_change = 1;
1707 break;
1708
1709
1710 case STAT_BMARK:
1711 pCh->bookMarks--;
1712 if (pCh->bookMarks <= 0 ) {
1713 pCh->bookMarks = 0;
1714 wake_up_interruptible( &pCh->pBookmarkWait );
1715
1716 ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires );
1717 }
1718 break;
1719
1720
1721
1722 case STAT_FLOW:
1723 pCh->outfl.room =
1724 ((flowStatPtr)pc)->room -
1725 (pCh->outfl.asof - ((flowStatPtr)pc)->asof);
1726
1727 ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room );
1728
1729 if (pCh->channelNeeds & NEED_CREDIT)
1730 {
1731 ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds);
1732
1733 pCh->channelNeeds &= ~NEED_CREDIT;
1734 i2QueueNeeds(pB, pCh, NEED_INLINE);
1735 if ( pCh->pTTY )
1736 ip2_owake(pCh->pTTY);
1737 }
1738
1739 ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds);
1740
1741 pc += sizeof(flowStat);
1742 break;
1743
1744
1745
1746
1747 case STAT_STATUS:
1748
1749 pCh->channelStatus = *((debugStatPtr)pc);
1750 pc += sizeof(debugStat);
1751 break;
1752
1753 case STAT_TXCNT:
1754
1755 pCh->channelTcount = *((cntStatPtr)pc);
1756 pc += sizeof(cntStat);
1757 break;
1758
1759 case STAT_RXCNT:
1760
1761 pCh->channelRcount = *((cntStatPtr)pc);
1762 pc += sizeof(cntStat);
1763 break;
1764
1765 case STAT_BOXIDS:
1766 pB->channelBtypes = *((bidStatPtr)pc);
1767 pc += sizeof(bidStat);
1768 set_baud_params(pB);
1769 break;
1770
1771 case STAT_HWFAIL:
1772 i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST);
1773 pCh->channelFail = *((failStatPtr)pc);
1774 pc += sizeof(failStat);
1775 break;
1776
1777
1778
1779
1780 default:
1781 switch (uc & STAT_MOD_ERROR)
1782 {
1783 case STAT_ERROR:
1784 if (uc & STAT_E_PARITY) {
1785 pCh->dataSetIn |= I2_PAR;
1786 pCh->icount.parity++;
1787 }
1788 if (uc & STAT_E_FRAMING){
1789 pCh->dataSetIn |= I2_FRA;
1790 pCh->icount.frame++;
1791 }
1792 if (uc & STAT_E_OVERRUN){
1793 pCh->dataSetIn |= I2_OVR;
1794 pCh->icount.overrun++;
1795 }
1796 break;
1797
1798 case STAT_MODEM:
1799
1800 pCh->dataSetIn = (pCh->dataSetIn
1801 & ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) )
1802 | xlatDss[uc & 0xf];
1803 wake_up_interruptible ( &pCh->dss_now_wait );
1804 default:
1805 break;
1806 }
1807 }
1808 if (dss_change) {
1809#ifdef USE_IQ
1810 schedule_work(&pCh->tqueue_status);
1811#else
1812 do_status(&pCh->tqueue_status);
1813#endif
1814 }
1815 }
1816 else
1817 {
1818
1819
1820
1821 switch (*pc++)
1822 {
1823 case STAT_FLOW:
1824 pc += 4;
1825 break;
1826
1827 default:
1828 break;
1829 }
1830 }
1831 }
1832 break;
1833
1834 default:
1835 ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1,
1836 PTYPE_OF(pB->i2eLeadoffWord) );
1837 write_unlock_irqrestore(&pB->read_fifo_spinlock,
1838 bflags);
1839
1840 break;
1841 }
1842 }
1843
1844 ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 );
1845
1846
1847 pB->i2eOutMailWaiting |= MB_IN_STRIPPED;
1848 return;
1849}
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860static int
1861i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve)
1862{
1863 int rc = 0;
1864 unsigned long flags;
1865 write_lock_irqsave(&pB->write_fifo_spinlock, flags);
1866 if (!pB->i2eWaitingForEmptyFifo) {
1867 if (pB->i2eFifoRemains > (count+reserve)) {
1868 pB->i2eFifoRemains -= count;
1869 iiWriteBuf(pB, source, count);
1870 pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
1871 rc = count;
1872 }
1873 }
1874 write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
1875 return rc;
1876}
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887static inline void
1888i2StuffFifoBypass(i2eBordStrPtr pB)
1889{
1890 i2ChanStrPtr pCh;
1891 unsigned char *pRemove;
1892 unsigned short stripIndex;
1893 unsigned short packetSize;
1894 unsigned short paddedSize;
1895 unsigned short notClogged = 1;
1896 unsigned long flags;
1897
1898 int bailout = 1000;
1899
1900
1901
1902 while ( --bailout && notClogged &&
1903 (NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS))))
1904 {
1905 write_lock_irqsave(&pCh->Cbuf_spinlock, flags);
1906 stripIndex = pCh->Cbuf_strip;
1907
1908
1909
1910 while (stripIndex != pCh->Cbuf_stuff) {
1911 pRemove = &(pCh->Cbuf[stripIndex]);
1912 packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader);
1913 paddedSize = roundup(packetSize, 2);
1914
1915 if (paddedSize > 0) {
1916 if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) {
1917 notClogged = 0;
1918 i2QueueNeeds(pB, pCh, NEED_BYPASS);
1919 break;
1920 }
1921 }
1922#ifdef DEBUG_FIFO
1923WriteDBGBuf("BYPS", pRemove, paddedSize);
1924#endif
1925 pB->debugBypassCount++;
1926
1927 pRemove += packetSize;
1928 stripIndex += packetSize;
1929 if (stripIndex >= CBUF_SIZE) {
1930 stripIndex = 0;
1931 pRemove = pCh->Cbuf;
1932 }
1933 }
1934
1935
1936 pCh->Cbuf_strip = stripIndex;
1937 write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
1938 }
1939
1940#ifdef IP2DEBUG_TRACE
1941 if ( !bailout ) {
1942 ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 );
1943 }
1944#endif
1945}
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957static inline void
1958i2StuffFifoFlow(i2eBordStrPtr pB)
1959{
1960 i2ChanStrPtr pCh;
1961 unsigned short paddedSize = roundup(sizeof(flowIn), 2);
1962
1963 ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2,
1964 pB->i2eFifoRemains, paddedSize );
1965
1966
1967
1968 while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) {
1969 pB->debugFlowCount++;
1970
1971
1972 if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) {
1973 break;
1974 }
1975#ifdef DEBUG_FIFO
1976 WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize);
1977#endif
1978
1979 }
1980
1981 ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 );
1982}
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994static inline void
1995i2StuffFifoInline(i2eBordStrPtr pB)
1996{
1997 i2ChanStrPtr pCh;
1998 unsigned char *pRemove;
1999 unsigned short stripIndex;
2000 unsigned short packetSize;
2001 unsigned short paddedSize;
2002 unsigned short notClogged = 1;
2003 unsigned short flowsize;
2004 unsigned long flags;
2005
2006 int bailout = 1000;
2007 int bailout2;
2008
2009 ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains,
2010 pB->i2Dbuf_strip, pB->i2Dbuf_stuff );
2011
2012
2013
2014 while ( --bailout && notClogged &&
2015 (NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) )
2016 {
2017 write_lock_irqsave(&pCh->Obuf_spinlock, flags);
2018 stripIndex = pCh->Obuf_strip;
2019
2020 ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff );
2021
2022
2023 bailout2 = 1000;
2024 while ( --bailout2 && stripIndex != pCh->Obuf_stuff) {
2025 pRemove = &(pCh->Obuf[stripIndex]);
2026
2027
2028
2029
2030 if (PTYPE_OF(pRemove) == PTYPE_DATA) {
2031 flowsize = DATA_COUNT_OF(pRemove);
2032 packetSize = flowsize + sizeof(i2DataHeader);
2033 } else {
2034 flowsize = CMD_COUNT_OF(pRemove);
2035 packetSize = flowsize + sizeof(i2CmdHeader);
2036 }
2037 flowsize = CREDIT_USAGE(flowsize);
2038 paddedSize = roundup(packetSize, 2);
2039
2040 ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize );
2041
2042
2043
2044
2045
2046
2047 ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize );
2048
2049 if (pCh->outfl.room <= flowsize) {
2050
2051 i2QueueNeeds(pB, pCh, NEED_CREDIT);
2052 notClogged = 0;
2053 break;
2054 }
2055 if ( (paddedSize > 0)
2056 && ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) {
2057
2058 notClogged = 0;
2059 i2QueueNeeds(pB, pCh, NEED_INLINE);
2060 break;
2061 }
2062#ifdef DEBUG_FIFO
2063WriteDBGBuf("DATA", pRemove, paddedSize);
2064#endif
2065 pB->debugInlineCount++;
2066
2067 pCh->icount.tx += flowsize;
2068
2069 pCh->outfl.room -= flowsize;
2070 pCh->outfl.asof += flowsize;
2071 if (PTYPE_OF(pRemove) == PTYPE_DATA) {
2072 pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove);
2073 }
2074 pRemove += packetSize;
2075 stripIndex += packetSize;
2076
2077 ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip);
2078
2079 if (stripIndex >= OBUF_SIZE) {
2080 stripIndex = 0;
2081 pRemove = pCh->Obuf;
2082
2083 ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex );
2084
2085 }
2086 }
2087 if ( !bailout2 ) {
2088 ip2trace (CHANN, ITRC_ERROR, 3, 0 );
2089 }
2090
2091
2092 pCh->Obuf_strip = stripIndex;
2093 write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
2094 if ( notClogged )
2095 {
2096
2097 ip2trace (CHANN, ITRC_SICMD, 8, 0 );
2098
2099 if ( pCh->pTTY ) {
2100 ip2_owake(pCh->pTTY);
2101 }
2102 }
2103 }
2104
2105 if ( !bailout ) {
2106 ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 );
2107 }
2108
2109 ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip);
2110}
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125static void
2126serviceOutgoingFifo(i2eBordStrPtr pB)
2127{
2128
2129
2130
2131 if ( ! pB->i2eWaitingForEmptyFifo )
2132 {
2133 i2StuffFifoFlow(pB);
2134 i2StuffFifoBypass(pB);
2135 i2StuffFifoInline(pB);
2136
2137 iiSendPendingMail(pB);
2138 }
2139}
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166static inline int
2167i2ServiceBoard ( i2eBordStrPtr pB )
2168{
2169 unsigned inmail;
2170 unsigned long flags;
2171
2172
2173
2174 if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) {
2175 inmail = iiGetMail(pB);
2176 }
2177 pB->i2eStartMail = NO_MAIL_HERE;
2178
2179 ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail );
2180
2181 if (inmail != NO_MAIL_HERE) {
2182
2183
2184 if ( inmail & MB_FATAL_ERROR ) {
2185 pB->i2eFatal = 1;
2186 goto exit_i2ServiceBoard;
2187 }
2188
2189
2190 if ( inmail & MB_IN_STUFFED ) {
2191 pB->i2eFifoInInts++;
2192 i2StripFifo(pB);
2193 }
2194
2195 if (inmail & MB_OUT_STRIPPED) {
2196 pB->i2eFifoOutInts++;
2197 write_lock_irqsave(&pB->write_fifo_spinlock, flags);
2198 pB->i2eFifoRemains = pB->i2eFifoSize;
2199 pB->i2eWaitingForEmptyFifo = 0;
2200 write_unlock_irqrestore(&pB->write_fifo_spinlock,
2201 flags);
2202
2203 ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains );
2204
2205 }
2206 serviceOutgoingFifo(pB);
2207 }
2208
2209 ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 );
2210
2211exit_i2ServiceBoard:
2212
2213 return 0;
2214}
2215