ia64/linux-2.6.18-xen.hg

view drivers/net/mac8390.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike)
2 Ethernet cards on Linux */
3 /* Based on the former daynaport.c driver, by Alan Cox. Some code
4 taken from or inspired by skeleton.c by Donald Becker, acenic.c by
5 Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker.
7 This software may be used and distributed according to the terms of
8 the GNU Public License, incorporated herein by reference. */
10 /* 2000-02-28: support added for Dayna and Kinetics cards by
11 A.G.deWijn@phys.uu.nl */
12 /* 2000-04-04: support added for Dayna2 by bart@etpmod.phys.tue.nl */
13 /* 2001-04-18: support for DaynaPort E/LC-M by rayk@knightsmanor.org */
14 /* 2001-05-15: support for Cabletron ported from old daynaport driver
15 * and fixed access to Sonic Sys card which masquerades as a Farallon
16 * by rayk@knightsmanor.org */
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/types.h>
21 #include <linux/fcntl.h>
22 #include <linux/interrupt.h>
23 #include <linux/ptrace.h>
24 #include <linux/ioport.h>
25 #include <linux/nubus.h>
26 #include <linux/in.h>
27 #include <linux/slab.h>
28 #include <linux/string.h>
29 #include <linux/errno.h>
30 #include <linux/init.h>
31 #include <linux/netdevice.h>
32 #include <linux/etherdevice.h>
33 #include <linux/skbuff.h>
34 #include <linux/bitops.h>
36 #include <asm/system.h>
37 #include <asm/io.h>
38 #include <asm/dma.h>
39 #include <asm/hwtest.h>
40 #include <asm/macints.h>
42 #include "8390.h"
44 #define WD_START_PG 0x00 /* First page of TX buffer */
45 #define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */
46 #define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */
47 #define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG /* First page of TX buffer */
49 /* Unfortunately it seems we have to hardcode these for the moment */
50 /* Shouldn't the card know about this? Does anyone know where to read it off the card? Do we trust the data provided by the card? */
52 #define DAYNA_8390_BASE 0x80000
53 #define DAYNA_8390_MEM 0x00000
55 #define KINETICS_8390_BASE 0x80000
56 #define KINETICS_8390_MEM 0x00000
58 #define CABLETRON_8390_BASE 0x90000
59 #define CABLETRON_8390_MEM 0x00000
61 enum mac8390_type {
62 MAC8390_NONE = -1,
63 MAC8390_APPLE,
64 MAC8390_ASANTE,
65 MAC8390_FARALLON, /* Apple, Asante, and Farallon are all compatible */
66 MAC8390_CABLETRON,
67 MAC8390_DAYNA,
68 MAC8390_INTERLAN,
69 MAC8390_KINETICS,
70 MAC8390_FOCUS,
71 MAC8390_SONICSYS,
72 MAC8390_DAYNA2,
73 MAC8390_DAYNA3,
74 };
76 static const char * cardname[] = {
77 "apple",
78 "asante",
79 "farallon",
80 "cabletron",
81 "dayna",
82 "interlan",
83 "kinetics",
84 "focus",
85 "sonic systems",
86 "dayna2",
87 "dayna_lc",
88 };
90 static int word16[] = {
91 1, /* apple */
92 1, /* asante */
93 1, /* farallon */
94 1, /* cabletron */
95 0, /* dayna */
96 1, /* interlan */
97 0, /* kinetics */
98 1, /* focus (??) */
99 1, /* sonic systems */
100 1, /* dayna2 */
101 1, /* dayna-lc */
102 };
104 /* on which cards do we use NuBus resources? */
105 static int useresources[] = {
106 1, /* apple */
107 1, /* asante */
108 1, /* farallon */
109 0, /* cabletron */
110 0, /* dayna */
111 0, /* interlan */
112 0, /* kinetics */
113 0, /* focus (??) */
114 1, /* sonic systems */
115 1, /* dayna2 */
116 1, /* dayna-lc */
117 };
119 static char version[] __initdata =
120 "mac8390.c: v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
122 extern enum mac8390_type mac8390_ident(struct nubus_dev * dev);
123 extern int mac8390_memsize(unsigned long membase);
124 extern int mac8390_memtest(struct net_device * dev);
125 static int mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev,
126 enum mac8390_type type);
128 static int mac8390_open(struct net_device * dev);
129 static int mac8390_close(struct net_device * dev);
130 static void mac8390_no_reset(struct net_device *dev);
132 /* Sane (32-bit chunk memory read/write) - Apple/Asante/Farallon do this*/
133 static void sane_get_8390_hdr(struct net_device *dev,
134 struct e8390_pkt_hdr *hdr, int ring_page);
135 static void sane_block_input(struct net_device * dev, int count,
136 struct sk_buff * skb, int ring_offset);
137 static void sane_block_output(struct net_device * dev, int count,
138 const unsigned char * buf, const int start_page);
140 /* dayna_memcpy to and from card */
141 static void dayna_memcpy_fromcard(struct net_device *dev, void *to,
142 int from, int count);
143 static void dayna_memcpy_tocard(struct net_device *dev, int to,
144 const void *from, int count);
146 /* Dayna - Dayna/Kinetics use this */
147 static void dayna_get_8390_hdr(struct net_device *dev,
148 struct e8390_pkt_hdr *hdr, int ring_page);
149 static void dayna_block_input(struct net_device *dev, int count,
150 struct sk_buff *skb, int ring_offset);
151 static void dayna_block_output(struct net_device *dev, int count,
152 const unsigned char *buf, int start_page);
154 #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
155 #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
157 /* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */
158 static void slow_sane_get_8390_hdr(struct net_device *dev,
159 struct e8390_pkt_hdr *hdr, int ring_page);
160 static void slow_sane_block_input(struct net_device *dev, int count,
161 struct sk_buff *skb, int ring_offset);
162 static void slow_sane_block_output(struct net_device *dev, int count,
163 const unsigned char *buf, int start_page);
164 static void word_memcpy_tocard(void *tp, const void *fp, int count);
165 static void word_memcpy_fromcard(void *tp, const void *fp, int count);
167 enum mac8390_type __init mac8390_ident(struct nubus_dev * dev)
168 {
169 if (dev->dr_sw == NUBUS_DRSW_ASANTE)
170 return MAC8390_ASANTE;
171 if (dev->dr_sw == NUBUS_DRSW_FARALLON)
172 return MAC8390_FARALLON;
173 if (dev->dr_sw == NUBUS_DRSW_KINETICS)
174 return MAC8390_KINETICS;
175 if (dev->dr_sw == NUBUS_DRSW_DAYNA)
176 return MAC8390_DAYNA;
177 if (dev->dr_sw == NUBUS_DRSW_DAYNA2)
178 return MAC8390_DAYNA2;
179 if (dev->dr_sw == NUBUS_DRSW_DAYNA_LC)
180 return MAC8390_DAYNA3;
181 if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
182 return MAC8390_CABLETRON;
183 return MAC8390_NONE;
184 }
186 int __init mac8390_memsize(unsigned long membase)
187 {
188 unsigned long flags;
189 int i, j;
191 local_irq_save(flags);
192 /* Check up to 32K in 4K increments */
193 for (i = 0; i < 8; i++) {
194 volatile unsigned short *m = (unsigned short *) (membase + (i * 0x1000));
196 /* Unwriteable - we have a fully decoded card and the
197 RAM end located */
198 if (hwreg_present(m) == 0)
199 break;
201 /* write a distinctive byte */
202 *m = 0xA5A0 | i;
203 /* check that we read back what we wrote */
204 if (*m != (0xA5A0 | i))
205 break;
207 /* check for partial decode and wrap */
208 for (j = 0; j < i; j++) {
209 volatile unsigned short *p = (unsigned short *) (membase + (j * 0x1000));
210 if (*p != (0xA5A0 | j))
211 break;
212 }
213 }
214 local_irq_restore(flags);
215 /* in any case, we stopped once we tried one block too many,
216 or once we reached 32K */
217 return i * 0x1000;
218 }
220 struct net_device * __init mac8390_probe(int unit)
221 {
222 struct net_device *dev;
223 volatile unsigned short *i;
224 int version_disp = 0;
225 struct nubus_dev * ndev = NULL;
226 int err = -ENODEV;
228 struct nubus_dir dir;
229 struct nubus_dirent ent;
230 int offset;
231 static unsigned int slots;
233 enum mac8390_type cardtype;
235 /* probably should check for Nubus instead */
237 if (!MACH_IS_MAC)
238 return ERR_PTR(-ENODEV);
240 dev = alloc_ei_netdev();
241 if (!dev)
242 return ERR_PTR(-ENOMEM);
244 if (unit >= 0)
245 sprintf(dev->name, "eth%d", unit);
247 SET_MODULE_OWNER(dev);
249 while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET, ndev))) {
250 /* Have we seen it already? */
251 if (slots & (1<<ndev->board->slot))
252 continue;
253 slots |= 1<<ndev->board->slot;
255 if ((cardtype = mac8390_ident(ndev)) == MAC8390_NONE)
256 continue;
258 if (version_disp == 0) {
259 version_disp = 1;
260 printk(version);
261 }
263 dev->irq = SLOT2IRQ(ndev->board->slot);
264 /* This is getting to be a habit */
265 dev->base_addr = ndev->board->slot_addr | ((ndev->board->slot&0xf) << 20);
267 /* Get some Nubus info - we will trust the card's idea
268 of where its memory and registers are. */
270 if (nubus_get_func_dir(ndev, &dir) == -1) {
271 printk(KERN_ERR "%s: Unable to get Nubus functional"
272 " directory for slot %X!\n",
273 dev->name, ndev->board->slot);
274 continue;
275 }
277 /* Get the MAC address */
278 if ((nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent)) == -1) {
279 printk(KERN_INFO "%s: Couldn't get MAC address!\n",
280 dev->name);
281 continue;
282 } else {
283 nubus_get_rsrc_mem(dev->dev_addr, &ent, 6);
284 /* Some Sonic Sys cards masquerade as Farallon */
285 if (cardtype == MAC8390_FARALLON &&
286 dev->dev_addr[0] == 0x0 &&
287 dev->dev_addr[1] == 0x40 &&
288 dev->dev_addr[2] == 0x10) {
289 /* This is really Sonic Sys card */
290 cardtype = MAC8390_SONICSYS;
291 }
292 }
294 if (useresources[cardtype] == 1) {
295 nubus_rewinddir(&dir);
296 if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS, &ent) == -1) {
297 printk(KERN_ERR "%s: Memory offset resource"
298 " for slot %X not found!\n",
299 dev->name, ndev->board->slot);
300 continue;
301 }
302 nubus_get_rsrc_mem(&offset, &ent, 4);
303 dev->mem_start = dev->base_addr + offset;
304 /* yes, this is how the Apple driver does it */
305 dev->base_addr = dev->mem_start + 0x10000;
306 nubus_rewinddir(&dir);
307 if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH, &ent) == -1) {
308 printk(KERN_INFO "%s: Memory length resource"
309 " for slot %X not found"
310 ", probing\n",
311 dev->name, ndev->board->slot);
312 offset = mac8390_memsize(dev->mem_start);
313 } else {
314 nubus_get_rsrc_mem(&offset, &ent, 4);
315 }
316 dev->mem_end = dev->mem_start + offset;
317 } else {
318 switch (cardtype) {
319 case MAC8390_KINETICS:
320 case MAC8390_DAYNA: /* it's the same */
321 dev->base_addr =
322 (int)(ndev->board->slot_addr +
323 DAYNA_8390_BASE);
324 dev->mem_start =
325 (int)(ndev->board->slot_addr +
326 DAYNA_8390_MEM);
327 dev->mem_end =
328 dev->mem_start +
329 mac8390_memsize(dev->mem_start);
330 break;
331 case MAC8390_CABLETRON:
332 dev->base_addr =
333 (int)(ndev->board->slot_addr +
334 CABLETRON_8390_BASE);
335 dev->mem_start =
336 (int)(ndev->board->slot_addr +
337 CABLETRON_8390_MEM);
338 /* The base address is unreadable if 0x00
339 * has been written to the command register
340 * Reset the chip by writing E8390_NODMA +
341 * E8390_PAGE0 + E8390_STOP just to be
342 * sure
343 */
344 i = (void *)dev->base_addr;
345 *i = 0x21;
346 dev->mem_end =
347 dev->mem_start +
348 mac8390_memsize(dev->mem_start);
349 break;
351 default:
352 printk(KERN_ERR "Card type %s is"
353 " unsupported, sorry\n",
354 cardname[cardtype]);
355 continue;
356 }
357 }
359 /* Do the nasty 8390 stuff */
360 if (!mac8390_initdev(dev, ndev, cardtype))
361 break;
362 }
364 if (!ndev)
365 goto out;
366 err = register_netdev(dev);
367 if (err)
368 goto out;
369 return dev;
371 out:
372 free_netdev(dev);
373 return ERR_PTR(err);
374 }
376 #ifdef MODULE
377 MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others");
378 MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver");
379 MODULE_LICENSE("GPL");
381 /* overkill, of course */
382 static struct net_device *dev_mac8390[15];
383 int init_module(void)
384 {
385 int i;
386 for (i = 0; i < 15; i++) {
387 struct net_device *dev = mac8390_probe(-1);
388 if (IS_ERR(dev))
389 break;
390 dev_mac890[i] = dev;
391 }
392 if (!i) {
393 printk(KERN_NOTICE "mac8390.c: No useable cards found, driver NOT installed.\n");
394 return -ENODEV;
395 }
396 return 0;
397 }
399 void cleanup_module(void)
400 {
401 int i;
402 for (i = 0; i < 15; i++) {
403 struct net_device *dev = dev_mac890[i];
404 if (dev) {
405 unregister_netdev(dev);
406 free_netdev(dev);
407 }
408 }
409 }
411 #endif /* MODULE */
413 static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev,
414 enum mac8390_type type)
415 {
416 static u32 fwrd4_offsets[16]={
417 0, 4, 8, 12,
418 16, 20, 24, 28,
419 32, 36, 40, 44,
420 48, 52, 56, 60
421 };
422 static u32 back4_offsets[16]={
423 60, 56, 52, 48,
424 44, 40, 36, 32,
425 28, 24, 20, 16,
426 12, 8, 4, 0
427 };
428 static u32 fwrd2_offsets[16]={
429 0, 2, 4, 6,
430 8, 10, 12, 14,
431 16, 18, 20, 22,
432 24, 26, 28, 30
433 };
435 int access_bitmode;
437 /* Now fill in our stuff */
438 dev->open = &mac8390_open;
439 dev->stop = &mac8390_close;
440 #ifdef CONFIG_NET_POLL_CONTROLLER
441 dev->poll_controller = ei_poll;
442 #endif
444 /* GAR, ei_status is actually a macro even though it looks global */
445 ei_status.name = cardname[type];
446 ei_status.word16 = word16[type];
448 /* Cabletron's TX/RX buffers are backwards */
449 if (type == MAC8390_CABLETRON) {
450 ei_status.tx_start_page = CABLETRON_TX_START_PG;
451 ei_status.rx_start_page = CABLETRON_RX_START_PG;
452 ei_status.stop_page = CABLETRON_RX_STOP_PG;
453 ei_status.rmem_start = dev->mem_start;
454 ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
455 } else {
456 ei_status.tx_start_page = WD_START_PG;
457 ei_status.rx_start_page = WD_START_PG + TX_PAGES;
458 ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
459 ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
460 ei_status.rmem_end = dev->mem_end;
461 }
463 /* Fill in model-specific information and functions */
464 switch(type) {
465 case MAC8390_SONICSYS:
466 /* 16 bit card, register map is reversed */
467 ei_status.reset_8390 = &mac8390_no_reset;
468 ei_status.block_input = &slow_sane_block_input;
469 ei_status.block_output = &slow_sane_block_output;
470 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
471 ei_status.reg_offset = back4_offsets;
472 access_bitmode = 0;
473 break;
474 case MAC8390_FARALLON:
475 case MAC8390_APPLE:
476 case MAC8390_ASANTE:
477 case MAC8390_DAYNA2:
478 case MAC8390_DAYNA3:
479 /* 32 bit card, register map is reversed */
480 /* sane */
481 ei_status.reset_8390 = &mac8390_no_reset;
482 ei_status.block_input = &sane_block_input;
483 ei_status.block_output = &sane_block_output;
484 ei_status.get_8390_hdr = &sane_get_8390_hdr;
485 ei_status.reg_offset = back4_offsets;
486 access_bitmode = 1;
487 break;
488 case MAC8390_CABLETRON:
489 /* 16 bit card, register map is short forward */
490 ei_status.reset_8390 = &mac8390_no_reset;
491 ei_status.block_input = &slow_sane_block_input;
492 ei_status.block_output = &slow_sane_block_output;
493 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
494 ei_status.reg_offset = fwrd2_offsets;
495 access_bitmode = 0;
496 break;
497 case MAC8390_DAYNA:
498 case MAC8390_KINETICS:
499 /* 16 bit memory */
500 /* dayna and similar */
501 ei_status.reset_8390 = &mac8390_no_reset;
502 ei_status.block_input = &dayna_block_input;
503 ei_status.block_output = &dayna_block_output;
504 ei_status.get_8390_hdr = &dayna_get_8390_hdr;
505 ei_status.reg_offset = fwrd4_offsets;
506 access_bitmode = 0;
507 break;
508 default:
509 printk(KERN_ERR "Card type %s is unsupported, sorry\n", cardname[type]);
510 return -ENODEV;
511 }
513 NS8390_init(dev, 0);
515 /* Good, done, now spit out some messages */
516 printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
517 dev->name, ndev->board->name, ndev->board->slot, cardname[type]);
518 printk(KERN_INFO "MAC ");
519 {
520 int i;
521 for (i = 0; i < 6; i++) {
522 printk("%2.2x", dev->dev_addr[i]);
523 if (i < 5)
524 printk(":");
525 }
526 }
527 printk(" IRQ %d, shared memory at %#lx-%#lx, %d-bit access.\n",
528 dev->irq, dev->mem_start, dev->mem_end-1,
529 access_bitmode?32:16);
530 return 0;
531 }
533 static int mac8390_open(struct net_device *dev)
534 {
535 ei_open(dev);
536 if (request_irq(dev->irq, ei_interrupt, 0, "8390 Ethernet", dev)) {
537 printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
538 return -EAGAIN;
539 }
540 return 0;
541 }
543 static int mac8390_close(struct net_device *dev)
544 {
545 free_irq(dev->irq, dev);
546 ei_close(dev);
547 return 0;
548 }
550 static void mac8390_no_reset(struct net_device *dev)
551 {
552 ei_status.txing = 0;
553 if (ei_debug > 1)
554 printk("reset not supported\n");
555 return;
556 }
558 /* dayna_memcpy_fromio/dayna_memcpy_toio */
559 /* directly from daynaport.c by Alan Cox */
560 static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
561 {
562 volatile unsigned char *ptr;
563 unsigned char *target=to;
564 from<<=1; /* word, skip overhead */
565 ptr=(unsigned char *)(dev->mem_start+from);
566 /* Leading byte? */
567 if (from&2) {
568 *target++ = ptr[-1];
569 ptr += 2;
570 count--;
571 }
572 while(count>=2)
573 {
574 *(unsigned short *)target = *(unsigned short volatile *)ptr;
575 ptr += 4; /* skip cruft */
576 target += 2;
577 count-=2;
578 }
579 /* Trailing byte? */
580 if(count)
581 *target = *ptr;
582 }
584 static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count)
585 {
586 volatile unsigned short *ptr;
587 const unsigned char *src=from;
588 to<<=1; /* word, skip overhead */
589 ptr=(unsigned short *)(dev->mem_start+to);
590 /* Leading byte? */
591 if (to&2) { /* avoid a byte write (stomps on other data) */
592 ptr[-1] = (ptr[-1]&0xFF00)|*src++;
593 ptr++;
594 count--;
595 }
596 while(count>=2)
597 {
598 *ptr++=*(unsigned short *)src; /* Copy and */
599 ptr++; /* skip cruft */
600 src += 2;
601 count-=2;
602 }
603 /* Trailing byte? */
604 if(count)
605 {
606 /* card doesn't like byte writes */
607 *ptr=(*ptr&0x00FF)|(*src << 8);
608 }
609 }
611 /* sane block input/output */
612 static void sane_get_8390_hdr(struct net_device *dev,
613 struct e8390_pkt_hdr *hdr, int ring_page)
614 {
615 unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
616 memcpy_fromio((void *)hdr, (char *)dev->mem_start + hdr_start, 4);
617 /* Fix endianness */
618 hdr->count = swab16(hdr->count);
619 }
621 static void sane_block_input(struct net_device *dev, int count,
622 struct sk_buff *skb, int ring_offset)
623 {
624 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
625 unsigned long xfer_start = xfer_base + dev->mem_start;
627 if (xfer_start + count > ei_status.rmem_end) {
628 /* We must wrap the input move. */
629 int semi_count = ei_status.rmem_end - xfer_start;
630 memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, semi_count);
631 count -= semi_count;
632 memcpy_toio(skb->data + semi_count, (char *)ei_status.rmem_start, count);
633 } else {
634 memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, count);
635 }
636 }
638 static void sane_block_output(struct net_device *dev, int count,
639 const unsigned char *buf, int start_page)
640 {
641 long shmem = (start_page - WD_START_PG)<<8;
643 memcpy_toio((char *)dev->mem_start + shmem, buf, count);
644 }
646 /* dayna block input/output */
647 static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
648 {
649 unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
651 dayna_memcpy_fromcard(dev, (void *)hdr, hdr_start, 4);
652 /* Fix endianness */
653 hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
654 }
656 static void dayna_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
657 {
658 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
659 unsigned long xfer_start = xfer_base+dev->mem_start;
661 /* Note the offset math is done in card memory space which is word
662 per long onto our space. */
664 if (xfer_start + count > ei_status.rmem_end)
665 {
666 /* We must wrap the input move. */
667 int semi_count = ei_status.rmem_end - xfer_start;
668 dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
669 count -= semi_count;
670 dayna_memcpy_fromcard(dev, skb->data + semi_count,
671 ei_status.rmem_start - dev->mem_start,
672 count);
673 }
674 else
675 {
676 dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
677 }
678 }
680 static void dayna_block_output(struct net_device *dev, int count, const unsigned char *buf,
681 int start_page)
682 {
683 long shmem = (start_page - WD_START_PG)<<8;
685 dayna_memcpy_tocard(dev, shmem, buf, count);
686 }
688 /* Cabletron block I/O */
689 static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
690 int ring_page)
691 {
692 unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
693 word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
694 /* Register endianism - fix here rather than 8390.c */
695 hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8);
696 }
698 static void slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb,
699 int ring_offset)
700 {
701 unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
702 unsigned long xfer_start = xfer_base+dev->mem_start;
704 if (xfer_start + count > ei_status.rmem_end)
705 {
706 /* We must wrap the input move. */
707 int semi_count = ei_status.rmem_end - xfer_start;
708 word_memcpy_fromcard(skb->data, (char *)dev->mem_start +
709 xfer_base, semi_count);
710 count -= semi_count;
711 word_memcpy_fromcard(skb->data + semi_count,
712 (char *)ei_status.rmem_start, count);
713 }
714 else
715 {
716 word_memcpy_fromcard(skb->data, (char *)dev->mem_start +
717 xfer_base, count);
718 }
719 }
721 static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
722 int start_page)
723 {
724 long shmem = (start_page - WD_START_PG)<<8;
726 word_memcpy_tocard((char *)dev->mem_start + shmem, buf, count);
727 }
729 static void word_memcpy_tocard(void *tp, const void *fp, int count)
730 {
731 volatile unsigned short *to = tp;
732 const unsigned short *from = fp;
734 count++;
735 count/=2;
737 while(count--)
738 *to++=*from++;
739 }
741 static void word_memcpy_fromcard(void *tp, const void *fp, int count)
742 {
743 unsigned short *to = tp;
744 const volatile unsigned short *from = fp;
746 count++;
747 count/=2;
749 while(count--)
750 *to++=*from++;
751 }