File: /usr/src/linux/drivers/net/daynaport.c

1     /* daynaport.c: A Macintosh 8390 based ethernet driver for linux. */
2     /*
3     	Derived from code:
4     	
5     	Written 1993-94 by Donald Becker.
6     
7     	Copyright 1993 United States Government as represented by the
8     	Director, National Security Agency.
9     
10     	This software may be used and distributed according to the terms
11     	of the GNU General Public License, incorporated herein by reference.
12     
13     	    TODO:
14     
15     	    The block output routines may be wrong for non Dayna
16     	    cards
17     
18     		Fix this driver so that it will attempt to use the info
19     		(i.e. iobase, iosize) given to it by the new and improved
20     		NuBus code.
21     
22     		Despite its misleading filename, this driver is not Dayna-specific
23     		anymore. */
24     /* Cabletron E6100 card support added by Tony Mantler (eek@escape.ca) April 1999 */
25     
26     static const char *version =
27     	"daynaport.c: v0.02 1999-05-17 Alan Cox (Alan.Cox@linux.org) and others\n";
28     static int version_printed;
29     
30     #include <linux/module.h>
31     #include <linux/init.h>
32     #include <linux/kernel.h>
33     #include <linux/sched.h>
34     #include <linux/errno.h>
35     #include <linux/string.h>
36     #include <linux/nubus.h>
37     #include <asm/io.h>
38     #include <asm/system.h>
39     #include <asm/hwtest.h>
40     #include <asm/macints.h>
41     #include <linux/delay.h>
42     
43     #include <linux/netdevice.h>
44     #include <linux/etherdevice.h>
45     #include "8390.h"
46     
47     static int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
48     				  int prom, struct nubus_dev *ndev);
49     
50     static int ns8390_open(struct net_device *dev);
51     static void ns8390_no_reset(struct net_device *dev);
52     static int ns8390_close_card(struct net_device *dev);
53     
54     /* Interlan */
55     static void interlan_reset(struct net_device *dev);
56     
57     /* Dayna */
58     static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
59     						int ring_page);
60     static void dayna_block_input(struct net_device *dev, int count,
61     						  struct sk_buff *skb, int ring_offset);
62     static void dayna_block_output(struct net_device *dev, int count,
63     						   const unsigned char *buf, const int start_page);
64     
65     /* Sane (32-bit chunk memory read/write) */
66     static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
67     						int ring_page);
68     static void sane_block_input(struct net_device *dev, int count,
69     						  struct sk_buff *skb, int ring_offset);
70     static void sane_block_output(struct net_device *dev, int count,
71     						   const unsigned char *buf, const int start_page);
72     
73     /* Slow Sane (16-bit chunk memory read/write) */
74     static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
75     						int ring_page);
76     static void slow_sane_block_input(struct net_device *dev, int count,
77     						  struct sk_buff *skb, int ring_offset);
78     static void slow_sane_block_output(struct net_device *dev, int count,
79     						   const unsigned char *buf, const int start_page);
80     
81     
82     #define WD_START_PG	0x00	/* First page of TX buffer */
83     #define WD03_STOP_PG	0x20	/* Last page +1 of RX ring */
84     #define WD13_STOP_PG	0x40	/* Last page +1 of RX ring */
85     
86     #define CABLETRON_RX_START_PG          0x00    /* First page of RX buffer */
87     #define CABLETRON_RX_STOP_PG           0x30    /* Last page +1 of RX ring */
88     #define CABLETRON_TX_START_PG          CABLETRON_RX_STOP_PG  /* First page of TX buffer */
89     
90     
91     #define DAYNA_MAC_BASE		0xf0007
92     #define DAYNA_8390_BASE		0x80000 /* 3 */
93     #define DAYNA_8390_MEM		0x00000
94     #define DAYNA_MEMSIZE		0x04000	/* First word of each long ! */
95     
96     #define APPLE_8390_BASE		0xE0000
97     #define APPLE_8390_MEM		0xD0000
98     #define APPLE_MEMSIZE		8192    /* FIXME: need to dynamically check */
99     
100     #define KINETICS_MAC_BASE	0xf0004 /* first byte of each long */
101     #define KINETICS_8390_BASE	0x80000
102     #define KINETICS_8390_MEM	0x00000 /* first word of each long */
103     #define KINETICS_MEMSIZE	8192    /* FIXME: need to dynamically check */
104     /*#define KINETICS_MEMSIZE	(0x10000/2) * CSA: on the board I have, at least */
105     
106     #define CABLETRON_8390_BASE		0x90000	
107     #define CABLETRON_8390_MEM		0x00000
108     
109     static int test_8390(volatile char *ptr, int scale)
110     {
111     	int regd;
112     	int v;
113     	
114     	if(hwreg_present(&ptr[0x00])==0)
115     		return -EIO;
116     	if(hwreg_present(&ptr[0x0D<<scale])==0)
117     		return -EIO;
118     	if(hwreg_present(&ptr[0x0D<<scale])==0)
119     		return -EIO;
120     	ptr[0x00]=E8390_NODMA+E8390_PAGE1+E8390_STOP;
121     	regd=ptr[0x0D<<scale];
122     	ptr[0x0D<<scale]=0xFF;
123     	ptr[0x00]=E8390_NODMA+E8390_PAGE0;
124     	v=ptr[0x0D<<scale];
125     	if(ptr[0x0D<<scale]!=0)
126     	{
127     		ptr[0x0D<<scale]=regd;
128     		return -ENODEV;
129     	}
130     /*	printk("NS8390 found at %p scaled %d\n", ptr,scale);*/
131     	return 0;
132     }
133     /*
134      *    Identify the species of NS8390 card/driver we need
135      */
136     
137     enum mac8390_type {
138     	NS8390_DAYNA,
139     	NS8390_INTERLAN,
140     	NS8390_KINETICS,
141     	NS8390_APPLE,
142     	NS8390_FARALLON,
143     	NS8390_ASANTE,
144     	NS8390_CABLETRON
145     };
146     
147     static int __init ns8390_ident(struct nubus_dev* ndev)
148     {
149     	/* This really needs to be tested and tested hard.  */
150     		
151     	/* Summary of what we know so far --
152     	 * SW: 0x0104 -- asante,    16 bit, back4_offsets
153     	 * SW: 0x010b -- daynaport, 16 bit, fwrd4_offsets
154     	 * SW: 0x010c -- farallon,  16 bit, back4_offsets, no long word access
155     	 * SW: 0x011a -- focus,     [no details yet]
156     	 * SW: ?????? -- interlan,  16 bit, back4_offsets, funny reset
157     	 * SW: ?????? -- kinetics,   8 bit, back4_offsets
158     	 * -- so i've this hypothesis going that says DrSW&1 says whether the
159     	 *    map is forward or backwards -- and maybe DrSW&256 says what the
160     	 *    register spacing is -- for all cards that report a DrSW in some
161     	 *    range.
162     	 *    This would allow the "apple compatible" driver to drive many
163     	 *    seemingly different types of cards.  More DrSW info is needed
164     	 *    to investigate this properly. [CSA, 21-May-1999]
165     	 */
166     	/* Dayna ex Kinetics board */
167     	if(ndev->dr_sw == NUBUS_DRSW_DAYNA)
168     		return NS8390_DAYNA;
169     	if(ndev->dr_sw == NUBUS_DRSW_ASANTE)
170     		return NS8390_ASANTE;
171     	if(ndev->dr_sw == NUBUS_DRSW_FARALLON) /* farallon or sonic systems */
172     		return NS8390_FARALLON;
173     	if(ndev->dr_sw == NUBUS_DRSW_KINETICS)
174     		return NS8390_KINETICS;
175     	/* My ATI Engineering card with this combination crashes the */
176     	/* driver trying to xmit packets. Best not touch it for now. */
177     	/*     - 1999-05-20 (funaho@jurai.org)                       */
178     	if(ndev->dr_sw == NUBUS_DRSW_FOCUS)
179     		return -1;
180     
181     	/* Check the HW on this one, because it shares the same DrSW as
182     	   the on-board SONIC chips */
183     	if(ndev->dr_hw == NUBUS_DRHW_CABLETRON)
184     		return NS8390_CABLETRON;
185     	/* does anyone have one of these? */
186     	if(ndev->dr_hw == NUBUS_DRHW_INTERLAN)
187     		return NS8390_INTERLAN;
188     
189     	/* FIXME: what do genuine Apple boards look like? */
190     	return -1;
191     }
192     
193     /*
194      *	Memory probe for 8390 cards
195      */
196      
197     static int __init apple_8390_mem_probe(volatile unsigned short *p)
198     {
199     	int i, j;
200     	/*
201     	 *	Algorithm.
202     	 *	1.	Check each block size of memory doesn't fault
203     	 *	2.	Write a value to it
204     	 *	3.	Check all previous blocks are unaffected
205     	 */
206     	
207     	for(i=0;i<2;i++)
208     	{
209     		volatile unsigned short *m=p+4096*i;
210     		/* Unwriteable - we have a fully decoded card and the
211     		   RAM end located */
212     		   
213     		if(hwreg_present(m)==0)
214     			return 8192*i;
215     			
216     		*m=0xA5A0|i;
217     		
218     		for(j=0;j<i;j++)
219     		{
220     			/* Partial decode and wrap ? */
221     			if(p[4096*j]!=(0xA5A0|j))
222     			{
223     				/* This is the first misdecode, so it had
224     				   one less page than we tried */
225     				return 8192*i;
226     			}
227      			j++;
228      		}
229      		/* Ok it still decodes.. move on 8K */
230      	}
231      	/* 
232      	 *	We don't look past 16K. That should cover most cards
233      	 *	and above 16K there isnt really any gain.
234      	 */
235      	return 16384;
236      }
237      		
238     /*
239      *    Probe for 8390 cards.  
240      *    The ns8390_probe1() routine initializes the card and fills the
241      *    station address field.
242      *
243      *    The NuBus interface has changed!  We now scan for these somewhat
244      *    like how the PCI and Zorro drivers do.  It's not clear whether
245      *    this is actually better, but it makes things more consistent.
246      *
247      *    dev->mem_start points
248      *    at the memory ring, dev->mem_end gives the end of it.
249      */
250     
251     int __init mac8390_probe(struct net_device *dev)
252     {
253     	static int slots;
254     	volatile unsigned short *i;
255     	volatile unsigned char *p;
256     	int plen;
257     	int id;
258     	static struct nubus_dev* ndev;
259     
260     	/* Find the first card that hasn't already been seen */
261     	while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
262     								   NUBUS_TYPE_ETHERNET, ndev)) != NULL) {
263     		/* Have we seen it already? */
264     		if (slots & (1<<ndev->board->slot))
265     			continue;
266     		slots |= 1<<ndev->board->slot;
267     
268     		/* Is it one of ours? */
269     		if ((id = ns8390_ident(ndev)) != -1)
270     			break;
271     	}
272     
273     	/* Hm.  No more cards, then */
274     	if (ndev == NULL)
275     		return -ENODEV;
276     
277     	dev = init_etherdev(dev, 0);
278     	if (!dev)
279     		return -ENOMEM;
280     	SET_MODULE_OWNER(dev);
281     
282     	if (!version_printed) {
283     		printk(KERN_INFO "%s", version);
284     		version_printed = 1;
285     	}
286     
287     	/*
288     	 *	Dayna specific init
289     	 */
290     	if(id==NS8390_DAYNA)
291     	{
292     		dev->base_addr = (int)(ndev->board->slot_addr+DAYNA_8390_BASE);
293     		dev->mem_start = (int)(ndev->board->slot_addr+DAYNA_8390_MEM);
294     		dev->mem_end = dev->mem_start+DAYNA_MEMSIZE; /* 8K it seems */
295     	
296     		printk(KERN_INFO "%s: daynaport. testing board: ", dev->name);
297     			
298     		printk("memory - ");	
299     			
300     		i = (void *)dev->mem_start;
301     		memset((void *)i,0xAA, DAYNA_MEMSIZE);
302     		while(i<(volatile unsigned short *)dev->mem_end)
303     		{
304     			if(*i!=0xAAAA)
305     				goto membad;
306     			*i=0x5678; /* make sure we catch byte smearing */
307     			if(*i!=0x5678)
308     				goto membad;
309     			i+=2;	/* Skip a word */
310     		}
311     			
312     		printk("controller - ");
313     			
314     		p=(void *)dev->base_addr;
315     		plen=0;
316     			
317     		while(plen<0x3FF00)
318     		{
319     			if(test_8390(p,0)==0)
320     				break;
321     			if(test_8390(p,1)==0)
322     				break;
323     			if(test_8390(p,2)==0)
324     				break;
325     			if(test_8390(p,3)==0)
326     				break;
327     			plen++;
328     			p++;
329     		}
330     		if(plen==0x3FF00)
331     			goto membad;
332     		printk("OK\n");
333     		dev->irq = SLOT2IRQ(ndev->board->slot);
334     		if(ns8390_probe1(dev, 0, "dayna", id, -1, ndev)==0)
335     			return 0;
336     	}
337     	/* Cabletron */
338     	if (id==NS8390_CABLETRON) {
339     		int memsize = 16<<10; /* fix this */
340     		  
341     		dev->base_addr=(int)(ndev->board->slot_addr+CABLETRON_8390_BASE);
342     		dev->mem_start=(int)(ndev->board->slot_addr+CABLETRON_8390_MEM);
343     		dev->mem_end=dev->mem_start+memsize;
344     		dev->irq = SLOT2IRQ(ndev->board->slot);
345     		  
346     		/* The base address is unreadable if 0x00 has been written to the command register */
347     		/* Reset the chip by writing E8390_NODMA+E8390_PAGE0+E8390_STOP just to be sure */
348     		i = (void *)dev->base_addr;
349     		*i = 0x21;
350     		  
351     		printk(KERN_INFO "%s: cabletron: testing board: ", dev->name);
352     		printk("%dK memory - ", memsize>>10);		
353     		i=(void *)dev->mem_start;
354     		while(i<(volatile unsigned short *)(dev->mem_start+memsize))
355     		{
356     			*i=0xAAAA;
357     			if(*i!=0xAAAA)
358     				goto membad;
359     			*i=0x5555;
360     			if(*i!=0x5555)
361     				goto membad;
362     			i+=2;	/* Skip a word */
363     		}
364     		printk("OK\n");
365     		  
366     		if(ns8390_probe1(dev, 1, "cabletron", id, -1, ndev)==0)
367     			return 0;
368     	}
369     	/* Apple, Farallon, Asante */
370     	if(id==NS8390_APPLE || id==NS8390_FARALLON || id==NS8390_ASANTE)
371     	{
372     		int memsize;
373     			
374     		dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
375     		dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
376     			
377     		memsize = apple_8390_mem_probe((void *)dev->mem_start);
378     			
379     		dev->mem_end=dev->mem_start+memsize;
380     		dev->irq = SLOT2IRQ(ndev->board->slot);
381     			
382     		switch(id)
383     		{
384     		case NS8390_FARALLON:
385     			printk(KERN_INFO "%s: farallon: testing board: ", dev->name);
386     			break;
387     		case NS8390_ASANTE:
388     			printk(KERN_INFO "%s: asante: testing board: ", dev->name);
389     			break;
390     		case NS8390_APPLE:
391     		default:
392     			printk(KERN_INFO "%s: apple/clone: testing board: ", dev->name);
393     			break;
394     		}
395     			
396     		printk("%dK memory - ", memsize>>10);		
397     			
398     		i=(void *)dev->mem_start;
399     		memset((void *)i,0xAA, memsize);
400     		while(i<(volatile unsigned short *)dev->mem_end)
401     		{
402     			if(*i!=0xAAAA)
403     				goto membad;
404     			*i=0x5555;
405     			if(*i!=0x5555)
406     				goto membad;
407     			i+=2;	/* Skip a word */
408     		}
409     		printk("OK\n");
410     			
411     		switch (id)
412     		{
413     		case NS8390_FARALLON:
414     			if(ns8390_probe1(dev, 1, "farallon", id, -1, ndev)==0)
415     				return 0;
416     			break;
417     		case NS8390_ASANTE:
418     			if(ns8390_probe1(dev, 1, "asante", id, -1, ndev)==0)
419     				return 0;
420     			break;
421     		case NS8390_APPLE:
422     		default:
423     			if(ns8390_probe1(dev, 1, "apple/clone", id, -1, ndev)==0)
424     				return 0;
425     			break;
426     		}
427     	}
428     	/* Interlan */
429     	if(id==NS8390_INTERLAN)
430     	{
431     		/* As apple and asante */
432     		dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
433     		dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
434     		dev->mem_end=dev->mem_start+APPLE_MEMSIZE; /* 8K it seems */
435     		dev->irq = SLOT2IRQ(ndev->board->slot);
436     		if(ns8390_probe1(dev, 1, "interlan", id, -1, ndev)==0)
437     			return 0;
438     	}
439     	/* Kinetics (Shiva Etherport) */
440     	if(id==NS8390_KINETICS)
441     	{
442     		dev->base_addr=(int)(ndev->board->slot_addr+KINETICS_8390_BASE);
443     		dev->mem_start=(int)(ndev->board->slot_addr+KINETICS_8390_MEM);
444     		dev->mem_end=dev->mem_start+KINETICS_MEMSIZE; /* 8K it seems */
445     		dev->irq = SLOT2IRQ(ndev->board->slot);
446     		if(ns8390_probe1(dev, 0, "kinetics", id, -1, ndev)==0)
447     			return 0;
448     	}
449     
450     	/* We should hopefully not get here */
451     	printk(KERN_ERR "Probe unsuccessful.\n");
452     	return -ENODEV;
453     
454      membad:
455     	printk(KERN_ERR "failed at %p in %p - %p.\n", i,
456     		   (void *)dev->mem_start, (void *)dev->mem_end);
457     	return -ENODEV;
458     }
459     
460     static int __init mac8390_ethernet_addr(struct nubus_dev* ndev, unsigned char addr[6])
461     {
462     	struct nubus_dir dir;
463     	struct nubus_dirent ent;
464     
465     	/* Get the functional resource for this device */
466     	if (nubus_get_func_dir(ndev, &dir) == -1)
467     		return -1;
468     	if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1)
469     		return -1;
470     	
471     	nubus_get_rsrc_mem(addr, &ent, 6);
472     	return 0;
473     }
474     
475     static int __init ns8390_probe1(struct net_device *dev, int word16, char *model_name,
476     			 	int type, int promoff, struct nubus_dev *ndev)
477     {
478     	static u32 fwrd4_offsets[16]={
479     		0,      4,      8,      12,
480     		16,     20,     24,     28,
481     		32,     36,     40,     44,
482     		48,     52,     56,     60
483     	};
484     	static u32 back4_offsets[16]={
485     		60,     56,     52,     48,
486     		44,     40,     36,     32,
487     		28,     24,     20,     16,
488     		12,     8,      4,      0
489     	};
490     	static u32 fwrd2_offsets[16]={
491     		0,      2,      4,      6,
492     		8,     10,     12,     14,
493     		16,    18,     20,     22,
494     		24,    26,     28,     30
495     	};
496     
497     	unsigned char *prom = (unsigned char*) ndev->board->slot_addr + promoff;
498     
499     	/* Allocate dev->priv and fill in 8390 specific dev fields. */
500     	if (ethdev_init(dev)) 
501     	{	
502     		printk ("%s: unable to get memory for dev->priv.\n", dev->name);
503     		return -ENOMEM;
504     	}
505     
506     	/* OK, we are certain this is going to work.  Setup the device. */
507     
508     	ei_status.name = model_name;
509     	ei_status.word16 = word16;
510     
511            if (type==NS8390_CABLETRON) {
512                    /* Cabletron card puts the RX buffer before the TX buffer */
513                    ei_status.tx_start_page = CABLETRON_TX_START_PG;
514                    ei_status.rx_start_page = CABLETRON_RX_START_PG;
515                    ei_status.stop_page = CABLETRON_RX_STOP_PG;
516                    dev->rmem_start = dev->mem_start;
517                    dev->rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
518            } else {
519                    ei_status.tx_start_page = WD_START_PG;
520                    ei_status.rx_start_page = WD_START_PG + TX_PAGES;
521                    ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
522                    dev->rmem_start = dev->mem_start + TX_PAGES*256;
523                    dev->rmem_end = dev->mem_end;
524            }
525     	
526     	if(promoff==-1)		/* Use nubus resources ? */
527     	{
528     		if(mac8390_ethernet_addr(ndev, dev->dev_addr))
529     		{
530     		  printk("mac_ns8390: MAC address not in resources!\n");
531     		  return -ENODEV;
532     		}
533     	}
534     	else			/* Pull it off the card */
535     	{
536     		int i=0;
537     		int x=1;
538     		/* These should go in the end I hope */
539     		if(type==NS8390_DAYNA)
540     			x=2;
541     		if(type==NS8390_INTERLAN || type==NS8390_KINETICS)
542     			x=4;
543     		while(i<6)
544     		{
545     			dev->dev_addr[i]=*prom;
546     			prom+=x;
547     			if(i)
548     				printk(":");
549     			printk("%02X",dev->dev_addr[i++]);
550     		}
551     	}
552     
553     	printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
554     		   dev->name, ndev->board->name, ndev->board->slot, model_name);
555     	printk(KERN_INFO "MAC ");
556     	{
557     		int i;
558     		for (i = 0; i < 6; i++) {
559     			printk("%2.2x", dev->dev_addr[i]);
560     			if (i < 5)
561     				printk(":");
562     		}
563     	}
564     	printk(" IRQ %d, shared memory at %#lx-%#lx.\n",
565     		   dev->irq, dev->mem_start, dev->mem_end-1);
566     
567     	switch(type)
568     	{
569     		case NS8390_DAYNA:      /* Dayna card */
570     		case NS8390_KINETICS:   /* Kinetics --  8 bit config, but 16 bit mem */
571     			/* 16 bit, 4 word offsets */
572     			ei_status.reset_8390 = &ns8390_no_reset;
573     			ei_status.block_input = &dayna_block_input;
574     			ei_status.block_output = &dayna_block_output;
575     			ei_status.get_8390_hdr = &dayna_get_8390_hdr;
576     			ei_status.reg_offset = fwrd4_offsets;
577     			break;
578     		case NS8390_CABLETRON: /* Cabletron */
579     			/*		16 bit card, register map is short forward */
580     			ei_status.reset_8390 = &ns8390_no_reset;
581     			/* Ctron card won't accept 32bit values read or written to it */
582     			ei_status.block_input = &slow_sane_block_input;
583     			ei_status.block_output = &slow_sane_block_output;
584     			ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
585     			ei_status.reg_offset = fwrd2_offsets;
586     			break;
587     		case NS8390_FARALLON:
588     		case NS8390_APPLE:	/* Apple/Asante/Farallon */
589     			/*      16 bit card, register map is reversed */
590     			ei_status.reset_8390 = &ns8390_no_reset;
591     			ei_status.block_input = &slow_sane_block_input;
592     			ei_status.block_output = &slow_sane_block_output;
593     			ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
594     			ei_status.reg_offset = back4_offsets;
595     			break;
596     		case NS8390_ASANTE:
597     			/*      16 bit card, register map is reversed */
598     			ei_status.reset_8390 = &ns8390_no_reset;
599     			ei_status.block_input = &sane_block_input;
600     			ei_status.block_output = &sane_block_output;
601     			ei_status.get_8390_hdr = &sane_get_8390_hdr;
602     			ei_status.reg_offset = back4_offsets;
603     			break;
604     		case NS8390_INTERLAN:   /* Interlan */
605     			/*      16 bit card, map is forward */
606     			ei_status.reset_8390 = &interlan_reset;
607     			ei_status.block_input = &sane_block_input;
608     			ei_status.block_output = &sane_block_output;
609     			ei_status.get_8390_hdr = &sane_get_8390_hdr;
610     			ei_status.reg_offset = back4_offsets;
611     			break;
612     #if 0 /* i think this suffered code rot.  my kinetics card has much
613     	   * different settings.  -- CSA [22-May-1999] */
614     		case NS8390_KINETICS:   /* Kinetics */
615     			/*      8bit card, map is forward */
616     			ei_status.reset_8390 = &ns8390_no_reset;
617     			ei_status.block_input = &sane_block_input;
618     			ei_status.block_output = &sane_block_output;
619     			ei_status.get_8390_hdr = &sane_get_8390_hdr;
620     			ei_status.reg_offset = back4_offsets;
621     			break;
622     #endif
623     		default:
624     			panic("Detected a card I can't drive - whoops\n");
625     	}
626     	dev->open = &ns8390_open;
627     	dev->stop = &ns8390_close_card;
628     
629     	NS8390_init(dev, 0);
630     
631     	return 0;
632     }
633     
634     static int ns8390_open(struct net_device *dev)
635     {
636     	int ret;
637     
638     	ei_open(dev);
639     
640     	/* At least on my card (a Focus Enhancements PDS card) I start */
641     	/* getting interrupts right away, so the driver needs to be    */
642     	/* completely initialized before enabling the interrupt.        */
643     	/*                             - funaho@jurai.org (1999-05-17) */
644     
645     	/* Non-slow interrupt, works around issues with the SONIC driver */
646     	ret = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); 
647     	if (ret) {
648     		printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
649     		return ret;
650     	}
651     	return 0;
652     }
653     
654     static void ns8390_no_reset(struct net_device *dev)
655     {
656     	if (ei_debug > 1) 
657     		printk("Need to reset the NS8390 t=%lu...", jiffies);
658     	ei_status.txing = 0;
659     	if (ei_debug > 1) printk("reset not supported\n");
660     }
661     
662     static int ns8390_close_card(struct net_device *dev)
663     {
664     	if (ei_debug > 1)
665     		printk("%s: Shutting down ethercard.\n", dev->name);
666     	free_irq(dev->irq, dev);
667     	ei_close(dev);
668     	return 0;
669     }
670     
671     /*
672      *    Interlan Specific Code Starts Here
673      */
674     
675     static void interlan_reset(struct net_device *dev)
676     {
677     	unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq));
678     	if (ei_debug > 1) 
679     		printk("Need to reset the NS8390 t=%lu...", jiffies);
680     	ei_status.txing = 0;
681     	/* This write resets the card */
682     	target[0xC0000]=0;
683     	if (ei_debug > 1) printk("reset complete\n");
684     	return;
685     }
686     
687     /*
688      *    Daynaport code (some is used by other drivers)
689      */
690     
691     
692     /* Grab the 8390 specific header. Similar to the block_input routine, but
693        we don't need to be concerned with ring wrap as the header will be at
694        the start of a page, so we optimize accordingly. */
695     
696     
697     /* Block input and output are easy on shared memory ethercards, and trivial
698        on the Daynaport card where there is no choice of how to do it.
699        The only complications are that the ring buffer wraps.
700     */
701     
702     static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
703     {
704     	volatile unsigned short *ptr;
705     	unsigned short *target=to;
706     	from<<=1;	/* word, skip overhead */
707     	ptr=(unsigned short *)(dev->mem_start+from);
708     	/*
709     	 * Leading byte?
710     	 */
711     	if (from&2) {
712     		*((char *)target)++ = *(((char *)ptr++)-1);
713     		count--;
714     	}
715     	while(count>=2)
716     	{
717     		*target++=*ptr++;	/* Copy and */
718     		ptr++;			/* skip cruft */
719     		count-=2;
720     	}
721     	/*
722     	 *	Trailing byte ?
723     	 */
724     	if(count)
725     	{
726     		/* Big endian */
727     		unsigned short v=*ptr;
728     		*((char *)target)=v>>8;
729     	}
730     }
731     
732     static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count)
733     {
734     	volatile unsigned short *ptr;
735     	const unsigned short *src=from;
736     	to<<=1;	/* word, skip overhead */
737     	ptr=(unsigned short *)(dev->mem_start+to);
738     	/*
739     	 * Leading byte?
740     	 */
741     	if (to&2) { /* avoid a byte write (stomps on other data) */
742     		ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++;
743     		ptr++;
744     		count--;
745     	}
746     	while(count>=2)
747     	{
748     		*ptr++=*src++;		/* Copy and */
749     		ptr++;			/* skip cruft */
750     		count-=2;
751     	}
752     	/*
753     	 *	Trailing byte ?
754     	 */
755     	if(count)
756     	{
757     		/* Big endian */
758     		unsigned short v=*src;
759     		/* card doesn't like byte writes */
760     		*ptr=(*ptr&0x00FF)|(v&0xFF00);
761     	}
762     }
763     
764     static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
765     {
766     	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
767     	dayna_memcpy_fromcard(dev, (void *)hdr, hdr_start, 4);
768     	/* Register endianism - fix here rather than 8390.c */
769     	hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
770     }
771     
772     static void dayna_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
773     {
774     	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
775     	unsigned long xfer_start = xfer_base+dev->mem_start;
776     
777     	/*
778     	 *	Note the offset maths is done in card memory space which
779     	 *	is word per long onto our space.
780     	 */
781     	 
782     	if (xfer_start + count > dev->rmem_end) 
783     	{
784     		/* We must wrap the input move. */
785     		int semi_count = dev->rmem_end - xfer_start;
786     		dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
787     		count -= semi_count;
788     		dayna_memcpy_fromcard(dev, skb->data + semi_count, 
789     			dev->rmem_start - dev->mem_start, count);
790     	}
791     	else
792     	{
793     		dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
794     	}
795     }
796     
797     static void dayna_block_output(struct net_device *dev, int count, const unsigned char *buf,
798     				int start_page)
799     {
800     	long shmem = (start_page - WD_START_PG)<<8;
801     	
802     	dayna_memcpy_tocard(dev, shmem, buf, count);
803     }
804     
805     /*
806      *	Cards with full width memory
807      */
808     
809     
810     static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
811     {
812     	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
813     	memcpy((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
814     	/* Register endianism - fix here rather than 8390.c */
815     	hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
816     }
817     
818     static void sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
819     {
820     	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
821     	unsigned long xfer_start = xfer_base+dev->mem_start;
822     
823     	if (xfer_start + count > dev->rmem_end) 
824     	{
825     		/* We must wrap the input move. */
826     		int semi_count = dev->rmem_end - xfer_start;
827     		memcpy(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
828     		count -= semi_count;
829     		memcpy(skb->data + semi_count, 
830     			(char *)dev->rmem_start, count);
831     	}
832     	else
833     	{
834     		memcpy(skb->data, (char *)dev->mem_start+xfer_base, count);
835     	}
836     }
837     
838     
839     static void sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
840     				int start_page)
841     {
842     	long shmem = (start_page - WD_START_PG)<<8;
843     	
844     	memcpy((char *)dev->mem_start+shmem, buf, count);
845     }
846     
847     static void word_memcpy_tocard(void *tp, const void *fp, int count)
848     {
849     	volatile unsigned short *to = tp;
850     	const unsigned short *from = fp;
851     	
852     	count++;
853     	count/=2;
854     	
855     	while(count--)
856     		*to++=*from++;
857     }
858     
859     static void word_memcpy_fromcard(void *tp, const void *fp, int count)
860     {
861     	unsigned short *to = tp;
862     	const volatile unsigned short *from = fp;
863     	
864     	count++;
865     	count/=2;
866     	
867     	while(count--)
868     		*to++=*from++;
869     }
870     
871     static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
872     {
873     	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
874     	word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
875     	/* Register endianism - fix here rather than 8390.c */
876     	hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
877     }
878     
879     static void slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
880     {
881     	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
882     	unsigned long xfer_start = xfer_base+dev->mem_start;
883     
884     	if (xfer_start + count > dev->rmem_end) 
885     	{
886     		/* We must wrap the input move. */
887     		int semi_count = dev->rmem_end - xfer_start;
888     		word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
889     		count -= semi_count;
890     		word_memcpy_fromcard(skb->data + semi_count, 
891     			(char *)dev->rmem_start, count);
892     	}
893     	else
894     	{
895     		word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, count);
896     	}
897     }
898     
899     static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
900     				int start_page)
901     {
902     	long shmem = (start_page - WD_START_PG)<<8;
903     	
904     	word_memcpy_tocard((char *)dev->mem_start+shmem, buf, count);
905     #if 0
906     	long shmem = (start_page - WD_START_PG)<<8;
907     	volatile unsigned short *to=(unsigned short *)(dev->mem_start+shmem);
908     	volatile int p;
909     	unsigned short *bp=(unsigned short *)buf;
910     	
911     	count=(count+1)/2;
912     	
913     	while(count--)
914     	{
915     		*to++=*bp++;
916     		for(p=0;p<10;p++)
917     			p++;
918     	}
919     #endif	
920     }
921     
922     /*
923      * Local variables:
924      *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c daynaport.c"
925      *  version-control: t
926      *  c-basic-offset: 4
927      *  tab-width: 4
928      *  kept-new-versions: 5
929      * End:
930      */
931