Linux 2.2.0
[davej-history.git] / drivers / net / daynaport.c
blob777a1dcab5b61e85c5ecfa53d5d7fcc09ecdcce8
1 /* mac_ns8390.c: A Macintosh 8390 based ethernet driver for linux. */
2 /*
3 Derived from code:
5 Written 1993-94 by Donald Becker.
7 Copyright 1993 United States Government as represented by the
8 Director, National Security Agency.
10 This software may be used and distributed according to the terms
11 of the GNU Public License, incorporated herein by reference.
13 TODO:
15 The block output routines may be wrong for non Dayna
16 cards
18 Reading MAC addresses
21 static const char *version =
22 "mac_ns8390.c:v0.01 7/5/97 Alan Cox (Alan.Cox@linux.org)\n";
24 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/sched.h>
28 #include <linux/errno.h>
29 #include <linux/string.h>
30 #include <linux/nubus.h>
31 #include <asm/io.h>
32 #include <asm/system.h>
33 #include <asm/hwtest.h>
34 #include <linux/delay.h>
36 #include <linux/netdevice.h>
37 #include <linux/etherdevice.h>
38 #include "8390.h"
40 int ns8390_probe1(struct device *dev, int word16, char *name, int id, int prom);
42 static int ns8390_open(struct device *dev);
43 static void ns8390_no_reset(struct device *dev);
44 static int ns8390_close_card(struct device *dev);
46 static void interlan_reset(struct device *dev);
48 static void dayna_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
49 int ring_page);
50 static void dayna_block_input(struct device *dev, int count,
51 struct sk_buff *skb, int ring_offset);
52 static void dayna_block_output(struct device *dev, int count,
53 const unsigned char *buf, const int start_page);
55 static void sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
56 int ring_page);
57 static void sane_block_input(struct device *dev, int count,
58 struct sk_buff *skb, int ring_offset);
59 static void sane_block_output(struct device *dev, int count,
60 const unsigned char *buf, const int start_page);
62 static void slow_sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
63 int ring_page);
64 static void slow_sane_block_input(struct device *dev, int count,
65 struct sk_buff *skb, int ring_offset);
66 static void slow_sane_block_output(struct device *dev, int count,
67 const unsigned char *buf, const int start_page);
70 #define WD_START_PG 0x00 /* First page of TX buffer */
71 #define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */
72 #define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */
75 #define DAYNA_MAC_BASE 0xf0007
76 #define DAYNA_8390_BASE 0x80000 /* 3 */
77 #define DAYNA_8390_MEM 0x00000
78 #define DAYNA_MEMSIZE 0x04000 /* First word of each long ! */
80 #define APPLE_8390_BASE 0xE0000
81 #define APPLE_8390_MEM 0xD0000
82 #define APPLE_MEMSIZE 8192 /* FIXME: need to dynamically check */
84 #define KINETICS_8390_BASE 0x80003
85 #define KINETICS_8390_MEM 0x00000
86 #define KINETICS_MEMSIZE 8192 /* FIXME: need to dynamically check */
88 static int test_8390(volatile char *ptr, int scale)
90 int regd;
91 int v;
93 if(hwreg_present(&ptr[0x00])==0)
94 return -EIO;
95 if(hwreg_present(&ptr[0x0D<<scale])==0)
96 return -EIO;
97 if(hwreg_present(&ptr[0x0D<<scale])==0)
98 return -EIO;
99 ptr[0x00]=E8390_NODMA+E8390_PAGE1+E8390_STOP;
100 regd=ptr[0x0D<<scale];
101 ptr[0x0D<<scale]=0xFF;
102 ptr[0x00]=E8390_NODMA+E8390_PAGE0;
103 v=ptr[0x0D<<scale];
104 if(ptr[0x0D<<scale]!=0)
106 ptr[0x0D<<scale]=regd;
107 return -ENODEV;
109 /* printk("NS8390 found at %p scaled %d\n", ptr,scale);*/
110 return 0;
113 * Identify the species of NS8390 card/driver we need
116 #define NS8390_DAYNA 1
117 #define NS8390_INTERLAN 2
118 #define NS8390_KINETICS 3
119 #define NS8390_APPLE 4
120 #define NS8390_FARALLON 5
121 #define NS8390_ASANTE 6
123 int ns8390_ident(struct nubus_type *nb)
125 /* It appears anything with a software type of 0 is an apple
126 compatible - even if the hardware matches others */
128 if(nb->DrSW==0x0001 || nb->DrSW==0x0109 || nb->DrSW==0x0000 || nb->DrSW==0x0100)
129 return NS8390_APPLE;
131 /* Dayna ex Kinetics board */
132 if(nb->DrHW==0x0103)
133 return NS8390_DAYNA;
135 /* Asante board */
136 if(nb->DrHW==0x0104)
137 return NS8390_ASANTE;
138 if(nb->DrHW==0x0100)
139 return NS8390_INTERLAN;
140 if(nb->DrHW==0x0106)
141 return NS8390_KINETICS;
142 if(nb->DrSW==0x010C)
143 return NS8390_FARALLON;
144 return -1;
148 * Memory probe for 8390 cards
151 int apple_8390_mem_probe(volatile unsigned short *p)
153 int i, j;
155 * Algorithm.
156 * 1. Check each block size of memory doesn't fault
157 * 2. Write a value to it
158 * 3. Check all previous blocks are unaffected
161 for(i=0;i<2;i++)
163 volatile unsigned short *m=p+4096*i;
164 /* Unwriteable - we have a fully decoded card and the
165 RAM end located */
167 if(hwreg_present(m)==0)
168 return 8192*i;
170 *m=0xA5A0|i;
172 for(j=0;j<i;j++)
174 /* Partial decode and wrap ? */
175 if(p[4096*j]!=(0xA5A0|j))
177 /* This is the first misdecode, so it had
178 one less page than we tried */
179 return 8192*i;
181 j++;
183 /* Ok it still decodes.. move on 8K */
186 * We don't look past 16K. That should cover most cards
187 * and above 16K there isnt really any gain.
189 return 16384;
193 * Probe for 8390 cards.
194 * The ns8390_probe1() routine initializes the card and fills the
195 * station address field. On entry base_addr is set, irq is set
196 * (These come from the nubus probe code). dev->mem_start points
197 * at the memory ring, dev->mem_end gives the end of it.
200 int ns8390_probe(struct nubus_device_specifier *d, int slot, struct nubus_type *match)
202 struct device *dev;
203 volatile unsigned short *i;
204 volatile unsigned char *p;
205 int plen;
206 int id;
208 if(match->category!=NUBUS_CAT_NETWORK || match->type!=1)
209 return -ENODEV;
210 /* Ok so it is an ethernet network device */
211 if((id=ns8390_ident(match))==-1)
213 printk("Ethernet but type unknown %d\n",match->DrHW);
214 return -ENODEV;
216 dev = init_etherdev(0, 0);
217 if(dev==NULL)
218 return -ENOMEM;
221 * Dayna specific init
223 if(id==NS8390_DAYNA)
225 dev->base_addr=(int)(nubus_slot_addr(slot)+DAYNA_8390_BASE);
226 dev->mem_start=(int)(nubus_slot_addr(slot)+DAYNA_8390_MEM);
227 dev->mem_end=dev->mem_start+DAYNA_MEMSIZE; /* 8K it seems */
229 printk("daynaport: testing board: ");
231 printk("memory - ");
233 i=(void *)dev->mem_start;
234 memset((void *)i,0xAA, DAYNA_MEMSIZE);
235 while(i<(volatile unsigned short *)dev->mem_end)
237 if(*i!=0xAAAA)
238 goto membad;
239 *i=0x5555;
240 if(*i!=0x5555)
241 goto membad;
242 i+=2; /* Skip a word */
245 printk("controller - ");
247 p=(void *)dev->base_addr;
248 plen=0;
250 while(plen<0x3FF00)
252 if(test_8390(p,0)==0)
253 break;
254 if(test_8390(p,1)==0)
255 break;
256 if(test_8390(p,2)==0)
257 break;
258 if(test_8390(p,3)==0)
259 break;
260 plen++;
261 p++;
263 if(plen==0x3FF00)
264 goto membad;
265 printk("OK\n");
266 dev->irq=slot;
267 if(ns8390_probe1(dev, 0, "dayna", id, -1)==0)
268 return 0;
270 /* Apple, Farallon, Asante */
271 if(id==NS8390_APPLE|| id==NS8390_FARALLON || id==NS8390_ASANTE)
273 int memsize;
275 dev->base_addr=(int)(nubus_slot_addr(slot)+APPLE_8390_BASE);
276 dev->mem_start=(int)(nubus_slot_addr(slot)+APPLE_8390_MEM);
278 memsize = apple_8390_mem_probe((void *)dev->mem_start);
280 dev->mem_end=dev->mem_start+memsize;
281 dev->irq=slot;
282 printk("apple/clone: testing board: ");
284 printk("%dK memory - ", memsize>>10);
286 i=(void *)dev->mem_start;
287 memset((void *)i,0xAA, memsize);
288 while(i<(volatile unsigned short *)dev->mem_end)
290 if(*i!=0xAAAA)
291 goto membad;
292 *i=0x5555;
293 if(*i!=0x5555)
294 goto membad;
295 i+=2; /* Skip a word */
297 printk("OK\n");
299 if(id==NS8390_FARALLON)
301 if(ns8390_probe1(dev, 1, "farallon", id, -1)==0)
302 return 0;
304 else
306 if(ns8390_probe1(dev, 1, "apple/clone", id, -1)==0)
307 return 0;
310 /* Interlan */
311 if(id==NS8390_INTERLAN)
313 /* As apple and asante */
314 dev->base_addr=(int)(nubus_slot_addr(slot)+APPLE_8390_BASE);
315 dev->mem_start=(int)(nubus_slot_addr(slot)+APPLE_8390_MEM);
316 dev->mem_end=dev->mem_start+APPLE_MEMSIZE; /* 8K it seems */
317 dev->irq=slot;
318 if(ns8390_probe1(dev, 1, "interlan", id, -1)==0)
319 return 0;
321 /* Kinetics */
322 if(id==NS8390_KINETICS)
324 dev->base_addr=(int)(nubus_slot_addr(slot)+KINETICS_8390_BASE);
325 dev->mem_start=(int)(nubus_slot_addr(slot)+KINETICS_8390_MEM);
326 dev->mem_end=dev->mem_start+KINETICS_MEMSIZE; /* 8K it seems */
327 dev->irq=slot;
328 if(ns8390_probe1(dev, 0, "kinetics", id, -1)==0)
329 return 0;
331 kfree(dev);
332 return -ENODEV;
333 membad:
334 printk("failed.\n");
335 kfree(dev);
336 return -ENODEV;
339 int ns8390_probe1(struct device *dev, int word16, char *model_name, int type, int promoff)
341 static unsigned version_printed = 0;
343 static u32 fwrd4_offsets[16]={
344 0, 4, 8, 12,
345 16, 20, 24, 28,
346 32, 36, 40, 44,
347 48, 52, 56, 60
349 static u32 back4_offsets[16]={
350 60, 56, 52, 48,
351 44, 40, 36, 32,
352 28, 24, 20, 16,
353 12, 8, 4, 0
356 unsigned char *prom=((unsigned char *)nubus_slot_addr(dev->irq))+promoff;
358 if (ei_debug && version_printed++ == 0)
359 printk(version);
361 /* Snarf the interrupt now. There's no point in waiting since we cannot
362 share a slot! and the board will usually be enabled. */
363 if (nubus_request_irq(dev->irq, dev, ei_interrupt))
365 printk (" unable to get nubus IRQ %d.\n", dev->irq);
366 return EAGAIN;
369 /* Allocate dev->priv and fill in 8390 specific dev fields. */
370 if (ethdev_init(dev))
372 printk (" unable to get memory for dev->priv.\n");
373 nubus_free_irq(dev->irq);
374 return -ENOMEM;
377 /* OK, we are certain this is going to work. Setup the device. */
379 ei_status.name = model_name;
380 ei_status.word16 = word16;
381 ei_status.tx_start_page = WD_START_PG;
382 ei_status.rx_start_page = WD_START_PG + TX_PAGES;
384 dev->rmem_start = dev->mem_start + TX_PAGES*256;
385 ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
386 dev->rmem_end = dev->mem_end;
388 if(promoff==-1) /* Use nubus resources ? */
390 if(nubus_ethernet_addr(dev->irq /* slot */, dev->dev_addr))
392 printk("mac_ns8390: MAC address not in resources!\n");
393 return -ENODEV;
396 else /* Pull it off the card */
398 int i=0;
399 int x=1;
400 /* These should go in the end I hope */
401 if(type==NS8390_DAYNA)
402 x=2;
403 if(type==NS8390_INTERLAN)
404 x=4;
405 while(i<6)
407 dev->dev_addr[i]=*prom;
408 prom+=x;
409 if(i)
410 printk(":");
411 printk("%02X",dev->dev_addr[i++]);
415 printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
416 model_name, dev->irq, dev->mem_start, dev->mem_end-1);
418 switch(type)
420 case NS8390_DAYNA: /* Dayna card */
421 /* 16 bit, 4 word offsets */
422 ei_status.reset_8390 = &ns8390_no_reset;
423 ei_status.block_input = &dayna_block_input;
424 ei_status.block_output = &dayna_block_output;
425 ei_status.get_8390_hdr = &dayna_get_8390_hdr;
426 ei_status.reg_offset = fwrd4_offsets;
427 break;
428 case NS8390_FARALLON:
429 case NS8390_APPLE: /* Apple/Asante/Farallon */
430 /* 16 bit card, register map is reversed */
431 ei_status.reset_8390 = &ns8390_no_reset;
432 ei_status.block_input = &slow_sane_block_input;
433 ei_status.block_output = &slow_sane_block_output;
434 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
435 ei_status.reg_offset = back4_offsets;
436 break;
437 case NS8390_ASANTE:
438 /* 16 bit card, register map is reversed */
439 ei_status.reset_8390 = &ns8390_no_reset;
440 ei_status.block_input = &sane_block_input;
441 ei_status.block_output = &sane_block_output;
442 ei_status.get_8390_hdr = &sane_get_8390_hdr;
443 ei_status.reg_offset = back4_offsets;
444 break;
445 case NS8390_INTERLAN: /* Interlan */
446 /* 16 bit card, map is forward */
447 ei_status.reset_8390 = &interlan_reset;
448 ei_status.block_input = &sane_block_input;
449 ei_status.block_output = &sane_block_output;
450 ei_status.get_8390_hdr = &sane_get_8390_hdr;
451 ei_status.reg_offset = back4_offsets;
452 break;
453 case NS8390_KINETICS: /* Kinetics */
454 /* 8bit card, map is forward */
455 ei_status.reset_8390 = &ns8390_no_reset;
456 ei_status.block_input = &sane_block_input;
457 ei_status.block_output = &sane_block_output;
458 ei_status.get_8390_hdr = &sane_get_8390_hdr;
459 ei_status.reg_offset = back4_offsets;
460 break;
461 default:
462 panic("Detected a card I can't drive - whoops\n");
464 dev->open = &ns8390_open;
465 dev->stop = &ns8390_close_card;
467 NS8390_init(dev, 0);
469 return 0;
472 static int ns8390_open(struct device *dev)
474 ei_open(dev);
475 MOD_INC_USE_COUNT;
476 return 0;
479 static void ns8390_no_reset(struct device *dev)
481 if (ei_debug > 1)
482 printk("Need to reset the NS8390 t=%lu...", jiffies);
483 ei_status.txing = 0;
484 if (ei_debug > 1) printk("reset not supported\n");
485 return;
488 static int ns8390_close_card(struct device *dev)
490 if (ei_debug > 1)
491 printk("%s: Shutting down ethercard.\n", dev->name);
492 ei_close(dev);
493 MOD_DEC_USE_COUNT;
494 return 0;
497 struct nubus_device_specifier nubus_8390={
498 ns8390_probe,
499 NULL
504 * Interlan Specific Code Starts Here
507 static void interlan_reset(struct device *dev)
509 unsigned char *target=nubus_slot_addr(dev->irq);
510 if (ei_debug > 1)
511 printk("Need to reset the NS8390 t=%lu...", jiffies);
512 ei_status.txing = 0;
513 /* This write resets the card */
514 target[0xC0000]=0;
515 if (ei_debug > 1) printk("reset complete\n");
516 return;
520 * Daynaport code (some is used by other drivers)
524 /* Grab the 8390 specific header. Similar to the block_input routine, but
525 we don't need to be concerned with ring wrap as the header will be at
526 the start of a page, so we optimize accordingly. */
529 /* Block input and output are easy on shared memory ethercards, and trivial
530 on the Daynaport card where there is no choice of how to do it.
531 The only complications are that the ring buffer wraps.
534 static void dayna_cpu_memcpy(struct device *dev, void *to, int from, int count)
536 volatile unsigned short *ptr;
537 unsigned short *target=to;
538 from<<=1; /* word, skip overhead */
539 ptr=(unsigned short *)(dev->mem_start+from);
540 while(count>=2)
542 *target++=*ptr++; /* Copy and */
543 ptr++; /* Cruft and */
544 count-=2;
547 * Trailing byte ?
549 if(count)
551 /* Big endian */
552 unsigned short v=*ptr;
553 *((char *)target)=v>>8;
557 static void cpu_dayna_memcpy(struct device *dev, int to, const void *from, int count)
559 volatile unsigned short *ptr;
560 const unsigned short *src=from;
561 to<<=1; /* word, skip overhead */
562 ptr=(unsigned short *)(dev->mem_start+to);
563 while(count>=2)
565 *ptr++=*src++; /* Copy and */
566 ptr++; /* Cruft and */
567 count-=2;
570 * Trailing byte ?
572 if(count)
574 /* Big endian */
575 unsigned short v=*src;
576 *((char *)ptr)=v>>8;
580 static void dayna_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
582 unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
583 dayna_cpu_memcpy(dev, (void *)hdr, hdr_start, 4);
584 /* Register endianism - fix here rather than 8390.c */
585 hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
588 static void dayna_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
590 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
591 unsigned long xfer_start = xfer_base+dev->mem_start;
594 * Note the offset maths is done in card memory space which
595 * is word per long onto our space.
598 if (xfer_start + count > dev->rmem_end)
600 /* We must wrap the input move. */
601 int semi_count = dev->rmem_end - xfer_start;
602 dayna_cpu_memcpy(dev, skb->data, xfer_base, semi_count);
603 count -= semi_count;
604 dayna_cpu_memcpy(dev, skb->data + semi_count,
605 dev->rmem_start - dev->mem_start, count);
607 else
609 dayna_cpu_memcpy(dev, skb->data, xfer_base, count);
613 static void dayna_block_output(struct device *dev, int count, const unsigned char *buf,
614 int start_page)
616 long shmem = (start_page - WD_START_PG)<<8;
618 cpu_dayna_memcpy(dev, shmem, buf, count);
622 * Cards with full width memory
626 static void sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
628 unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
629 memcpy((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
630 /* Register endianism - fix here rather than 8390.c */
631 hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
634 static void sane_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
636 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
637 unsigned long xfer_start = xfer_base+dev->mem_start;
639 if (xfer_start + count > dev->rmem_end)
641 /* We must wrap the input move. */
642 int semi_count = dev->rmem_end - xfer_start;
643 memcpy(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
644 count -= semi_count;
645 memcpy(skb->data + semi_count,
646 (char *)dev->rmem_start, count);
648 else
650 memcpy(skb->data, (char *)dev->mem_start+xfer_base, count);
655 static void sane_block_output(struct device *dev, int count, const unsigned char *buf,
656 int start_page)
658 long shmem = (start_page - WD_START_PG)<<8;
660 memcpy((char *)dev->mem_start+shmem, buf, count);
663 static void word_memcpy_tocard(void *tp, const void *fp, int count)
665 volatile unsigned short *to = tp;
666 const unsigned short *from = fp;
668 count++;
669 count/=2;
671 while(count--)
672 *to++=*from++;
675 static void word_memcpy_fromcard(void *tp, const void *fp, int count)
677 unsigned short *to = tp;
678 const volatile unsigned short *from = fp;
680 count++;
681 count/=2;
683 while(count--)
684 *to++=*from++;
687 static void slow_sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
689 unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
690 word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
691 /* Register endianism - fix here rather than 8390.c */
692 hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
695 static void slow_sane_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
697 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
698 unsigned long xfer_start = xfer_base+dev->mem_start;
700 if (xfer_start + count > dev->rmem_end)
702 /* We must wrap the input move. */
703 int semi_count = dev->rmem_end - xfer_start;
704 word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
705 count -= semi_count;
706 word_memcpy_fromcard(skb->data + semi_count,
707 (char *)dev->rmem_start, count);
709 else
711 word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, count);
715 static void slow_sane_block_output(struct device *dev, int count, const unsigned char *buf,
716 int start_page)
718 long shmem = (start_page - WD_START_PG)<<8;
720 word_memcpy_tocard((char *)dev->mem_start+shmem, buf, count);
721 #if 0
722 long shmem = (start_page - WD_START_PG)<<8;
723 volatile unsigned short *to=(unsigned short *)(dev->mem_start+shmem);
724 volatile int p;
725 unsigned short *bp=(unsigned short *)buf;
727 count=(count+1)/2;
729 while(count--)
731 *to++=*bp++;
732 for(p=0;p<10;p++)
733 p++;
735 #endif
739 * Local variables:
740 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c daynaport.c"
741 * version-control: t
742 * tab-width: 4
743 * kept-new-versions: 5
744 * End: