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
26static const char *version =
27 "daynaport.c: v0.02 1999-05-17 Alan Cox (Alan.Cox@linux.org) and others\n";
28static 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
47static int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
48 int prom, struct nubus_dev *ndev);
49
50static int ns8390_open(struct net_device *dev);
51static void ns8390_no_reset(struct net_device *dev);
52static int ns8390_close_card(struct net_device *dev);
53
54
55static void interlan_reset(struct net_device *dev);
56
57
58static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
59 int ring_page);
60static void dayna_block_input(struct net_device *dev, int count,
61 struct sk_buff *skb, int ring_offset);
62static void dayna_block_output(struct net_device *dev, int count,
63 const unsigned char *buf, const int start_page);
64
65
66static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
67 int ring_page);
68static void sane_block_input(struct net_device *dev, int count,
69 struct sk_buff *skb, int ring_offset);
70static void sane_block_output(struct net_device *dev, int count,
71 const unsigned char *buf, const int start_page);
72
73
74static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
75 int ring_page);
76static void slow_sane_block_input(struct net_device *dev, int count,
77 struct sk_buff *skb, int ring_offset);
78static 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
83#define WD03_STOP_PG 0x20
84#define WD13_STOP_PG 0x40
85
86#define CABLETRON_RX_START_PG 0x00
87#define CABLETRON_RX_STOP_PG 0x30
88#define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG
89
90
91#define DAYNA_MAC_BASE 0xf0007
92#define DAYNA_8390_BASE 0x80000
93#define DAYNA_8390_MEM 0x00000
94#define DAYNA_MEMSIZE 0x04000
95
96#define APPLE_8390_BASE 0xE0000
97#define APPLE_8390_MEM 0xD0000
98#define APPLE_MEMSIZE 8192
99
100#define KINETICS_MAC_BASE 0xf0004
101#define KINETICS_8390_BASE 0x80000
102#define KINETICS_8390_MEM 0x00000
103#define KINETICS_MEMSIZE 8192
104
105
106#define CABLETRON_8390_BASE 0x90000
107#define CABLETRON_8390_MEM 0x00000
108
109static 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
131 return 0;
132}
133
134
135
136
137enum 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
147static int __init ns8390_ident(struct nubus_dev* ndev)
148{
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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)
172 return NS8390_FARALLON;
173 if(ndev->dr_sw == NUBUS_DRSW_KINETICS)
174 return NS8390_KINETICS;
175
176
177
178 if(ndev->dr_sw == NUBUS_DRSW_FOCUS)
179 return -1;
180
181
182
183 if(ndev->dr_hw == NUBUS_DRHW_CABLETRON)
184 return NS8390_CABLETRON;
185
186 if(ndev->dr_hw == NUBUS_DRHW_INTERLAN)
187 return NS8390_INTERLAN;
188
189
190 return -1;
191}
192
193
194
195
196
197static int __init apple_8390_mem_probe(volatile unsigned short *p)
198{
199 int i, j;
200
201
202
203
204
205
206
207 for(i=0;i<2;i++)
208 {
209 volatile unsigned short *m=p+4096*i;
210
211
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
221 if(p[4096*j]!=(0xA5A0|j))
222 {
223
224
225 return 8192*i;
226 }
227 j++;
228 }
229
230 }
231
232
233
234
235 return 16384;
236 }
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251int __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
261 while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
262 NUBUS_TYPE_ETHERNET, ndev)) != NULL) {
263
264 if (slots & (1<<ndev->board->slot))
265 continue;
266 slots |= 1<<ndev->board->slot;
267
268
269 if ((id = ns8390_ident(ndev)) != -1)
270 break;
271 }
272
273
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
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;
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;
307 if(*i!=0x5678)
308 goto membad;
309 i+=2;
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
338 if (id==NS8390_CABLETRON) {
339 int memsize = 16<<10;
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
347
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;
363 }
364 printk("OK\n");
365
366 if(ns8390_probe1(dev, 1, "cabletron", id, -1, ndev)==0)
367 return 0;
368 }
369
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;
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
429 if(id==NS8390_INTERLAN)
430 {
431
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;
435 dev->irq = SLOT2IRQ(ndev->board->slot);
436 if(ns8390_probe1(dev, 1, "interlan", id, -1, ndev)==0)
437 return 0;
438 }
439
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;
445 dev->irq = SLOT2IRQ(ndev->board->slot);
446 if(ns8390_probe1(dev, 0, "kinetics", id, -1, ndev)==0)
447 return 0;
448 }
449
450
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
460static 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
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
475static 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
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
507
508 ei_status.name = model_name;
509 ei_status.word16 = word16;
510
511 if (type==NS8390_CABLETRON) {
512
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 ei_status.rmem_start = dev->mem_start;
517 ei_status.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 ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
523 ei_status.rmem_end = dev->mem_end;
524 }
525
526 if(promoff==-1)
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
535 {
536 int i=0;
537 int x=1;
538
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:
570 case NS8390_KINETICS:
571
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:
579
580 ei_status.reset_8390 = &ns8390_no_reset;
581
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:
589
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
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:
605
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
613
614 case NS8390_KINETICS:
615
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
634static int ns8390_open(struct net_device *dev)
635{
636 int ret;
637
638 ei_open(dev);
639
640
641
642
643
644
645
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
654static 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
662static 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
673
674
675static 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
682 target[0xC0000]=0;
683 if (ei_debug > 1) printk("reset complete\n");
684 return;
685}
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702static 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;
707 ptr=(unsigned short *)(dev->mem_start+from);
708
709
710
711 if (from&2) {
712 *((char *)target)++ = *(((char *)ptr++)-1);
713 count--;
714 }
715 while(count>=2)
716 {
717 *target++=*ptr++;
718 ptr++;
719 count-=2;
720 }
721
722
723
724 if(count)
725 {
726
727 unsigned short v=*ptr;
728 *((char *)target)=v>>8;
729 }
730}
731
732static 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;
737 ptr=(unsigned short *)(dev->mem_start+to);
738
739
740
741 if (to&2) {
742 ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++;
743 ptr++;
744 count--;
745 }
746 while(count>=2)
747 {
748 *ptr++=*src++;
749 ptr++;
750 count-=2;
751 }
752
753
754
755 if(count)
756 {
757
758 unsigned short v=*src;
759
760 *ptr=(*ptr&0x00FF)|(v&0xFF00);
761 }
762}
763
764static 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
769 hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
770}
771
772static 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
779
780
781
782 if (xfer_start + count > ei_status.rmem_end)
783 {
784
785 int semi_count = ei_status.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 ei_status.rmem_start - dev->mem_start, count);
790 }
791 else
792 {
793 dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
794 }
795}
796
797static 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
807
808
809
810static 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
815 hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
816}
817
818static 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 > ei_status.rmem_end)
824 {
825
826 int semi_count = ei_status.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 *)ei_status.rmem_start, count);
831 }
832 else
833 {
834 memcpy(skb->data, (char *)dev->mem_start+xfer_base, count);
835 }
836}
837
838
839static 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
847static 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
859static 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
871static 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
876 hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
877}
878
879static 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 > ei_status.rmem_end)
885 {
886
887 int semi_count = ei_status.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 *)ei_status.rmem_start, count);
892 }
893 else
894 {
895 word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, count);
896 }
897}
898
899static 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
922MODULE_LICENSE("GPL");
923