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/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */ 18/* 2003-12-26: Make sure Asante cards always work. */ 19 20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 21 22#include <linux/module.h> 23#include <linux/kernel.h> 24#include <linux/types.h> 25#include <linux/fcntl.h> 26#include <linux/interrupt.h> 27#include <linux/ptrace.h> 28#include <linux/ioport.h> 29#include <linux/nubus.h> 30#include <linux/in.h> 31#include <linux/string.h> 32#include <linux/errno.h> 33#include <linux/init.h> 34#include <linux/netdevice.h> 35#include <linux/etherdevice.h> 36#include <linux/skbuff.h> 37#include <linux/bitops.h> 38#include <linux/io.h> 39 40#include <asm/system.h> 41#include <asm/dma.h> 42#include <asm/hwtest.h> 43#include <asm/macints.h> 44 45static char version[] = 46 "v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n"; 47 48#define EI_SHIFT(x) (ei_local->reg_offset[x]) 49#define ei_inb(port) in_8(port) 50#define ei_outb(val, port) out_8(port, val) 51#define ei_inb_p(port) in_8(port) 52#define ei_outb_p(val, port) out_8(port, val) 53 54#include "lib8390.c" 55 56#define WD_START_PG 0x00 /* First page of TX buffer */ 57#define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */ 58#define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */ 59#define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG 60 /* First page of TX buffer */ 61 62/* 63 * Unfortunately it seems we have to hardcode these for the moment 64 * Shouldn't the card know about this? 65 * Does anyone know where to read it off the card? 66 * Do we trust the data provided by the card? 67 */ 68 69#define DAYNA_8390_BASE 0x80000 70#define DAYNA_8390_MEM 0x00000 71 72#define CABLETRON_8390_BASE 0x90000 73#define CABLETRON_8390_MEM 0x00000 74 75#define INTERLAN_8390_BASE 0xE0000 76#define INTERLAN_8390_MEM 0xD0000 77 78enum mac8390_type { 79 MAC8390_NONE = -1, 80 MAC8390_APPLE, 81 MAC8390_ASANTE, 82 MAC8390_FARALLON, 83 MAC8390_CABLETRON, 84 MAC8390_DAYNA, 85 MAC8390_INTERLAN, 86 MAC8390_KINETICS, 87}; 88 89static const char *cardname[] = { 90 "apple", 91 "asante", 92 "farallon", 93 "cabletron", 94 "dayna", 95 "interlan", 96 "kinetics", 97}; 98 99static const int word16[] = { 100 1, /* apple */ 101 1, /* asante */ 102 1, /* farallon */ 103 1, /* cabletron */ 104 0, /* dayna */ 105 1, /* interlan */ 106 0, /* kinetics */ 107}; 108 109/* on which cards do we use NuBus resources? */ 110static const int useresources[] = { 111 1, /* apple */ 112 1, /* asante */ 113 1, /* farallon */ 114 0, /* cabletron */ 115 0, /* dayna */ 116 0, /* interlan */ 117 0, /* kinetics */ 118}; 119 120enum mac8390_access { 121 ACCESS_UNKNOWN = 0, 122 ACCESS_32, 123 ACCESS_16, 124}; 125 126extern int mac8390_memtest(struct net_device *dev); 127static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev, 128 enum mac8390_type type); 129 130static int mac8390_open(struct net_device *dev); 131static int mac8390_close(struct net_device *dev); 132static void mac8390_no_reset(struct net_device *dev); 133static void interlan_reset(struct net_device *dev); 134 135/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/ 136static void sane_get_8390_hdr(struct net_device *dev, 137 struct e8390_pkt_hdr *hdr, int ring_page); 138static void sane_block_input(struct net_device *dev, int count, 139 struct sk_buff *skb, int ring_offset); 140static void sane_block_output(struct net_device *dev, int count, 141 const unsigned char *buf, const int start_page); 142 143/* dayna_memcpy to and from card */ 144static void dayna_memcpy_fromcard(struct net_device *dev, void *to, 145 int from, int count); 146static void dayna_memcpy_tocard(struct net_device *dev, int to, 147 const void *from, int count); 148 149/* Dayna - Dayna/Kinetics use this */ 150static void dayna_get_8390_hdr(struct net_device *dev, 151 struct e8390_pkt_hdr *hdr, int ring_page); 152static void dayna_block_input(struct net_device *dev, int count, 153 struct sk_buff *skb, int ring_offset); 154static void dayna_block_output(struct net_device *dev, int count, 155 const unsigned char *buf, int start_page); 156 157#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c)) 158#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c)) 159 160#define memcmp_withio(a, b, c) memcmp((a), (void *)(b), (c)) 161 162/* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */ 163static void slow_sane_get_8390_hdr(struct net_device *dev, 164 struct e8390_pkt_hdr *hdr, int ring_page); 165static void slow_sane_block_input(struct net_device *dev, int count, 166 struct sk_buff *skb, int ring_offset); 167static void slow_sane_block_output(struct net_device *dev, int count, 168 const unsigned char *buf, int start_page); 169static void word_memcpy_tocard(unsigned long tp, const void *fp, int count); 170static void word_memcpy_fromcard(void *tp, unsigned long fp, int count); 171 172static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) 173{ 174 switch (dev->dr_sw) { 175 case NUBUS_DRSW_3COM: 176 switch (dev->dr_hw) { 177 case NUBUS_DRHW_APPLE_SONIC_NB: 178 case NUBUS_DRHW_APPLE_SONIC_LC: 179 case NUBUS_DRHW_SONNET: 180 return MAC8390_NONE; 181 break; 182 default: 183 return MAC8390_APPLE; 184 break; 185 } 186 break; 187 188 case NUBUS_DRSW_APPLE: 189 switch (dev->dr_hw) { 190 case NUBUS_DRHW_ASANTE_LC: 191 return MAC8390_NONE; 192 break; 193 case NUBUS_DRHW_CABLETRON: 194 return MAC8390_CABLETRON; 195 break; 196 default: 197 return MAC8390_APPLE; 198 break; 199 } 200 break; 201 202 case NUBUS_DRSW_ASANTE: 203 return MAC8390_ASANTE; 204 break; 205 206 case NUBUS_DRSW_TECHWORKS: 207 case NUBUS_DRSW_DAYNA2: 208 case NUBUS_DRSW_DAYNA_LC: 209 if (dev->dr_hw == NUBUS_DRHW_CABLETRON) 210 return MAC8390_CABLETRON; 211 else 212 return MAC8390_APPLE; 213 break; 214 215 case NUBUS_DRSW_FARALLON: 216 return MAC8390_FARALLON; 217 break; 218 219 case NUBUS_DRSW_KINETICS: 220 switch (dev->dr_hw) { 221 case NUBUS_DRHW_INTERLAN: 222 return MAC8390_INTERLAN; 223 break; 224 default: 225 return MAC8390_KINETICS; 226 break; 227 } 228 break; 229 230 case NUBUS_DRSW_DAYNA: 231 /* 232 * These correspond to Dayna Sonic cards 233 * which use the macsonic driver 234 */ 235 if (dev->dr_hw == NUBUS_DRHW_SMC9194 || 236 dev->dr_hw == NUBUS_DRHW_INTERLAN) 237 return MAC8390_NONE; 238 else 239 return MAC8390_DAYNA; 240 break; 241 } 242 return MAC8390_NONE; 243} 244 245static enum mac8390_access __init mac8390_testio(volatile unsigned long membase) 246{ 247 unsigned long outdata = 0xA5A0B5B0; 248 unsigned long indata = 0x00000000; 249 /* Try writing 32 bits */ 250 memcpy_toio(membase, &outdata, 4); 251 /* Now compare them */ 252 if (memcmp_withio(&outdata, membase, 4) == 0) 253 return ACCESS_32; 254 /* Write 16 bit output */ 255 word_memcpy_tocard(membase, &outdata, 4); 256 /* Now read it back */ 257 word_memcpy_fromcard(&indata, membase, 4); 258 if (outdata == indata) 259 return ACCESS_16; 260 return ACCESS_UNKNOWN; 261} 262 263static int __init mac8390_memsize(unsigned long membase) 264{ 265 unsigned long flags; 266 int i, j; 267 268 local_irq_save(flags); 269 /* Check up to 32K in 4K increments */ 270 for (i = 0; i < 8; i++) { 271 volatile unsigned short *m = (unsigned short *)(membase + (i * 0x1000)); 272 273 /* Unwriteable - we have a fully decoded card and the 274 RAM end located */ 275 if (hwreg_present(m) == 0) 276 break; 277 278 /* write a distinctive byte */ 279 *m = 0xA5A0 | i; 280 /* check that we read back what we wrote */ 281 if (*m != (0xA5A0 | i)) 282 break; 283 284 /* check for partial decode and wrap */ 285 for (j = 0; j < i; j++) { 286 volatile unsigned short *p = (unsigned short *)(membase + (j * 0x1000)); 287 if (*p != (0xA5A0 | j)) 288 break; 289 } 290 } 291 local_irq_restore(flags); 292 /* 293 * in any case, we stopped once we tried one block too many, 294 * or once we reached 32K 295 */ 296 return i * 0x1000; 297} 298 299static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev, 300 enum mac8390_type cardtype) 301{ 302 struct nubus_dir dir; 303 struct nubus_dirent ent; 304 int offset; 305 volatile unsigned short *i; 306 307 printk_once(KERN_INFO pr_fmt("%s"), version); 308 309 dev->irq = SLOT2IRQ(ndev->board->slot); 310 /* This is getting to be a habit */ 311 dev->base_addr = (ndev->board->slot_addr | 312 ((ndev->board->slot & 0xf) << 20)); 313 314 /* 315 * Get some Nubus info - we will trust the card's idea 316 * of where its memory and registers are. 317 */ 318 319 if (nubus_get_func_dir(ndev, &dir) == -1) { 320 pr_err("%s: Unable to get Nubus functional directory for slot %X!\n", 321 dev->name, ndev->board->slot); 322 return false; 323 } 324 325 /* Get the MAC address */ 326 if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) { 327 pr_info("%s: Couldn't get MAC address!\n", dev->name); 328 return false; 329 } 330 331 nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); 332 333 if (useresources[cardtype] == 1) { 334 nubus_rewinddir(&dir); 335 if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS, 336 &ent) == -1) { 337 pr_err("%s: Memory offset resource for slot %X not found!\n", 338 dev->name, ndev->board->slot); 339 return false; 340 } 341 nubus_get_rsrc_mem(&offset, &ent, 4); 342 dev->mem_start = dev->base_addr + offset; 343 /* yes, this is how the Apple driver does it */ 344 dev->base_addr = dev->mem_start + 0x10000; 345 nubus_rewinddir(&dir); 346 if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH, 347 &ent) == -1) { 348 pr_info("%s: Memory length resource for slot %X not found, probing\n", 349 dev->name, ndev->board->slot); 350 offset = mac8390_memsize(dev->mem_start); 351 } else { 352 nubus_get_rsrc_mem(&offset, &ent, 4); 353 } 354 dev->mem_end = dev->mem_start + offset; 355 } else { 356 switch (cardtype) { 357 case MAC8390_KINETICS: 358 case MAC8390_DAYNA: /* it's the same */ 359 dev->base_addr = (int)(ndev->board->slot_addr + 360 DAYNA_8390_BASE); 361 dev->mem_start = (int)(ndev->board->slot_addr + 362 DAYNA_8390_MEM); 363 dev->mem_end = dev->mem_start + 364 mac8390_memsize(dev->mem_start); 365 break; 366 case MAC8390_INTERLAN: 367 dev->base_addr = (int)(ndev->board->slot_addr + 368 INTERLAN_8390_BASE); 369 dev->mem_start = (int)(ndev->board->slot_addr + 370 INTERLAN_8390_MEM); 371 dev->mem_end = dev->mem_start + 372 mac8390_memsize(dev->mem_start); 373 break; 374 case MAC8390_CABLETRON: 375 dev->base_addr = (int)(ndev->board->slot_addr + 376 CABLETRON_8390_BASE); 377 dev->mem_start = (int)(ndev->board->slot_addr + 378 CABLETRON_8390_MEM); 379 /* The base address is unreadable if 0x00 380 * has been written to the command register 381 * Reset the chip by writing E8390_NODMA + 382 * E8390_PAGE0 + E8390_STOP just to be 383 * sure 384 */ 385 i = (void *)dev->base_addr; 386 *i = 0x21; 387 dev->mem_end = dev->mem_start + 388 mac8390_memsize(dev->mem_start); 389 break; 390 391 default: 392 pr_err("Card type %s is unsupported, sorry\n", 393 ndev->board->name); 394 return false; 395 } 396 } 397 398 return true; 399} 400 401struct net_device * __init mac8390_probe(int unit) 402{ 403 struct net_device *dev; 404 struct nubus_dev *ndev = NULL; 405 int err = -ENODEV; 406 407 static unsigned int slots; 408 409 enum mac8390_type cardtype; 410 411 /* probably should check for Nubus instead */ 412 413 if (!MACH_IS_MAC) 414 return ERR_PTR(-ENODEV); 415 416 dev = ____alloc_ei_netdev(0); 417 if (!dev) 418 return ERR_PTR(-ENOMEM); 419 420 if (unit >= 0) 421 sprintf(dev->name, "eth%d", unit); 422 423 while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET, 424 ndev))) { 425 /* Have we seen it already? */ 426 if (slots & (1 << ndev->board->slot)) 427 continue; 428 slots |= 1 << ndev->board->slot; 429 430 cardtype = mac8390_ident(ndev); 431 if (cardtype == MAC8390_NONE) 432 continue; 433 434 if (!mac8390_init(dev, ndev, cardtype)) 435 continue; 436 437 /* Do the nasty 8390 stuff */ 438 if (!mac8390_initdev(dev, ndev, cardtype)) 439 break; 440 } 441 442 if (!ndev) 443 goto out; 444 err = register_netdev(dev); 445 if (err) 446 goto out; 447 return dev; 448 449out: 450 free_netdev(dev); 451 return ERR_PTR(err); 452} 453 454#ifdef MODULE 455MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others"); 456MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver"); 457MODULE_LICENSE("GPL"); 458 459/* overkill, of course */ 460static struct net_device *dev_mac8390[15]; 461int init_module(void) 462{ 463 int i; 464 for (i = 0; i < 15; i++) { 465 struct net_device *dev = mac8390_probe(-1); 466 if (IS_ERR(dev)) 467 break; 468 dev_mac890[i] = dev; 469 } 470 if (!i) { 471 pr_notice("No useable cards found, driver NOT installed.\n"); 472 return -ENODEV; 473 } 474 return 0; 475} 476 477void cleanup_module(void) 478{ 479 int i; 480 for (i = 0; i < 15; i++) { 481 struct net_device *dev = dev_mac890[i]; 482 if (dev) { 483 unregister_netdev(dev); 484 free_netdev(dev); 485 } 486 } 487} 488 489#endif /* MODULE */ 490 491static const struct net_device_ops mac8390_netdev_ops = { 492 .ndo_open = mac8390_open, 493 .ndo_stop = mac8390_close, 494 .ndo_start_xmit = __ei_start_xmit, 495 .ndo_tx_timeout = __ei_tx_timeout, 496 .ndo_get_stats = __ei_get_stats, 497 .ndo_set_multicast_list = __ei_set_multicast_list, 498 .ndo_validate_addr = eth_validate_addr, 499 .ndo_set_mac_address = eth_mac_addr, 500 .ndo_change_mtu = eth_change_mtu, 501#ifdef CONFIG_NET_POLL_CONTROLLER 502 .ndo_poll_controller = __ei_poll, 503#endif 504}; 505 506static int __init mac8390_initdev(struct net_device *dev, 507 struct nubus_dev *ndev, 508 enum mac8390_type type) 509{ 510 static u32 fwrd4_offsets[16] = { 511 0, 4, 8, 12, 512 16, 20, 24, 28, 513 32, 36, 40, 44, 514 48, 52, 56, 60 515 }; 516 static u32 back4_offsets[16] = { 517 60, 56, 52, 48, 518 44, 40, 36, 32, 519 28, 24, 20, 16, 520 12, 8, 4, 0 521 }; 522 static u32 fwrd2_offsets[16] = { 523 0, 2, 4, 6, 524 8, 10, 12, 14, 525 16, 18, 20, 22, 526 24, 26, 28, 30 527 }; 528 529 int access_bitmode = 0; 530 531 /* Now fill in our stuff */ 532 dev->netdev_ops = &mac8390_netdev_ops; 533 534 /* GAR, ei_status is actually a macro even though it looks global */ 535 ei_status.name = cardname[type]; 536 ei_status.word16 = word16[type]; 537 538 /* Cabletron's TX/RX buffers are backwards */ 539 if (type == MAC8390_CABLETRON) { 540 ei_status.tx_start_page = CABLETRON_TX_START_PG; 541 ei_status.rx_start_page = CABLETRON_RX_START_PG; 542 ei_status.stop_page = CABLETRON_RX_STOP_PG; 543 ei_status.rmem_start = dev->mem_start; 544 ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256; 545 } else { 546 ei_status.tx_start_page = WD_START_PG; 547 ei_status.rx_start_page = WD_START_PG + TX_PAGES; 548 ei_status.stop_page = (dev->mem_end - dev->mem_start)/256; 549 ei_status.rmem_start = dev->mem_start + TX_PAGES*256; 550 ei_status.rmem_end = dev->mem_end; 551 } 552 553 /* Fill in model-specific information and functions */ 554 switch (type) { 555 case MAC8390_FARALLON: 556 case MAC8390_APPLE: 557 switch (mac8390_testio(dev->mem_start)) { 558 case ACCESS_UNKNOWN: 559 pr_err("Don't know how to access card memory!\n"); 560 return -ENODEV; 561 break; 562 563 case ACCESS_16: 564 /* 16 bit card, register map is reversed */ 565 ei_status.reset_8390 = &mac8390_no_reset; 566 ei_status.block_input = &slow_sane_block_input; 567 ei_status.block_output = &slow_sane_block_output; 568 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; 569 ei_status.reg_offset = back4_offsets; 570 break; 571 572 case ACCESS_32: 573 /* 32 bit card, register map is reversed */ 574 ei_status.reset_8390 = &mac8390_no_reset; 575 ei_status.block_input = &sane_block_input; 576 ei_status.block_output = &sane_block_output; 577 ei_status.get_8390_hdr = &sane_get_8390_hdr; 578 ei_status.reg_offset = back4_offsets; 579 access_bitmode = 1; 580 break; 581 } 582 break; 583 584 case MAC8390_ASANTE: 585 /* Some Asante cards pass the 32 bit test 586 * but overwrite system memory when run at 32 bit. 587 * so we run them all at 16 bit. 588 */ 589 ei_status.reset_8390 = &mac8390_no_reset; 590 ei_status.block_input = &slow_sane_block_input; 591 ei_status.block_output = &slow_sane_block_output; 592 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; 593 ei_status.reg_offset = back4_offsets; 594 break; 595 596 case MAC8390_CABLETRON: 597 /* 16 bit card, register map is short forward */ 598 ei_status.reset_8390 = &mac8390_no_reset; 599 ei_status.block_input = &slow_sane_block_input; 600 ei_status.block_output = &slow_sane_block_output; 601 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; 602 ei_status.reg_offset = fwrd2_offsets; 603 break; 604 605 case MAC8390_DAYNA: 606 case MAC8390_KINETICS: 607 /* 16 bit memory, register map is forward */ 608 /* dayna and similar */ 609 ei_status.reset_8390 = &mac8390_no_reset; 610 ei_status.block_input = &dayna_block_input; 611 ei_status.block_output = &dayna_block_output; 612 ei_status.get_8390_hdr = &dayna_get_8390_hdr; 613 ei_status.reg_offset = fwrd4_offsets; 614 break; 615 616 case MAC8390_INTERLAN: 617 /* 16 bit memory, register map is forward */ 618 ei_status.reset_8390 = &interlan_reset; 619 ei_status.block_input = &slow_sane_block_input; 620 ei_status.block_output = &slow_sane_block_output; 621 ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; 622 ei_status.reg_offset = fwrd4_offsets; 623 break; 624 625 default: 626 pr_err("Card type %s is unsupported, sorry\n", 627 ndev->board->name); 628 return -ENODEV; 629 } 630 631 __NS8390_init(dev, 0); 632 633 /* Good, done, now spit out some messages */ 634 pr_info("%s: %s in slot %X (type %s)\n", 635 dev->name, ndev->board->name, ndev->board->slot, 636 cardname[type]); 637 pr_info("MAC %pM IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n", 638 dev->dev_addr, dev->irq, 639 (unsigned int)(dev->mem_end - dev->mem_start) >> 10, 640 dev->mem_start, access_bitmode ? 32 : 16); 641 return 0; 642} 643 644static int mac8390_open(struct net_device *dev) 645{ 646 int err; 647 648 __ei_open(dev); 649 err = request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev); 650 if (err) 651 pr_err("%s: unable to get IRQ %d\n", dev->name, dev->irq); 652 return err; 653} 654 655static int mac8390_close(struct net_device *dev) 656{ 657 free_irq(dev->irq, dev); 658 __ei_close(dev); 659 return 0; 660} 661 662static void mac8390_no_reset(struct net_device *dev) 663{ 664 ei_status.txing = 0; 665 if (ei_debug > 1) 666 pr_info("reset not supported\n"); 667} 668 669static void interlan_reset(struct net_device *dev) 670{ 671 unsigned char *target = nubus_slot_addr(IRQ2SLOT(dev->irq)); 672 if (ei_debug > 1) 673 pr_info("Need to reset the NS8390 t=%lu...", jiffies); 674 ei_status.txing = 0; 675 target[0xC0000] = 0; 676 if (ei_debug > 1) 677 pr_cont("reset complete\n"); 678} 679 680/* dayna_memcpy_fromio/dayna_memcpy_toio */ 681/* directly from daynaport.c by Alan Cox */ 682static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, 683 int count) 684{ 685 volatile unsigned char *ptr; 686 unsigned char *target = to; 687 from <<= 1; /* word, skip overhead */ 688 ptr = (unsigned char *)(dev->mem_start+from); 689 /* Leading byte? */ 690 if (from & 2) { 691 *target++ = ptr[-1]; 692 ptr += 2; 693 count--; 694 } 695 while (count >= 2) { 696 *(unsigned short *)target = *(unsigned short volatile *)ptr; 697 ptr += 4; /* skip cruft */ 698 target += 2; 699 count -= 2; 700 } 701 /* Trailing byte? */ 702 if (count) 703 *target = *ptr; 704} 705 706static void dayna_memcpy_tocard(struct net_device *dev, int to, 707 const void *from, int count) 708{ 709 volatile unsigned short *ptr; 710 const unsigned char *src = from; 711 to <<= 1; /* word, skip overhead */ 712 ptr = (unsigned short *)(dev->mem_start+to); 713 /* Leading byte? */ 714 if (to & 2) { /* avoid a byte write (stomps on other data) */ 715 ptr[-1] = (ptr[-1]&0xFF00)|*src++; 716 ptr++; 717 count--; 718 } 719 while (count >= 2) { 720 *ptr++ = *(unsigned short *)src; /* Copy and */ 721 ptr++; /* skip cruft */ 722 src += 2; 723 count -= 2; 724 } 725 /* Trailing byte? */ 726 if (count) { 727 /* card doesn't like byte writes */ 728 *ptr = (*ptr & 0x00FF) | (*src << 8); 729 } 730} 731 732/* sane block input/output */ 733static void sane_get_8390_hdr(struct net_device *dev, 734 struct e8390_pkt_hdr *hdr, int ring_page) 735{ 736 unsigned long hdr_start = (ring_page - WD_START_PG)<<8; 737 memcpy_fromio(hdr, dev->mem_start + hdr_start, 4); 738 /* Fix endianness */ 739 hdr->count = swab16(hdr->count); 740} 741 742static void sane_block_input(struct net_device *dev, int count, 743 struct sk_buff *skb, int ring_offset) 744{ 745 unsigned long xfer_base = ring_offset - (WD_START_PG<<8); 746 unsigned long xfer_start = xfer_base + dev->mem_start; 747 748 if (xfer_start + count > ei_status.rmem_end) { 749 /* We must wrap the input move. */ 750 int semi_count = ei_status.rmem_end - xfer_start; 751 memcpy_fromio(skb->data, dev->mem_start + xfer_base, 752 semi_count); 753 count -= semi_count; 754 memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, 755 count); 756 } else { 757 memcpy_fromio(skb->data, dev->mem_start + xfer_base, count); 758 } 759} 760 761static void sane_block_output(struct net_device *dev, int count, 762 const unsigned char *buf, int start_page) 763{ 764 long shmem = (start_page - WD_START_PG)<<8; 765 766 memcpy_toio(dev->mem_start + shmem, buf, count); 767} 768 769/* dayna block input/output */ 770static void dayna_get_8390_hdr(struct net_device *dev, 771 struct e8390_pkt_hdr *hdr, int ring_page) 772{ 773 unsigned long hdr_start = (ring_page - WD_START_PG)<<8; 774 775 dayna_memcpy_fromcard(dev, hdr, hdr_start, 4); 776 /* Fix endianness */ 777 hdr->count = (hdr->count & 0xFF) << 8 | (hdr->count >> 8); 778} 779 780static void dayna_block_input(struct net_device *dev, int count, 781 struct sk_buff *skb, int ring_offset) 782{ 783 unsigned long xfer_base = ring_offset - (WD_START_PG<<8); 784 unsigned long xfer_start = xfer_base+dev->mem_start; 785 786 /* Note the offset math is done in card memory space which is word 787 per long onto our space. */ 788 789 if (xfer_start + count > ei_status.rmem_end) { 790 /* We must wrap the input move. */ 791 int semi_count = ei_status.rmem_end - xfer_start; 792 dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count); 793 count -= semi_count; 794 dayna_memcpy_fromcard(dev, skb->data + semi_count, 795 ei_status.rmem_start - dev->mem_start, 796 count); 797 } else { 798 dayna_memcpy_fromcard(dev, skb->data, xfer_base, count); 799 } 800} 801 802static void dayna_block_output(struct net_device *dev, int count, 803 const unsigned char *buf, 804 int start_page) 805{ 806 long shmem = (start_page - WD_START_PG)<<8; 807 808 dayna_memcpy_tocard(dev, shmem, buf, count); 809} 810 811/* Cabletron block I/O */ 812static void slow_sane_get_8390_hdr(struct net_device *dev, 813 struct e8390_pkt_hdr *hdr, 814 int ring_page) 815{ 816 unsigned long hdr_start = (ring_page - WD_START_PG)<<8; 817 word_memcpy_fromcard(hdr, dev->mem_start + hdr_start, 4); 818 /* Register endianism - fix here rather than 8390.c */ 819 hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8); 820} 821 822static void slow_sane_block_input(struct net_device *dev, int count, 823 struct sk_buff *skb, int ring_offset) 824{ 825 unsigned long xfer_base = ring_offset - (WD_START_PG<<8); 826 unsigned long xfer_start = xfer_base+dev->mem_start; 827 828 if (xfer_start + count > ei_status.rmem_end) { 829 /* We must wrap the input move. */ 830 int semi_count = ei_status.rmem_end - xfer_start; 831 word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base, 832 semi_count); 833 count -= semi_count; 834 word_memcpy_fromcard(skb->data + semi_count, 835 ei_status.rmem_start, count); 836 } else { 837 word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base, 838 count); 839 } 840} 841 842static void slow_sane_block_output(struct net_device *dev, int count, 843 const unsigned char *buf, int start_page) 844{ 845 long shmem = (start_page - WD_START_PG)<<8; 846 847 word_memcpy_tocard(dev->mem_start + shmem, buf, count); 848} 849 850static void word_memcpy_tocard(unsigned long tp, const void *fp, int count) 851{ 852 volatile unsigned short *to = (void *)tp; 853 const unsigned short *from = fp; 854 855 count++; 856 count /= 2; 857 858 while (count--) 859 *to++ = *from++; 860} 861 862static void word_memcpy_fromcard(void *tp, unsigned long fp, int count) 863{ 864 unsigned short *to = tp; 865 const volatile unsigned short *from = (const void *)fp; 866 867 count++; 868 count /= 2; 869 870 while (count--) 871 *to++ = *from++; 872} 873