This source file includes following definitions.
- fmv18x_probe
- fmv18x_probe1
- net_open
- net_send_packet
- net_interrupt
- net_rx
- net_close
- net_get_stats
- set_multicast_list
- init_module
- cleanup_module
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 static const char *version =
35 "fmv18x.c:v1.3.71e 03/04/96 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
36
37 #include <linux/module.h>
38
39 #include <linux/kernel.h>
40 #include <linux/sched.h>
41 #include <linux/types.h>
42 #include <linux/fcntl.h>
43 #include <linux/interrupt.h>
44 #include <linux/ptrace.h>
45 #include <linux/ioport.h>
46 #include <linux/in.h>
47 #include <linux/malloc.h>
48 #include <linux/string.h>
49 #include <asm/system.h>
50 #include <asm/bitops.h>
51 #include <asm/io.h>
52 #include <asm/dma.h>
53 #include <linux/errno.h>
54
55 #include <linux/netdevice.h>
56 #include <linux/etherdevice.h>
57 #include <linux/skbuff.h>
58 #include <linux/delay.h>
59
60 static int fmv18x_probe_list[] =
61 {0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};
62
63
64 #ifndef NET_DEBUG
65 #define NET_DEBUG 1
66 #endif
67 static unsigned int net_debug = NET_DEBUG;
68
69 typedef unsigned char uchar;
70
71
72 struct net_local {
73 struct enet_statistics stats;
74 long open_time;
75 uint tx_started:1;
76 uchar tx_queue;
77 ushort tx_queue_len;
78 };
79
80
81
82 #define STATUS 0
83 #define TX_STATUS 0
84 #define RX_STATUS 1
85 #define TX_INTR 2
86 #define RX_INTR 3
87 #define TX_MODE 4
88 #define RX_MODE 5
89 #define CONFIG_0 6
90 #define CONFIG_1 7
91
92 #define DATAPORT 8
93 #define TX_START 10
94 #define COL16CNTL 11
95 #define MODE13 13
96
97 #define FJ_STATUS0 0x10
98 #define FJ_STATUS1 0x11
99 #define FJ_CONFIG0 0x12
100 #define FJ_CONFIG1 0x13
101 #define FJ_MACADDR 0x14
102 #define FJ_BUFCNTL 0x1A
103 #define FJ_BUFDATA 0x1C
104 #define FMV18X_IO_EXTENT 32
105
106
107
108 extern int fmv18x_probe(struct device *dev);
109
110 static int fmv18x_probe1(struct device *dev, short ioaddr);
111 static int net_open(struct device *dev);
112 static int net_send_packet(struct sk_buff *skb, struct device *dev);
113 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
114 static void net_rx(struct device *dev);
115 static int net_close(struct device *dev);
116 static struct enet_statistics *net_get_stats(struct device *dev);
117 static void set_multicast_list(struct device *dev);
118
119
120
121
122
123
124
125
126 #ifdef HAVE_DEVLIST
127
128
129 struct netdev_entry fmv18x_drv =
130 {"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
131 #else
132 int
133 fmv18x_probe(struct device *dev)
134 {
135 int i;
136 int base_addr = dev ? dev->base_addr : 0;
137
138 if (base_addr > 0x1ff)
139 return fmv18x_probe1(dev, base_addr);
140 else if (base_addr != 0)
141 return ENXIO;
142
143 for (i = 0; fmv18x_probe_list[i]; i++) {
144 int ioaddr = fmv18x_probe_list[i];
145 if (check_region(ioaddr, FMV18X_IO_EXTENT))
146 continue;
147 if (fmv18x_probe1(dev, ioaddr) == 0)
148 return 0;
149 }
150
151 return ENODEV;
152 }
153 #endif
154
155
156
157
158
159
160
161
162
163 int fmv18x_probe1(struct device *dev, short ioaddr)
164 {
165 char irqmap[4] = {3, 7, 10, 15};
166 unsigned int i, irq;
167
168
169
170
171
172
173 if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr
174 || inb(ioaddr+FJ_MACADDR ) != 0x00
175 || inb(ioaddr+FJ_MACADDR+1) != 0x00
176 || inb(ioaddr+FJ_MACADDR+2) != 0x0e)
177 return -ENODEV;
178
179 irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
180
181
182 if (request_irq(irq, &net_interrupt, 0, "fmv18x", NULL)) {
183 printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
184 "IRQ %d.\n", ioaddr, irq);
185 return EAGAIN;
186 }
187
188
189 if (dev == NULL)
190 dev = init_etherdev(0, sizeof(struct net_local));
191
192
193
194 request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x");
195
196 printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
197 ioaddr, irq);
198
199 dev->base_addr = ioaddr;
200 dev->irq = irq;
201 irq2dev_map[irq] = dev;
202
203 for(i = 0; i < 6; i++) {
204 unsigned char val = inb(ioaddr + FJ_MACADDR + i);
205 printk("%02x", val);
206 dev->dev_addr[i] = val;
207 }
208
209
210
211
212
213
214
215 {
216 const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};
217 ushort setup_value = inb(ioaddr + FJ_STATUS0);
218
219 switch( setup_value & 0x07 ){
220 case 0x01 :
221 case 0x02 : dev->if_port = 0x18; break;
222 case 0x04 : dev->if_port = 0x08; break;
223 default : dev->if_port = 0x00; break;
224 }
225 printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
226 }
227
228
229 outb(0xda, ioaddr + CONFIG_0);
230 outb(0x00, ioaddr + CONFIG_1);
231 outb(0x00, ioaddr + FJ_CONFIG1);
232 outb(0x00, ioaddr + FJ_BUFCNTL);
233
234
235 udelay(200);
236
237
238 outb(0x00, ioaddr + CONFIG_1);
239 for (i = 0; i < 6; i++)
240 outb(dev->dev_addr[i], ioaddr + 8 + i);
241
242
243 outb(0x04, ioaddr + CONFIG_1);
244 for (i = 0; i < 8; i++)
245 outb(0x00, ioaddr + 8 + i);
246
247
248 outb(0x08, ioaddr + CONFIG_1);
249 outb(dev->if_port, ioaddr + MODE13);
250
251 if (net_debug)
252 printk(version);
253
254
255 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
256 if (dev->priv == NULL)
257 return -ENOMEM;
258 memset(dev->priv, 0, sizeof(struct net_local));
259
260 dev->open = net_open;
261 dev->stop = net_close;
262 dev->hard_start_xmit = net_send_packet;
263 dev->get_stats = net_get_stats;
264 dev->set_multicast_list = &set_multicast_list;
265
266
267
268 ether_setup(dev);
269 return 0;
270 }
271
272
273 static int net_open(struct device *dev)
274 {
275 struct net_local *lp = (struct net_local *)dev->priv;
276 int ioaddr = dev->base_addr;
277
278
279
280 outb(0x5a, ioaddr + CONFIG_0);
281
282
283 outb(0xe8, ioaddr + CONFIG_1);
284
285 lp->tx_started = 0;
286 lp->tx_queue = 0;
287 lp->tx_queue_len = 0;
288
289
290 outb(0xff, ioaddr + TX_STATUS);
291 outb(0xff, ioaddr + RX_STATUS);
292 lp->open_time = jiffies;
293
294 dev->tbusy = 0;
295 dev->interrupt = 0;
296 dev->start = 1;
297
298
299 outb(0x80, ioaddr + FJ_CONFIG1);
300
301
302 outw(0x8182, ioaddr+TX_INTR);
303
304 MOD_INC_USE_COUNT;
305
306 return 0;
307 }
308
309 static int
310 net_send_packet(struct sk_buff *skb, struct device *dev)
311 {
312 struct net_local *lp = (struct net_local *)dev->priv;
313 int ioaddr = dev->base_addr;
314
315 if (dev->tbusy) {
316
317
318 int tickssofar = jiffies - dev->trans_start;
319 if (tickssofar < 10)
320 return 1;
321 printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
322 htons(inw(ioaddr + TX_STATUS)),
323 inb(ioaddr + TX_STATUS) & 0x80
324 ? "IRQ conflict" : "network cable problem");
325 printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
326 dev->name, htons(inw(ioaddr + 0)),
327 htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
328 htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
329 htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
330 htons(inw(ioaddr +14)));
331 printk("eth card: %04x %04x\n",
332 htons(inw(ioaddr+FJ_STATUS0)),
333 htons(inw(ioaddr+FJ_CONFIG0)));
334 lp->stats.tx_errors++;
335
336 cli();
337
338
339 outb(0xda, ioaddr + CONFIG_0);
340 outb(0x00, ioaddr + CONFIG_1);
341 outb(0x00, ioaddr + FJ_CONFIG1);
342 outb(0x00, ioaddr + FJ_BUFCNTL);
343 net_open(dev);
344
345 sti();
346 }
347
348
349
350
351 if (skb == NULL) {
352 dev_tint(dev);
353 return 0;
354 }
355
356
357
358 if (set_bit(0, (void*)&dev->tbusy) != 0)
359 printk("%s: Transmitter access conflict.\n", dev->name);
360 else {
361 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
362 unsigned char *buf = skb->data;
363
364 if (length > ETH_FRAME_LEN) {
365 if (net_debug)
366 printk("%s: Attempting to send a large packet (%d bytes).\n",
367 dev->name, length);
368 return 1;
369 }
370
371 if (net_debug > 4)
372 printk("%s: Transmitting a packet of length %lu.\n", dev->name,
373 (unsigned long)skb->len);
374
375
376 outw(0x0000, ioaddr + TX_INTR);
377
378 outw(length, ioaddr + DATAPORT);
379 outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
380
381 lp->tx_queue++;
382 lp->tx_queue_len += length + 2;
383
384 if (lp->tx_started == 0) {
385
386 outb(0x80 | lp->tx_queue, ioaddr + TX_START);
387 lp->tx_queue = 0;
388 lp->tx_queue_len = 0;
389 dev->trans_start = jiffies;
390 lp->tx_started = 1;
391 dev->tbusy = 0;
392 } else if (lp->tx_queue_len < 4096 - 1502)
393
394 dev->tbusy = 0;
395
396
397 outw(0x8182, ioaddr + TX_INTR);
398 }
399 dev_kfree_skb (skb, FREE_WRITE);
400
401 return 0;
402 }
403
404
405
406 static void
407 net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
408 {
409 struct device *dev = (struct device *)(irq2dev_map[irq]);
410 struct net_local *lp;
411 int ioaddr, status;
412
413 if (dev == NULL) {
414 printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq);
415 return;
416 }
417 dev->interrupt = 1;
418
419 ioaddr = dev->base_addr;
420 lp = (struct net_local *)dev->priv;
421
422
423 outw(0x0000, ioaddr + TX_INTR);
424
425 status = inw(ioaddr + TX_STATUS);
426 outw(status, ioaddr + TX_STATUS);
427
428 if (net_debug > 4)
429 printk("%s: Interrupt with status %04x.\n", dev->name, status);
430 if (status & 0xff00
431 || (inb(ioaddr + RX_MODE) & 0x40) == 0) {
432 net_rx(dev);
433 }
434 if (status & 0x00ff) {
435 if (status & 0x80) {
436 lp->stats.tx_packets++;
437 if (lp->tx_queue) {
438 outb(0x80 | lp->tx_queue, ioaddr + TX_START);
439 lp->tx_queue = 0;
440 lp->tx_queue_len = 0;
441 dev->trans_start = jiffies;
442 dev->tbusy = 0;
443 mark_bh(NET_BH);
444 } else {
445 lp->tx_started = 0;
446 dev->tbusy = 0;
447 mark_bh(NET_BH);
448 }
449 }
450 if (status & 0x02 ) {
451 if (net_debug > 4)
452 printk("%s: 16 Collision occur during Txing.\n", dev->name);
453
454 outb(0x02, ioaddr + COL16CNTL);
455 }
456 }
457
458 dev->interrupt = 0;
459 outw(0x8182, ioaddr + TX_INTR);
460 return;
461 }
462
463
464 static void
465 net_rx(struct device *dev)
466 {
467 struct net_local *lp = (struct net_local *)dev->priv;
468 int ioaddr = dev->base_addr;
469 int boguscount = 10;
470
471 while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
472
473
474 ushort status = inw(ioaddr + DATAPORT);
475
476 if (net_debug > 4)
477 printk("%s: Rxing packet mode %02x status %04x.\n",
478 dev->name, inb(ioaddr + RX_MODE), status);
479 #ifndef final_version
480 if (status == 0) {
481 outb(0x05, ioaddr + 14);
482 break;
483 }
484 #endif
485
486 if ((status & 0xF0) != 0x20) {
487 lp->stats.rx_errors++;
488 if (status & 0x08) lp->stats.rx_length_errors++;
489 if (status & 0x04) lp->stats.rx_frame_errors++;
490 if (status & 0x02) lp->stats.rx_crc_errors++;
491 if (status & 0x01) lp->stats.rx_over_errors++;
492 } else {
493 ushort pkt_len = inw(ioaddr + DATAPORT);
494
495 struct sk_buff *skb;
496
497 if (pkt_len > 1550) {
498 printk("%s: The FMV-18x claimed a very large packet, size %d.\n",
499 dev->name, pkt_len);
500 outb(0x05, ioaddr + 14);
501 lp->stats.rx_errors++;
502 break;
503 }
504 skb = dev_alloc_skb(pkt_len+3);
505 if (skb == NULL) {
506 printk("%s: Memory squeeze, dropping packet (len %d).\n",
507 dev->name, pkt_len);
508 outb(0x05, ioaddr + 14);
509 lp->stats.rx_dropped++;
510 break;
511 }
512 skb->dev = dev;
513 skb_reserve(skb,2);
514
515 insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
516
517 if (net_debug > 5) {
518 int i;
519 printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
520 for (i = 0; i < 14; i++)
521 printk(" %02x", skb->data[i]);
522 printk(".\n");
523 }
524
525 skb->protocol=eth_type_trans(skb, dev);
526 netif_rx(skb);
527 lp->stats.rx_packets++;
528 }
529 if (--boguscount <= 0)
530 break;
531 }
532
533
534
535
536 {
537 int i;
538 for (i = 0; i < 20; i++) {
539 if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
540 break;
541 (void)inw(ioaddr + DATAPORT);
542 outb(0x05, ioaddr + 14);
543 }
544
545 if (net_debug > 5 && i > 0)
546 printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
547 dev->name, inb(ioaddr + RX_MODE), i);
548 }
549
550 return;
551 }
552
553
554 static int net_close(struct device *dev)
555 {
556 int ioaddr = dev->base_addr;
557
558 ((struct net_local *)dev->priv)->open_time = 0;
559
560 dev->tbusy = 1;
561 dev->start = 0;
562
563
564 outb(0xda, ioaddr + CONFIG_0);
565
566
567
568
569 outb(0x00, ioaddr + CONFIG_1);
570
571 MOD_DEC_USE_COUNT;
572
573
574 outb(0x00, ioaddr + FJ_CONFIG1);
575
576 return 0;
577 }
578
579
580
581 static struct enet_statistics *
582 net_get_stats(struct device *dev)
583 {
584 struct net_local *lp = (struct net_local *)dev->priv;
585
586 cli();
587
588 sti();
589
590 return &lp->stats;
591 }
592
593
594
595
596
597
598
599 static void
600 set_multicast_list(struct device *dev)
601 {
602 short ioaddr = dev->base_addr;
603 if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
604 {
605
606
607
608
609
610 dev->flags|=IFF_PROMISC;
611
612 outb(3, ioaddr + RX_MODE);
613 }
614 else
615 outb(2, ioaddr + RX_MODE);
616 }
617
618 #ifdef MODULE
619 static char devicename[9] = { 0, };
620 static struct device dev_fmv18x = {
621 devicename,
622 0, 0, 0, 0,
623 0, 0,
624 0, 0, 0, NULL, fmv18x_probe };
625
626 static int io = 0x220;
627 static int irq = 0;
628
629 int init_module(void)
630 {
631 if (io == 0)
632 printk("fmv18x: You should not use auto-probing with insmod!\n");
633 dev_fmv18x.base_addr = io;
634 dev_fmv18x.irq = irq;
635 if (register_netdev(&dev_fmv18x) != 0) {
636 printk("fmv18x: register_netdev() returned non-zero.\n");
637 return -EIO;
638 }
639 return 0;
640 }
641
642 void
643 cleanup_module(void)
644 {
645 unregister_netdev(&dev_fmv18x);
646 kfree(dev_fmv18x.priv);
647 dev_fmv18x.priv = NULL;
648
649
650 free_irq(dev_fmv18x.irq, NULL);
651 irq2dev_map[dev_fmv18x.irq] = NULL;
652 release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT);
653 }
654 #endif
655
656
657
658
659
660
661
662
663
664