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