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