00001
00002
00003
00004
00005
00006
00007
00008 static char *version =
00009 "sunhme.c:v1.10 27/Jan/99 David S. Miller (davem@caipfs.rutgers.edu)\n";
00010
00011 #include <linux/module.h>
00012
00013 #include <linux/config.h>
00014 #include <linux/kernel.h>
00015 #include <linux/sched.h>
00016 #include <linux/types.h>
00017 #include <linux/fcntl.h>
00018 #include <linux/interrupt.h>
00019 #include <linux/ptrace.h>
00020 #include <linux/ioport.h>
00021 #include <linux/in.h>
00022 #include <linux/malloc.h>
00023 #include <linux/string.h>
00024 #include <linux/delay.h>
00025 #include <linux/init.h>
00026 #include <asm/system.h>
00027 #include <asm/bitops.h>
00028 #include <asm/io.h>
00029 #include <asm/dma.h>
00030 #include <linux/errno.h>
00031 #include <asm/byteorder.h>
00032
00033 #include <asm/idprom.h>
00034 #include <asm/sbus.h>
00035 #include <asm/openprom.h>
00036 #include <asm/oplib.h>
00037 #include <asm/auxio.h>
00038 #include <asm/pgtable.h>
00039 #include <asm/irq.h>
00040 #ifndef __sparc_v9__
00041 #include <asm/io-unit.h>
00042 #endif
00043 #include <asm/ethtool.h>
00044 #include <asm/uaccess.h>
00045
00046 #include <linux/netdevice.h>
00047 #include <linux/etherdevice.h>
00048 #include <linux/skbuff.h>
00049
00050 #ifdef CONFIG_PCI
00051 #include <linux/pci.h>
00052 #include <asm/pbm.h>
00053 #endif
00054
00055 #include "sunhme.h"
00056
00057 #ifdef MODULE
00058 static struct happy_meal *root_happy_dev = NULL;
00059 #endif
00060
00061 static struct quattro *qfe_sbus_list = NULL;
00062 #ifdef CONFIG_PCI
00063 static struct quattro *qfe_pci_list = NULL;
00064 #endif
00065
00066 #undef HMEDEBUG
00067 #undef SXDEBUG
00068 #undef RXDEBUG
00069 #undef TXDEBUG
00070 #undef TXLOGGING
00071
00072 #ifdef TXLOGGING
00073 struct hme_tx_logent {
00074 unsigned int tstamp;
00075 int tx_new, tx_old;
00076 unsigned int action;
00077 #define TXLOG_ACTION_IRQ 0x01
00078 #define TXLOG_ACTION_TXMIT 0x02
00079 #define TXLOG_ACTION_TBUSY 0x04
00080 #define TXLOG_ACTION_NBUFS 0x08
00081 unsigned int status;
00082 };
00083 #define TX_LOG_LEN 128
00084 static struct hme_tx_logent tx_log[TX_LOG_LEN];
00085 static int txlog_cur_entry = 0;
00086 static __inline__ void tx_add_log(struct happy_meal *hp, unsigned int a, unsigned int s)
00087 {
00088 struct hme_tx_logent *tlp;
00089 unsigned long flags;
00090
00091 save_and_cli(flags);
00092 tlp = &tx_log[txlog_cur_entry];
00093 tlp->tstamp = (unsigned int)jiffies;
00094 tlp->tx_new = hp->tx_new;
00095 tlp->tx_old = hp->tx_old;
00096 tlp->action = a;
00097 tlp->status = s;
00098 txlog_cur_entry = (txlog_cur_entry + 1) & (TX_LOG_LEN - 1);
00099 restore_flags(flags);
00100 }
00101 static __inline__ void tx_dump_log(void)
00102 {
00103 int i, this;
00104
00105 this = txlog_cur_entry;
00106 for(i = 0; i < TX_LOG_LEN; i++) {
00107 printk("TXLOG[%d]: j[%08x] tx[N(%d)O(%d)] action[%08x] stat[%08x]\n", i,
00108 tx_log[this].tstamp,
00109 tx_log[this].tx_new, tx_log[this].tx_old,
00110 tx_log[this].action, tx_log[this].status);
00111 this = (this + 1) & (TX_LOG_LEN - 1);
00112 }
00113 }
00114 static __inline__ void tx_dump_ring(struct happy_meal *hp)
00115 {
00116 struct hmeal_init_block *hb = hp->happy_block;
00117 struct happy_meal_txd *tp = &hb->happy_meal_txd[0];
00118 int i;
00119
00120 for(i = 0; i < TX_RING_SIZE; i+=4) {
00121 printk("TXD[%d..%d]: [%08x:%08x] [%08x:%08x] [%08x:%08x] [%08x:%08x]\n",
00122 i, i + 4,
00123 le32_to_cpu(tp[i].tx_flags), le32_to_cpu(tp[i].tx_addr),
00124 le32_to_cpu(tp[i + 1].tx_flags), le32_to_cpu(tp[i + 1].tx_addr),
00125 le32_to_cpu(tp[i + 2].tx_flags), le32_to_cpu(tp[i + 2].tx_addr),
00126 le32_to_cpu(tp[i + 3].tx_flags), le32_to_cpu(tp[i + 3].tx_addr));
00127 }
00128 }
00129 #else
00130 #define tx_add_log(hp, a, s) do { } while(0)
00131 #define tx_dump_log() do { } while(0)
00132 #define tx_dump_ring(hp) do { } while(0)
00133 #endif
00134
00135 #ifdef HMEDEBUG
00136 #define HMD(x) printk x
00137 #else
00138 #define HMD(x)
00139 #endif
00140
00141
00142
00143 #ifdef AUTO_SWITCH_DEBUG
00144 #define ASD(x) printk x
00145 #else
00146 #define ASD(x)
00147 #endif
00148
00149 #define DEFAULT_IPG0 16
00150 #define DEFAULT_IPG1 8
00151 #define DEFAULT_IPG2 4
00152 #define DEFAULT_JAMSIZE 4
00153
00154
00155 #define BB_PUT_BIT(hp, tregs, bit) \
00156 do { hme_write32(hp, &(tregs)->bb_data, (bit)); \
00157 hme_write32(hp, &(tregs)->bb_clock, 0); \
00158 hme_write32(hp, &(tregs)->bb_clock, 1); \
00159 } while(0)
00160
00161 #define BB_GET_BIT(hp, tregs, internal) \
00162 ({ \
00163 hme_write32(hp, &(tregs)->bb_clock, 0); \
00164 hme_write32(hp, &(tregs)->bb_clock, 1); \
00165 if(internal) \
00166 hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO0; \
00167 else \
00168 hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO1; \
00169 })
00170
00171 #define BB_GET_BIT2(hp, tregs, internal) \
00172 ({ \
00173 int retval; \
00174 hme_write32(hp, &(tregs)->bb_clock, 0); \
00175 udelay(1); \
00176 if(internal) \
00177 retval = hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO0; \
00178 else \
00179 retval = hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO1; \
00180 hme_write32(hp, &(tregs)->bb_clock, 1); \
00181 retval; \
00182 })
00183
00184 #define TCVR_FAILURE 0x80000000
00185
00186 static inline int happy_meal_bb_read(struct happy_meal *hp,
00187 struct hmeal_tcvregs *tregs, int reg)
00188 {
00189 volatile int unused;
00190 unsigned long tmp;
00191 int retval = 0;
00192 int i;
00193
00194 ASD(("happy_meal_bb_read: reg=%d ", reg));
00195
00196
00197 hme_write32(hp, &tregs->bb_oenab, 1);
00198
00199
00200 for(i = 0; i < 32; i++)
00201 BB_PUT_BIT(hp, tregs, 1);
00202
00203
00204 BB_PUT_BIT(hp, tregs, 0);
00205 BB_PUT_BIT(hp, tregs, 1);
00206 BB_PUT_BIT(hp, tregs, 1);
00207 BB_PUT_BIT(hp, tregs, 0);
00208
00209
00210 tmp = hp->paddr & 0xff;
00211 for(i = 4; i >= 0; i--)
00212 BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1));
00213
00214
00215 tmp = (reg & 0xff);
00216 for(i = 4; i >= 0; i--)
00217 BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1));
00218
00219
00220 hme_write32(hp, &tregs->bb_oenab, 0);
00221
00222
00223 unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
00224 for(i = 15; i >= 0; i--)
00225 retval |= BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
00226 unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
00227 unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
00228 unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
00229 ASD(("value=%x\n", retval));
00230 return retval;
00231 }
00232
00233 static inline void happy_meal_bb_write(struct happy_meal *hp,
00234 struct hmeal_tcvregs *tregs, int reg,
00235 unsigned short value)
00236 {
00237 unsigned long tmp;
00238 int i;
00239
00240 ASD(("happy_meal_bb_write: reg=%d value=%x\n", reg, value));
00241
00242
00243 hme_write32(hp, &tregs->bb_oenab, 1);
00244
00245
00246 for(i = 0; i < 32; i++)
00247 BB_PUT_BIT(hp, tregs, 1);
00248
00249
00250 BB_PUT_BIT(hp, tregs, 0);
00251 BB_PUT_BIT(hp, tregs, 1);
00252 BB_PUT_BIT(hp, tregs, 0);
00253 BB_PUT_BIT(hp, tregs, 1);
00254
00255
00256 tmp = (hp->paddr & 0xff);
00257 for(i = 4; i >= 0; i--)
00258 BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1));
00259
00260
00261 tmp = (reg & 0xff);
00262 for(i = 4; i >= 0; i--)
00263 BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1));
00264
00265
00266 BB_PUT_BIT(hp, tregs, 1);
00267 BB_PUT_BIT(hp, tregs, 0);
00268
00269 for(i = 15; i >= 0; i--)
00270 BB_PUT_BIT(hp, tregs, ((value >> i) & 1));
00271
00272
00273 hme_write32(hp, &tregs->bb_oenab, 0);
00274 }
00275
00276 #define TCVR_READ_TRIES 16
00277
00278 static inline int happy_meal_tcvr_read(struct happy_meal *hp,
00279 struct hmeal_tcvregs *tregs, int reg)
00280 {
00281 int tries = TCVR_READ_TRIES;
00282 int retval;
00283
00284 ASD(("happy_meal_tcvr_read: reg=0x%02x ", reg));
00285 if(hp->tcvr_type == none) {
00286 ASD(("no transceiver, value=TCVR_FAILURE\n"));
00287 return TCVR_FAILURE;
00288 }
00289
00290 if(!(hp->happy_flags & HFLAG_FENABLE)) {
00291 ASD(("doing bit bang\n"));
00292 return happy_meal_bb_read(hp, tregs, reg);
00293 }
00294
00295 hme_write32(hp, &tregs->frame,
00296 (FRAME_READ | (hp->paddr << 23) | ((reg & 0xff) << 18)));
00297 while(!(hme_read32(hp, &tregs->frame) & 0x10000) && --tries)
00298 udelay(20);
00299 if(!tries) {
00300 printk(KERN_ERR "happy meal: Aieee, transceiver MIF read bolixed\n");
00301 return TCVR_FAILURE;
00302 }
00303 retval = hme_read32(hp, &tregs->frame) & 0xffff;
00304 ASD(("value=%04x\n", retval));
00305 return retval;
00306 }
00307
00308 #define TCVR_WRITE_TRIES 16
00309
00310 static inline void happy_meal_tcvr_write(struct happy_meal *hp,
00311 struct hmeal_tcvregs *tregs, int reg,
00312 unsigned short value)
00313 {
00314 int tries = TCVR_WRITE_TRIES;
00315
00316 ASD(("happy_meal_tcvr_write: reg=0x%02x value=%04x\n", reg, value));
00317
00318
00319 if(!hp->happy_flags & HFLAG_FENABLE)
00320 return happy_meal_bb_write(hp, tregs, reg, value);
00321
00322
00323 hme_write32(hp, &tregs->frame,
00324 (FRAME_WRITE | (hp->paddr << 23) |
00325 ((reg & 0xff) << 18) | (value & 0xffff)));
00326 while(!(hme_read32(hp, &tregs->frame) & 0x10000) && --tries)
00327 udelay(20);
00328
00329
00330 if(!tries)
00331 printk(KERN_ERR "happy meal: Aieee, transceiver MIF write bolixed\n");
00332
00333
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 static int try_next_permutation(struct happy_meal *hp, struct hmeal_tcvregs *tregs)
00369 {
00370 hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
00371
00372
00373
00374
00375 if(hp->sw_bmcr & BMCR_FULLDPLX) {
00376 hp->sw_bmcr &= ~(BMCR_FULLDPLX);
00377 happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
00378 return 0;
00379 }
00380
00381
00382 if(hp->sw_bmcr & BMCR_SPEED100) {
00383 hp->sw_bmcr &= ~(BMCR_SPEED100);
00384 happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
00385 return 0;
00386 }
00387
00388
00389 return -1;
00390 }
00391
00392 static void display_link_mode(struct happy_meal *hp, struct hmeal_tcvregs *tregs)
00393 {
00394 printk(KERN_INFO "%s: Link is up using ", hp->dev->name);
00395 if(hp->tcvr_type == external)
00396 printk("external ");
00397 else
00398 printk("internal ");
00399 printk("transceiver at ");
00400 hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA);
00401 if(hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) {
00402 if(hp->sw_lpa & LPA_100FULL)
00403 printk("100Mb/s, Full Duplex.\n");
00404 else
00405 printk("100Mb/s, Half Duplex.\n");
00406 } else {
00407 if(hp->sw_lpa & LPA_10FULL)
00408 printk("10Mb/s, Full Duplex.\n");
00409 else
00410 printk("10Mb/s, Half Duplex.\n");
00411 }
00412 }
00413
00414 static void display_forced_link_mode(struct happy_meal *hp, struct hmeal_tcvregs *tregs)
00415 {
00416 printk(KERN_INFO "%s: Link has been forced up using ", hp->dev->name);
00417 if(hp->tcvr_type == external)
00418 printk("external ");
00419 else
00420 printk("internal ");
00421 printk("transceiver at ");
00422 hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
00423 if(hp->sw_bmcr & BMCR_SPEED100)
00424 printk("100Mb/s, ");
00425 else
00426 printk("10Mb/s, ");
00427 if(hp->sw_bmcr & BMCR_FULLDPLX)
00428 printk("Full Duplex.\n");
00429 else
00430 printk("Half Duplex.\n");
00431 }
00432
00433 static int set_happy_link_modes(struct happy_meal *hp, struct hmeal_tcvregs *tregs)
00434 {
00435 int full;
00436
00437
00438
00439
00440 if(hp->timer_state == arbwait) {
00441 hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA);
00442 if(!(hp->sw_lpa & (LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL)))
00443 goto no_response;
00444 if(hp->sw_lpa & LPA_100FULL)
00445 full = 1;
00446 else if(hp->sw_lpa & LPA_100HALF)
00447 full = 0;
00448 else if(hp->sw_lpa & LPA_10FULL)
00449 full = 1;
00450 else
00451 full = 0;
00452 } else {
00453
00454 hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
00455 if(hp->sw_bmcr & BMCR_FULLDPLX)
00456 full = 1;
00457 else
00458 full = 0;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 hme_write32(hp, &hp->bigmacregs->tx_cfg,
00470 hme_read32(hp, &hp->bigmacregs->tx_cfg) &
00471 ~(BIGMAC_TXCFG_ENABLE));
00472 while(hme_read32(hp, &hp->bigmacregs->tx_cfg) & BIGMAC_TXCFG_ENABLE)
00473 barrier();
00474 if(full) {
00475 hp->happy_flags |= HFLAG_FULL;
00476 hme_write32(hp, &hp->bigmacregs->tx_cfg,
00477 hme_read32(hp, &hp->bigmacregs->tx_cfg) |
00478 BIGMAC_TXCFG_FULLDPLX);
00479 } else {
00480 hp->happy_flags &= ~(HFLAG_FULL);
00481 hme_write32(hp, &hp->bigmacregs->tx_cfg,
00482 hme_read32(hp, &hp->bigmacregs->tx_cfg) &
00483 ~(BIGMAC_TXCFG_FULLDPLX));
00484 }
00485 hme_write32(hp, &hp->bigmacregs->tx_cfg,
00486 hme_read32(hp, &hp->bigmacregs->tx_cfg) |
00487 BIGMAC_TXCFG_ENABLE);
00488 return 0;
00489 no_response:
00490 return 1;
00491 }
00492
00493 static int happy_meal_init(struct happy_meal *hp, int from_irq);
00494
00495 static int is_lucent_phy(struct happy_meal *hp)
00496 {
00497 struct hmeal_tcvregs *tregs = hp->tcvregs;
00498 unsigned short mr2, mr3;
00499 int ret = 0;
00500
00501 mr2 = happy_meal_tcvr_read(hp, tregs, 2);
00502 mr3 = happy_meal_tcvr_read(hp, tregs, 3);
00503 if ((mr2 & 0xffff) == 0x0180 &&
00504 ((mr3 & 0xffff) >> 10) == 0x1d) {
00505 #if 0
00506 printk("HMEDEBUG: Lucent PHY detected.\n");
00507 #endif
00508 ret = 1;
00509 }
00510
00511 return ret;
00512 }
00513
00514 static void happy_meal_timer(unsigned long data)
00515 {
00516 struct happy_meal *hp = (struct happy_meal *) data;
00517 struct hmeal_tcvregs *tregs = hp->tcvregs;
00518 int restart_timer = 0;
00519
00520 hp->timer_ticks++;
00521 switch(hp->timer_state) {
00522 case arbwait:
00523
00524
00525
00526 if(hp->timer_ticks >= 10) {
00527
00528 do_force_mode:
00529 hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
00530 printk(KERN_NOTICE "%s: Auto-Negotiation unsuccessful, trying force link mode\n",
00531 hp->dev->name);
00532 hp->sw_bmcr = BMCR_SPEED100;
00533 happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
00534
00535 if (!is_lucent_phy(hp)) {
00536
00537
00538
00539
00540 hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs,
00541 DP83840_CSCONFIG);
00542 hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
00543 happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG,
00544 hp->sw_csconfig);
00545 }
00546 hp->timer_state = ltrywait;
00547 hp->timer_ticks = 0;
00548 restart_timer = 1;
00549 } else {
00550
00551 hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR);
00552 if(hp->sw_bmsr & BMSR_ANEGCOMPLETE) {
00553 int ret;
00554
00555
00556 ret = set_happy_link_modes(hp, tregs);
00557 if(ret) {
00558
00559
00560
00561
00562
00563
00564 goto do_force_mode;
00565 }
00566
00567
00568 hp->timer_state = lupwait;
00569 restart_timer = 1;
00570 } else {
00571 restart_timer = 1;
00572 }
00573 }
00574 break;
00575
00576 case lupwait:
00577
00578
00579
00580
00581
00582 hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR);
00583 if(hp->sw_bmsr & BMSR_LSTATUS) {
00584
00585
00586
00587 display_link_mode(hp, tregs);
00588 hp->timer_state = asleep;
00589 restart_timer = 0;
00590 } else {
00591 if(hp->timer_ticks >= 10) {
00592 printk(KERN_NOTICE "%s: Auto negotiation successful, link still "
00593 "not completely up.\n", hp->dev->name);
00594 hp->timer_ticks = 0;
00595 restart_timer = 1;
00596 } else {
00597 restart_timer = 1;
00598 }
00599 }
00600 break;
00601
00602 case ltrywait:
00603
00604
00605
00606
00607
00608 hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR);
00609 hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
00610 if(hp->timer_ticks == 1) {
00611
00612
00613
00614
00615 if (!is_lucent_phy(hp)) {
00616 hp->sw_csconfig |= CSCONFIG_TCVDISAB;
00617 happy_meal_tcvr_write(hp, tregs,
00618 DP83840_CSCONFIG, hp->sw_csconfig);
00619 }
00620 restart_timer = 1;
00621 break;
00622 }
00623 if(hp->timer_ticks == 2) {
00624
00625 if (!is_lucent_phy(hp)) {
00626 hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
00627 happy_meal_tcvr_write(hp, tregs,
00628 DP83840_CSCONFIG, hp->sw_csconfig);
00629 }
00630 restart_timer = 1;
00631 break;
00632 }
00633 if(hp->sw_bmsr & BMSR_LSTATUS) {
00634
00635 display_forced_link_mode(hp, tregs);
00636 set_happy_link_modes(hp, tregs);
00637 hp->timer_state = asleep;
00638 restart_timer = 0;
00639 } else {
00640 if(hp->timer_ticks >= 4) {
00641 int ret;
00642
00643 ret = try_next_permutation(hp, tregs);
00644 if(ret == -1) {
00645
00646
00647
00648
00649
00650 printk(KERN_NOTICE "%s: Link down, cable problem?\n",
00651 hp->dev->name);
00652
00653 ret = happy_meal_init(hp, 0);
00654 if(ret) {
00655
00656 printk(KERN_ERR "%s: Error, cannot re-init the "
00657 "Happy Meal.\n", hp->dev->name);
00658 }
00659 return;
00660 }
00661 hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs,
00662 DP83840_CSCONFIG);
00663 if (!is_lucent_phy(hp)) {
00664 hp->sw_csconfig |= CSCONFIG_TCVDISAB;
00665 happy_meal_tcvr_write(hp, tregs,
00666 DP83840_CSCONFIG,
00667 hp->sw_csconfig);
00668 }
00669 hp->timer_ticks = 0;
00670 restart_timer = 1;
00671 } else {
00672 restart_timer = 1;
00673 }
00674 }
00675 break;
00676
00677 case asleep:
00678 default:
00679
00680 printk(KERN_ERR "%s: Aieee, link timer is asleep but we got one anyways!\n",
00681 hp->dev->name);
00682 restart_timer = 0;
00683 hp->timer_ticks = 0;
00684 hp->timer_state = asleep;
00685 break;
00686 };
00687
00688 if(restart_timer) {
00689 hp->happy_timer.expires = jiffies + ((12 * HZ)/10);
00690 add_timer(&hp->happy_timer);
00691 }
00692 }
00693
00694 #define TX_RESET_TRIES 32
00695 #define RX_RESET_TRIES 32
00696
00697 static inline void happy_meal_tx_reset(struct happy_meal *hp,
00698 struct hmeal_bigmacregs *bregs)
00699 {
00700 int tries = TX_RESET_TRIES;
00701
00702 HMD(("happy_meal_tx_reset: reset, "));
00703
00704
00705 hme_write32(hp, &bregs->tx_swreset, 0);
00706 while((hme_read32(hp, &bregs->tx_swreset) & 1) && --tries)
00707 udelay(20);
00708
00709
00710 if(!tries)
00711 printk(KERN_ERR "happy meal: Transceiver BigMac ATTACK!");
00712
00713
00714 HMD(("done\n"));
00715 }
00716
00717 static inline void happy_meal_rx_reset(struct happy_meal *hp,
00718 struct hmeal_bigmacregs *bregs)
00719 {
00720 int tries = RX_RESET_TRIES;
00721
00722 HMD(("happy_meal_rx_reset: reset, "));
00723
00724
00725 hme_write32(hp, &bregs->rx_swreset, 0);
00726 while((hme_read32(hp, &bregs->rx_swreset) & 1) && --tries)
00727 udelay(20);
00728
00729
00730 if(!tries)
00731 printk(KERN_ERR "happy meal: Receiver BigMac ATTACK!");
00732
00733
00734 HMD(("done\n"));
00735 }
00736
00737 #define STOP_TRIES 16
00738
00739 static inline void happy_meal_stop(struct happy_meal *hp,
00740 struct hmeal_gregs *gregs)
00741 {
00742 int tries = STOP_TRIES;
00743
00744 HMD(("happy_meal_stop: reset, "));
00745
00746
00747 hme_write32(hp, &gregs->sw_reset, GREG_RESET_ALL);
00748 while(hme_read32(hp, &gregs->sw_reset) && --tries)
00749 udelay(20);
00750
00751
00752 if(!tries)
00753 printk(KERN_ERR "happy meal: Fry guys.");
00754
00755
00756 HMD(("done\n"));
00757 }
00758
00759 static void happy_meal_get_counters(struct happy_meal *hp,
00760 struct hmeal_bigmacregs *bregs)
00761 {
00762 struct net_device_stats *stats = &hp->net_stats;
00763
00764 stats->rx_crc_errors += hme_read32(hp, &bregs->rcrce_ctr);
00765 hme_write32(hp, &bregs->rcrce_ctr, 0);
00766
00767 stats->rx_frame_errors += hme_read32(hp, &bregs->unale_ctr);
00768 hme_write32(hp, &bregs->unale_ctr, 0);
00769
00770 stats->rx_length_errors += hme_read32(hp, &bregs->gle_ctr);
00771 hme_write32(hp, &bregs->gle_ctr, 0);
00772
00773 stats->tx_aborted_errors += hme_read32(hp, &bregs->ex_ctr);
00774
00775 stats->collisions +=
00776 (hme_read32(hp, &bregs->ex_ctr) +
00777 hme_read32(hp, &bregs->lt_ctr));
00778 hme_write32(hp, &bregs->ex_ctr, 0);
00779 hme_write32(hp, &bregs->lt_ctr, 0);
00780 }
00781
00782 static inline void happy_meal_poll_start(struct happy_meal *hp,
00783 struct hmeal_tcvregs *tregs)
00784 {
00785 unsigned long tmp;
00786 int speed;
00787
00788 ASD(("happy_meal_poll_start: "));
00789 if(!(hp->happy_flags & HFLAG_POLLENABLE)) {
00790 HMD(("polling disabled, return\n"));
00791 return;
00792 }
00793
00794
00795 ASD(("polling on, "));
00796 tmp = hme_read32(hp, &tregs->cfg);
00797 tmp &= ~(TCV_CFG_PDADDR | TCV_CFG_PREGADDR);
00798 tmp |= ((hp->paddr & 0x1f) << 10);
00799 tmp |= (TCV_PADDR_ETX << 3);
00800 tmp |= TCV_CFG_PENABLE;
00801 hme_write32(hp, &tregs->cfg, tmp);
00802
00803
00804 udelay(200);
00805
00806
00807 ASD(("now polling, "));
00808 hp->happy_flags |= HFLAG_POLL;
00809
00810
00811 hp->poll_flag = 0;
00812 hp->poll_data = tregs->status >> 16;
00813
00814 if(hp->happy_flags & HFLAG_AUTO)
00815 speed = hp->auto_speed;
00816 else
00817 speed = hp->forced_speed;
00818
00819
00820 ASD(("mif ints on, "));
00821 if(speed == 100)
00822 hme_write32(hp, &tregs->int_mask, 0xfffb);
00823 else
00824 hme_write32(hp, &tregs->int_mask, 0xfff9);
00825 ASD(("done\n"));
00826 }
00827
00828 static inline void happy_meal_poll_stop(struct happy_meal *hp,
00829 struct hmeal_tcvregs *tregs)
00830 {
00831 ASD(("happy_meal_poll_stop: "));
00832
00833
00834 if((hp->happy_flags & (HFLAG_POLLENABLE | HFLAG_POLL)) !=
00835 (HFLAG_POLLENABLE | HFLAG_POLL)) {
00836 HMD(("not polling, return\n"));
00837 return;
00838 }
00839
00840
00841 ASD(("were polling, mif ints off, "));
00842 hme_write32(hp, &tregs->int_mask, 0xffff);
00843
00844
00845 ASD(("polling off, "));
00846 hme_write32(hp, &tregs->cfg,
00847 hme_read32(hp, &tregs->cfg) & ~(TCV_CFG_PENABLE));
00848
00849
00850 hp->happy_flags &= ~(HFLAG_POLL);
00851
00852
00853 udelay(200);
00854 ASD(("done\n"));
00855 }
00856
00857
00858
00859
00860 #define TCVR_RESET_TRIES 16
00861 #define TCVR_UNISOLATE_TRIES 32
00862
00863 static int happy_meal_tcvr_reset(struct happy_meal *hp,
00864 struct hmeal_tcvregs *tregs)
00865 {
00866 unsigned long tconfig;
00867 int result, tries = TCVR_RESET_TRIES;
00868
00869 tconfig = hme_read32(hp, &tregs->cfg);
00870 ASD(("happy_meal_tcvr_reset: tcfg<%08lx> ", tconfig));
00871 if(hp->tcvr_type == external) {
00872 ASD(("external<"));
00873 hme_write32(hp, &tregs->cfg, tconfig & ~(TCV_CFG_PSELECT));
00874 hp->tcvr_type = internal;
00875 hp->paddr = TCV_PADDR_ITX;
00876 ASD(("ISOLATE,"));
00877 happy_meal_tcvr_write(hp, tregs, DP83840_BMCR,
00878 (BMCR_LOOPBACK|BMCR_PDOWN|BMCR_ISOLATE));
00879 result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
00880 if(result == TCVR_FAILURE) {
00881 ASD(("phyread_fail>\n"));
00882 return -1;
00883 }
00884 ASD(("phyread_ok,PSELECT>"));
00885 hme_write32(hp, &tregs->cfg, tconfig | TCV_CFG_PSELECT);
00886 hp->tcvr_type = external;
00887 hp->paddr = TCV_PADDR_ETX;
00888 } else {
00889 if(tconfig & TCV_CFG_MDIO1) {
00890 ASD(("internal<PSELECT,"));
00891 hme_write32(hp, &tregs->cfg, (tconfig | TCV_CFG_PSELECT));
00892 ASD(("ISOLATE,"));
00893 happy_meal_tcvr_write(hp, tregs, DP83840_BMCR,
00894 (BMCR_LOOPBACK|BMCR_PDOWN|BMCR_ISOLATE));
00895 result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
00896 if(result == TCVR_FAILURE) {
00897 ASD(("phyread_fail>\n"));
00898 return -1;
00899 }
00900 ASD(("phyread_ok,~PSELECT>"));
00901 hme_write32(hp, &tregs->cfg, (tconfig & ~(TCV_CFG_PSELECT)));
00902 hp->tcvr_type = internal;
00903 hp->paddr = TCV_PADDR_ITX;
00904 }
00905 }
00906
00907 ASD(("BMCR_RESET "));
00908 happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, BMCR_RESET);
00909
00910 while(--tries) {
00911 result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
00912 if(result == TCVR_FAILURE)
00913 return -1;
00914 hp->sw_bmcr = result;
00915 if(!(result & BMCR_RESET))
00916 break;
00917 udelay(20);
00918 }
00919 if(!tries) {
00920 ASD(("BMCR RESET FAILED!\n"));
00921 return -1;
00922 }
00923 ASD(("RESET_OK\n"));
00924
00925
00926 hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR);
00927 hp->sw_physid1 = happy_meal_tcvr_read(hp, tregs, DP83840_PHYSID1);
00928 hp->sw_physid2 = happy_meal_tcvr_read(hp, tregs, DP83840_PHYSID2);
00929 hp->sw_advertise = happy_meal_tcvr_read(hp, tregs, DP83840_ADVERTISE);
00930
00931 ASD(("UNISOLATE"));
00932 hp->sw_bmcr &= ~(BMCR_ISOLATE);
00933 happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
00934
00935 tries = TCVR_UNISOLATE_TRIES;
00936 while(--tries) {
00937 result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
00938 if(result == TCVR_FAILURE)
00939 return -1;
00940 if(!(result & BMCR_ISOLATE))
00941 break;
00942 udelay(20);
00943 }
00944 if(!tries) {
00945 ASD((" FAILED!\n"));
00946 return -1;
00947 }
00948 ASD((" SUCCESS and CSCONFIG_DFBYPASS\n"));
00949 if (!is_lucent_phy(hp)) {
00950 result = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
00951 happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG,
00952 (result | CSCONFIG_DFBYPASS));
00953 }
00954 return 0;
00955 }
00956
00957
00958 static void happy_meal_transceiver_check(struct happy_meal *hp,
00959 struct hmeal_tcvregs *tregs)
00960 {
00961 unsigned long tconfig = hme_read32(hp, &tregs->cfg);
00962
00963 ASD(("happy_meal_transceiver_check: tcfg=%08lx ", tconfig));
00964 if(hp->happy_flags & HFLAG_POLL) {
00965
00966 ASD(("<polling> "));
00967 if(hp->tcvr_type == internal) {
00968 if(tconfig & TCV_CFG_MDIO1) {
00969 ASD(("<internal> <poll stop> "));
00970 happy_meal_poll_stop(hp, tregs);
00971 hp->paddr = TCV_PADDR_ETX;
00972 hp->tcvr_type = external;
00973 ASD(("<external>\n"));
00974 tconfig &= ~(TCV_CFG_PENABLE);
00975 tconfig |= TCV_CFG_PSELECT;
00976 hme_write32(hp, &tregs->cfg, tconfig);
00977 }
00978 } else {
00979 if(hp->tcvr_type == external) {
00980 ASD(("<external> "));
00981 if(!(hme_read32(hp, &tregs->status) >> 16)) {
00982 ASD(("<poll stop> "));
00983 happy_meal_poll_stop(hp, tregs);
00984 hp->paddr = TCV_PADDR_ITX;
00985 hp->tcvr_type = internal;
00986 ASD(("<internal>\n"));
00987 hme_write32(hp, &tregs->cfg,
00988 hme_read32(hp, &tregs->cfg) &
00989 ~(TCV_CFG_PSELECT));
00990 }
00991 ASD(("\n"));
00992 } else {
00993 ASD(("<none>\n"));
00994 }
00995 }
00996 } else {
00997 unsigned long reread = hme_read32(hp, &tregs->cfg);
00998
00999
01000 ASD(("<not polling> "));
01001 if(reread & TCV_CFG_MDIO1) {
01002 hme_write32(hp, &tregs->cfg, tconfig | TCV_CFG_PSELECT);
01003 hp->paddr = TCV_PADDR_ETX;
01004 hp->tcvr_type = external;
01005 ASD(("<external>\n"));
01006 } else {
01007 if(reread & TCV_CFG_MDIO0) {
01008 hme_write32(hp, &tregs->cfg,
01009 tconfig & ~(TCV_CFG_PSELECT));
01010 hp->paddr = TCV_PADDR_ITX;
01011 hp->tcvr_type = internal;
01012 ASD(("<internal>\n"));
01013 } else {
01014 printk(KERN_ERR "happy meal: Transceiver and a coke please.");
01015 hp->tcvr_type = none;
01016 ASD(("<none>\n"));
01017 }
01018 }
01019 }
01020 }
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066 static inline void happy_meal_clean_rings(struct happy_meal *hp)
01067 {
01068 int i;
01069
01070 for(i = 0; i < RX_RING_SIZE; i++) {
01071 if(hp->rx_skbs[i] != NULL) {
01072 dev_kfree_skb(hp->rx_skbs[i]);
01073 hp->rx_skbs[i] = NULL;
01074 }
01075 }
01076
01077 for(i = 0; i < TX_RING_SIZE; i++) {
01078 if(hp->tx_skbs[i] != NULL) {
01079 dev_kfree_skb(hp->tx_skbs[i]);
01080 hp->tx_skbs[i] = NULL;
01081 }
01082 }
01083 }
01084
01085 static void happy_meal_init_rings(struct happy_meal *hp, int from_irq)
01086 {
01087 struct hmeal_init_block *hb = hp->happy_block;
01088 struct device *dev = hp->dev;
01089 int i, gfp_flags = GFP_KERNEL;
01090
01091 if(from_irq || in_interrupt())
01092 gfp_flags = GFP_ATOMIC;
01093
01094 HMD(("happy_meal_init_rings: counters to zero, "));
01095 hp->rx_new = hp->rx_old = hp->tx_new = hp->tx_old = 0;
01096
01097
01098 HMD(("clean, "));
01099 happy_meal_clean_rings(hp);
01100
01101
01102 HMD(("init rxring, "));
01103 for(i = 0; i < RX_RING_SIZE; i++) {
01104 struct sk_buff *skb;
01105
01106 skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, gfp_flags | GFP_DMA);
01107 if(!skb)
01108 continue;
01109 hp->rx_skbs[i] = skb;
01110 skb->dev = dev;
01111
01112
01113 skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET));
01114
01115 #ifdef CONFIG_PCI
01116 if(hp->happy_flags & HFLAG_PCI) {
01117 pcihme_write_rxd(&hb->happy_meal_rxd[i],
01118 (RXFLAG_OWN |
01119 ((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
01120 (u32)virt_to_bus((volatile void *)skb->data));
01121 } else
01122 #endif
01123 #ifndef __sparc_v9__
01124 if (sparc_cpu_model == sun4d) {
01125 __u32 va = (__u32)hp->sun4d_buffers + i * PAGE_SIZE;
01126
01127 hb->happy_meal_rxd[i].rx_addr =
01128 iounit_map_dma_page(va, skb->data, hp->happy_sbus_dev->my_bus);
01129 hb->happy_meal_rxd[i].rx_flags =
01130 (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
01131 } else
01132 #endif
01133 {
01134 hb->happy_meal_rxd[i].rx_addr = sbus_dvma_addr(skb->data);
01135 hb->happy_meal_rxd[i].rx_flags =
01136 (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
01137 }
01138 skb_reserve(skb, RX_OFFSET);
01139 }
01140
01141 HMD(("init txring, "));
01142 for(i = 0; i < TX_RING_SIZE; i++)
01143 hb->happy_meal_txd[i].tx_flags = 0;
01144 HMD(("done\n"));
01145 }
01146
01147 #ifndef __sparc_v9__
01148 static void sun4c_happy_meal_init_rings(struct happy_meal *hp)
01149 {
01150 struct hmeal_init_block *hb = hp->happy_block;
01151 __u32 hbufs = hp->s4c_buf_dvma;
01152 int i;
01153
01154 HMD(("happy_meal_init_rings: counters to zero, "));
01155 hp->rx_new = hp->rx_old = hp->tx_new = hp->tx_old = 0;
01156
01157 HMD(("init rxring, "));
01158 for(i = 0; i < RX_RING_SIZE; i++) {
01159 hb->happy_meal_rxd[i].rx_addr = hbufs + hbuf_offset(rx_buf, i);
01160 hb->happy_meal_rxd[i].rx_flags =
01161 (RXFLAG_OWN | ((SUN4C_RX_BUFF_SIZE - RX_OFFSET) << 16));
01162 }
01163
01164 HMD(("init txring, "));
01165 for(i = 0; i < TX_RING_SIZE; i++)
01166 hb->happy_meal_txd[i].tx_flags = 0;
01167 HMD(("done\n"));
01168 }
01169 #endif
01170
01171 static void happy_meal_begin_auto_negotiation(struct happy_meal *hp,
01172 struct hmeal_tcvregs *tregs,
01173 struct ethtool_cmd *ep)
01174 {
01175 int timeout;
01176
01177
01178 hp->