Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.15-rc3 756 lines 21 kB view raw
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. 6 7 This software may be used and distributed according to the terms of 8 the GNU Public License, incorporated herein by reference. */ 9 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 */ 17 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> 35 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> 41 42#include "8390.h" 43 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 */ 48 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? */ 51 52#define DAYNA_8390_BASE 0x80000 53#define DAYNA_8390_MEM 0x00000 54 55#define KINETICS_8390_BASE 0x80000 56#define KINETICS_8390_MEM 0x00000 57 58#define CABLETRON_8390_BASE 0x90000 59#define CABLETRON_8390_MEM 0x00000 60 61enum 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}; 75 76static 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}; 89 90static 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}; 103 104/* on which cards do we use NuBus resources? */ 105static 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}; 118 119static char version[] __initdata = 120 "mac8390.c: v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n"; 121 122extern enum mac8390_type mac8390_ident(struct nubus_dev * dev); 123extern int mac8390_memsize(unsigned long membase); 124extern int mac8390_memtest(struct net_device * dev); 125static int mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev, 126 enum mac8390_type type); 127 128static int mac8390_open(struct net_device * dev); 129static int mac8390_close(struct net_device * dev); 130static void mac8390_no_reset(struct net_device *dev); 131 132/* Sane (32-bit chunk memory read/write) - Apple/Asante/Farallon do this*/ 133static void sane_get_8390_hdr(struct net_device *dev, 134 struct e8390_pkt_hdr *hdr, int ring_page); 135static void sane_block_input(struct net_device * dev, int count, 136 struct sk_buff * skb, int ring_offset); 137static void sane_block_output(struct net_device * dev, int count, 138 const unsigned char * buf, const int start_page); 139 140/* dayna_memcpy to and from card */ 141static void dayna_memcpy_fromcard(struct net_device *dev, void *to, 142 int from, int count); 143static void dayna_memcpy_tocard(struct net_device *dev, int to, 144 const void *from, int count); 145 146/* Dayna - Dayna/Kinetics use this */ 147static void dayna_get_8390_hdr(struct net_device *dev, 148 struct e8390_pkt_hdr *hdr, int ring_page); 149static void dayna_block_input(struct net_device *dev, int count, 150 struct sk_buff *skb, int ring_offset); 151static void dayna_block_output(struct net_device *dev, int count, 152 const unsigned char *buf, int start_page); 153 154#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) 155#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) 156 157/* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */ 158static void slow_sane_get_8390_hdr(struct net_device *dev, 159 struct e8390_pkt_hdr *hdr, int ring_page); 160static void slow_sane_block_input(struct net_device *dev, int count, 161 struct sk_buff *skb, int ring_offset); 162static void slow_sane_block_output(struct net_device *dev, int count, 163 const unsigned char *buf, int start_page); 164static void word_memcpy_tocard(void *tp, const void *fp, int count); 165static void word_memcpy_fromcard(void *tp, const void *fp, int count); 166 167enum 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} 185 186int __init mac8390_memsize(unsigned long membase) 187{ 188 unsigned long flags; 189 int i, j; 190 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)); 195 196 /* Unwriteable - we have a fully decoded card and the 197 RAM end located */ 198 if (hwreg_present(m) == 0) 199 break; 200 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; 206 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} 219 220struct 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; 227 228 struct nubus_dir dir; 229 struct nubus_dirent ent; 230 int offset; 231 static unsigned int slots; 232 233 enum mac8390_type cardtype; 234 235 /* probably should check for Nubus instead */ 236 237 if (!MACH_IS_MAC) 238 return ERR_PTR(-ENODEV); 239 240 dev = alloc_ei_netdev(); 241 if (!dev) 242 return ERR_PTR(-ENOMEM); 243 244 if (unit >= 0) 245 sprintf(dev->name, "eth%d", unit); 246 247 SET_MODULE_OWNER(dev); 248 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; 254 255 if ((cardtype = mac8390_ident(ndev)) == MAC8390_NONE) 256 continue; 257 258 if (version_disp == 0) { 259 version_disp = 1; 260 printk(version); 261 } 262 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); 266 267 /* Get some Nubus info - we will trust the card's idea 268 of where its memory and registers are. */ 269 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 } 276 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 } 293 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; 350 351 default: 352 printk(KERN_ERR "Card type %s is" 353 " unsupported, sorry\n", 354 cardname[cardtype]); 355 continue; 356 } 357 } 358 359 /* Do the nasty 8390 stuff */ 360 if (!mac8390_initdev(dev, ndev, cardtype)) 361 break; 362 } 363 364 if (!ndev) 365 goto out; 366 err = register_netdev(dev); 367 if (err) 368 goto out; 369 return dev; 370 371out: 372 free_netdev(dev); 373 return ERR_PTR(err); 374} 375 376#ifdef MODULE 377MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others"); 378MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver"); 379MODULE_LICENSE("GPL"); 380 381/* overkill, of course */ 382static struct net_device *dev_mac8390[15]; 383int 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} 398 399void 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} 410 411#endif /* MODULE */ 412 413static 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 }; 434 435 int access_bitmode; 436 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 443 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]; 447 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 } 462 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 } 512 513 NS8390_init(dev, 0); 514 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} 532 533static 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} 542 543static int mac8390_close(struct net_device *dev) 544{ 545 free_irq(dev->irq, dev); 546 ei_close(dev); 547 return 0; 548} 549 550static 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} 557 558/* dayna_memcpy_fromio/dayna_memcpy_toio */ 559/* directly from daynaport.c by Alan Cox */ 560static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) 561{ 562 volatile unsigned short *ptr; 563 unsigned short *target=to; 564 from<<=1; /* word, skip overhead */ 565 ptr=(unsigned short *)(dev->mem_start+from); 566 /* Leading byte? */ 567 if (from&2) { 568 *((char *)target)++ = *(((char *)ptr++)-1); 569 count--; 570 } 571 while(count>=2) 572 { 573 *target++=*ptr++; /* Copy and */ 574 ptr++; /* skip cruft */ 575 count-=2; 576 } 577 /* Trailing byte? */ 578 if(count) 579 { 580 /* Big endian */ 581 unsigned short v=*ptr; 582 *((char *)target)=v>>8; 583 } 584} 585 586static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count) 587{ 588 volatile unsigned short *ptr; 589 const unsigned short *src=from; 590 to<<=1; /* word, skip overhead */ 591 ptr=(unsigned short *)(dev->mem_start+to); 592 /* Leading byte? */ 593 if (to&2) { /* avoid a byte write (stomps on other data) */ 594 ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++; 595 ptr++; 596 count--; 597 } 598 while(count>=2) 599 { 600 *ptr++=*src++; /* Copy and */ 601 ptr++; /* skip cruft */ 602 count-=2; 603 } 604 /* Trailing byte? */ 605 if(count) 606 { 607 /* Big endian */ 608 unsigned short v=*src; 609 /* card doesn't like byte writes */ 610 *ptr=(*ptr&0x00FF)|(v&0xFF00); 611 } 612} 613 614/* sane block input/output */ 615static void sane_get_8390_hdr(struct net_device *dev, 616 struct e8390_pkt_hdr *hdr, int ring_page) 617{ 618 unsigned long hdr_start = (ring_page - WD_START_PG)<<8; 619 memcpy_fromio((void *)hdr, (char *)dev->mem_start + hdr_start, 4); 620 /* Fix endianness */ 621 hdr->count = swab16(hdr->count); 622} 623 624static void sane_block_input(struct net_device *dev, int count, 625 struct sk_buff *skb, int ring_offset) 626{ 627 unsigned long xfer_base = ring_offset - (WD_START_PG<<8); 628 unsigned long xfer_start = xfer_base + dev->mem_start; 629 630 if (xfer_start + count > ei_status.rmem_end) { 631 /* We must wrap the input move. */ 632 int semi_count = ei_status.rmem_end - xfer_start; 633 memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, semi_count); 634 count -= semi_count; 635 memcpy_toio(skb->data + semi_count, (char *)ei_status.rmem_start, count); 636 } else { 637 memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, count); 638 } 639} 640 641static void sane_block_output(struct net_device *dev, int count, 642 const unsigned char *buf, int start_page) 643{ 644 long shmem = (start_page - WD_START_PG)<<8; 645 646 memcpy_toio((char *)dev->mem_start + shmem, buf, count); 647} 648 649/* dayna block input/output */ 650static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) 651{ 652 unsigned long hdr_start = (ring_page - WD_START_PG)<<8; 653 654 dayna_memcpy_fromcard(dev, (void *)hdr, hdr_start, 4); 655 /* Fix endianness */ 656 hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8); 657} 658 659static void dayna_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) 660{ 661 unsigned long xfer_base = ring_offset - (WD_START_PG<<8); 662 unsigned long xfer_start = xfer_base+dev->mem_start; 663 664 /* Note the offset math is done in card memory space which is word 665 per long onto our space. */ 666 667 if (xfer_start + count > ei_status.rmem_end) 668 { 669 /* We must wrap the input move. */ 670 int semi_count = ei_status.rmem_end - xfer_start; 671 dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count); 672 count -= semi_count; 673 dayna_memcpy_fromcard(dev, skb->data + semi_count, 674 ei_status.rmem_start - dev->mem_start, 675 count); 676 } 677 else 678 { 679 dayna_memcpy_fromcard(dev, skb->data, xfer_base, count); 680 } 681} 682 683static void dayna_block_output(struct net_device *dev, int count, const unsigned char *buf, 684 int start_page) 685{ 686 long shmem = (start_page - WD_START_PG)<<8; 687 688 dayna_memcpy_tocard(dev, shmem, buf, count); 689} 690 691/* Cabletron block I/O */ 692static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, 693 int ring_page) 694{ 695 unsigned long hdr_start = (ring_page - WD_START_PG)<<8; 696 word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4); 697 /* Register endianism - fix here rather than 8390.c */ 698 hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8); 699} 700 701static void slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, 702 int ring_offset) 703{ 704 unsigned long xfer_base = ring_offset - (WD_START_PG<<8); 705 unsigned long xfer_start = xfer_base+dev->mem_start; 706 707 if (xfer_start + count > ei_status.rmem_end) 708 { 709 /* We must wrap the input move. */ 710 int semi_count = ei_status.rmem_end - xfer_start; 711 word_memcpy_fromcard(skb->data, (char *)dev->mem_start + 712 xfer_base, semi_count); 713 count -= semi_count; 714 word_memcpy_fromcard(skb->data + semi_count, 715 (char *)ei_status.rmem_start, count); 716 } 717 else 718 { 719 word_memcpy_fromcard(skb->data, (char *)dev->mem_start + 720 xfer_base, count); 721 } 722} 723 724static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf, 725 int start_page) 726{ 727 long shmem = (start_page - WD_START_PG)<<8; 728 729 word_memcpy_tocard((char *)dev->mem_start + shmem, buf, count); 730} 731 732static void word_memcpy_tocard(void *tp, const void *fp, int count) 733{ 734 volatile unsigned short *to = tp; 735 const unsigned short *from = fp; 736 737 count++; 738 count/=2; 739 740 while(count--) 741 *to++=*from++; 742} 743 744static void word_memcpy_fromcard(void *tp, const void *fp, int count) 745{ 746 unsigned short *to = tp; 747 const volatile unsigned short *from = fp; 748 749 count++; 750 count/=2; 751 752 while(count--) 753 *to++=*from++; 754} 755 756