This source file includes following definitions.
- max
- wd_start
- wd8003_open
- wdget
- wd8003_start_xmit
- wd_put_bnd
- wd_get_bnd
- wd_get_cur
- wd_rcv
- wd_rx_over
- wd_trs
- wd8003_interrupt
- wd8003_init
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 #include <linux/config.h>
85 #include <linux/kernel.h>
86 #include <linux/sched.h>
87 #include <linux/fs.h>
88 #include <linux/tty.h>
89 #include <linux/types.h>
90 #include <linux/ptrace.h>
91 #include <linux/string.h>
92 #include <asm/system.h>
93 #include <asm/segment.h>
94 #include <asm/io.h>
95 #include <errno.h>
96 #include <linux/fcntl.h>
97 #include <netinet/in.h>
98 #include <linux/interrupt.h>
99
100 #include "dev.h"
101 #include "eth.h"
102 #include "timer.h"
103 #include "ip.h"
104 #include "tcp.h"
105 #include "sock.h"
106 #include "arp.h"
107
108 #include "wereg.h"
109
110 static unsigned char interrupt_mask;
111
112 static struct enet_statistics stats;
113 static unsigned char max_pages;
114 static unsigned char wd_debug = 0;
115 static unsigned char dconfig = WD_DCONFIG;
116 static int tx_aborted = 0;
117
118 static void wd_trs (struct device *);
119
120 static int
121 max(int a, int b)
122 {
123 if (a>b) return (a);
124 return (b);
125 }
126
127 static void
128 wd_start(struct device *dev)
129 {
130 unsigned char cmd;
131 interrupt_mask=RECV_MASK|TRANS_MASK;
132 cli();
133 cmd = inb_p(WD_COMM);
134 cmd &= ~(CSTOP|CPAGE);
135 cmd |= CSTART;
136 outb_p(cmd, WD_COMM);
137 outb_p(interrupt_mask,WD_IMR);
138 sti();
139 dev->start = 1;
140 }
141
142 int
143 wd8003_open(struct device *dev)
144 {
145 unsigned char cmd;
146 int i;
147
148 cli();
149
150
151
152
153 cmd=inb_p(WD_COMM);
154 cmd|=CSTOP;
155 cmd &= ~(CSTART|CPAGE);
156 outb_p(cmd, WD_COMM);
157 outb_p(0, WD_IMR);
158 sti();
159 outb_p( dconfig,WD_DCR);
160
161 outb_p(0, WD_RBY0);
162 outb_p(0, WD_RBY1);
163 outb_p(WD_MCONFIG,WD_RCC);
164 outb_p(WD_TCONFIG,WD_TRC);
165 outb_p(0,WD_TRPG);
166 outb_p( max_pages,WD_PSTOP);
167 outb_p(WD_TXBS,WD_PSTRT);
168 outb_p(WD_TXBS,WD_BNDR);
169
170 outb_p(0xff,WD_ISR);
171
172 outb_p(0 ,WD_IMR);
173 cmd|=1<<CPAGE_SHIFT;
174 outb_p(cmd,WD_COMM);
175
176 for (i=0; i < ETHER_ADDR_LEN; i++)
177 {
178 outb_p(dev->dev_addr[i],WD_PAR0+i);
179 }
180
181 outb_p(WD_TXBS+1,WD_CUR);
182
183 for (i=0; i < ETHER_ADDR_LEN; i++)
184 {
185 outb_p(dev->broadcast[i],WD_MAR0+i);
186 }
187
188 cmd&=~(CPAGE|CRDMA);
189 cmd|= 4<<CRDMA_SHIFT;
190 outb_p(cmd, WD_COMM);
191 outb_p(WD_RCONFIG,WD_RCC);
192 wd_start(dev);
193 return (0);
194 }
195
196
197 static int
198 wdget(volatile struct wd_ring *ring, struct device *dev)
199 {
200 unsigned char *fptr;
201 long len;
202 fptr = (unsigned char *)(ring +1);
203
204
205
206 len = ring->count-4;
207 if (len < 56)
208 printk ("we.c: Hardware problem, runt packet. ring->count = %d\n",
209 ring->count);
210 return (dev_rint(fptr, len, 0, dev));
211 }
212
213 int
214 wd8003_start_xmit(struct sk_buff *skb, struct device *dev)
215 {
216 unsigned char cmd;
217 int len;
218
219 cli();
220 if (dev->tbusy)
221 {
222
223 if (jiffies - dev->trans_start < 30)
224 {
225 sti();
226 return (1);
227 }
228
229 printk ("wd8003 transmit timed out. \n");
230 }
231 dev->tbusy = 1;
232
233 if (skb == NULL)
234 {
235 sti();
236 wd_trs(dev);
237 return (0);
238 }
239
240
241 if (skb->dev != dev)
242 {
243 sti();
244 return (0);
245 }
246
247
248 if (!skb->arp)
249 {
250 if ( dev->rebuild_header (skb+1, dev))
251 {
252 cli();
253 if (skb->dev == dev)
254 {
255 arp_queue (skb);
256 }
257 cli ();
258 dev->tbusy = 0;
259 sti();
260 return (0);
261 }
262 }
263
264 memcpy ((unsigned char *)dev->mem_start, skb+1, skb->len);
265
266 len = skb->len;
267
268
269 dev->trans_start = jiffies;
270 len=max(len, ETHER_MIN_LEN);
271
272
273
274 cmd=inb_p(WD_COMM);
275 cmd &= ~CPAGE;
276 outb_p(cmd, WD_COMM);
277
278 interrupt_mask |= TRANS_MASK;
279 if (!(dev->interrupt))
280 outb (interrupt_mask, WD_IMR);
281
282 outb_p(len&0xff,WD_TB0);
283 outb_p(len>>8,WD_TB1);
284 cmd |= CTRANS;
285 outb_p(cmd,WD_COMM);
286 sti();
287
288 if (skb->free)
289 {
290 kfree_skb (skb, FREE_WRITE);
291 }
292
293 return (0);
294 }
295
296
297
298 static void
299 wd_put_bnd(unsigned char bnd, struct device *dev )
300 {
301
302 unsigned char cmd;
303
304
305 cmd = inb_p( CR );
306 if (cmd & 0x40) {
307 outb_p(cmd & (~CPAGE1), WD_COMM);
308 outb_p(bnd, WD_BNDR);
309 outb_p(cmd | CPAGE1, WD_COMM);
310 } else {
311 outb_p(bnd, WD_BNDR);
312 }
313 }
314
315 static unsigned char
316 wd_get_bnd( struct device *dev )
317 {
318
319 unsigned char cmd, bnd;
320
321
322 cmd = inb_p(WD_COMM);
323 if (cmd & 0x40) {
324 outb_p(cmd & (~CPAGE1), WD_COMM);
325 bnd = inb_p(WD_BNDR);
326 outb_p(cmd | CPAGE1, WD_COMM);
327 return (bnd);
328 } else {
329 return (inb_p(WD_BNDR));
330 }
331 }
332
333 static unsigned char
334 wd_get_cur( struct device *dev )
335 {
336
337 unsigned char cmd, cur;
338
339
340 cmd = inb_p(WD_COMM);
341 if (cmd & 0x40) {
342 return (inb_p(WD_CUR));
343 } else {
344 outb_p(cmd | CPAGE1, WD_COMM);
345 cur = inb_p(WD_CUR);
346 outb_p(cmd & (~CPAGE1), WD_COMM);
347 return (cur);
348 }
349 }
350
351
352
353
354
355 static void
356 wd_rcv( struct device *dev )
357 {
358
359 unsigned char pkt;
360 unsigned char bnd;
361 unsigned char cur;
362 unsigned char cmd;
363 volatile struct wd_ring *ring;
364 int done=0;
365
366
367 cur = wd_get_cur( dev );
368 bnd = wd_get_bnd( dev );
369 if( (pkt = bnd + 1) == max_pages )
370 pkt = WD_TXBS;
371
372 while( done != 1)
373 {
374 if (pkt != cur)
375 {
376
377
378 ring = (volatile struct wd_ring *) (dev->mem_start + (pkt << 8));
379
380
381 if( ring->status & 1 )
382 {
383
384
385 if( wd_debug )
386 printk("\nwd8013 - wdget: bnd = %d, pkt = %d, "
387 "cur = %d, status = %d, len = %d, next = %d",
388 bnd, pkt, cur, ring->status, ring->count,
389 ring->next);
390
391 stats.rx_packets++;
392 done = wdget( ring, dev );
393
394
395 pkt = ring->next;
396
397
398 if( (bnd = pkt - 1) < WD_TXBS )
399 bnd = max_pages - 1;
400 wd_put_bnd(bnd, dev);
401
402
403 cur = wd_get_cur(dev);
404 }
405 else
406 {
407
408 printk("wd8013 - bad packet: len = %d, status = x%x, "
409 "bnd = %d, pkt = %d, cur = %d\n"
410 "trashing receive buffer!",
411 ring->count, ring->status, bnd, pkt,
412 cur);
413
414 if( ( bnd = wd_get_cur( dev ) - 1 ) < WD_TXBS )
415 bnd = max_pages - 1;
416 wd_put_bnd( bnd, dev );
417 break;
418 }
419
420 }
421 else
422 {
423 done = dev_rint(NULL, 0,0, dev);
424 }
425 }
426
427
428 cmd = inb_p(WD_COMM);
429 if (cmd & 0x40)
430 {
431 outb_p(cmd & ~(CPAGE1), WD_COMM);
432 }
433 }
434
435
436
437 static void
438 wd_rx_over( struct device *dev )
439 {
440 unsigned char cmd, dummy;
441
442
443
444
445 printk ("wd_rx_over\n");
446 cmd = inb_p( CR );
447 cmd = (cmd&~(STA|PS0|PS1))|STOP;
448 outb_p( cmd, CR );
449 dummy = inb_p( RBCR0 );
450 dummy = inb_p( RBCR1 );
451 wd_rcv( dev );
452
453 if( inb_p( ISR ) & PRX )
454 outb_p( PRX, ISR );
455 while( ( inb_p( ISR ) & RST ) == 0 );
456 outb_p( RST, ISR );
457 outb_p( (cmd&~STOP)|STA, CR );
458 outb_p( WD_TCONFIG, TCR );
459 }
460
461
462
463
464
465
466 static void
467 wd_trs( struct device *dev )
468 {
469 unsigned char errors;
470
471 if( wd_debug )
472 printk("\nwd_trs() - TX complete, status = x%x", inb_p(TSR));
473
474 if( ( errors = inb_p( TSR ) & PTXOK ) || tx_aborted ){
475 if( (errors&~0x02) == 0 ){
476 stats.tx_packets++;
477 tx_aborted = 0;
478 }
479 dev->tbusy = 0;
480 mark_bh (INET_BH);
481
482 #if 0
483
484 len = dev_tint( (unsigned char *)dev->mem_start, dev );
485 if( len != 0 ){
486 len=max(len, ETHER_MIN_LEN);
487 cmd=inb_p(WD_COMM);
488 outb_p(len&0xff,WD_TB0);
489 outb_p(len>>8,WD_TB1);
490 cmd |= CTRANS;
491 outb_p(cmd,WD_COMM);
492 interrupt_mask |= TRANS_MASK;
493 }
494 else
495 {
496 dev->tbusy = 0
497 interrupt_mask &= ~TRANS_MASK;
498 return;
499 }
500 #endif
501 }
502 else{
503 if( errors & CRS ){
504 stats.tx_carrier_errors++;
505 printk("\nwd8013 - network cable short!");
506 }
507 if (errors & COL )
508 stats.collisions += inb_p( NCR );
509 if (errors & CDH )
510 stats.tx_heartbeat_errors++;
511 if (errors & OWC )
512 stats.tx_window_errors++;
513 }
514 }
515
516 void
517 wd8003_interrupt(int reg_ptr)
518 {
519 unsigned char cmd;
520 unsigned char errors;
521 unsigned char isr;
522 struct device *dev;
523 struct pt_regs *ptr;
524 int irq;
525 int count = 0;
526
527 ptr = (struct pt_regs *)reg_ptr;
528 irq = -(ptr->orig_eax+2);
529 for (dev = dev_base; dev != NULL; dev = dev->next)
530 {
531 if (dev->irq == irq) break;
532 }
533 if (dev == NULL)
534 {
535 printk ("we.c: irq %d for unknown device\n", irq);
536 return;
537 }
538 sti();
539
540 cmd = inb_p( CR );
541 if( cmd & (PS0|PS1 ) ){
542 cmd &= ~(PS0|PS1);
543 outb_p(cmd, CR );
544 }
545
546 if (wd_debug)
547 printk("\nwd8013 - interrupt isr = x%x", inb_p( ISR ) );
548
549 dev->interrupt = 1;
550
551 do{
552 sti();
553
554 if ( ( isr = inb_p( ISR ) ) & OVW ) {
555 stats.rx_over_errors++;
556 if( wd_debug )
557 printk("\nwd8013 overrun bnd = %d, cur = %d", wd_get_bnd( dev ), wd_get_cur( dev ) );
558 wd_rx_over( dev );
559 outb_p( OVW, ISR );
560 }
561 else if ( isr & PRX ) {
562 wd_rcv( dev );
563 outb_p( PRX, ISR );
564 }
565
566
567 if ( inb_p( ISR ) & PTX ) {
568 wd_trs( dev );
569 outb_p( PTX, ISR );
570 }
571
572 if (inb_p( ISR ) & RXE ) {
573 stats.rx_errors++;
574 errors = inb_p( RSR );
575 if (errors & CRC )
576 stats.rx_crc_errors++;
577 if (errors & FAE )
578 stats.rx_frame_errors++;
579 if (errors & FO )
580 stats.rx_fifo_errors++;
581 if (errors & MPA )
582 stats.rx_missed_errors++;
583 outb_p( RXE, ISR );
584 }
585
586 if (inb_p( ISR ) & TXE ) {
587 stats.tx_errors++;
588 errors = inb_p( TSR );
589 if (errors & ABT ){
590 stats.tx_aborted_errors++;
591 printk("\nwd8013 - network cable open!");
592 }
593 if (errors & FU )
594 {
595 stats.tx_fifo_errors++;
596 printk("\nwd8013 - TX FIFO underrun!");
597 }
598
599
600 tx_aborted = 1;
601 wd_trs( dev );
602 tx_aborted = 0;
603
604 outb_p( TXE, ISR );
605 }
606
607 if( inb_p( ISR ) & CNTE ){
608 errors = inb_p( CNTR0 );
609 errors = inb_p( CNTR1 );
610 errors = inb_p( CNTR2 );
611 outb_p( CNTE, ISR );
612 }
613 if( inb_p( ISR ) & RST )
614 outb_p( RST, ISR );
615
616 if( wd_debug ){
617 if( ( isr = inb_p( ISR ) ) != 0 )
618 printk("\nwd8013 - ISR not cleared = x%x", isr );
619 }
620 if( ++count > max_pages + 1 ){
621 printk("\nwd8013_interrupt - infinite loop detected, isr = x%x, count = %d", isr, count );
622 }
623 cli();
624 } while( inb_p( ISR ) != 0 );
625
626 dev->interrupt = 0;
627 }
628
629
630 static struct sigaction wd8003_sigaction =
631 {
632 wd8003_interrupt,
633 0,
634 0,
635 NULL
636 };
637
638 int
639 wd8003_init(struct device *dev)
640 {
641 unsigned char csum;
642 int i;
643 csum = 0;
644 for (i = 0; i < 8; i++)
645 {
646 csum += inb_p(WD_ROM+i);
647 }
648 if (csum != WD_CHECK)
649 {
650 printk ("Warning WD8013 board not found at i/o = %X.\n",dev->base_addr);
651
652
653 return (1);
654 }
655 printk("wd8013");
656
657 dev->mtu = 1500;
658 dev->hard_start_xmit = wd8003_start_xmit;
659 dev->open = wd8003_open;
660 dev->hard_header = eth_hard_header;
661 dev->add_arp = eth_add_arp;
662 dev->type_trans = eth_type_trans;
663 dev->hard_header_len = sizeof (struct enet_header);
664 dev->addr_len = ETHER_ADDR_LEN;
665 dev->type = ETHER_TYPE;
666 dev->queue_xmit = dev_queue_xmit;
667 dev->rebuild_header = eth_rebuild_header;
668 for (i = 0; i < DEV_NUMBUFFS; i++)
669 dev->buffs[i] = NULL;
670
671 #ifndef FORCE_8BIT
672
673 for (i = 0; i < 8; i++) {
674 if( inb_p( EN_SAPROM+i ) != inb_p( EN_CMD+i) ){
675 csum = inb_p( EN_REG1 );
676 outb( csum ^ BUS16, EN_REG1 );
677 if( (csum & BUS16) == (inb_p( EN_REG1 ) & BUS16) ) {
678 printk(", using 16 bit I/F ");
679 dconfig |= 1;
680 outb_p( LAN16ENABLE|MEMMASK, EN_REG5);
681 outb( csum , EN_REG1 );
682 break;
683 }
684 outb( csum , EN_REG1 );
685 }
686 }
687 #endif
688
689
690 outb_p(WD_IMEM,WD_CTL);
691
692
693 for (i = dev->mem_start; i < dev->mem_end; i++)
694 {
695 *((unsigned char *)i) = 0;
696 if (*((unsigned char *)i) != 0)
697 {
698 printk ("WD Memory error.\n");
699 if( (i - dev->mem_start) > 4096 )
700 break;
701 else
702 return (1);
703 }
704 }
705
706 max_pages = ( i - dev->mem_start )/256;
707
708
709 dev->rmem_end = i;
710 dev->mem_end = i;
711
712
713
714 printk (", %d pages memory, ethernet Address: ", max_pages );
715 for (i = 0; i <ETHER_ADDR_LEN; i++)
716 {
717 dev->dev_addr[i]=inb_p(WD_ROM+i);
718 dev->broadcast[i]=0xff;
719 printk ("%2.2X ",dev->dev_addr[i]);
720 }
721
722
723 for( i = 0; i < sizeof( struct enet_statistics ); i++ )
724 ((char *)&stats)[i] = 0;
725
726 printk ("\n");
727 dev->tbusy = 0;
728 dev->interrupt = 0;
729
730 if (irqaction (dev->irq, &wd8003_sigaction))
731 {
732 printk ("Unable to get IRQ%d for wd8013 board\n", dev->irq);
733 return (1);
734 }
735 return (0);
736 }