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 return (1);
226 }
227
228 printk ("wd8003 transmit timed out. \n");
229 }
230 dev->tbusy = 1;
231
232 if (skb == NULL)
233 {
234 sti();
235 wd_trs(dev);
236 return (0);
237 }
238
239
240 if (skb->dev != dev)
241 {
242 sti();
243 return (0);
244 }
245
246
247 if (!skb->arp)
248 {
249 if ( dev->rebuild_header (skb+1, dev))
250 {
251 cli();
252 if (skb->dev == dev)
253 {
254 arp_queue (skb);
255 }
256 cli ();
257 dev->tbusy = 0;
258 sti();
259 return (0);
260 }
261 }
262
263 memcpy ((unsigned char *)dev->mem_start, skb+1, skb->len);
264
265 len = skb->len;
266
267
268 dev->trans_start = jiffies;
269 len=max(len, ETHER_MIN_LEN);
270
271
272
273 cmd=inb_p(WD_COMM);
274 cmd &= ~CPAGE;
275 outb_p(cmd, WD_COMM);
276
277 interrupt_mask |= TRANS_MASK;
278 if (!(dev->interrupt))
279 outb (interrupt_mask, WD_IMR);
280
281 outb_p(len&0xff,WD_TB0);
282 outb_p(len>>8,WD_TB1);
283 cmd |= CTRANS;
284 outb_p(cmd,WD_COMM);
285 sti();
286
287 if (skb->free)
288 {
289 kfree_skb (skb, FREE_WRITE);
290 }
291
292 return (0);
293 }
294
295
296
297 static void
298 wd_put_bnd(unsigned char bnd, struct device *dev )
299 {
300
301 unsigned char cmd;
302
303
304 cmd = inb_p( CR );
305 if (cmd & 0x40) {
306 outb_p(cmd & (~CPAGE1), WD_COMM);
307 outb_p(bnd, WD_BNDR);
308 outb_p(cmd | CPAGE1, WD_COMM);
309 } else {
310 outb_p(bnd, WD_BNDR);
311 }
312 }
313
314 static unsigned char
315 wd_get_bnd( struct device *dev )
316 {
317
318 unsigned char cmd, bnd;
319
320
321 cmd = inb_p(WD_COMM);
322 if (cmd & 0x40) {
323 outb_p(cmd & (~CPAGE1), WD_COMM);
324 bnd = inb_p(WD_BNDR);
325 outb_p(cmd | CPAGE1, WD_COMM);
326 return (bnd);
327 } else {
328 return (inb_p(WD_BNDR));
329 }
330 }
331
332 static unsigned char
333 wd_get_cur( struct device *dev )
334 {
335
336 unsigned char cmd, cur;
337
338
339 cmd = inb_p(WD_COMM);
340 if (cmd & 0x40) {
341 return (inb_p(WD_CUR));
342 } else {
343 outb_p(cmd | CPAGE1, WD_COMM);
344 cur = inb_p(WD_CUR);
345 outb_p(cmd & (~CPAGE1), WD_COMM);
346 return (cur);
347 }
348 }
349
350
351
352
353
354 static void
355 wd_rcv( struct device *dev )
356 {
357
358 unsigned char pkt;
359 unsigned char bnd;
360 unsigned char cur;
361 unsigned char cmd;
362 volatile struct wd_ring *ring;
363 int done=0;
364
365
366 cur = wd_get_cur( dev );
367 bnd = wd_get_bnd( dev );
368 if( (pkt = bnd + 1) == max_pages )
369 pkt = WD_TXBS;
370
371 while( done != 1)
372 {
373 if (pkt != cur)
374 {
375
376
377 ring = (volatile struct wd_ring *) (dev->mem_start + (pkt << 8));
378
379
380 if( ring->status & 1 )
381 {
382
383
384 if( wd_debug )
385 printk("\nwd8013 - wdget: bnd = %d, pkt = %d, "
386 "cur = %d, status = %d, len = %d, next = %d",
387 bnd, pkt, cur, ring->status, ring->count,
388 ring->next);
389
390 stats.rx_packets++;
391 done = wdget( ring, dev );
392
393
394 pkt = ring->next;
395
396
397 if( (bnd = pkt - 1) < WD_TXBS )
398 bnd = max_pages - 1;
399 wd_put_bnd(bnd, dev);
400
401
402 cur = wd_get_cur(dev);
403 }
404 else
405 {
406
407 printk("wd8013 - bad packet: len = %d, status = x%x, "
408 "bnd = %d, pkt = %d, cur = %d\n"
409 "trashing receive buffer!",
410 ring->count, ring->status, bnd, pkt,
411 cur);
412
413 if( ( bnd = wd_get_cur( dev ) - 1 ) < WD_TXBS )
414 bnd = max_pages - 1;
415 wd_put_bnd( bnd, dev );
416 break;
417 }
418
419 }
420 else
421 {
422 done = dev_rint(NULL, 0,0, dev);
423 }
424 }
425
426
427 cmd = inb_p(WD_COMM);
428 if (cmd & 0x40)
429 {
430 outb_p(cmd & ~(CPAGE1), WD_COMM);
431 }
432 }
433
434
435
436 static void
437 wd_rx_over( struct device *dev )
438 {
439 unsigned char cmd, dummy;
440
441
442
443
444 printk ("wd_rx_over\n");
445 cmd = inb_p( CR );
446 cmd = (cmd&~(STA|PS0|PS1))|STOP;
447 outb_p( cmd, CR );
448 dummy = inb_p( RBCR0 );
449 dummy = inb_p( RBCR1 );
450 wd_rcv( dev );
451
452 if( inb_p( ISR ) & PRX )
453 outb_p( PRX, ISR );
454 while( ( inb_p( ISR ) & RST ) == 0 );
455 outb_p( RST, ISR );
456 outb_p( (cmd&~STOP)|STA, CR );
457 outb_p( WD_TCONFIG, TCR );
458 }
459
460
461
462
463
464
465 static void
466 wd_trs( struct device *dev )
467 {
468 unsigned char errors;
469
470 if( wd_debug )
471 printk("\nwd_trs() - TX complete, status = x%x", inb_p(TSR));
472
473 if( ( errors = inb_p( TSR ) & PTXOK ) || tx_aborted ){
474 if( (errors&~0x02) == 0 ){
475 stats.tx_packets++;
476 tx_aborted = 0;
477 }
478 dev->tbusy = 0;
479 mark_bh (INET_BH);
480
481 #if 0
482
483 len = dev_tint( (unsigned char *)dev->mem_start, dev );
484 if( len != 0 ){
485 len=max(len, ETHER_MIN_LEN);
486 cmd=inb_p(WD_COMM);
487 outb_p(len&0xff,WD_TB0);
488 outb_p(len>>8,WD_TB1);
489 cmd |= CTRANS;
490 outb_p(cmd,WD_COMM);
491 interrupt_mask |= TRANS_MASK;
492 }
493 else
494 {
495 dev->tbusy = 0
496 interrupt_mask &= ~TRANS_MASK;
497 return;
498 }
499 #endif
500 }
501 else{
502 if( errors & CRS ){
503 stats.tx_carrier_errors++;
504 printk("\nwd8013 - network cable short!");
505 }
506 if (errors & COL )
507 stats.collisions += inb_p( NCR );
508 if (errors & CDH )
509 stats.tx_heartbeat_errors++;
510 if (errors & OWC )
511 stats.tx_window_errors++;
512 }
513 }
514
515 void
516 wd8003_interrupt(int reg_ptr)
517 {
518 unsigned char cmd;
519 unsigned char errors;
520 unsigned char isr;
521 struct device *dev;
522 struct pt_regs *ptr;
523 int irq;
524 int count = 0;
525
526 ptr = (struct pt_regs *)reg_ptr;
527 irq = -(ptr->orig_eax+2);
528 for (dev = dev_base; dev != NULL; dev = dev->next)
529 {
530 if (dev->irq == irq) break;
531 }
532 if (dev == NULL)
533 {
534 printk ("we.c: irq %d for unknown device\n", irq);
535 return;
536 }
537 sti();
538
539 cmd = inb_p( CR );
540 if( cmd & (PS0|PS1 ) ){
541 cmd &= ~(PS0|PS1);
542 outb_p(cmd, CR );
543 }
544
545 if (wd_debug)
546 printk("\nwd8013 - interrupt isr = x%x", inb_p( ISR ) );
547
548 dev->interrupt = 1;
549
550 do{
551 sti();
552
553 if ( ( isr = inb_p( ISR ) ) & OVW ) {
554 stats.rx_over_errors++;
555 if( wd_debug )
556 printk("\nwd8013 overrun bnd = %d, cur = %d", wd_get_bnd( dev ), wd_get_cur( dev ) );
557 wd_rx_over( dev );
558 outb_p( OVW, ISR );
559 }
560 else if ( isr & PRX ) {
561 wd_rcv( dev );
562 outb_p( PRX, ISR );
563 }
564
565
566 if ( inb_p( ISR ) & PTX ) {
567 wd_trs( dev );
568 outb_p( PTX, ISR );
569 }
570
571 if (inb_p( ISR ) & RXE ) {
572 stats.rx_errors++;
573 errors = inb_p( RSR );
574 if (errors & CRC )
575 stats.rx_crc_errors++;
576 if (errors & FAE )
577 stats.rx_frame_errors++;
578 if (errors & FO )
579 stats.rx_fifo_errors++;
580 if (errors & MPA )
581 stats.rx_missed_errors++;
582 outb_p( RXE, ISR );
583 }
584
585 if (inb_p( ISR ) & TXE ) {
586 stats.tx_errors++;
587 errors = inb_p( TSR );
588 if (errors & ABT ){
589 stats.tx_aborted_errors++;
590 printk("\nwd8013 - network cable open!");
591 }
592 if (errors & FU )
593 {
594 stats.tx_fifo_errors++;
595 printk("\nwd8013 - TX FIFO underrun!");
596 }
597
598
599 tx_aborted = 1;
600 wd_trs( dev );
601 tx_aborted = 0;
602
603 outb_p( TXE, ISR );
604 }
605
606 if( inb_p( ISR ) & CNTE ){
607 errors = inb_p( CNTR0 );
608 errors = inb_p( CNTR1 );
609 errors = inb_p( CNTR2 );
610 outb_p( CNTE, ISR );
611 }
612 if( inb_p( ISR ) & RST )
613 outb_p( RST, ISR );
614
615 if( wd_debug ){
616 if( ( isr = inb_p( ISR ) ) != 0 )
617 printk("\nwd8013 - ISR not cleared = x%x", isr );
618 }
619 if( ++count > max_pages + 1 ){
620 printk("\nwd8013_interrupt - infinite loop detected, isr = x%x, count = %d", isr, count );
621 }
622 cli();
623 } while( inb_p( ISR ) != 0 );
624
625 dev->interrupt = 0;
626 }
627
628
629 static struct sigaction wd8003_sigaction =
630 {
631 wd8003_interrupt,
632 0,
633 0,
634 NULL
635 };
636
637 int
638 wd8003_init(struct device *dev)
639 {
640 unsigned char csum;
641 int i;
642 csum = 0;
643 for (i = 0; i < 8; i++)
644 {
645 csum += inb_p(WD_ROM+i);
646 }
647 if (csum != WD_CHECK)
648 {
649 printk ("Warning WD8013 board not found at i/o = %X.\n",dev->base_addr);
650
651
652 return (1);
653 }
654 printk("wd8013");
655
656 dev->mtu = 1500;
657 dev->hard_start_xmit = wd8003_start_xmit;
658 dev->open = wd8003_open;
659 dev->hard_header = eth_hard_header;
660 dev->add_arp = eth_add_arp;
661 dev->type_trans = eth_type_trans;
662 dev->hard_header_len = sizeof (struct enet_header);
663 dev->addr_len = ETHER_ADDR_LEN;
664 dev->type = ETHER_TYPE;
665 dev->queue_xmit = dev_queue_xmit;
666 dev->rebuild_header = eth_rebuild_header;
667 for (i = 0; i < DEV_NUMBUFFS; i++)
668 dev->buffs[i] = NULL;
669
670 #ifndef FORCE_8BIT
671
672 for (i = 0; i < 8; i++) {
673 if( inb_p( EN_SAPROM+i ) != inb_p( EN_CMD+i) ){
674 csum = inb_p( EN_REG1 );
675 outb( csum ^ BUS16, EN_REG1 );
676 if( (csum & BUS16) == (inb_p( EN_REG1 ) & BUS16) ) {
677 printk(", using 16 bit I/F ");
678 dconfig |= 1;
679 outb_p( LAN16ENABLE|MEMMASK, EN_REG5);
680 outb( csum , EN_REG1 );
681 break;
682 }
683 outb( csum , EN_REG1 );
684 }
685 }
686 #endif
687
688
689 outb_p(WD_IMEM,WD_CTL);
690
691
692 for (i = dev->mem_start; i < dev->mem_end; i++)
693 {
694 *((unsigned char *)i) = 0;
695 if (*((unsigned char *)i) != 0)
696 {
697 printk ("WD Memory error.\n");
698 if( (i - dev->mem_start) > 4096 )
699 break;
700 else
701 return (1);
702 }
703 }
704
705 max_pages = ( i - dev->mem_start )/256;
706
707
708 dev->rmem_end = i;
709 dev->mem_end = i;
710
711
712
713 printk (", %d pages memory, ethernet Address: ", max_pages );
714 for (i = 0; i <ETHER_ADDR_LEN; i++)
715 {
716 dev->dev_addr[i]=inb_p(WD_ROM+i);
717 dev->broadcast[i]=0xff;
718 printk ("%2.2X ",dev->dev_addr[i]);
719 }
720
721
722 for( i = 0; i < sizeof( struct enet_statistics ); i++ )
723 ((char *)&stats)[i] = 0;
724
725 printk ("\n");
726 dev->tbusy = 0;
727 dev->interrupt = 0;
728
729 if (irqaction (dev->irq, &wd8003_sigaction))
730 {
731 printk ("Unable to get IRQ%d for wd8013 board\n", dev->irq);
732 return (1);
733 }
734 return (0);
735 }