|
|
1.1 ! root 1: /* ! 2: * AT&T GIS (nee NCR) WaveLAN card: ! 3: * An Ethernet-like radio transceiver ! 4: * controlled by an Intel 82586 coprocessor. ! 5: */ ! 6: ! 7: #include <linux/module.h> ! 8: ! 9: #include <linux/kernel.h> ! 10: #include <linux/sched.h> ! 11: #include <linux/types.h> ! 12: #include <linux/fcntl.h> ! 13: #include <linux/interrupt.h> ! 14: #include <linux/stat.h> ! 15: #include <linux/ptrace.h> ! 16: #include <linux/ioport.h> ! 17: #include <linux/in.h> ! 18: #include <linux/string.h> ! 19: #include <linux/delay.h> ! 20: #include <asm/system.h> ! 21: #include <asm/bitops.h> ! 22: #include <asm/io.h> ! 23: #include <asm/dma.h> ! 24: #include <linux/errno.h> ! 25: #include <linux/netdevice.h> ! 26: #include <linux/etherdevice.h> ! 27: #include <linux/skbuff.h> ! 28: #include <linux/malloc.h> ! 29: #include <linux/timer.h> ! 30: #include <linux/proc_fs.h> ! 31: #define STRUCT_CHECK 1 ! 32: #ifdef MACH ! 33: #include <net/i82586.h> ! 34: #else ! 35: #include "i82586.h" ! 36: #endif ! 37: #include "wavelan.h" ! 38: ! 39: #ifndef WAVELAN_DEBUG ! 40: #define WAVELAN_DEBUG 0 ! 41: #endif /* WAVELAN_DEBUG */ ! 42: ! 43: #define WATCHDOG_JIFFIES 512 /* TODO: express in HZ. */ ! 44: #define ENABLE_FULL_PROMISCUOUS 0x10000 ! 45: ! 46: #define nels(a) (sizeof(a) / sizeof(a[0])) ! 47: ! 48: typedef struct device device; ! 49: typedef struct enet_statistics en_stats; ! 50: typedef struct net_local net_local; ! 51: typedef struct timer_list timer_list; ! 52: ! 53: struct net_local ! 54: { ! 55: en_stats stats; ! 56: unsigned int tx_n_in_use; ! 57: unsigned char nwid[2]; ! 58: unsigned short hacr; ! 59: unsigned short rx_head; ! 60: unsigned short rx_last; ! 61: unsigned short tx_first_free; ! 62: unsigned short tx_first_in_use; ! 63: unsigned int nresets; ! 64: unsigned int correct_nwid; ! 65: unsigned int wrong_nwid; ! 66: unsigned int promiscuous; ! 67: unsigned int full_promiscuous; ! 68: timer_list watchdog; ! 69: device *dev; ! 70: net_local *prev; ! 71: net_local *next; ! 72: }; ! 73: ! 74: extern int wavelan_probe(device *); /* See Space.c */ ! 75: ! 76: static const char *version = "wavelan.c:v7 95/4/8\n"; ! 77: ! 78: /* ! 79: * Entry point forward declarations. ! 80: */ ! 81: static int wavelan_probe1(device *, unsigned short); ! 82: static int wavelan_open(device *); ! 83: static int wavelan_send_packet(struct sk_buff *, device *); ! 84: static void wavelan_interrupt(int, struct pt_regs *); ! 85: static int wavelan_close(device *); ! 86: static en_stats *wavelan_get_stats(device *); ! 87: static void wavelan_set_multicast_list(device *); ! 88: static int wavelan_get_info(char*, char**, off_t, int, int); ! 89: ! 90: /* ! 91: * Other forward declarations. ! 92: */ ! 93: static void wavelan_cu_show_one(device *, net_local *, int, unsigned short); ! 94: static void wavelan_cu_start(device *); ! 95: static void wavelan_ru_start(device *); ! 96: static void wavelan_watchdog(unsigned long); ! 97: #if 0 ! 98: static void wavelan_psa_show(psa_t *); ! 99: static void wavelan_mmc_show(unsigned short); ! 100: #endif /* 0 */ ! 101: static void wavelan_scb_show(unsigned short); ! 102: static void wavelan_ru_show(device *); ! 103: static void wavelan_cu_show(device *); ! 104: static void wavelan_dev_show(device *); ! 105: static void wavelan_local_show(device *); ! 106: ! 107: static unsigned int wavelan_debug = WAVELAN_DEBUG; ! 108: static net_local *first_wavelan = (net_local *)0; ! 109: ! 110: static ! 111: unsigned long ! 112: wavelan_splhi(void) ! 113: { ! 114: unsigned long flags; ! 115: ! 116: save_flags(flags); ! 117: cli(); ! 118: ! 119: return flags; ! 120: } ! 121: ! 122: static ! 123: void ! 124: wavelan_splx(unsigned long flags) ! 125: { ! 126: restore_flags(flags); ! 127: } ! 128: ! 129: static ! 130: unsigned short ! 131: hasr_read(unsigned short ioaddr) ! 132: { ! 133: return inw(HASR(ioaddr)); ! 134: } ! 135: ! 136: static ! 137: void ! 138: hacr_write(unsigned short ioaddr, int hacr) ! 139: { ! 140: outw(hacr, HACR(ioaddr)); ! 141: } ! 142: ! 143: static ! 144: void ! 145: hacr_write_slow(unsigned short ioaddr, int hacr) ! 146: { ! 147: hacr_write(ioaddr, hacr); ! 148: /* delay might only be needed sometimes */ ! 149: udelay(1000); ! 150: } ! 151: ! 152: /* ! 153: * Set the channel attention bit. ! 154: */ ! 155: static ! 156: void ! 157: set_chan_attn(unsigned short ioaddr, unsigned short current_hacr) ! 158: { ! 159: hacr_write(ioaddr, current_hacr | HACR_CA); ! 160: } ! 161: ! 162: /* ! 163: * Reset, and then set host adaptor into default mode. ! 164: */ ! 165: static ! 166: void ! 167: wavelan_reset(unsigned short ioaddr) ! 168: { ! 169: hacr_write_slow(ioaddr, HACR_RESET); ! 170: hacr_write(ioaddr, HACR_DEFAULT); ! 171: } ! 172: ! 173: static ! 174: void ! 175: wavelan_16_off(unsigned short ioaddr, unsigned short hacr) ! 176: { ! 177: hacr &= ~HACR_16BITS; ! 178: ! 179: hacr_write(ioaddr, hacr); ! 180: } ! 181: ! 182: static ! 183: void ! 184: wavelan_16_on(unsigned short ioaddr, unsigned short hacr) ! 185: { ! 186: hacr |= HACR_16BITS; ! 187: ! 188: hacr_write(ioaddr, hacr); ! 189: } ! 190: ! 191: static ! 192: void ! 193: wavelan_ints_off(device *dev) ! 194: { ! 195: unsigned short ioaddr; ! 196: net_local *lp; ! 197: unsigned long x; ! 198: ! 199: ioaddr = dev->base_addr; ! 200: lp = (net_local *)dev->priv; ! 201: ! 202: x = wavelan_splhi(); ! 203: ! 204: lp->hacr &= ~HACR_INTRON; ! 205: hacr_write(ioaddr, lp->hacr); ! 206: ! 207: wavelan_splx(x); ! 208: } ! 209: ! 210: static ! 211: void ! 212: wavelan_ints_on(device *dev) ! 213: { ! 214: unsigned short ioaddr; ! 215: net_local *lp; ! 216: unsigned long x; ! 217: ! 218: ioaddr = dev->base_addr; ! 219: lp = (net_local *)dev->priv; ! 220: ! 221: x = wavelan_splhi(); ! 222: ! 223: lp->hacr |= HACR_INTRON; ! 224: hacr_write(ioaddr, lp->hacr); ! 225: ! 226: wavelan_splx(x); ! 227: } ! 228: ! 229: /* ! 230: * Read bytes from the PSA. ! 231: */ ! 232: static ! 233: void ! 234: psa_read(unsigned short ioaddr, unsigned short hacr, int o, unsigned char *b, int n) ! 235: { ! 236: wavelan_16_off(ioaddr, hacr); ! 237: ! 238: while (n-- > 0) ! 239: { ! 240: outw(o, PIOR2(ioaddr)); ! 241: o++; ! 242: *b++ = inb(PIOP2(ioaddr)); ! 243: } ! 244: ! 245: wavelan_16_on(ioaddr, hacr); ! 246: } ! 247: ! 248: #if defined(IRQ_SET_WORKS) ! 249: /* ! 250: * Write bytes to the PSA. ! 251: */ ! 252: static ! 253: void ! 254: psa_write(unsigned short ioaddr, unsigned short hacr, int o, unsigned char *b, int n) ! 255: { ! 256: wavelan_16_off(ioaddr, hacr); ! 257: ! 258: while (n-- > 0) ! 259: { ! 260: outw(o, PIOR2(ioaddr)); ! 261: o++; ! 262: outb(*b, PIOP2(ioaddr)); ! 263: b++; ! 264: } ! 265: ! 266: wavelan_16_on(ioaddr, hacr); ! 267: } ! 268: #endif /* defined(IRQ_SET_WORKS) */ ! 269: ! 270: /* ! 271: * Read bytes from the on-board RAM. ! 272: */ ! 273: static ! 274: void ! 275: obram_read(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) ! 276: { ! 277: n = (n + 1) / (sizeof(unsigned short) / sizeof(unsigned char)); ! 278: ! 279: outw(o, PIOR1(ioaddr)); ! 280: ! 281: insw(PIOP1(ioaddr), (unsigned short *)b, n); ! 282: } ! 283: ! 284: /* ! 285: * Write bytes to the on-board RAM. ! 286: */ ! 287: static ! 288: void ! 289: obram_write(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) ! 290: { ! 291: n = (n + 1) / (sizeof(unsigned short) / sizeof(unsigned char)); ! 292: ! 293: outw(o, PIOR1(ioaddr)); ! 294: ! 295: outsw(PIOP1(ioaddr), (unsigned short *)b, n); ! 296: } ! 297: ! 298: /* ! 299: * Read bytes from the MMC. ! 300: */ ! 301: static ! 302: void ! 303: mmc_read(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) ! 304: { ! 305: while (n-- > 0) ! 306: { ! 307: while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) ! 308: ; ! 309: ! 310: outw(o << 1, MMCR(ioaddr)); ! 311: o++; ! 312: ! 313: while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) ! 314: ; ! 315: ! 316: *b++ = (unsigned char)(inw(MMCR(ioaddr)) >> 8); ! 317: } ! 318: } ! 319: ! 320: /* ! 321: * Write bytes to the MMC. ! 322: */ ! 323: static ! 324: void ! 325: mmc_write(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) ! 326: { ! 327: while (n-- > 0) ! 328: { ! 329: while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) ! 330: ; ! 331: ! 332: outw((unsigned short)(((unsigned short)*b << 8) | (o << 1) | 1), MMCR(ioaddr)); ! 333: b++; ! 334: o++; ! 335: } ! 336: } ! 337: ! 338: static int irqvals[] = ! 339: { ! 340: 0, 0, 0, 0x01, ! 341: 0x02, 0x04, 0, 0x08, ! 342: 0, 0, 0x10, 0x20, ! 343: 0x40, 0, 0, 0x80, ! 344: }; ! 345: ! 346: #if defined(IRQ_SET_WORKS) ! 347: static ! 348: int ! 349: wavelan_unmap_irq(int irq, unsigned char *irqval) ! 350: { ! 351: if (irq < 0 || irq >= nels(irqvals) || irqvals[irq] == 0) ! 352: return -1; ! 353: ! 354: *irqval = (unsigned char)irqvals[irq]; ! 355: ! 356: return 0; ! 357: } ! 358: #endif /* defined(IRQ_SET_WORKS) */ ! 359: ! 360: /* ! 361: * Map values from the irq parameter register to irq numbers. ! 362: */ ! 363: static ! 364: int ! 365: wavelan_map_irq(unsigned char irqval) ! 366: { ! 367: int irq; ! 368: ! 369: for (irq = 0; irq < nels(irqvals); irq++) ! 370: { ! 371: if (irqvals[irq] == (int)irqval) ! 372: return irq; ! 373: } ! 374: ! 375: return -1; ! 376: } ! 377: ! 378: /* ! 379: * Initialize the Modem Management Controller. ! 380: */ ! 381: static ! 382: void ! 383: wavelan_mmc_init(device *dev, psa_t *psa) ! 384: { ! 385: unsigned short ioaddr; ! 386: net_local *lp; ! 387: mmw_t m; ! 388: int configured; ! 389: ! 390: ioaddr = dev->base_addr; ! 391: lp = (net_local *)dev->priv; ! 392: memset(&m, 0x00, sizeof(m)); ! 393: ! 394: /* ! 395: * configured = psa->psa_conf_status & 1; ! 396: * ! 397: * For now we use the persistent PSA ! 398: * information as little as possible, thereby ! 399: * allowing us to return to the same known state ! 400: * during a hardware reset. ! 401: */ ! 402: configured = 0; ! 403: ! 404: /* ! 405: * Set default modem control parameters. ! 406: * See NCR document 407-0024326 Rev. A. ! 407: */ ! 408: m.mmw_jabber_enable = 0x01; ! 409: m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN; ! 410: m.mmw_ifs = 0x20; ! 411: m.mmw_mod_delay = 0x04; ! 412: m.mmw_jam_time = 0x38; ! 413: ! 414: m.mmw_encr_enable = 0; ! 415: m.mmw_des_io_invert = 0; ! 416: m.mmw_freeze = 0; ! 417: m.mmw_decay_prm = 0; ! 418: m.mmw_decay_updat_prm = 0; ! 419: ! 420: if (configured) ! 421: { ! 422: /* ! 423: * Use configuration defaults from parameter storage area. ! 424: */ ! 425: if (psa->psa_undefined & 1) ! 426: m.mmw_loopt_sel = 0x00; ! 427: else ! 428: m.mmw_loopt_sel = MMW_LOOPT_SEL_UNDEFINED; ! 429: ! 430: m.mmw_thr_pre_set = psa->psa_thr_pre_set & 0x3F; ! 431: m.mmw_quality_thr = psa->psa_quality_thr & 0x0F; ! 432: } ! 433: else ! 434: { ! 435: if (lp->promiscuous && lp->full_promiscuous) ! 436: m.mmw_loopt_sel = MMW_LOOPT_SEL_UNDEFINED; ! 437: else ! 438: m.mmw_loopt_sel = 0x00; ! 439: ! 440: /* ! 441: * 0x04 for AT, ! 442: * 0x01 for MCA. ! 443: */ ! 444: if (psa->psa_comp_number & 1) ! 445: m.mmw_thr_pre_set = 0x01; ! 446: else ! 447: m.mmw_thr_pre_set = 0x04; ! 448: ! 449: m.mmw_quality_thr = 0x03; ! 450: } ! 451: ! 452: m.mmw_netw_id_l = lp->nwid[1]; ! 453: m.mmw_netw_id_h = lp->nwid[0]; ! 454: ! 455: mmc_write(ioaddr, 0, (unsigned char *)&m, sizeof(m)); ! 456: } ! 457: ! 458: static ! 459: void ! 460: wavelan_ack(device *dev) ! 461: { ! 462: unsigned short ioaddr; ! 463: net_local *lp; ! 464: unsigned short scb_cs; ! 465: int i; ! 466: ! 467: ioaddr = dev->base_addr; ! 468: lp = (net_local *)dev->priv; ! 469: ! 470: obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs)); ! 471: scb_cs &= SCB_ST_INT; ! 472: ! 473: if (scb_cs == 0) ! 474: return; ! 475: ! 476: obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); ! 477: ! 478: set_chan_attn(ioaddr, lp->hacr); ! 479: ! 480: for (i = 1000; i > 0; i--) ! 481: { ! 482: obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); ! 483: if (scb_cs == 0) ! 484: break; ! 485: ! 486: udelay(1000); ! 487: } ! 488: ! 489: if (i <= 0) ! 490: printk("%s: wavelan_ack(): board not accepting command.\n", dev->name); ! 491: } ! 492: ! 493: /* ! 494: * Set channel attention bit and busy wait until command has ! 495: * completed, then acknowledge the command completion. ! 496: */ ! 497: static ! 498: int ! 499: wavelan_synchronous_cmd(device *dev, const char *str) ! 500: { ! 501: unsigned short ioaddr; ! 502: net_local *lp; ! 503: unsigned short scb_cmd; ! 504: ach_t cb; ! 505: int i; ! 506: ! 507: ioaddr = dev->base_addr; ! 508: lp = (net_local *)dev->priv; ! 509: ! 510: scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO; ! 511: obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cmd, sizeof(scb_cmd)); ! 512: ! 513: set_chan_attn(ioaddr, lp->hacr); ! 514: ! 515: for (i = 64; i > 0; i--) ! 516: { ! 517: obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); ! 518: if (cb.ac_status & AC_SFLD_C) ! 519: break; ! 520: ! 521: udelay(1000); ! 522: } ! 523: ! 524: if (i <= 0 || !(cb.ac_status & AC_SFLD_OK)) ! 525: { ! 526: printk("%s: %s failed; status = 0x%x\n", dev->name, str, cb.ac_status); ! 527: wavelan_scb_show(ioaddr); ! 528: return -1; ! 529: } ! 530: ! 531: wavelan_ack(dev); ! 532: ! 533: return 0; ! 534: } ! 535: ! 536: static ! 537: int ! 538: wavelan_hardware_reset(device *dev) ! 539: { ! 540: unsigned short ioaddr; ! 541: psa_t psa; ! 542: net_local *lp; ! 543: scp_t scp; ! 544: iscp_t iscp; ! 545: scb_t scb; ! 546: ach_t cb; ! 547: int i; ! 548: ac_cfg_t cfg; ! 549: ac_ias_t ias; ! 550: ! 551: if (wavelan_debug > 0) ! 552: printk("%s: ->wavelan_hardware_reset(dev=0x%x)\n", dev->name, (unsigned int)dev); ! 553: ! 554: ioaddr = dev->base_addr; ! 555: lp = (net_local *)dev->priv; ! 556: ! 557: lp->nresets++; ! 558: ! 559: wavelan_reset(ioaddr); ! 560: lp->hacr = HACR_DEFAULT; ! 561: ! 562: /* ! 563: * Clear the onboard RAM. ! 564: */ ! 565: { ! 566: unsigned char zeroes[512]; ! 567: ! 568: memset(&zeroes[0], 0x00, sizeof(zeroes)); ! 569: ! 570: for (i = 0; i < I82586_MEMZ; i += sizeof(zeroes)) ! 571: obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes)); ! 572: } ! 573: ! 574: psa_read(ioaddr, lp->hacr, 0, (unsigned char *)&psa, sizeof(psa)); ! 575: ! 576: wavelan_mmc_init(dev, &psa); ! 577: ! 578: /* ! 579: * Construct the command unit structures: ! 580: * scp, iscp, scb, cb. ! 581: */ ! 582: memset(&scp, 0x00, sizeof(scp)); ! 583: scp.scp_sysbus = SCP_SY_16BBUS; ! 584: scp.scp_iscpl = OFFSET_ISCP; ! 585: obram_write(ioaddr, OFFSET_SCP, (unsigned char *)&scp, sizeof(scp)); ! 586: ! 587: memset(&iscp, 0x00, sizeof(iscp)); ! 588: iscp.iscp_busy = 1; ! 589: iscp.iscp_offset = OFFSET_SCB; ! 590: obram_write(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); ! 591: ! 592: memset(&scb, 0x00, sizeof(scb)); ! 593: scb.scb_command = SCB_CMD_RESET; ! 594: scb.scb_cbl_offset = OFFSET_CU; ! 595: scb.scb_rfa_offset = OFFSET_RU; ! 596: obram_write(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); ! 597: ! 598: set_chan_attn(ioaddr, lp->hacr); ! 599: ! 600: for (i = 1000; i > 0; i--) ! 601: { ! 602: obram_read(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); ! 603: ! 604: if (iscp.iscp_busy == (unsigned short)0) ! 605: break; ! 606: ! 607: udelay(1000); ! 608: } ! 609: ! 610: if (i <= 0) ! 611: { ! 612: printk("%s: wavelan_hardware_reset(): iscp_busy timeout.\n", dev->name); ! 613: if (wavelan_debug > 0) ! 614: printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); ! 615: return -1; ! 616: } ! 617: ! 618: for (i = 15; i > 0; i--) ! 619: { ! 620: obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); ! 621: ! 622: if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA)) ! 623: break; ! 624: ! 625: udelay(1000); ! 626: } ! 627: ! 628: if (i <= 0) ! 629: { ! 630: printk("%s: wavelan_hardware_reset(): status: expected 0x%02x, got 0x%02x.\n", dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status); ! 631: if (wavelan_debug > 0) ! 632: printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); ! 633: return -1; ! 634: } ! 635: ! 636: wavelan_ack(dev); ! 637: ! 638: memset(&cb, 0x00, sizeof(cb)); ! 639: cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose); ! 640: cb.ac_link = OFFSET_CU; ! 641: obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); ! 642: ! 643: if (wavelan_synchronous_cmd(dev, "diag()") == -1) ! 644: { ! 645: if (wavelan_debug > 0) ! 646: printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); ! 647: return -1; ! 648: } ! 649: ! 650: obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); ! 651: if (cb.ac_status & AC_SFLD_FAIL) ! 652: { ! 653: printk("%s: wavelan_hardware_reset(): i82586 Self Test failed.\n", dev->name); ! 654: if (wavelan_debug > 0) ! 655: printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); ! 656: return -1; ! 657: } ! 658: ! 659: memset(&cfg, 0x00, sizeof(cfg)); ! 660: ! 661: #if 0 ! 662: /* ! 663: * The default board configuration. ! 664: */ ! 665: cfg.fifolim_bytecnt = 0x080c; ! 666: cfg.addrlen_mode = 0x2600; ! 667: cfg.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */ ! 668: cfg.slot_time = 0xf00c; /* slottime=12 */ ! 669: cfg.hardware = 0x0008; /* tx even w/o CD */ ! 670: cfg.min_frame_len = 0x0040; ! 671: #endif /* 0 */ ! 672: ! 673: /* ! 674: * For Linux we invert AC_CFG_ALOC(..) so as to conform ! 675: * to the way that net packets reach us from above. ! 676: * (See also ac_tx_t.) ! 677: */ ! 678: cfg.cfg_byte_cnt = AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t)); ! 679: cfg.cfg_fifolim = AC_CFG_FIFOLIM(8); ! 680: cfg.cfg_byte8 = AC_CFG_SAV_BF(0) | ! 681: AC_CFG_SRDY(0); ! 682: cfg.cfg_byte9 = AC_CFG_ELPBCK(0) | ! 683: AC_CFG_ILPBCK(0) | ! 684: AC_CFG_PRELEN(AC_CFG_PLEN_2) | ! 685: AC_CFG_ALOC(1) | ! 686: AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE); ! 687: cfg.cfg_byte10 = AC_CFG_BOFMET(0) | ! 688: AC_CFG_ACR(0) | ! 689: AC_CFG_LINPRIO(0); ! 690: cfg.cfg_ifs = 32; ! 691: cfg.cfg_slotl = 0; ! 692: cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) | ! 693: AC_CFG_SLTTMHI(2); ! 694: cfg.cfg_byte14 = AC_CFG_FLGPAD(0) | ! 695: AC_CFG_BTSTF(0) | ! 696: AC_CFG_CRC16(0) | ! 697: AC_CFG_NCRC(0) | ! 698: AC_CFG_TNCRS(1) | ! 699: AC_CFG_MANCH(0) | ! 700: AC_CFG_BCDIS(0) | ! 701: AC_CFG_PRM(lp->promiscuous); ! 702: cfg.cfg_byte15 = AC_CFG_ICDS(0) | ! 703: AC_CFG_CDTF(0) | ! 704: AC_CFG_ICSS(0) | ! 705: AC_CFG_CSTF(0); ! 706: /* ! 707: cfg.cfg_min_frm_len = AC_CFG_MNFRM(64); ! 708: */ ! 709: cfg.cfg_min_frm_len = AC_CFG_MNFRM(8); ! 710: ! 711: cfg.cfg_h.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_configure); ! 712: cfg.cfg_h.ac_link = OFFSET_CU; ! 713: obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cfg, sizeof(cfg)); ! 714: ! 715: if (wavelan_synchronous_cmd(dev, "reset()-configure") == -1) ! 716: { ! 717: if (wavelan_debug > 0) ! 718: printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); ! 719: ! 720: return -1; ! 721: } ! 722: ! 723: memset(&ias, 0x00, sizeof(ias)); ! 724: ias.ias_h.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_ia_setup); ! 725: ias.ias_h.ac_link = OFFSET_CU; ! 726: memcpy(&ias.ias_addr[0], (unsigned char *)&dev->dev_addr[0], sizeof(ias.ias_addr)); ! 727: obram_write(ioaddr, OFFSET_CU, (unsigned char *)&ias, sizeof(ias)); ! 728: ! 729: if (wavelan_synchronous_cmd(dev, "reset()-address") == -1) ! 730: { ! 731: if (wavelan_debug > 0) ! 732: printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); ! 733: ! 734: return -1; ! 735: } ! 736: ! 737: wavelan_ints_on(dev); ! 738: ! 739: if (wavelan_debug > 4) ! 740: wavelan_scb_show(ioaddr); ! 741: ! 742: wavelan_ru_start(dev); ! 743: wavelan_cu_start(dev); ! 744: ! 745: if (wavelan_debug > 0) ! 746: printk("%s: <-wavelan_hardware_reset(): 0\n", dev->name); ! 747: ! 748: return 0; ! 749: } ! 750: ! 751: #if STRUCT_CHECK == 1 ! 752: ! 753: static ! 754: const char * ! 755: wavelan_struct_check(void) ! 756: { ! 757: #define SC(t,s,n) if (sizeof(t) != s) return n ! 758: SC(psa_t, PSA_SIZE, "psa_t"); ! 759: SC(mmw_t, MMW_SIZE, "mmw_t"); ! 760: SC(mmr_t, MMR_SIZE, "mmr_t"); ! 761: SC(ha_t, HA_SIZE, "ha_t"); ! 762: #undef SC ! 763: ! 764: return (char *)0; ! 765: } ! 766: ! 767: #endif /* STRUCT_CHECK == 1 */ ! 768: ! 769: /* ! 770: * Check for a network adaptor of this type. ! 771: * Return '0' iff one exists. ! 772: * (There seem to be different interpretations of ! 773: * the initial value of dev->base_addr. ! 774: * We follow the example in drivers/net/ne.c.) ! 775: */ ! 776: int ! 777: wavelan_probe(device *dev) ! 778: { ! 779: int i; ! 780: int r; ! 781: short base_addr; ! 782: static unsigned short iobase[] = ! 783: { ! 784: #if 0 ! 785: Leave out 0x3C0 for now -- seems to clash ! 786: with some video controllers. ! 787: Leave out the others too -- we will always ! 788: use 0x390 and leave 0x300 for the Ethernet device. ! 789: 0x300, 0x390, 0x3E0, 0x3C0, ! 790: #endif /* 0 */ ! 791: 0x390, ! 792: }; ! 793: ! 794: if (wavelan_debug > 0) ! 795: printk("%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n", dev->name, (unsigned int)dev, (unsigned int)dev->base_addr); ! 796: ! 797: #if STRUCT_CHECK == 1 ! 798: if (wavelan_struct_check() != (char *)0) ! 799: { ! 800: printk("%s: structure/compiler botch: \"%s\"\n", dev->name, wavelan_struct_check()); ! 801: ! 802: if (wavelan_debug > 0) ! 803: printk("%s: <-wavelan_probe(): ENODEV\n", dev->name); ! 804: ! 805: return ENODEV; ! 806: } ! 807: #endif /* STRUCT_CHECK == 1 */ ! 808: ! 809: base_addr = dev->base_addr; ! 810: ! 811: if (base_addr < 0) ! 812: { ! 813: /* ! 814: * Don't probe at all. ! 815: */ ! 816: if (wavelan_debug > 0) ! 817: printk("%s: <-wavelan_probe(): ENXIO\n", dev->name); ! 818: return ENXIO; ! 819: } ! 820: ! 821: if (base_addr > 0x100) ! 822: { ! 823: /* ! 824: * Check a single specified location. ! 825: */ ! 826: r = wavelan_probe1(dev, base_addr); ! 827: if (wavelan_debug > 0) ! 828: printk("%s: <-wavelan_probe(): %d\n", dev->name, r); ! 829: return r; ! 830: } ! 831: ! 832: for (i = 0; i < nels(iobase); i++) ! 833: { ! 834: if (check_region(iobase[i], sizeof(ha_t))) ! 835: continue; ! 836: ! 837: if (wavelan_probe1(dev, iobase[i]) == 0) ! 838: { ! 839: if (wavelan_debug > 0) ! 840: printk("%s: <-wavelan_probe(): 0\n", dev->name); ! 841: proc_net_register(&(struct proc_dir_entry) { ! 842: PROC_NET_WAVELAN, 7, "wavelan", ! 843: S_IFREG | S_IRUGO, 1, 0, 0, ! 844: 0, &proc_net_inode_operations, ! 845: wavelan_get_info ! 846: }); ! 847: ! 848: return 0; ! 849: } ! 850: } ! 851: ! 852: if (wavelan_debug > 0) ! 853: printk("%s: <-wavelan_probe(): ENODEV\n", dev->name); ! 854: ! 855: return ENODEV; ! 856: } ! 857: ! 858: static ! 859: int ! 860: wavelan_probe1(device *dev, unsigned short ioaddr) ! 861: { ! 862: psa_t psa; ! 863: int irq; ! 864: int i; ! 865: net_local *lp; ! 866: int enable_full_promiscuous; ! 867: ! 868: if (wavelan_debug > 0) ! 869: printk("%s: ->wavelan_probe1(dev=0x%x, ioaddr=0x%x)\n", dev->name, (unsigned int)dev, ioaddr); ! 870: ! 871: wavelan_reset(ioaddr); ! 872: ! 873: psa_read(ioaddr, HACR_DEFAULT, 0, (unsigned char *)&psa, sizeof(psa)); ! 874: ! 875: /* ! 876: * Check the first three octets of the MAC address ! 877: * for the manufacturer's code. ! 878: */ ! 879: if ! 880: ( ! 881: psa.psa_univ_mac_addr[0] != SA_ADDR0 ! 882: || ! 883: psa.psa_univ_mac_addr[1] != SA_ADDR1 ! 884: || ! 885: psa.psa_univ_mac_addr[2] != SA_ADDR2 ! 886: ) ! 887: { ! 888: if (wavelan_debug > 0) ! 889: printk("%s: <-wavelan_probe1(): ENODEV\n", dev->name); ! 890: return ENODEV; ! 891: } ! 892: ! 893: printk("%s: WaveLAN at %#x,", dev->name, ioaddr); ! 894: ! 895: if (dev->irq != 0) ! 896: { ! 897: printk("[WARNING: explicit IRQ value %d ignored: using PSA value instead]", dev->irq); ! 898: #if defined(IRQ_SET_WORKS) ! 899: Leave this out until I can get it to work -- BJ. ! 900: if (wavelan_unmap_irq(dev->irq, &psa.psa_int_req_no) == -1) ! 901: { ! 902: printk(" could not wavelan_unmap_irq(%d, ..) -- ignored.\n", dev->irq); ! 903: dev->irq = 0; ! 904: } ! 905: else ! 906: { ! 907: psa_write(ioaddr, HACR_DEFAULT, (char *)&psa.psa_int_req_no - (char *)&psa, (unsigned char *)&psa.psa_int_req_no, sizeof(psa.psa_int_req_no)); ! 908: wavelan_reset(ioaddr); ! 909: } ! 910: #endif /* defined(IRQ_SET_WORKS) */ ! 911: } ! 912: ! 913: if ((irq = wavelan_map_irq(psa.psa_int_req_no)) == -1) ! 914: { ! 915: printk(" could not wavelan_map_irq(%d).\n", psa.psa_int_req_no); ! 916: if (wavelan_debug > 0) ! 917: printk("%s: <-wavelan_probe1(): EAGAIN\n", dev->name); ! 918: return EAGAIN; ! 919: } ! 920: ! 921: dev->irq = irq; ! 922: ! 923: request_region(ioaddr, sizeof(ha_t), "wavelan"); ! 924: dev->base_addr = ioaddr; ! 925: ! 926: /* ! 927: * The third numeric argument to LILO's ! 928: * `ether=' control line arrives here as `dev->mem_start'. ! 929: * ! 930: * If bit 16 of dev->mem_start is non-zero we enable ! 931: * full promiscuity. ! 932: * ! 933: * If either of the least significant two bytes of ! 934: * dev->mem_start are non-zero we use them instead ! 935: * of the PSA NWID. ! 936: */ ! 937: enable_full_promiscuous = (dev->mem_start & ENABLE_FULL_PROMISCUOUS) == ENABLE_FULL_PROMISCUOUS; ! 938: dev->mem_start &= ~ENABLE_FULL_PROMISCUOUS; ! 939: ! 940: if (dev->mem_start != 0) ! 941: { ! 942: psa.psa_nwid[0] = (dev->mem_start >> 8) & 0xFF; ! 943: psa.psa_nwid[1] = (dev->mem_start >> 0) & 0xFF; ! 944: } ! 945: ! 946: dev->mem_start = 0x0000; ! 947: dev->mem_end = 0x0000; ! 948: dev->if_port = 0; ! 949: ! 950: memcpy(&dev->dev_addr[0], &psa.psa_univ_mac_addr[0], WAVELAN_ADDR_SIZE); ! 951: ! 952: for (i = 0; i < WAVELAN_ADDR_SIZE; i++) ! 953: printk("%s%02x", (i == 0) ? " " : ":", dev->dev_addr[i]); ! 954: ! 955: printk(", IRQ %d", dev->irq); ! 956: if (enable_full_promiscuous) ! 957: printk(", promisc"); ! 958: printk(", nwid 0x%02x%02x", psa.psa_nwid[0], psa.psa_nwid[1]); ! 959: ! 960: printk(", PC"); ! 961: switch (psa.psa_comp_number) ! 962: { ! 963: case PSA_COMP_PC_AT_915: ! 964: case PSA_COMP_PC_AT_2400: ! 965: printk("-AT"); ! 966: break; ! 967: ! 968: case PSA_COMP_PC_MC_915: ! 969: case PSA_COMP_PC_MC_2400: ! 970: printk("-MC"); ! 971: break; ! 972: ! 973: case PSA_COMP_PCMCIA_915: ! 974: printk("MCIA"); ! 975: break; ! 976: ! 977: default: ! 978: printk("???"); ! 979: break; ! 980: } ! 981: ! 982: printk(", "); ! 983: switch (psa.psa_subband) ! 984: { ! 985: case PSA_SUBBAND_915: ! 986: printk("915"); ! 987: break; ! 988: ! 989: case PSA_SUBBAND_2425: ! 990: printk("2425"); ! 991: break; ! 992: ! 993: case PSA_SUBBAND_2460: ! 994: printk("2460"); ! 995: break; ! 996: ! 997: case PSA_SUBBAND_2484: ! 998: printk("2484"); ! 999: break; ! 1000: ! 1001: case PSA_SUBBAND_2430_5: ! 1002: printk("2430.5"); ! 1003: break; ! 1004: ! 1005: default: ! 1006: printk("???"); ! 1007: break; ! 1008: } ! 1009: printk(" MHz"); ! 1010: ! 1011: printk("\n"); ! 1012: ! 1013: if (wavelan_debug > 0) ! 1014: printk(version); ! 1015: ! 1016: dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL); ! 1017: if (dev->priv == NULL) ! 1018: return -ENOMEM; ! 1019: memset(dev->priv, 0x00, sizeof(net_local)); ! 1020: lp = (net_local *)dev->priv; ! 1021: ! 1022: if (first_wavelan == (net_local *)0) ! 1023: { ! 1024: first_wavelan = lp; ! 1025: lp->prev = lp; ! 1026: lp->next = lp; ! 1027: } ! 1028: else ! 1029: { ! 1030: lp->prev = first_wavelan->prev; ! 1031: lp->next = first_wavelan; ! 1032: first_wavelan->prev->next = lp; ! 1033: first_wavelan->prev = lp; ! 1034: } ! 1035: lp->dev = dev; ! 1036: ! 1037: lp->hacr = HACR_DEFAULT; ! 1038: ! 1039: lp->full_promiscuous = enable_full_promiscuous; ! 1040: lp->nwid[0] = psa.psa_nwid[0]; ! 1041: lp->nwid[1] = psa.psa_nwid[1]; ! 1042: ! 1043: lp->watchdog.function = wavelan_watchdog; ! 1044: lp->watchdog.data = (unsigned long)dev; ! 1045: ! 1046: dev->open = wavelan_open; ! 1047: dev->stop = wavelan_close; ! 1048: dev->hard_start_xmit = wavelan_send_packet; ! 1049: dev->get_stats = wavelan_get_stats; ! 1050: dev->set_multicast_list = &wavelan_set_multicast_list; ! 1051: ! 1052: /* ! 1053: * Fill in the fields of the device structure ! 1054: * with ethernet-generic values. ! 1055: */ ! 1056: ether_setup(dev); ! 1057: ! 1058: dev->flags &= ~IFF_MULTICAST; /* Not yet supported */ ! 1059: ! 1060: dev->mtu = WAVELAN_MTU; ! 1061: ! 1062: if (wavelan_debug > 0) ! 1063: printk("%s: <-wavelan_probe1(): 0\n", dev->name); ! 1064: ! 1065: return 0; ! 1066: } ! 1067: ! 1068: /* ! 1069: * Construct the fd and rbd structures. ! 1070: * Start the receive unit. ! 1071: */ ! 1072: static ! 1073: void ! 1074: wavelan_ru_start(device *dev) ! 1075: { ! 1076: unsigned short ioaddr; ! 1077: net_local *lp; ! 1078: unsigned short scb_cs; ! 1079: fd_t fd; ! 1080: rbd_t rbd; ! 1081: unsigned short rx; ! 1082: unsigned short rx_next; ! 1083: int i; ! 1084: ! 1085: ioaddr = dev->base_addr; ! 1086: lp = (net_local *)dev->priv; ! 1087: ! 1088: obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs)); ! 1089: if ((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY) ! 1090: return; ! 1091: ! 1092: lp->rx_head = OFFSET_RU; ! 1093: ! 1094: for (i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next) ! 1095: { ! 1096: rx_next = (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ; ! 1097: ! 1098: fd.fd_status = 0; ! 1099: fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0; ! 1100: fd.fd_link_offset = rx_next; ! 1101: fd.fd_rbd_offset = rx + sizeof(fd); ! 1102: obram_write(ioaddr, rx, (unsigned char *)&fd, sizeof(fd)); ! 1103: ! 1104: rbd.rbd_status = 0; ! 1105: rbd.rbd_next_rbd_offset = I82586NULL; ! 1106: rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd); ! 1107: rbd.rbd_bufh = 0; ! 1108: rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ); ! 1109: obram_write(ioaddr, rx + sizeof(fd), (unsigned char *)&rbd, sizeof(rbd)); ! 1110: ! 1111: lp->rx_last = rx; ! 1112: } ! 1113: ! 1114: obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset), (unsigned char *)&lp->rx_head, sizeof(lp->rx_head)); ! 1115: ! 1116: scb_cs = SCB_CMD_RUC_GO; ! 1117: obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); ! 1118: ! 1119: set_chan_attn(ioaddr, lp->hacr); ! 1120: ! 1121: for (i = 1000; i > 0; i--) ! 1122: { ! 1123: obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); ! 1124: if (scb_cs == 0) ! 1125: break; ! 1126: ! 1127: udelay(1000); ! 1128: } ! 1129: ! 1130: if (i <= 0) ! 1131: printk("%s: wavelan_ru_start(): board not accepting command.\n", dev->name); ! 1132: } ! 1133: ! 1134: /* ! 1135: * Initialise the transmit blocks. ! 1136: * Start the command unit executing the NOP ! 1137: * self-loop of the first transmit block. ! 1138: */ ! 1139: static ! 1140: void ! 1141: wavelan_cu_start(device *dev) ! 1142: { ! 1143: unsigned short ioaddr; ! 1144: net_local *lp; ! 1145: int i; ! 1146: unsigned short txblock; ! 1147: unsigned short first_nop; ! 1148: unsigned short scb_cs; ! 1149: ! 1150: ioaddr = dev->base_addr; ! 1151: lp = (net_local *)dev->priv; ! 1152: ! 1153: lp->tx_first_free = OFFSET_CU; ! 1154: lp->tx_first_in_use = I82586NULL; ! 1155: ! 1156: for ! 1157: ( ! 1158: i = 0, txblock = OFFSET_CU; ! 1159: i < NTXBLOCKS; ! 1160: i++, txblock += TXBLOCKZ ! 1161: ) ! 1162: { ! 1163: ac_tx_t tx; ! 1164: ac_nop_t nop; ! 1165: tbd_t tbd; ! 1166: unsigned short tx_addr; ! 1167: unsigned short nop_addr; ! 1168: unsigned short tbd_addr; ! 1169: unsigned short buf_addr; ! 1170: ! 1171: tx_addr = txblock; ! 1172: nop_addr = tx_addr + sizeof(tx); ! 1173: tbd_addr = nop_addr + sizeof(nop); ! 1174: buf_addr = tbd_addr + sizeof(tbd); ! 1175: ! 1176: tx.tx_h.ac_status = 0; ! 1177: tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I; ! 1178: tx.tx_h.ac_link = nop_addr; ! 1179: tx.tx_tbd_offset = tbd_addr; ! 1180: obram_write(ioaddr, tx_addr, (unsigned char *)&tx, sizeof(tx)); ! 1181: ! 1182: nop.nop_h.ac_status = 0; ! 1183: nop.nop_h.ac_command = acmd_nop; ! 1184: nop.nop_h.ac_link = nop_addr; ! 1185: obram_write(ioaddr, nop_addr, (unsigned char *)&nop, sizeof(nop)); ! 1186: ! 1187: tbd.tbd_status = TBD_STATUS_EOF; ! 1188: tbd.tbd_next_bd_offset = I82586NULL; ! 1189: tbd.tbd_bufl = buf_addr; ! 1190: tbd.tbd_bufh = 0; ! 1191: obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd)); ! 1192: } ! 1193: ! 1194: first_nop = OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t); ! 1195: obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset), (unsigned char *)&first_nop, sizeof(first_nop)); ! 1196: ! 1197: scb_cs = SCB_CMD_CUC_GO; ! 1198: obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); ! 1199: ! 1200: set_chan_attn(ioaddr, lp->hacr); ! 1201: ! 1202: for (i = 1000; i > 0; i--) ! 1203: { ! 1204: obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); ! 1205: if (scb_cs == 0) ! 1206: break; ! 1207: ! 1208: udelay(1000); ! 1209: } ! 1210: ! 1211: if (i <= 0) ! 1212: printk("%s: wavelan_cu_start(): board not accepting command.\n", dev->name); ! 1213: ! 1214: lp->tx_n_in_use = 0; ! 1215: dev->tbusy = 0; ! 1216: } ! 1217: ! 1218: static ! 1219: int ! 1220: wavelan_open(device *dev) ! 1221: { ! 1222: unsigned short ioaddr; ! 1223: net_local *lp; ! 1224: unsigned long x; ! 1225: int r; ! 1226: ! 1227: if (wavelan_debug > 0) ! 1228: printk("%s: ->wavelan_open(dev=0x%x)\n", dev->name, (unsigned int)dev); ! 1229: ! 1230: ioaddr = dev->base_addr; ! 1231: lp = (net_local *)dev->priv; ! 1232: ! 1233: if (dev->irq == 0) ! 1234: { ! 1235: if (wavelan_debug > 0) ! 1236: printk("%s: <-wavelan_open(): -ENXIO\n", dev->name); ! 1237: return -ENXIO; ! 1238: } ! 1239: ! 1240: if ! 1241: ( ! 1242: irq2dev_map[dev->irq] != (device *)0 ! 1243: /* This is always true, but avoid the false IRQ. */ ! 1244: || ! 1245: (irq2dev_map[dev->irq] = dev) == (device *)0 ! 1246: || ! 1247: request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN") != 0 ! 1248: ) ! 1249: { ! 1250: irq2dev_map[dev->irq] = (device *)0; ! 1251: if (wavelan_debug > 0) ! 1252: printk("%s: <-wavelan_open(): -EAGAIN\n", dev->name); ! 1253: return -EAGAIN; ! 1254: } ! 1255: ! 1256: x = wavelan_splhi(); ! 1257: if ((r = wavelan_hardware_reset(dev)) != -1) ! 1258: { ! 1259: dev->interrupt = 0; ! 1260: dev->start = 1; ! 1261: } ! 1262: wavelan_splx(x); ! 1263: ! 1264: if (r == -1) ! 1265: { ! 1266: free_irq(dev->irq); ! 1267: irq2dev_map[dev->irq] = (device *)0; ! 1268: if (wavelan_debug > 0) ! 1269: printk("%s: <-wavelan_open(): -EAGAIN(2)\n", dev->name); ! 1270: return -EAGAIN; ! 1271: } ! 1272: ! 1273: MOD_INC_USE_COUNT; ! 1274: ! 1275: if (wavelan_debug > 0) ! 1276: printk("%s: <-wavelan_open(): 0\n", dev->name); ! 1277: ! 1278: return 0; ! 1279: } ! 1280: ! 1281: static ! 1282: void ! 1283: hardware_send_packet(device *dev, void *buf, short length) ! 1284: { ! 1285: unsigned short ioaddr; ! 1286: net_local *lp; ! 1287: unsigned short txblock; ! 1288: unsigned short txpred; ! 1289: unsigned short tx_addr; ! 1290: unsigned short nop_addr; ! 1291: unsigned short tbd_addr; ! 1292: unsigned short buf_addr; ! 1293: ac_tx_t tx; ! 1294: ac_nop_t nop; ! 1295: tbd_t tbd; ! 1296: unsigned long x; ! 1297: ! 1298: ioaddr = dev->base_addr; ! 1299: lp = (net_local *)dev->priv; ! 1300: ! 1301: x = wavelan_splhi(); ! 1302: ! 1303: txblock = lp->tx_first_free; ! 1304: txpred = txblock - TXBLOCKZ; ! 1305: if (txpred < OFFSET_CU) ! 1306: txpred += NTXBLOCKS * TXBLOCKZ; ! 1307: lp->tx_first_free += TXBLOCKZ; ! 1308: if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) ! 1309: lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; ! 1310: ! 1311: /* ! 1312: if (lp->tx_n_in_use > 0) ! 1313: printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); ! 1314: */ ! 1315: ! 1316: lp->tx_n_in_use++; ! 1317: ! 1318: tx_addr = txblock; ! 1319: nop_addr = tx_addr + sizeof(tx); ! 1320: tbd_addr = nop_addr + sizeof(nop); ! 1321: buf_addr = tbd_addr + sizeof(tbd); ! 1322: ! 1323: /* ! 1324: * Transmit command. ! 1325: */ ! 1326: tx.tx_h.ac_status = 0; ! 1327: obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), (unsigned char *)&tx.tx_h.ac_status, sizeof(tx.tx_h.ac_status)); ! 1328: ! 1329: /* ! 1330: * NOP command. ! 1331: */ ! 1332: nop.nop_h.ac_status = 0; ! 1333: obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), (unsigned char *)&nop.nop_h.ac_status, sizeof(nop.nop_h.ac_status)); ! 1334: nop.nop_h.ac_link = nop_addr; ! 1335: obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), (unsigned char *)&nop.nop_h.ac_link, sizeof(nop.nop_h.ac_link)); ! 1336: ! 1337: /* ! 1338: * Transmit buffer descriptor. ! 1339: */ ! 1340: tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & length); ! 1341: tbd.tbd_next_bd_offset = I82586NULL; ! 1342: tbd.tbd_bufl = buf_addr; ! 1343: tbd.tbd_bufh = 0; ! 1344: obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd)); ! 1345: ! 1346: /* ! 1347: * Data. ! 1348: */ ! 1349: obram_write(ioaddr, buf_addr, buf, length); ! 1350: ! 1351: /* ! 1352: * Overwrite the predecessor NOP link ! 1353: * so that it points to this txblock. ! 1354: */ ! 1355: nop_addr = txpred + sizeof(tx); ! 1356: nop.nop_h.ac_status = 0; ! 1357: obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), (unsigned char *)&nop.nop_h.ac_status, sizeof(nop.nop_h.ac_status)); ! 1358: nop.nop_h.ac_link = txblock; ! 1359: obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), (unsigned char *)&nop.nop_h.ac_link, sizeof(nop.nop_h.ac_link)); ! 1360: ! 1361: if (lp->tx_first_in_use == I82586NULL) ! 1362: lp->tx_first_in_use = txblock; ! 1363: ! 1364: if (lp->tx_n_in_use < NTXBLOCKS - 1) ! 1365: dev->tbusy = 0; ! 1366: ! 1367: dev->trans_start = jiffies; ! 1368: ! 1369: if (lp->watchdog.next == (timer_list *)0) ! 1370: wavelan_watchdog((unsigned long)dev); ! 1371: ! 1372: wavelan_splx(x); ! 1373: ! 1374: if (wavelan_debug > 4) ! 1375: { ! 1376: unsigned char *a; ! 1377: ! 1378: a = (unsigned char *)buf; ! 1379: ! 1380: printk ! 1381: ( ! 1382: "%s: tx: dest %02x:%02x:%02x:%02x:%02x:%02x, length %d, tbd.tbd_bufl 0x%x.\n", ! 1383: dev->name, ! 1384: a[0], a[1], a[2], a[3], a[4], a[5], ! 1385: length, ! 1386: buf_addr ! 1387: ); ! 1388: } ! 1389: } ! 1390: ! 1391: static ! 1392: int ! 1393: wavelan_send_packet(struct sk_buff *skb, device *dev) ! 1394: { ! 1395: unsigned short ioaddr; ! 1396: ! 1397: ioaddr = dev->base_addr; ! 1398: ! 1399: if (dev->tbusy) ! 1400: { ! 1401: /* ! 1402: * If we get here, some higher level ! 1403: * has decided we are broken. ! 1404: */ ! 1405: int tickssofar; ! 1406: ! 1407: tickssofar = jiffies - dev->trans_start; ! 1408: ! 1409: /* ! 1410: * But for the moment, we will rely on wavelan_watchdog() ! 1411: * instead as it allows finer control over exactly when we ! 1412: * make the determination of failure. ! 1413: * ! 1414: if (tickssofar < 5) ! 1415: */ ! 1416: return 1; ! 1417: ! 1418: wavelan_scb_show(ioaddr); ! 1419: wavelan_ru_show(dev); ! 1420: wavelan_cu_show(dev); ! 1421: wavelan_dev_show(dev); ! 1422: wavelan_local_show(dev); ! 1423: ! 1424: printk("%s: transmit timed out -- resetting board.\n", dev->name); ! 1425: ! 1426: (void)wavelan_hardware_reset(dev); ! 1427: } ! 1428: ! 1429: /* ! 1430: * If some higher layer thinks we've missed ! 1431: * a tx-done interrupt we are passed NULL. ! 1432: * Caution: dev_tint() handles the cli()/sti() itself. ! 1433: */ ! 1434: if (skb == (struct sk_buff *)0) ! 1435: { ! 1436: dev_tint(dev); ! 1437: return 0; ! 1438: } ! 1439: ! 1440: /* ! 1441: * Block a timer-based transmit from overlapping. ! 1442: */ ! 1443: if (set_bit(0, (void *)&dev->tbusy) == 0) ! 1444: { ! 1445: short length; ! 1446: unsigned char *buf; ! 1447: ! 1448: length = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; ! 1449: buf = skb->data; ! 1450: ! 1451: hardware_send_packet(dev, buf, length); ! 1452: } ! 1453: else ! 1454: printk("%s: Transmitter access conflict.\n", dev->name); ! 1455: ! 1456: dev_kfree_skb(skb, FREE_WRITE); ! 1457: ! 1458: return 0; ! 1459: } ! 1460: ! 1461: #if 0 ! 1462: static ! 1463: int ! 1464: addrcmp(unsigned char *a0, unsigned char *a1) ! 1465: { ! 1466: int i; ! 1467: ! 1468: for (i = 0; i < WAVELAN_ADDR_SIZE; i++) ! 1469: { ! 1470: if (a0[i] != a1[i]) ! 1471: return a0[i] - a1[i]; ! 1472: } ! 1473: ! 1474: return 0; ! 1475: } ! 1476: #endif /* 0 */ ! 1477: ! 1478: /* ! 1479: * Transfer as many packets as we can ! 1480: * from the device RAM. ! 1481: * Called by the interrupt handler. ! 1482: */ ! 1483: static ! 1484: void ! 1485: wavelan_receive(device *dev) ! 1486: { ! 1487: unsigned short ioaddr; ! 1488: net_local *lp; ! 1489: int nreaped; ! 1490: ! 1491: ioaddr = dev->base_addr; ! 1492: lp = (net_local *)dev->priv; ! 1493: nreaped = 0; ! 1494: ! 1495: for (;;) ! 1496: { ! 1497: fd_t fd; ! 1498: rbd_t rbd; ! 1499: ushort pkt_len; ! 1500: int sksize; ! 1501: struct sk_buff *skb; ! 1502: ! 1503: obram_read(ioaddr, lp->rx_head, (unsigned char *)&fd, sizeof(fd)); ! 1504: ! 1505: if ((fd.fd_status & FD_STATUS_C) != FD_STATUS_C) ! 1506: break; ! 1507: ! 1508: nreaped++; ! 1509: ! 1510: if ! 1511: ( ! 1512: (fd.fd_status & (FD_STATUS_B | FD_STATUS_OK)) ! 1513: != ! 1514: (FD_STATUS_B | FD_STATUS_OK) ! 1515: ) ! 1516: { ! 1517: /* ! 1518: * Not sure about this one -- it does not seem ! 1519: * to be an error so we will keep quiet about it. ! 1520: if ((fd.fd_status & FD_STATUS_B) != FD_STATUS_B) ! 1521: printk("%s: frame not consumed by RU.\n", dev->name); ! 1522: */ ! 1523: ! 1524: if ((fd.fd_status & FD_STATUS_OK) != FD_STATUS_OK) ! 1525: printk("%s: frame not received successfully.\n", dev->name); ! 1526: } ! 1527: ! 1528: if ((fd.fd_status & (FD_STATUS_S6 | FD_STATUS_S7 | FD_STATUS_S8 | FD_STATUS_S9 | FD_STATUS_S10 | FD_STATUS_S11)) != 0) ! 1529: { ! 1530: lp->stats.rx_errors++; ! 1531: ! 1532: if ((fd.fd_status & FD_STATUS_S6) != 0) ! 1533: printk("%s: no EOF flag.\n", dev->name); ! 1534: ! 1535: if ((fd.fd_status & FD_STATUS_S7) != 0) ! 1536: { ! 1537: lp->stats.rx_length_errors++; ! 1538: printk("%s: frame too short.\n", dev->name); ! 1539: } ! 1540: ! 1541: if ((fd.fd_status & FD_STATUS_S8) != 0) ! 1542: { ! 1543: lp->stats.rx_over_errors++; ! 1544: printk("%s: rx DMA overrun.\n", dev->name); ! 1545: } ! 1546: ! 1547: if ((fd.fd_status & FD_STATUS_S9) != 0) ! 1548: { ! 1549: lp->stats.rx_fifo_errors++; ! 1550: printk("%s: ran out of resources.\n", dev->name); ! 1551: } ! 1552: ! 1553: if ((fd.fd_status & FD_STATUS_S10) != 0) ! 1554: { ! 1555: lp->stats.rx_frame_errors++; ! 1556: printk("%s: alignment error.\n", dev->name); ! 1557: } ! 1558: ! 1559: if ((fd.fd_status & FD_STATUS_S11) != 0) ! 1560: { ! 1561: lp->stats.rx_crc_errors++; ! 1562: printk("%s: CRC error.\n", dev->name); ! 1563: } ! 1564: } ! 1565: ! 1566: if (fd.fd_rbd_offset == I82586NULL) ! 1567: printk("%s: frame has no data.\n", dev->name); ! 1568: else ! 1569: { ! 1570: obram_read(ioaddr, fd.fd_rbd_offset, (unsigned char *)&rbd, sizeof(rbd)); ! 1571: ! 1572: if ((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF) ! 1573: printk("%s: missing EOF flag.\n", dev->name); ! 1574: ! 1575: if ((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F) ! 1576: printk("%s: missing F flag.\n", dev->name); ! 1577: ! 1578: pkt_len = rbd.rbd_status & RBD_STATUS_ACNT; ! 1579: ! 1580: #if 0 ! 1581: { ! 1582: unsigned char addr[WAVELAN_ADDR_SIZE]; ! 1583: int i; ! 1584: static unsigned char toweraddr[WAVELAN_ADDR_SIZE] = ! 1585: { ! 1586: 0x08, 0x00, 0x0e, 0x20, 0x3e, 0xd3, ! 1587: }; ! 1588: ! 1589: obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr), &addr[0], sizeof(addr)); ! 1590: if ! 1591: ( ! 1592: /* ! 1593: addrcmp(&addr[0], &dev->dev_addr[0]) != 0 ! 1594: && ! 1595: */ ! 1596: addrcmp(&addr[0], toweraddr) != 0 ! 1597: ) ! 1598: { ! 1599: printk("%s: foreign MAC source addr=", dev->name); ! 1600: for (i = 0; i < WAVELAN_ADDR_SIZE; i++) ! 1601: printk("%s%02x", (i == 0) ? "" : ":", addr[i]); ! 1602: printk("\n"); ! 1603: } ! 1604: } ! 1605: #endif /* 0 */ ! 1606: ! 1607: if (wavelan_debug > 5) ! 1608: { ! 1609: unsigned char addr[WAVELAN_ADDR_SIZE]; ! 1610: unsigned short ltype; ! 1611: int i; ! 1612: ! 1613: #if 0 ! 1614: printk("%s: fd_dest=", dev->name); ! 1615: for (i = 0; i < WAVELAN_ADDR_SIZE; i++) ! 1616: printk("%s%02x", (i == 0) ? "" : ":", fd.fd_dest[i]); ! 1617: printk("\n"); ! 1618: ! 1619: printk("%s: fd_src=", dev->name); ! 1620: for (i = 0; i < WAVELAN_ADDR_SIZE; i++) ! 1621: printk("%s%02x", (i == 0) ? "" : ":", fd.fd_src[i]); ! 1622: printk("\n"); ! 1623: printk("%s: fd_length=%d\n", dev->name, fd.fd_length); ! 1624: #endif /* 0 */ ! 1625: ! 1626: obram_read(ioaddr, rbd.rbd_bufl, &addr[0], sizeof(addr)); ! 1627: printk("%s: dest=", dev->name); ! 1628: for (i = 0; i < WAVELAN_ADDR_SIZE; i++) ! 1629: printk("%s%02x", (i == 0) ? "" : ":", addr[i]); ! 1630: printk("\n"); ! 1631: ! 1632: obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr), &addr[0], sizeof(addr)); ! 1633: printk("%s: src=", dev->name); ! 1634: for (i = 0; i < WAVELAN_ADDR_SIZE; i++) ! 1635: printk("%s%02x", (i == 0) ? "" : ":", addr[i]); ! 1636: printk("\n"); ! 1637: ! 1638: obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr) * 2, (unsigned char *)<ype, sizeof(ltype)); ! 1639: printk("%s: ntohs(length/type)=0x%04x\n", dev->name, ntohs(ltype)); ! 1640: } ! 1641: ! 1642: sksize = pkt_len; ! 1643: ! 1644: if ((skb = dev_alloc_skb(sksize)) == (struct sk_buff *)0) ! 1645: { ! 1646: printk("%s: could not alloc_skb(%d, GFP_ATOMIC).\n", dev->name, sksize); ! 1647: lp->stats.rx_dropped++; ! 1648: } ! 1649: else ! 1650: { ! 1651: skb->dev = dev; ! 1652: ! 1653: obram_read(ioaddr, rbd.rbd_bufl, skb_put(skb,pkt_len), pkt_len); ! 1654: ! 1655: if (wavelan_debug > 5) ! 1656: { ! 1657: int i; ! 1658: int maxi; ! 1659: ! 1660: printk("%s: pkt_len=%d, data=\"", dev->name, pkt_len); ! 1661: ! 1662: if ((maxi = pkt_len) > 16) ! 1663: maxi = 16; ! 1664: ! 1665: for (i = 0; i < maxi; i++) ! 1666: { ! 1667: unsigned char c; ! 1668: ! 1669: c = skb->data[i]; ! 1670: if (c >= ' ' && c <= '~') ! 1671: printk(" %c", skb->data[i]); ! 1672: else ! 1673: printk("%02x", skb->data[i]); ! 1674: } ! 1675: ! 1676: if (maxi < pkt_len) ! 1677: printk(".."); ! 1678: ! 1679: printk("\"\n\n"); ! 1680: } ! 1681: ! 1682: skb->protocol=eth_type_trans(skb,dev); ! 1683: netif_rx(skb); ! 1684: ! 1685: lp->stats.rx_packets++; ! 1686: } ! 1687: } ! 1688: ! 1689: fd.fd_status = 0; ! 1690: obram_write(ioaddr, fdoff(lp->rx_head, fd_status), (unsigned char *)&fd.fd_status, sizeof(fd.fd_status)); ! 1691: ! 1692: fd.fd_command = FD_COMMAND_EL; ! 1693: obram_write(ioaddr, fdoff(lp->rx_head, fd_command), (unsigned char *)&fd.fd_command, sizeof(fd.fd_command)); ! 1694: ! 1695: fd.fd_command = 0; ! 1696: obram_write(ioaddr, fdoff(lp->rx_last, fd_command), (unsigned char *)&fd.fd_command, sizeof(fd.fd_command)); ! 1697: ! 1698: lp->rx_last = lp->rx_head; ! 1699: lp->rx_head = fd.fd_link_offset; ! 1700: } ! 1701: ! 1702: /* ! 1703: if (nreaped > 1) ! 1704: printk("r%d", nreaped); ! 1705: */ ! 1706: } ! 1707: ! 1708: /* ! 1709: * Command completion interrupt. ! 1710: * Reclaim as many freed tx buffers as we can. ! 1711: */ ! 1712: static ! 1713: int ! 1714: wavelan_complete(device *dev, unsigned short ioaddr, net_local *lp) ! 1715: { ! 1716: int nreaped; ! 1717: ! 1718: nreaped = 0; ! 1719: ! 1720: for (;;) ! 1721: { ! 1722: unsigned short tx_status; ! 1723: ! 1724: if (lp->tx_first_in_use == I82586NULL) ! 1725: break; ! 1726: ! 1727: obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status)); ! 1728: ! 1729: if ((tx_status & AC_SFLD_C) == 0) ! 1730: break; ! 1731: ! 1732: nreaped++; ! 1733: ! 1734: --lp->tx_n_in_use; ! 1735: ! 1736: /* ! 1737: if (lp->tx_n_in_use > 0) ! 1738: printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); ! 1739: */ ! 1740: ! 1741: if (lp->tx_n_in_use <= 0) ! 1742: lp->tx_first_in_use = I82586NULL; ! 1743: else ! 1744: { ! 1745: lp->tx_first_in_use += TXBLOCKZ; ! 1746: if (lp->tx_first_in_use >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) ! 1747: lp->tx_first_in_use -= NTXBLOCKS * TXBLOCKZ; ! 1748: } ! 1749: ! 1750: if (tx_status & AC_SFLD_OK) ! 1751: { ! 1752: int ncollisions; ! 1753: ! 1754: lp->stats.tx_packets++; ! 1755: ncollisions = tx_status & AC_SFLD_MAXCOL; ! 1756: lp->stats.collisions += ncollisions; ! 1757: /* ! 1758: if (ncollisions > 0) ! 1759: printk("%s: tx completed after %d collisions.\n", dev->name, ncollisions); ! 1760: */ ! 1761: } ! 1762: else ! 1763: { ! 1764: lp->stats.tx_errors++; ! 1765: if (tx_status & AC_SFLD_S10) ! 1766: { ! 1767: lp->stats.tx_carrier_errors++; ! 1768: if (wavelan_debug > 0) ! 1769: printk("%s: tx error: no CS.\n", dev->name); ! 1770: } ! 1771: if (tx_status & AC_SFLD_S9) ! 1772: { ! 1773: lp->stats.tx_carrier_errors++; ! 1774: printk("%s: tx error: lost CTS.\n", dev->name); ! 1775: } ! 1776: if (tx_status & AC_SFLD_S8) ! 1777: { ! 1778: lp->stats.tx_fifo_errors++; ! 1779: printk("%s: tx error: slow DMA.\n", dev->name); ! 1780: } ! 1781: if (tx_status & AC_SFLD_S6) ! 1782: { ! 1783: lp->stats.tx_heartbeat_errors++; ! 1784: if (wavelan_debug > 0) ! 1785: printk("%s: tx error: heart beat.\n", dev->name); ! 1786: } ! 1787: if (tx_status & AC_SFLD_S5) ! 1788: { ! 1789: lp->stats.tx_aborted_errors++; ! 1790: if (wavelan_debug > 0) ! 1791: printk("%s: tx error: too many collisions.\n", dev->name); ! 1792: } ! 1793: } ! 1794: ! 1795: if (wavelan_debug > 5) ! 1796: printk("%s: tx completed, tx_status 0x%04x.\n", dev->name, tx_status); ! 1797: } ! 1798: ! 1799: /* ! 1800: if (nreaped > 1) ! 1801: printk("c%d", nreaped); ! 1802: */ ! 1803: ! 1804: /* ! 1805: * Inform upper layers. ! 1806: */ ! 1807: if (lp->tx_n_in_use < NTXBLOCKS - 1) ! 1808: { ! 1809: dev->tbusy = 0; ! 1810: mark_bh(NET_BH); ! 1811: } ! 1812: ! 1813: return nreaped; ! 1814: } ! 1815: ! 1816: static ! 1817: void ! 1818: wavelan_watchdog(unsigned long a) ! 1819: { ! 1820: device *dev; ! 1821: net_local *lp; ! 1822: unsigned short ioaddr; ! 1823: unsigned long x; ! 1824: unsigned int nreaped; ! 1825: ! 1826: x = wavelan_splhi(); ! 1827: ! 1828: dev = (device *)a; ! 1829: ioaddr = dev->base_addr; ! 1830: lp = (net_local *)dev->priv; ! 1831: ! 1832: if (lp->tx_n_in_use <= 0) ! 1833: { ! 1834: wavelan_splx(x); ! 1835: return; ! 1836: } ! 1837: ! 1838: lp->watchdog.expires = jiffies+WATCHDOG_JIFFIES; ! 1839: add_timer(&lp->watchdog); ! 1840: ! 1841: if (jiffies - dev->trans_start < WATCHDOG_JIFFIES) ! 1842: { ! 1843: wavelan_splx(x); ! 1844: return; ! 1845: } ! 1846: ! 1847: nreaped = wavelan_complete(dev, ioaddr, lp); ! 1848: ! 1849: printk("%s: warning: wavelan_watchdog(): %d reaped, %d remain.\n", dev->name, nreaped, lp->tx_n_in_use); ! 1850: /* ! 1851: wavelan_scb_show(ioaddr); ! 1852: wavelan_ru_show(dev); ! 1853: wavelan_cu_show(dev); ! 1854: wavelan_dev_show(dev); ! 1855: wavelan_local_show(dev); ! 1856: */ ! 1857: ! 1858: wavelan_splx(x); ! 1859: } ! 1860: ! 1861: static ! 1862: void ! 1863: wavelan_interrupt(int irq, struct pt_regs *regs) ! 1864: { ! 1865: device *dev; ! 1866: unsigned short ioaddr; ! 1867: net_local *lp; ! 1868: unsigned short hasr; ! 1869: unsigned short status; ! 1870: unsigned short ack_cmd; ! 1871: ! 1872: if ((dev = (device *)(irq2dev_map[irq])) == (device *)0) ! 1873: { ! 1874: printk("wavelan_interrupt(): irq %d for unknown device.\n", irq); ! 1875: return; ! 1876: } ! 1877: ! 1878: ioaddr = dev->base_addr; ! 1879: lp = (net_local *)dev->priv; ! 1880: ! 1881: dev->interrupt = 1; ! 1882: ! 1883: if ((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR) ! 1884: { ! 1885: unsigned char dce_status; ! 1886: ! 1887: /* ! 1888: * Interrupt from the modem management controller. ! 1889: * This will clear it -- ignored for now. ! 1890: */ ! 1891: mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status)); ! 1892: if (wavelan_debug > 0) ! 1893: printk("%s: warning: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", dev->name, dce_status); ! 1894: } ! 1895: ! 1896: if ((hasr & HASR_82586_INTR) == 0) ! 1897: { ! 1898: dev->interrupt = 0; ! 1899: if (wavelan_debug > 0) ! 1900: printk("%s: warning: wavelan_interrupt() but (hasr & HASR_82586_INTR) == 0.\n", dev->name); ! 1901: return; ! 1902: } ! 1903: ! 1904: obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&status, sizeof(status)); ! 1905: ! 1906: /* ! 1907: * Acknowledge the interrupt(s). ! 1908: */ ! 1909: ack_cmd = status & SCB_ST_INT; ! 1910: ! 1911: obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&ack_cmd, sizeof(ack_cmd)); ! 1912: ! 1913: set_chan_attn(ioaddr, lp->hacr); ! 1914: ! 1915: if (wavelan_debug > 5) ! 1916: printk("%s: interrupt, status 0x%04x.\n", dev->name, status); ! 1917: ! 1918: if ((status & SCB_ST_CX) == SCB_ST_CX) ! 1919: { ! 1920: /* ! 1921: * Command completed. ! 1922: */ ! 1923: if (wavelan_debug > 5) ! 1924: printk("%s: command completed.\n", dev->name); ! 1925: (void)wavelan_complete(dev, ioaddr, lp); ! 1926: } ! 1927: ! 1928: if ((status & SCB_ST_FR) == SCB_ST_FR) ! 1929: { ! 1930: /* ! 1931: * Frame received. ! 1932: */ ! 1933: if (wavelan_debug > 5) ! 1934: printk("%s: received packet.\n", dev->name); ! 1935: wavelan_receive(dev); ! 1936: } ! 1937: ! 1938: if ! 1939: ( ! 1940: (status & SCB_ST_CNA) == SCB_ST_CNA ! 1941: || ! 1942: (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && dev->start) ! 1943: ) ! 1944: { ! 1945: printk("%s: warning: CU inactive -- restarting.\n", dev->name); ! 1946: ! 1947: (void)wavelan_hardware_reset(dev); ! 1948: } ! 1949: ! 1950: if ! 1951: ( ! 1952: (status & SCB_ST_RNR) == SCB_ST_RNR ! 1953: || ! 1954: (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && dev->start) ! 1955: ) ! 1956: { ! 1957: printk("%s: warning: RU not ready -- restarting.\n", dev->name); ! 1958: ! 1959: (void)wavelan_hardware_reset(dev); ! 1960: } ! 1961: ! 1962: dev->interrupt = 0; ! 1963: } ! 1964: ! 1965: static ! 1966: int ! 1967: wavelan_close(device *dev) ! 1968: { ! 1969: unsigned short ioaddr; ! 1970: net_local *lp; ! 1971: unsigned short scb_cmd; ! 1972: ! 1973: if (wavelan_debug > 0) ! 1974: printk("%s: ->wavelan_close(dev=0x%x)\n", dev->name, (unsigned int)dev); ! 1975: ! 1976: ioaddr = dev->base_addr; ! 1977: lp = (net_local *)dev->priv; ! 1978: ! 1979: dev->tbusy = 1; ! 1980: dev->start = 0; ! 1981: ! 1982: /* ! 1983: * Flush the Tx and disable Rx. ! 1984: */ ! 1985: scb_cmd = (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & SCB_CMD_RUC_SUS); ! 1986: obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cmd, sizeof(scb_cmd)); ! 1987: set_chan_attn(ioaddr, lp->hacr); ! 1988: ! 1989: wavelan_ints_off(dev); ! 1990: ! 1991: free_irq(dev->irq); ! 1992: irq2dev_map[dev->irq] = (device *)0; ! 1993: ! 1994: /* ! 1995: * Release the ioport-region. ! 1996: */ ! 1997: release_region(ioaddr, sizeof(ha_t)); ! 1998: ! 1999: MOD_DEC_USE_COUNT; ! 2000: ! 2001: if (wavelan_debug > 0) ! 2002: printk("%s: <-wavelan_close(): 0\n", dev->name); ! 2003: ! 2004: return 0; ! 2005: } ! 2006: ! 2007: /* ! 2008: * Get the current statistics. ! 2009: * This may be called with the card open or closed. ! 2010: */ ! 2011: static ! 2012: en_stats * ! 2013: wavelan_get_stats(device *dev) ! 2014: { ! 2015: net_local *lp; ! 2016: ! 2017: lp = (net_local *)dev->priv; ! 2018: ! 2019: return &lp->stats; ! 2020: } ! 2021: ! 2022: static ! 2023: void ! 2024: wavelan_set_multicast_list(device *dev) ! 2025: { ! 2026: net_local *lp; ! 2027: unsigned long x; ! 2028: ! 2029: if (wavelan_debug > 0) ! 2030: printk("%s: ->wavelan_set_multicast_list(dev=0x%x)", dev->name, dev); ! 2031: ! 2032: lp = (net_local *)dev->priv; ! 2033: ! 2034: if(dev->flags&IFF_PROMISC) ! 2035: { ! 2036: /* ! 2037: * Promiscuous mode: receive all packets. ! 2038: */ ! 2039: lp->promiscuous = 1; ! 2040: x = wavelan_splhi(); ! 2041: (void)wavelan_hardware_reset(dev); ! 2042: wavelan_splx(x); ! 2043: } ! 2044: #if MULTICAST_IS_ADDED ! 2045: else if((dev->flags&IFF_ALLMULTI)||dev->mc_list) ! 2046: { ! 2047: ! 2048: ! 2049: } ! 2050: #endif ! 2051: else ! 2052: { ! 2053: /* ! 2054: * Normal mode: disable promiscuous mode, ! 2055: * clear multicast list. ! 2056: */ ! 2057: lp->promiscuous = 0; ! 2058: x = wavelan_splhi(); ! 2059: (void)wavelan_hardware_reset(dev); ! 2060: wavelan_splx(x); ! 2061: } ! 2062: ! 2063: if (wavelan_debug > 0) ! 2064: printk("%s: <-wavelan_set_multicast_list()\n", dev->name); ! 2065: } ! 2066: ! 2067: /* ! 2068: * Extra WaveLAN-specific device data. ! 2069: * "cat /proc/net/wavelan" -- see fs/proc/net.c. ! 2070: */ ! 2071: static ! 2072: int ! 2073: sprintf_stats(char *buffer, device *dev) ! 2074: { ! 2075: net_local *lp; ! 2076: unsigned char v; ! 2077: mmr_t m; ! 2078: ! 2079: lp = (net_local *)dev->priv; ! 2080: ! 2081: if (lp == (net_local *)0) ! 2082: return sprintf(buffer, "%6s: No statistics available.\n", dev->name); ! 2083: ! 2084: v = (unsigned char)1; ! 2085: mmc_write(dev->base_addr, mmwoff(0, mmw_freeze), &v, sizeof(v)); ! 2086: ! 2087: mmc_read(dev->base_addr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, sizeof(m.mmr_dce_status)); ! 2088: mmc_read(dev->base_addr, mmroff(0, mmr_correct_nwid_h), &m.mmr_correct_nwid_h, sizeof(m.mmr_correct_nwid_h)); ! 2089: mmc_read(dev->base_addr, mmroff(0, mmr_correct_nwid_l), &m.mmr_correct_nwid_l, sizeof(m.mmr_correct_nwid_l)); ! 2090: mmc_read(dev->base_addr, mmroff(0, mmr_wrong_nwid_h), &m.mmr_wrong_nwid_h, sizeof(m.mmr_wrong_nwid_h)); ! 2091: mmc_read(dev->base_addr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, sizeof(m.mmr_wrong_nwid_l)); ! 2092: mmc_read(dev->base_addr, mmroff(0, mmr_signal_lvl), &m.mmr_signal_lvl, sizeof(m.mmr_signal_lvl)); ! 2093: mmc_read(dev->base_addr, mmroff(0, mmr_silence_lvl), &m.mmr_silence_lvl, sizeof(m.mmr_silence_lvl)); ! 2094: mmc_read(dev->base_addr, mmroff(0, mmr_sgnl_qual), &m.mmr_sgnl_qual, sizeof(m.mmr_sgnl_qual)); ! 2095: ! 2096: v = (unsigned char)0; ! 2097: mmc_write(dev->base_addr, mmwoff(0, mmw_freeze), &v, sizeof(v)); ! 2098: ! 2099: lp->correct_nwid += (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l; ! 2100: lp->wrong_nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; ! 2101: ! 2102: return sprintf ! 2103: ( ! 2104: buffer, ! 2105: "%6s: %02x %08x %08x %02x %02x %02x %02x %u\n", ! 2106: dev->name, ! 2107: m.mmr_dce_status, ! 2108: lp->correct_nwid, ! 2109: lp->wrong_nwid, ! 2110: m.mmr_signal_lvl, ! 2111: m.mmr_silence_lvl, ! 2112: m.mmr_sgnl_qual, ! 2113: lp->tx_n_in_use, ! 2114: lp->nresets ! 2115: ); ! 2116: } ! 2117: ! 2118: static int ! 2119: wavelan_get_info(char *buffer, char **start, off_t offset, int length, int dummy) ! 2120: { ! 2121: int len; ! 2122: off_t begin; ! 2123: off_t pos; ! 2124: int size; ! 2125: unsigned long x; ! 2126: ! 2127: len = 0; ! 2128: begin = 0; ! 2129: pos = 0; ! 2130: ! 2131: size = sprintf(buffer, "%s", "Iface | dce +nwid -nwid lvl slnc qual ntxq nrst\n"); ! 2132: ! 2133: pos += size; ! 2134: len += size; ! 2135: ! 2136: x = wavelan_splhi(); ! 2137: ! 2138: if (first_wavelan != (net_local *)0) ! 2139: { ! 2140: net_local *lp; ! 2141: ! 2142: lp = first_wavelan; ! 2143: do ! 2144: { ! 2145: size = sprintf_stats(buffer + len, lp->dev); ! 2146: ! 2147: len += size; ! 2148: pos = begin + len; ! 2149: ! 2150: if (pos < offset) ! 2151: { ! 2152: len = 0; ! 2153: begin = pos; ! 2154: } ! 2155: ! 2156: if (pos > offset + length) ! 2157: break; ! 2158: } ! 2159: while ((lp = lp->next) != first_wavelan); ! 2160: } ! 2161: ! 2162: wavelan_splx(x); ! 2163: ! 2164: *start = buffer + (offset - begin); /* Start of wanted data */ ! 2165: len -= (offset - begin); /* Start slop */ ! 2166: if (len > length) ! 2167: len = length; /* Ending slop */ ! 2168: ! 2169: return len; ! 2170: } ! 2171: ! 2172: #if defined(MODULE) ! 2173: static char devicename[9] = { 0, }; ! 2174: static struct device dev_wavelan = ! 2175: { ! 2176: devicename, /* device name is inserted by linux/drivers/net/net_init.c */ ! 2177: 0, 0, 0, 0, ! 2178: 0, 0, ! 2179: 0, 0, 0, NULL, wavelan_probe ! 2180: }; ! 2181: ! 2182: static int io = 0x390; /* Default from above.. */ ! 2183: static int irq = 0; ! 2184: ! 2185: int ! 2186: init_module(void) ! 2187: { ! 2188: dev_wavelan.base_addr = io; ! 2189: dev_wavelan.irq = irq; ! 2190: if (register_netdev(&dev_wavelan) != 0) ! 2191: return -EIO; ! 2192: ! 2193: return 0; ! 2194: } ! 2195: ! 2196: void ! 2197: cleanup_module(void) ! 2198: { ! 2199: proc_net_unregister(PROC_NET_WAVELAN); ! 2200: unregister_netdev(&dev_wavelan); ! 2201: kfree_s(dev_wavelan.priv, sizeof(struct net_local)); ! 2202: dev_wavelan.priv = NULL; ! 2203: } ! 2204: #endif /* defined(MODULE) */ ! 2205: ! 2206: static ! 2207: void ! 2208: wavelan_cu_show_one(device *dev, net_local *lp, int i, unsigned short p) ! 2209: { ! 2210: unsigned short ioaddr; ! 2211: ac_tx_t actx; ! 2212: ! 2213: ioaddr = dev->base_addr; ! 2214: ! 2215: printk("%d: 0x%x:", i, p); ! 2216: ! 2217: obram_read(ioaddr, p, (unsigned char *)&actx, sizeof(actx)); ! 2218: printk(" status=0x%x,", actx.tx_h.ac_status); ! 2219: printk(" command=0x%x,", actx.tx_h.ac_command); ! 2220: ! 2221: /* ! 2222: { ! 2223: tbd_t tbd; ! 2224: ! 2225: obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd)); ! 2226: printk(" tbd_status=0x%x,", tbd.tbd_status); ! 2227: } ! 2228: */ ! 2229: ! 2230: printk("|"); ! 2231: } ! 2232: ! 2233: #if 0 ! 2234: static ! 2235: void ! 2236: wavelan_psa_show(psa_t *p) ! 2237: { ! 2238: printk("psa:"); ! 2239: ! 2240: printk("psa_io_base_addr_1: 0x%02x,", p->psa_io_base_addr_1); ! 2241: printk("psa_io_base_addr_2: 0x%02x,", p->psa_io_base_addr_2); ! 2242: printk("psa_io_base_addr_3: 0x%02x,", p->psa_io_base_addr_3); ! 2243: printk("psa_io_base_addr_4: 0x%02x,", p->psa_io_base_addr_4); ! 2244: printk("psa_rem_boot_addr_1: 0x%02x,", p->psa_rem_boot_addr_1); ! 2245: printk("psa_rem_boot_addr_2: 0x%02x,", p->psa_rem_boot_addr_2); ! 2246: printk("psa_rem_boot_addr_3: 0x%02x,", p->psa_rem_boot_addr_3); ! 2247: printk("psa_holi_params: 0x%02x,", p->psa_holi_params); ! 2248: printk("psa_int_req_no: %d,", p->psa_int_req_no); ! 2249: printk ! 2250: ( ! 2251: "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x,", ! 2252: p->psa_univ_mac_addr[0], ! 2253: p->psa_univ_mac_addr[1], ! 2254: p->psa_univ_mac_addr[2], ! 2255: p->psa_univ_mac_addr[3], ! 2256: p->psa_univ_mac_addr[4], ! 2257: p->psa_univ_mac_addr[5] ! 2258: ); ! 2259: printk ! 2260: ( ! 2261: "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x,", ! 2262: p->psa_local_mac_addr[0], ! 2263: p->psa_local_mac_addr[1], ! 2264: p->psa_local_mac_addr[2], ! 2265: p->psa_local_mac_addr[3], ! 2266: p->psa_local_mac_addr[4], ! 2267: p->psa_local_mac_addr[5] ! 2268: ); ! 2269: printk("psa_univ_local_sel: %d,", p->psa_univ_local_sel); ! 2270: printk("psa_comp_number: %d,", p->psa_comp_number); ! 2271: printk("psa_thr_pre_set: 0x%02x,", p->psa_thr_pre_set); ! 2272: printk("psa_feature_select/decay_prm: 0x%02x,", p->psa_feature_select); ! 2273: printk("psa_subband/decay_update_prm: %d,", p->psa_subband); ! 2274: printk("psa_quality_thr: 0x%02x,", p->psa_quality_thr); ! 2275: printk("psa_mod_delay: 0x%02x,", p->psa_mod_delay); ! 2276: printk("psa_nwid: 0x%02x%02x,", p->psa_nwid[0], p->psa_nwid[1]); ! 2277: printk("psa_undefined: %d,", p->psa_undefined); ! 2278: printk("psa_encryption_select: %d,", p->psa_encryption_select); ! 2279: printk ! 2280: ( ! 2281: "psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,", ! 2282: p->psa_encryption_key[0], ! 2283: p->psa_encryption_key[1], ! 2284: p->psa_encryption_key[2], ! 2285: p->psa_encryption_key[3], ! 2286: p->psa_encryption_key[4], ! 2287: p->psa_encryption_key[5], ! 2288: p->psa_encryption_key[6], ! 2289: p->psa_encryption_key[7] ! 2290: ); ! 2291: printk("psa_databus_width: %d,", p->psa_databus_width); ! 2292: printk("psa_call_code/auto_squelch: 0x%02x,", p->psa_call_code); ! 2293: printk("psa_no_of_retries: %d,", p->psa_no_of_retries); ! 2294: printk("psa_acr: %d,", p->psa_acr); ! 2295: printk("psa_dump_count: %d,", p->psa_dump_count); ! 2296: printk("psa_nwid_prefix: 0x%02x,", p->psa_nwid_prefix); ! 2297: printk("psa_conf_status: %d,", p->psa_conf_status); ! 2298: printk("psa_crc: 0x%02x%02x,", p->psa_crc[0], p->psa_crc[1]); ! 2299: printk("psa_crc_status: 0x%02x,", p->psa_crc_status); ! 2300: ! 2301: printk("\n"); ! 2302: } ! 2303: ! 2304: static ! 2305: void ! 2306: wavelan_mmc_show(unsigned short ioaddr) ! 2307: { ! 2308: mmr_t m; ! 2309: ! 2310: mmc_read(ioaddr, 0, (unsigned char *)&m, sizeof(m)); ! 2311: ! 2312: printk("mmr:"); ! 2313: printk(" des_status: 0x%x", m.mmr_des_status); ! 2314: printk(" des_avail: 0x%x", m.mmr_des_avail); ! 2315: printk(" des_io_invert: 0x%x", m.mmr_des_io_invert); ! 2316: printk ! 2317: ( ! 2318: " dce_status: 0x%x[%s%s%s%s]", ! 2319: m.mmr_dce_status & 0x0F, ! 2320: (m.mmr_dce_status & MMR_DCE_STATUS_ENERG_DET) ? "energy detected," : "", ! 2321: (m.mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ? "loop test indicated," : "", ! 2322: (m.mmr_dce_status & MMR_DCE_STATUS_XMTITR_IND) ? "transmitter on," : "", ! 2323: (m.mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ? "jabber timer expired," : "" ! 2324: ); ! 2325: printk(" correct_nwid: %d", m.mmr_correct_nwid_h << 8 | m.mmr_correct_nwid_l); ! 2326: printk(" wrong_nwid: %d", (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l); ! 2327: printk(" thr_pre_set: 0x%x", m.mmr_thr_pre_set); ! 2328: printk(" signal_lvl: %d", m.mmr_signal_lvl); ! 2329: printk(" silence_lvl: %d", m.mmr_silence_lvl); ! 2330: printk(" sgnl_qual: 0x%x", m.mmr_sgnl_qual); ! 2331: printk(" netw_id_l: %x", m.mmr_netw_id_l); ! 2332: ! 2333: printk("\n"); ! 2334: } ! 2335: #endif /* 0 */ ! 2336: ! 2337: static ! 2338: void ! 2339: wavelan_scb_show(unsigned short ioaddr) ! 2340: { ! 2341: scb_t scb; ! 2342: ! 2343: obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); ! 2344: ! 2345: printk("scb:"); ! 2346: ! 2347: printk(" status:"); ! 2348: printk ! 2349: ( ! 2350: " stat 0x%x[%s%s%s%s]", ! 2351: (scb.scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | SCB_ST_RNR)) >> 12, ! 2352: (scb.scb_status & SCB_ST_CX) ? "cmd completion interrupt," : "", ! 2353: (scb.scb_status & SCB_ST_FR) ? "frame received," : "", ! 2354: (scb.scb_status & SCB_ST_CNA) ? "cmd unit not active," : "", ! 2355: (scb.scb_status & SCB_ST_RNR) ? "rcv unit not ready," : "" ! 2356: ); ! 2357: printk ! 2358: ( ! 2359: " cus 0x%x[%s%s%s]", ! 2360: (scb.scb_status & SCB_ST_CUS) >> 8, ! 2361: ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_IDLE) ? "idle" : "", ! 2362: ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_SUSP) ? "suspended" : "", ! 2363: ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_ACTV) ? "active" : "" ! 2364: ); ! 2365: printk ! 2366: ( ! 2367: " rus 0x%x[%s%s%s%s]", ! 2368: (scb.scb_status & SCB_ST_RUS) >> 4, ! 2369: ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_IDLE) ? "idle" : "", ! 2370: ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_SUSP) ? "suspended" : "", ! 2371: ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_NRES) ? "no resources" : "", ! 2372: ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_RDY) ? "ready" : "" ! 2373: ); ! 2374: ! 2375: printk(" command:"); ! 2376: printk ! 2377: ( ! 2378: " ack 0x%x[%s%s%s%s]", ! 2379: (scb.scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12, ! 2380: (scb.scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "", ! 2381: (scb.scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "", ! 2382: (scb.scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "", ! 2383: (scb.scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : "" ! 2384: ); ! 2385: printk ! 2386: ( ! 2387: " cuc 0x%x[%s%s%s%s%s]", ! 2388: (scb.scb_command & SCB_CMD_CUC) >> 8, ! 2389: ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_NOP) ? "nop" : "", ! 2390: ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_GO) ? "start cbl_offset" : "", ! 2391: ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_RES) ? "resume execution" : "", ! 2392: ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_SUS) ? "suspend execution" : "", ! 2393: ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_ABT) ? "abort execution" : "" ! 2394: ); ! 2395: printk ! 2396: ( ! 2397: " ruc 0x%x[%s%s%s%s%s]", ! 2398: (scb.scb_command & SCB_CMD_RUC) >> 4, ! 2399: ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_NOP) ? "nop" : "", ! 2400: ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_GO) ? "start rfa_offset" : "", ! 2401: ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_RES) ? "resume reception" : "", ! 2402: ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_SUS) ? "suspend reception" : "", ! 2403: ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_ABT) ? "abort reception" : "" ! 2404: ); ! 2405: ! 2406: printk(" cbl_offset 0x%x", scb.scb_cbl_offset); ! 2407: printk(" rfa_offset 0x%x", scb.scb_rfa_offset); ! 2408: ! 2409: printk(" crcerrs %d", scb.scb_crcerrs); ! 2410: printk(" alnerrs %d", scb.scb_alnerrs); ! 2411: printk(" rscerrs %d", scb.scb_rscerrs); ! 2412: printk(" ovrnerrs %d", scb.scb_ovrnerrs); ! 2413: ! 2414: printk("\n"); ! 2415: } ! 2416: ! 2417: static ! 2418: void ! 2419: wavelan_ru_show(device *dev) ! 2420: { ! 2421: net_local *lp; ! 2422: ! 2423: lp = (net_local *)dev->priv; ! 2424: ! 2425: printk("ru:"); ! 2426: /* ! 2427: * Not implemented yet... ! 2428: */ ! 2429: printk("\n"); ! 2430: } ! 2431: ! 2432: static ! 2433: void ! 2434: wavelan_cu_show(device *dev) ! 2435: { ! 2436: net_local *lp; ! 2437: unsigned int i; ! 2438: unsigned short p; ! 2439: ! 2440: lp = (net_local *)dev->priv; ! 2441: ! 2442: printk("cu:"); ! 2443: printk("\n"); ! 2444: ! 2445: for (i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) ! 2446: { ! 2447: wavelan_cu_show_one(dev, lp, i, p); ! 2448: ! 2449: p += TXBLOCKZ; ! 2450: if (p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) ! 2451: p -= NTXBLOCKS * TXBLOCKZ; ! 2452: } ! 2453: } ! 2454: ! 2455: static ! 2456: void ! 2457: wavelan_dev_show(device *dev) ! 2458: { ! 2459: printk("dev:"); ! 2460: printk(" start=%d,", dev->start); ! 2461: printk(" tbusy=%ld,", dev->tbusy); ! 2462: printk(" interrupt=%d,", dev->interrupt); ! 2463: printk(" trans_start=%ld,", dev->trans_start); ! 2464: printk(" flags=0x%x,", dev->flags); ! 2465: printk("\n"); ! 2466: } ! 2467: ! 2468: static ! 2469: void ! 2470: wavelan_local_show(device *dev) ! 2471: { ! 2472: net_local *lp; ! 2473: ! 2474: lp = (net_local *)dev->priv; ! 2475: ! 2476: printk("local:"); ! 2477: printk(" tx_n_in_use=%d,", lp->tx_n_in_use); ! 2478: printk(" hacr=0x%x,", lp->hacr); ! 2479: printk(" rx_head=0x%x,", lp->rx_head); ! 2480: printk(" rx_last=0x%x,", lp->rx_last); ! 2481: printk(" tx_first_free=0x%x,", lp->tx_first_free); ! 2482: printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use); ! 2483: printk("\n"); ! 2484: } ! 2485: ! 2486: /* ! 2487: * This software may only be used and distributed ! 2488: * according to the terms of the GNU Public License. ! 2489: * ! 2490: * This software was developed as a component of the ! 2491: * Linux operating system. ! 2492: * It is based on other device drivers and information ! 2493: * either written or supplied by: ! 2494: * Ajay Bakre ([email protected]), ! 2495: * Donald Becker ([email protected]), ! 2496: * Loeke Brederveld ([email protected]), ! 2497: * Anders Klemets ([email protected]), ! 2498: * Vladimir V. Kolpakov ([email protected]), ! 2499: * Marc Meertens ([email protected]), ! 2500: * Pauline Middelink ([email protected]), ! 2501: * Robert Morris ([email protected]), ! 2502: * Girish Welling ([email protected]), ! 2503: * ! 2504: * Thanks go also to: ! 2505: * James Ashton ([email protected]), ! 2506: * Alan Cox ([email protected]), ! 2507: * Allan Creighton ([email protected]), ! 2508: * Matthew Geier ([email protected]), ! 2509: * Remo di Giovanni ([email protected]), ! 2510: * Eckhard Grah ([email protected]), ! 2511: * Vipul Gupta ([email protected]), ! 2512: * Mark Hagan ([email protected]), ! 2513: * Tim Nicholson ([email protected]), ! 2514: * Ian Parkin ([email protected]), ! 2515: * John Rosenberg ([email protected]), ! 2516: * George Rossi ([email protected]), ! 2517: * Arthur Scott ([email protected]), ! 2518: * Peter Storey, ! 2519: * for their assistance and advice. ! 2520: * ! 2521: * Please send bug reports, updates, comments to: ! 2522: * ! 2523: * Bruce Janson Email: [email protected] ! 2524: * Basser Department of Computer Science Phone: +61-2-351-3423 ! 2525: * University of Sydney, N.S.W., 2006, AUSTRALIA Fax: +61-2-351-3838 ! 2526: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.