Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / net / daynaport.c
blobee4ba5876a4c7ba1208d27d39b9fc4fdc3aa8cc5
1 /* daynaport.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 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.
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 */
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;
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>
43 #include <linux/netdevice.h>
44 #include <linux/etherdevice.h>
45 #include "8390.h"
47 int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
48 int prom, struct nubus_dev *ndev);
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);
54 /* Interlan */
55 static void interlan_reset(struct net_device *dev);
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);
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);
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);
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 */
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 */
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 ! */
96 #define APPLE_8390_BASE 0xE0000
97 #define APPLE_8390_MEM 0xD0000
98 #define APPLE_MEMSIZE 8192 /* FIXME: need to dynamically check */
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 */
106 #define CABLETRON_8390_BASE 0x90000
107 #define CABLETRON_8390_MEM 0x00000
109 static int test_8390(volatile char *ptr, int scale)
111 int regd;
112 int v;
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)
127 ptr[0x0D<<scale]=regd;
128 return -ENODEV;
130 /* printk("NS8390 found at %p scaled %d\n", ptr,scale);*/
131 return 0;
134 * Identify the species of NS8390 card/driver we need
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
147 int __init ns8390_ident(struct nubus_dev* ndev)
149 /* This really needs to be tested and tested hard. */
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]
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;
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;
189 /* FIXME: what do genuine Apple boards look like? */
190 return -1;
194 * Memory probe for 8390 cards
197 int __init apple_8390_mem_probe(volatile unsigned short *p)
199 int i, j;
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
207 for(i=0;i<2;i++)
209 volatile unsigned short *m=p+4096*i;
210 /* Unwriteable - we have a fully decoded card and the
211 RAM end located */
213 if(hwreg_present(m)==0)
214 return 8192*i;
216 *m=0xA5A0|i;
218 for(j=0;j<i;j++)
220 /* Partial decode and wrap ? */
221 if(p[4096*j]!=(0xA5A0|j))
223 /* This is the first misdecode, so it had
224 one less page than we tried */
225 return 8192*i;
227 j++;
229 /* Ok it still decodes.. move on 8K */
232 * We don't look past 16K. That should cover most cards
233 * and above 16K there isnt really any gain.
235 return 16384;
239 * Probe for 8390 cards.
240 * The ns8390_probe1() routine initializes the card and fills the
241 * station address field.
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.
247 * dev->mem_start points
248 * at the memory ring, dev->mem_end gives the end of it.
251 int __init mac8390_probe(struct net_device *dev)
253 static int slots = 0;
254 volatile unsigned short *i;
255 volatile unsigned char *p;
256 int plen;
257 int id;
258 static struct nubus_dev* ndev = NULL;
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;
268 /* Is it one of ours? */
269 if ((id = ns8390_ident(ndev)) != -1)
270 break;
273 /* Hm. No more cards, then */
274 if (ndev == NULL)
275 return -ENODEV;
277 dev = init_etherdev(dev, 0);
279 if (!version_printed) {
280 printk(KERN_INFO "%s", version);
281 version_printed = 1;
285 * Dayna specific init
287 if(id==NS8390_DAYNA)
289 dev->base_addr = (int)(ndev->board->slot_addr+DAYNA_8390_BASE);
290 dev->mem_start = (int)(ndev->board->slot_addr+DAYNA_8390_MEM);
291 dev->mem_end = dev->mem_start+DAYNA_MEMSIZE; /* 8K it seems */
293 printk(KERN_INFO "%s: daynaport. testing board: ", dev->name);
295 printk("memory - ");
297 i = (void *)dev->mem_start;
298 memset((void *)i,0xAA, DAYNA_MEMSIZE);
299 while(i<(volatile unsigned short *)dev->mem_end)
301 if(*i!=0xAAAA)
302 goto membad;
303 *i=0x5678; /* make sure we catch byte smearing */
304 if(*i!=0x5678)
305 goto membad;
306 i+=2; /* Skip a word */
309 printk("controller - ");
311 p=(void *)dev->base_addr;
312 plen=0;
314 while(plen<0x3FF00)
316 if(test_8390(p,0)==0)
317 break;
318 if(test_8390(p,1)==0)
319 break;
320 if(test_8390(p,2)==0)
321 break;
322 if(test_8390(p,3)==0)
323 break;
324 plen++;
325 p++;
327 if(plen==0x3FF00)
328 goto membad;
329 printk("OK\n");
330 dev->irq = SLOT2IRQ(ndev->board->slot);
331 if(ns8390_probe1(dev, 0, "dayna", id, -1, ndev)==0)
332 return 0;
334 /* Cabletron */
335 if (id==NS8390_CABLETRON) {
336 int memsize = 16<<10; /* fix this */
338 dev->base_addr=(int)(ndev->board->slot_addr+CABLETRON_8390_BASE);
339 dev->mem_start=(int)(ndev->board->slot_addr+CABLETRON_8390_MEM);
340 dev->mem_end=dev->mem_start+memsize;
341 dev->irq = SLOT2IRQ(ndev->board->slot);
343 /* The base address is unreadable if 0x00 has been written to the command register */
344 /* Reset the chip by writing E8390_NODMA+E8390_PAGE0+E8390_STOP just to be sure */
345 i = (void *)dev->base_addr;
346 *i = 0x21;
348 printk(KERN_INFO "%s: cabletron: testing board: ", dev->name);
349 printk("%dK memory - ", memsize>>10);
350 i=(void *)dev->mem_start;
351 while(i<(volatile unsigned short *)(dev->mem_start+memsize))
353 *i=0xAAAA;
354 if(*i!=0xAAAA)
355 goto membad;
356 *i=0x5555;
357 if(*i!=0x5555)
358 goto membad;
359 i+=2; /* Skip a word */
361 printk("OK\n");
363 if(ns8390_probe1(dev, 1, "cabletron", id, -1, ndev)==0)
364 return 0;
366 /* Apple, Farallon, Asante */
367 if(id==NS8390_APPLE || id==NS8390_FARALLON || id==NS8390_ASANTE)
369 int memsize;
371 dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
372 dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
374 memsize = apple_8390_mem_probe((void *)dev->mem_start);
376 dev->mem_end=dev->mem_start+memsize;
377 dev->irq = SLOT2IRQ(ndev->board->slot);
379 switch(id)
381 case NS8390_FARALLON:
382 printk(KERN_INFO "%s: farallon: testing board: ", dev->name);
383 break;
384 case NS8390_ASANTE:
385 printk(KERN_INFO "%s: asante: testing board: ", dev->name);
386 break;
387 case NS8390_APPLE:
388 default:
389 printk(KERN_INFO "%s: apple/clone: testing board: ", dev->name);
390 break;
393 printk("%dK memory - ", memsize>>10);
395 i=(void *)dev->mem_start;
396 memset((void *)i,0xAA, memsize);
397 while(i<(volatile unsigned short *)dev->mem_end)
399 if(*i!=0xAAAA)
400 goto membad;
401 *i=0x5555;
402 if(*i!=0x5555)
403 goto membad;
404 i+=2; /* Skip a word */
406 printk("OK\n");
408 switch (id)
410 case NS8390_FARALLON:
411 if(ns8390_probe1(dev, 1, "farallon", id, -1, ndev)==0)
412 return 0;
413 break;
414 case NS8390_ASANTE:
415 if(ns8390_probe1(dev, 1, "asante", id, -1, ndev)==0)
416 return 0;
417 break;
418 case NS8390_APPLE:
419 default:
420 if(ns8390_probe1(dev, 1, "apple/clone", id, -1, ndev)==0)
421 return 0;
422 break;
425 /* Interlan */
426 if(id==NS8390_INTERLAN)
428 /* As apple and asante */
429 dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
430 dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
431 dev->mem_end=dev->mem_start+APPLE_MEMSIZE; /* 8K it seems */
432 dev->irq = SLOT2IRQ(ndev->board->slot);
433 if(ns8390_probe1(dev, 1, "interlan", id, -1, ndev)==0)
434 return 0;
436 /* Kinetics (Shiva Etherport) */
437 if(id==NS8390_KINETICS)
439 dev->base_addr=(int)(ndev->board->slot_addr+KINETICS_8390_BASE);
440 dev->mem_start=(int)(ndev->board->slot_addr+KINETICS_8390_MEM);
441 dev->mem_end=dev->mem_start+KINETICS_MEMSIZE; /* 8K it seems */
442 dev->irq = SLOT2IRQ(ndev->board->slot);
443 if(ns8390_probe1(dev, 0, "kinetics", id, -1, ndev)==0)
444 return 0;
447 /* We should hopefully not get here */
448 printk(KERN_ERR "Probe unsucessful.\n");
449 return -ENODEV;
451 membad:
452 printk(KERN_ERR "failed at %p in %p - %p.\n", i,
453 (void *)dev->mem_start, (void *)dev->mem_end);
454 return -ENODEV;
457 int __init mac8390_ethernet_addr(struct nubus_dev* ndev,
458 unsigned char addr[6])
460 struct nubus_dir dir;
461 struct nubus_dirent ent;
463 /* Get the functional resource for this device */
464 if (nubus_get_func_dir(ndev, &dir) == -1)
465 return -1;
466 if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1)
467 return -1;
469 nubus_get_rsrc_mem(addr, &ent, 6);
470 return 0;
473 int __init ns8390_probe1(struct net_device *dev, int word16, char *model_name,
474 int type, int promoff, struct nubus_dev *ndev)
476 static u32 fwrd4_offsets[16]={
477 0, 4, 8, 12,
478 16, 20, 24, 28,
479 32, 36, 40, 44,
480 48, 52, 56, 60
482 static u32 back4_offsets[16]={
483 60, 56, 52, 48,
484 44, 40, 36, 32,
485 28, 24, 20, 16,
486 12, 8, 4, 0
488 static u32 fwrd2_offsets[16]={
489 0, 2, 4, 6,
490 8, 10, 12, 14,
491 16, 18, 20, 22,
492 24, 26, 28, 30
495 unsigned char *prom = (unsigned char*) ndev->board->slot_addr + promoff;
497 /* Allocate dev->priv and fill in 8390 specific dev fields. */
498 if (ethdev_init(dev))
500 printk ("%s: unable to get memory for dev->priv.\n", dev->name);
501 return -ENOMEM;
504 /* OK, we are certain this is going to work. Setup the device. */
506 ei_status.name = model_name;
507 ei_status.word16 = word16;
509 if (type==NS8390_CABLETRON) {
510 /* Cabletron card puts the RX buffer before the TX buffer */
511 ei_status.tx_start_page = CABLETRON_TX_START_PG;
512 ei_status.rx_start_page = CABLETRON_RX_START_PG;
513 ei_status.stop_page = CABLETRON_RX_STOP_PG;
514 dev->rmem_start = dev->mem_start;
515 dev->rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
516 } else {
517 ei_status.tx_start_page = WD_START_PG;
518 ei_status.rx_start_page = WD_START_PG + TX_PAGES;
519 ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
520 dev->rmem_start = dev->mem_start + TX_PAGES*256;
521 dev->rmem_end = dev->mem_end;
524 if(promoff==-1) /* Use nubus resources ? */
526 if(mac8390_ethernet_addr(ndev, dev->dev_addr))
528 printk("mac_ns8390: MAC address not in resources!\n");
529 return -ENODEV;
532 else /* Pull it off the card */
534 int i=0;
535 int x=1;
536 /* These should go in the end I hope */
537 if(type==NS8390_DAYNA)
538 x=2;
539 if(type==NS8390_INTERLAN || type==NS8390_KINETICS)
540 x=4;
541 while(i<6)
543 dev->dev_addr[i]=*prom;
544 prom+=x;
545 if(i)
546 printk(":");
547 printk("%02X",dev->dev_addr[i++]);
551 printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
552 dev->name, ndev->board->name, ndev->board->slot, model_name);
553 printk(KERN_INFO "MAC ");
555 int i;
556 for (i = 0; i < 6; i++) {
557 printk("%2.2x", dev->dev_addr[i]);
558 if (i < 5)
559 printk(":");
562 printk(" IRQ %d, shared memory at %#lx-%#lx.\n",
563 dev->irq, dev->mem_start, dev->mem_end-1);
565 switch(type)
567 case NS8390_DAYNA: /* Dayna card */
568 case NS8390_KINETICS: /* Kinetics -- 8 bit config, but 16 bit mem */
569 /* 16 bit, 4 word offsets */
570 ei_status.reset_8390 = &ns8390_no_reset;
571 ei_status.block_input = &dayna_block_input;
572 ei_status.block_output = &dayna_block_output;
573 ei_status.get_8390_hdr = &dayna_get_8390_hdr;
574 ei_status.reg_offset = fwrd4_offsets;
575 break;
576 case NS8390_CABLETRON: /* Cabletron */
577 /* 16 bit card, register map is short forward */
578 ei_status.reset_8390 = &ns8390_no_reset;
579 /* Ctron card won't accept 32bit values read or written to it */
580 ei_status.block_input = &slow_sane_block_input;
581 ei_status.block_output = &slow_sane_block_output;
582 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
583 ei_status.reg_offset = fwrd2_offsets;
584 break;
585 case NS8390_FARALLON:
586 case NS8390_APPLE: /* Apple/Asante/Farallon */
587 /* 16 bit card, register map is reversed */
588 ei_status.reset_8390 = &ns8390_no_reset;
589 ei_status.block_input = &slow_sane_block_input;
590 ei_status.block_output = &slow_sane_block_output;
591 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
592 ei_status.reg_offset = back4_offsets;
593 break;
594 case NS8390_ASANTE:
595 /* 16 bit card, register map is reversed */
596 ei_status.reset_8390 = &ns8390_no_reset;
597 ei_status.block_input = &sane_block_input;
598 ei_status.block_output = &sane_block_output;
599 ei_status.get_8390_hdr = &sane_get_8390_hdr;
600 ei_status.reg_offset = back4_offsets;
601 break;
602 case NS8390_INTERLAN: /* Interlan */
603 /* 16 bit card, map is forward */
604 ei_status.reset_8390 = &interlan_reset;
605 ei_status.block_input = &sane_block_input;
606 ei_status.block_output = &sane_block_output;
607 ei_status.get_8390_hdr = &sane_get_8390_hdr;
608 ei_status.reg_offset = back4_offsets;
609 break;
610 #if 0 /* i think this suffered code rot. my kinetics card has much
611 * different settings. -- CSA [22-May-1999] */
612 case NS8390_KINETICS: /* Kinetics */
613 /* 8bit card, map is forward */
614 ei_status.reset_8390 = &ns8390_no_reset;
615 ei_status.block_input = &sane_block_input;
616 ei_status.block_output = &sane_block_output;
617 ei_status.get_8390_hdr = &sane_get_8390_hdr;
618 ei_status.reg_offset = back4_offsets;
619 break;
620 #endif
621 default:
622 panic("Detected a card I can't drive - whoops\n");
624 dev->open = &ns8390_open;
625 dev->stop = &ns8390_close_card;
627 NS8390_init(dev, 0);
629 return 0;
632 static int ns8390_open(struct net_device *dev)
634 MOD_INC_USE_COUNT;
635 ei_open(dev);
637 /* At least on my card (a Focus Enhancements PDS card) I start */
638 /* getting interrupts right away, so the driver needs to be */
639 /* completely initialized before enabling the interrupt. */
640 /* - funaho@jurai.org (1999-05-17) */
642 /* Non-slow interrupt, works around issues with the SONIC driver */
643 if (request_irq(dev->irq, ei_interrupt, 0, "8390 Ethernet", dev))
645 printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
646 MOD_DEC_USE_COUNT;
647 return -EAGAIN;
649 return 0;
652 static void ns8390_no_reset(struct net_device *dev)
654 if (ei_debug > 1)
655 printk("Need to reset the NS8390 t=%lu...", jiffies);
656 ei_status.txing = 0;
657 if (ei_debug > 1) printk("reset not supported\n");
658 return;
661 static int ns8390_close_card(struct net_device *dev)
663 if (ei_debug > 1)
664 printk("%s: Shutting down ethercard.\n", dev->name);
665 free_irq(dev->irq, dev);
666 ei_close(dev);
667 MOD_DEC_USE_COUNT;
668 return 0;
672 * Interlan Specific Code Starts Here
675 static void interlan_reset(struct net_device *dev)
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;
688 * Daynaport code (some is used by other drivers)
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. */
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.
702 static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
704 volatile unsigned short *ptr;
705 unsigned short *target=to;
706 from<<=1; /* word, skip overhead */
707 ptr=(unsigned short *)(dev->mem_start+from);
709 * Leading byte?
711 if (from&2) {
712 *((char *)target)++ = *(((char *)ptr++)-1);
713 count--;
715 while(count>=2)
717 *target++=*ptr++; /* Copy and */
718 ptr++; /* skip cruft */
719 count-=2;
722 * Trailing byte ?
724 if(count)
726 /* Big endian */
727 unsigned short v=*ptr;
728 *((char *)target)=v>>8;
732 static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count)
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);
739 * Leading byte?
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--;
746 while(count>=2)
748 *ptr++=*src++; /* Copy and */
749 ptr++; /* skip cruft */
750 count-=2;
753 * Trailing byte ?
755 if(count)
757 /* Big endian */
758 unsigned short v=*src;
759 /* card doesn't like byte writes */
760 *ptr=(*ptr&0x00FF)|(v&0xFF00);
764 static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
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);
772 static void dayna_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
774 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
775 unsigned long xfer_start = xfer_base+dev->mem_start;
778 * Note the offset maths is done in card memory space which
779 * is word per long onto our space.
782 if (xfer_start + count > dev->rmem_end)
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);
791 else
793 dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
797 static void dayna_block_output(struct net_device *dev, int count, const unsigned char *buf,
798 int start_page)
800 long shmem = (start_page - WD_START_PG)<<8;
802 dayna_memcpy_tocard(dev, shmem, buf, count);
806 * Cards with full width memory
810 static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
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);
818 static void sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
820 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
821 unsigned long xfer_start = xfer_base+dev->mem_start;
823 if (xfer_start + count > dev->rmem_end)
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);
832 else
834 memcpy(skb->data, (char *)dev->mem_start+xfer_base, count);
839 static void sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
840 int start_page)
842 long shmem = (start_page - WD_START_PG)<<8;
844 memcpy((char *)dev->mem_start+shmem, buf, count);
847 static void word_memcpy_tocard(void *tp, const void *fp, int count)
849 volatile unsigned short *to = tp;
850 const unsigned short *from = fp;
852 count++;
853 count/=2;
855 while(count--)
856 *to++=*from++;
859 static void word_memcpy_fromcard(void *tp, const void *fp, int count)
861 unsigned short *to = tp;
862 const volatile unsigned short *from = fp;
864 count++;
865 count/=2;
867 while(count--)
868 *to++=*from++;
871 static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
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);
879 static void slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
881 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
882 unsigned long xfer_start = xfer_base+dev->mem_start;
884 if (xfer_start + count > dev->rmem_end)
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);
893 else
895 word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, count);
899 static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
900 int start_page)
902 long shmem = (start_page - WD_START_PG)<<8;
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;
911 count=(count+1)/2;
913 while(count--)
915 *to++=*bp++;
916 for(p=0;p<10;p++)
917 p++;
919 #endif
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: