1*53897Smckusick /* 2*53897Smckusick * Copyright (c) 1992 The Regents of the University of California. 3*53897Smckusick * All rights reserved. 4*53897Smckusick * 5*53897Smckusick * This code is derived from software contributed to Berkeley by 6*53897Smckusick * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 7*53897Smckusick * 8*53897Smckusick * %sccs.include.redist.c% 9*53897Smckusick * 10*53897Smckusick * from: $Hdr: if_lance.c,v 4.300 91/06/09 06:25:58 root Rel41 $ SONY 11*53897Smckusick * 12*53897Smckusick * @(#)if_lance.c 7.1 (Berkeley) 06/04/92 13*53897Smckusick */ 14*53897Smckusick 15*53897Smckusick /* 16*53897Smckusick * if_lance: Am7990 LANCE driver 17*53897Smckusick * 18*53897Smckusick * This driver is available only for single CPU machine. 19*53897Smckusick */ 20*53897Smckusick 21*53897Smckusick #define LANCE_LED 22*53897Smckusick 23*53897Smckusick #include "en.h" 24*53897Smckusick 25*53897Smckusick #if NEN > 0 26*53897Smckusick 27*53897Smckusick #include "../include/fix_machine_type.h" 28*53897Smckusick #include "../include/adrsmap.h" 29*53897Smckusick 30*53897Smckusick #include "param.h" 31*53897Smckusick 32*53897Smckusick #include "../if/lancereg.h" 33*53897Smckusick #include "../if/if_lance.h" 34*53897Smckusick 35*53897Smckusick #ifdef mips 36*53897Smckusick #define VOLATILE volatile 37*53897Smckusick #else 38*53897Smckusick #define VOLATILE 39*53897Smckusick #endif 40*53897Smckusick 41*53897Smckusick #ifdef LANCE_LED 42*53897Smckusick #ifdef news3400 43*53897Smckusick #define LED_ON { \ 44*53897Smckusick VOLATILE u_char *p = (u_char *)DEBUG_PORT; \ 45*53897Smckusick *p = DP_WRITE | (*p & ~DP_LED2); \ 46*53897Smckusick } 47*53897Smckusick #define LED_OFF { \ 48*53897Smckusick VOLATILE u_char *p = (u_char *)DEBUG_PORT; \ 49*53897Smckusick *p = DP_WRITE | (*p | DP_LED2); \ 50*53897Smckusick } 51*53897Smckusick #else /* news3400 */ 52*53897Smckusick #define LED_ON 53*53897Smckusick #define LED_OFF 54*53897Smckusick #endif /* news3400 */ 55*53897Smckusick #else /* LANCE_LED */ 56*53897Smckusick #define LED_ON 57*53897Smckusick #define LED_OFF 58*53897Smckusick #endif /* LANCE_LED */ 59*53897Smckusick 60*53897Smckusick /* 61*53897Smckusick * LANCE memory configuration 62*53897Smckusick */ 63*53897Smckusick #define INIT_BLOCK 0x000000 64*53897Smckusick #define RECV_MSG_DESC 0x000100 65*53897Smckusick #define XMIT_MSG_DESC 0x000200 66*53897Smckusick #ifdef mips 67*53897Smckusick #define RECV_BUFFER (0x000300 + 2) 68*53897Smckusick /* for data alignment to long word */ 69*53897Smckusick #else /* mips */ 70*53897Smckusick #define RECV_BUFFER 0x000300 71*53897Smckusick #endif /* mips */ 72*53897Smckusick #define XMIT_BUFFER (RECV_BUFFER+(RECV_BUFFER_SIZE*RECV_BUFFERS)) 73*53897Smckusick 74*53897Smckusick #define RECV_RING_LEN 3 /* log2(8) */ 75*53897Smckusick #define XMIT_RING_LEN 1 /* log2(2) */ 76*53897Smckusick 77*53897Smckusick #define RECV_BUFFER_SIZE 0x600 78*53897Smckusick #define XMIT_BUFFER_SIZE 0x600 79*53897Smckusick 80*53897Smckusick #define RECV_BUFFERS (1 << RECV_RING_LEN) 81*53897Smckusick #define XMIT_BUFFERS (1 << XMIT_RING_LEN) 82*53897Smckusick 83*53897Smckusick /* 84*53897Smckusick * Initialization block 85*53897Smckusick */ 86*53897Smckusick struct init_block init_block = { 87*53897Smckusick 0, 88*53897Smckusick 0, 0, 0, 0, 0, 0, 89*53897Smckusick 0, 0, 0, 0, 0, 0, 0, 0, 90*53897Smckusick RECV_MSG_DESC & 0xffff, 91*53897Smckusick (RECV_RING_LEN << 13) | (RECV_MSG_DESC >> 16), 92*53897Smckusick XMIT_MSG_DESC & 0xffff, 93*53897Smckusick (XMIT_RING_LEN << 13) | (XMIT_MSG_DESC >> 16) 94*53897Smckusick }; 95*53897Smckusick 96*53897Smckusick /* 97*53897Smckusick * LANCE control block 98*53897Smckusick */ 99*53897Smckusick Lance_chan lancesw[NEN] = { 100*53897Smckusick { (Lance_reg *)LANCE_PORT, 101*53897Smckusick (caddr_t)LANCE_MEMORY, 102*53897Smckusick (caddr_t)ETHER_ID }, 103*53897Smckusick #if NEN > 1 104*53897Smckusick { (Lance_reg *)LANCE_PORT1, 105*53897Smckusick (caddr_t)LANCE_MEMORY1, 106*53897Smckusick (caddr_t)ETHER_ID1 }, 107*53897Smckusick #endif /* NEN > 1 */ 108*53897Smckusick #if NEN > 2 109*53897Smckusick { (Lance_reg *)LANCE_PORT2, 110*53897Smckusick (caddr_t)LANCE_MEMORY2, 111*53897Smckusick (caddr_t)ETHER_ID2 }, 112*53897Smckusick #endif /* NEN > 2 */ 113*53897Smckusick }; 114*53897Smckusick 115*53897Smckusick lance_probe(chan) 116*53897Smckusick int chan; 117*53897Smckusick { 118*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 119*53897Smckusick VOLATILE int *p = (VOLATILE int *)lance->lance_memory; 120*53897Smckusick 121*53897Smckusick if (badaddr(lance->lance_addr, 1)) 122*53897Smckusick return (0); 123*53897Smckusick 124*53897Smckusick *p = 0x12345678; 125*53897Smckusick 126*53897Smckusick return (*p == 0x12345678); 127*53897Smckusick } 128*53897Smckusick 129*53897Smckusick lance_open(chan) 130*53897Smckusick int chan; 131*53897Smckusick { 132*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 133*53897Smckusick register recv_msg_desc *rmd; 134*53897Smckusick register xmit_msg_desc *tmd; 135*53897Smckusick register struct init_block *ib; 136*53897Smckusick register int buffer, i; 137*53897Smckusick 138*53897Smckusick if ((lance->lance_flags & LANCE_ACTIVE) == 0) { 139*53897Smckusick if (lance->lance_addr == (Lance_reg *)0) 140*53897Smckusick return (-1); 141*53897Smckusick 142*53897Smckusick lance_write_reg(chan, CSR0, CSR_STOP); 143*53897Smckusick 144*53897Smckusick rmd = (recv_msg_desc *) 145*53897Smckusick (RECV_MSG_DESC + lance->lance_memory); 146*53897Smckusick lance->lance_last_rmd = 147*53897Smckusick (lance->lance_rmd = rmd) + RECV_BUFFERS - 1; 148*53897Smckusick buffer = RECV_BUFFER; 149*53897Smckusick for (i = 0; i < RECV_BUFFERS; i++) { 150*53897Smckusick rmd->rmd_ladr = buffer & 0xffff; 151*53897Smckusick rmd->rmd_stat = RMD_OWN | (buffer >> 16); 152*53897Smckusick rmd->rmd_bcnt = -RECV_BUFFER_SIZE; 153*53897Smckusick rmd->rmd_mcnt = 0; 154*53897Smckusick rmd++; 155*53897Smckusick buffer += RECV_BUFFER_SIZE; 156*53897Smckusick } 157*53897Smckusick 158*53897Smckusick tmd = (xmit_msg_desc *) 159*53897Smckusick (XMIT_MSG_DESC + lance->lance_memory); 160*53897Smckusick lance->lance_last_tmd = 161*53897Smckusick (lance->lance_tmd = tmd) + XMIT_BUFFERS - 1; 162*53897Smckusick buffer = XMIT_BUFFER; 163*53897Smckusick for (i = 0; i < XMIT_BUFFERS; i++) { 164*53897Smckusick tmd->tmd_ladr = buffer & 0xffff; 165*53897Smckusick tmd->tmd_stat = buffer >> 16; 166*53897Smckusick tmd->tmd_bcnt = 0; 167*53897Smckusick tmd++; 168*53897Smckusick buffer += XMIT_BUFFER_SIZE; 169*53897Smckusick } 170*53897Smckusick get_hard_addr(chan, lance->lance_stats.ens_addr); 171*53897Smckusick 172*53897Smckusick ib = (struct init_block *)(INIT_BLOCK + lance->lance_memory); 173*53897Smckusick lance->lance_ib = ib; 174*53897Smckusick *ib = init_block; 175*53897Smckusick ib->ib_padr[0] = lance->lance_stats.ens_addr[1]; 176*53897Smckusick ib->ib_padr[1] = lance->lance_stats.ens_addr[0]; 177*53897Smckusick ib->ib_padr[2] = lance->lance_stats.ens_addr[3]; 178*53897Smckusick ib->ib_padr[3] = lance->lance_stats.ens_addr[2]; 179*53897Smckusick ib->ib_padr[4] = lance->lance_stats.ens_addr[5]; 180*53897Smckusick ib->ib_padr[5] = lance->lance_stats.ens_addr[4]; 181*53897Smckusick 182*53897Smckusick if (lance->lance_flags & LANCE_PROM) 183*53897Smckusick ib->ib_mode |= IB_PROM; 184*53897Smckusick 185*53897Smckusick lance->lance_flags |= LANCE_ACTIVE; 186*53897Smckusick lance_init(chan); 187*53897Smckusick 188*53897Smckusick if (lance_read_reg(chan, CSR0) != 189*53897Smckusick (CSR_INEA|CSR_RXON|CSR_TXON|CSR_STRT|CSR_INIT)) { 190*53897Smckusick lance->lance_flags &= ~LANCE_ACTIVE; 191*53897Smckusick return (-1); 192*53897Smckusick } 193*53897Smckusick 194*53897Smckusick } 195*53897Smckusick 196*53897Smckusick return (0); 197*53897Smckusick } 198*53897Smckusick 199*53897Smckusick lance_close(chan) 200*53897Smckusick int chan; 201*53897Smckusick { 202*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 203*53897Smckusick 204*53897Smckusick lance_write_reg(chan, CSR0, CSR_STOP); 205*53897Smckusick lance->lance_flags &= ~LANCE_ACTIVE; 206*53897Smckusick 207*53897Smckusick } 208*53897Smckusick 209*53897Smckusick #define RECEIVE(lance, rmd) { \ 210*53897Smckusick register int i; \ 211*53897Smckusick (rmd) = (lance)->lance_last_rmd + 1; \ 212*53897Smckusick if ((rmd) >= (lance)->lance_rmd + RECV_BUFFERS) \ 213*53897Smckusick (rmd) = (lance)->lance_rmd; \ 214*53897Smckusick if (((rmd)->rmd_stat & RMD_OWN) == 0) \ 215*53897Smckusick (lance)->lance_last_rmd = (rmd); \ 216*53897Smckusick else \ 217*53897Smckusick (rmd) = NULL; \ 218*53897Smckusick } 219*53897Smckusick #define RECV_BUF(lance, rmd) (char *)((rmd)->rmd_ladr \ 220*53897Smckusick + (((rmd)->rmd_stat & RMD_HADR) << 16) \ 221*53897Smckusick + (lance)->lance_memory) 222*53897Smckusick #define RECV_CNT(rmd) ((rmd)->rmd_mcnt - 4) 223*53897Smckusick #define RECV_ERR(rmd) ((rmd)->rmd_stat & RMD_ERR) 224*53897Smckusick #define RELEASE_RECV_BUF(rmd) { \ 225*53897Smckusick (rmd)->rmd_mcnt = 0; \ 226*53897Smckusick (rmd)->rmd_stat = ((rmd)->rmd_stat & RMD_HADR) | RMD_OWN; \ 227*53897Smckusick } 228*53897Smckusick 229*53897Smckusick 230*53897Smckusick caddr_t 231*53897Smckusick get_recv_buffer(chan) 232*53897Smckusick int chan; 233*53897Smckusick { 234*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 235*53897Smckusick register recv_msg_desc *rmd; 236*53897Smckusick 237*53897Smckusick next: 238*53897Smckusick RECEIVE(lance, rmd); 239*53897Smckusick if (rmd == NULL) 240*53897Smckusick return (NULL); 241*53897Smckusick 242*53897Smckusick #ifdef news700 243*53897Smckusick lance_led(); 244*53897Smckusick #endif /* news700 */ 245*53897Smckusick 246*53897Smckusick if (RECV_ERR(rmd)) { 247*53897Smckusick recv_error(lance, rmd); 248*53897Smckusick RELEASE_RECV_BUF(rmd); 249*53897Smckusick goto next; 250*53897Smckusick } 251*53897Smckusick 252*53897Smckusick return (RECV_BUF(lance, rmd)); 253*53897Smckusick } 254*53897Smckusick 255*53897Smckusick get_recv_length(chan) 256*53897Smckusick int chan; 257*53897Smckusick { 258*53897Smckusick 259*53897Smckusick return (RECV_CNT(lancesw[chan].lance_last_rmd)); 260*53897Smckusick } 261*53897Smckusick 262*53897Smckusick free_recv_buffer(chan) 263*53897Smckusick int chan; 264*53897Smckusick { 265*53897Smckusick register recv_msg_desc *rmd = lancesw[chan].lance_last_rmd; 266*53897Smckusick 267*53897Smckusick RELEASE_RECV_BUF(rmd); 268*53897Smckusick } 269*53897Smckusick 270*53897Smckusick #define GET_XMIT_BUF(lance, tmd) { \ 271*53897Smckusick (tmd) = (lance)->lance_last_tmd + 1; \ 272*53897Smckusick if ((tmd) >= (lance)->lance_tmd + XMIT_BUFFERS) \ 273*53897Smckusick (tmd) = (lance)->lance_tmd; \ 274*53897Smckusick if ((tmd)->tmd_stat & TMD_OWN) \ 275*53897Smckusick (tmd) = NULL; \ 276*53897Smckusick else \ 277*53897Smckusick (lance)->lance_last_tmd = (tmd); \ 278*53897Smckusick } 279*53897Smckusick #define XMIT_BUF(lance, tmd) (char *)((tmd)->tmd_ladr \ 280*53897Smckusick + (((tmd)->tmd_stat & TMD_HADR) << 16) \ 281*53897Smckusick + (lance)->lance_memory) 282*53897Smckusick #define XMIT_ERR(tmd) ((tmd)->tmd_stat & TMD_ERR) 283*53897Smckusick #define TRANSMIT(lance, tmd, count) { \ 284*53897Smckusick (tmd)->tmd_bcnt = -(count); \ 285*53897Smckusick (tmd)->tmd_error = 0; \ 286*53897Smckusick (tmd)->tmd_stat = ((tmd)->tmd_stat & TMD_HADR) | (TMD_OWN|TMD_STP|TMD_ENP); \ 287*53897Smckusick (lance)->lance_addr->rap = CSR0; \ 288*53897Smckusick (lance)->lance_addr->rdp = (CSR_INEA|CSR_TDMD); \ 289*53897Smckusick } 290*53897Smckusick 291*53897Smckusick caddr_t 292*53897Smckusick get_xmit_buffer(chan) 293*53897Smckusick int chan; 294*53897Smckusick { 295*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 296*53897Smckusick register xmit_msg_desc *tmd; 297*53897Smckusick 298*53897Smckusick GET_XMIT_BUF(lance, tmd); 299*53897Smckusick if (tmd == NULL) 300*53897Smckusick return (NULL); 301*53897Smckusick return (XMIT_BUF(lance, tmd)); 302*53897Smckusick } 303*53897Smckusick 304*53897Smckusick lance_transmit(chan, count) 305*53897Smckusick int chan; 306*53897Smckusick int count; 307*53897Smckusick { 308*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 309*53897Smckusick register xmit_msg_desc *tmd; 310*53897Smckusick 311*53897Smckusick tmd = lance->lance_last_tmd; 312*53897Smckusick TRANSMIT(lance, tmd, count); 313*53897Smckusick 314*53897Smckusick #ifdef news700 315*53897Smckusick lance_led(); 316*53897Smckusick #endif /* news700 */ 317*53897Smckusick } 318*53897Smckusick 319*53897Smckusick lance_xmit_error(chan) 320*53897Smckusick int chan; 321*53897Smckusick { 322*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 323*53897Smckusick register xmit_msg_desc *tmd; 324*53897Smckusick 325*53897Smckusick tmd = lance->lance_last_tmd; 326*53897Smckusick if (XMIT_ERR(tmd)) { 327*53897Smckusick xmit_error(lance, tmd); 328*53897Smckusick return (1); 329*53897Smckusick } 330*53897Smckusick 331*53897Smckusick return (0); 332*53897Smckusick } 333*53897Smckusick 334*53897Smckusick lance_collision(chan) 335*53897Smckusick int chan; 336*53897Smckusick { 337*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 338*53897Smckusick 339*53897Smckusick if (lance->lance_last_tmd->tmd_stat & (TMD_MORE|TMD_ONE)) { 340*53897Smckusick lance->lance_stats.ens_collis++; 341*53897Smckusick return (1); 342*53897Smckusick } 343*53897Smckusick 344*53897Smckusick return (0); 345*53897Smckusick } 346*53897Smckusick 347*53897Smckusick lance_get_addr(chan, addr) 348*53897Smckusick int chan; 349*53897Smckusick caddr_t addr; 350*53897Smckusick { 351*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 352*53897Smckusick 353*53897Smckusick bcopy(lance->lance_stats.ens_addr, addr, 354*53897Smckusick sizeof(lance->lance_stats.ens_addr)); 355*53897Smckusick } 356*53897Smckusick 357*53897Smckusick lance_prom_mode(chan, cmd) 358*53897Smckusick int chan; 359*53897Smckusick { 360*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 361*53897Smckusick 362*53897Smckusick lance_close(chan); 363*53897Smckusick if (cmd) 364*53897Smckusick lance->lance_flags |= LANCE_PROM; 365*53897Smckusick else 366*53897Smckusick lance->lance_flags &= ~LANCE_PROM; 367*53897Smckusick lance_open(chan); 368*53897Smckusick } 369*53897Smckusick 370*53897Smckusick lance_get_status(chan, addr) 371*53897Smckusick int chan; 372*53897Smckusick caddr_t addr; 373*53897Smckusick { 374*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 375*53897Smckusick register int s; 376*53897Smckusick 377*53897Smckusick s = splimp(); 378*53897Smckusick bcopy(&lance->lance_stats.ens_frames, addr, 379*53897Smckusick sizeof(lance->lance_stats) - sizeof (lance->lance_stats.ens_addr)); 380*53897Smckusick bzero(&lance->lance_stats.ens_frames, 381*53897Smckusick sizeof(lance->lance_stats) - sizeof (lance->lance_stats.ens_addr)); 382*53897Smckusick (void) splx(s); 383*53897Smckusick } 384*53897Smckusick 385*53897Smckusick lance_intr() 386*53897Smckusick { 387*53897Smckusick register Lance_chan *lance; 388*53897Smckusick register Lance_reg *reg; 389*53897Smckusick register int stat, chan; 390*53897Smckusick int retval = 0; 391*53897Smckusick 392*53897Smckusick LED_ON; 393*53897Smckusick 394*53897Smckusick for (chan = 0, lance = lancesw; chan < NEN ; lance++, chan++) { 395*53897Smckusick if ((lance->lance_flags & LANCE_ACTIVE) == 0) 396*53897Smckusick continue; 397*53897Smckusick 398*53897Smckusick reg = lance->lance_addr; 399*53897Smckusick reg->rap = CSR0; 400*53897Smckusick stat = reg->rdp & ~CSR_INEA; 401*53897Smckusick if ((stat & CSR_INTR) == 0) 402*53897Smckusick continue; 403*53897Smckusick 404*53897Smckusick retval = 1; 405*53897Smckusick reg->rdp = stat; 406*53897Smckusick reg->rdp = CSR_INEA; 407*53897Smckusick 408*53897Smckusick if (stat & CSR_ERR) { 409*53897Smckusick if (stat & CSR_BABL) 410*53897Smckusick printf("lance %d error: babl\n", chan); 411*53897Smckusick if (stat & CSR_MISS) 412*53897Smckusick lance->lance_stats.ens_lost++; 413*53897Smckusick if (stat & CSR_MERR) 414*53897Smckusick printf("lance %d error: merr\n", chan); 415*53897Smckusick } 416*53897Smckusick if (stat & CSR_RINT) { 417*53897Smckusick lance->lance_stats.ens_frames++; 418*53897Smckusick enrint(chan); 419*53897Smckusick } 420*53897Smckusick if (stat & CSR_TINT) { 421*53897Smckusick lance->lance_stats.ens_xmit++; 422*53897Smckusick enxint(chan); 423*53897Smckusick } 424*53897Smckusick if (stat & CSR_IDON) 425*53897Smckusick lance->lance_flags |= LANCE_IDON; 426*53897Smckusick } 427*53897Smckusick 428*53897Smckusick LED_OFF; 429*53897Smckusick 430*53897Smckusick return (retval); 431*53897Smckusick } 432*53897Smckusick 433*53897Smckusick lance_init(chan) 434*53897Smckusick int chan; 435*53897Smckusick { 436*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 437*53897Smckusick register int s; 438*53897Smckusick 439*53897Smckusick s = splimp(); 440*53897Smckusick lance_write_reg(chan, CSR1, INIT_BLOCK & 0xffff); 441*53897Smckusick lance_write_reg(chan, CSR2, INIT_BLOCK >> 16); 442*53897Smckusick lance_write_reg(chan, CSR3, CSR_BSWP|CSR_BCON); 443*53897Smckusick 444*53897Smckusick lance_write_reg(chan, CSR0, CSR_INEA|CSR_STRT|CSR_INIT); 445*53897Smckusick (void) splx(s); 446*53897Smckusick 447*53897Smckusick while ((lance->lance_flags & LANCE_IDON) == 0) 448*53897Smckusick ; 449*53897Smckusick } 450*53897Smckusick 451*53897Smckusick recv_error(lance, rmd) 452*53897Smckusick register Lance_chan *lance; 453*53897Smckusick register recv_msg_desc *rmd; 454*53897Smckusick { 455*53897Smckusick register int status = rmd->rmd_stat; 456*53897Smckusick register int chan = lance - lancesw; 457*53897Smckusick 458*53897Smckusick if (status & RMD_FRAM) 459*53897Smckusick lance->lance_stats.ens_align++; 460*53897Smckusick if (status & RMD_OFLO) 461*53897Smckusick printf("lance %d recv error: overflow\n", chan); 462*53897Smckusick if (status & RMD_CRC) 463*53897Smckusick lance->lance_stats.ens_crc++; 464*53897Smckusick if (status & RMD_BUFF) 465*53897Smckusick printf("lance %d:recv error: buffer\n", chan); 466*53897Smckusick } 467*53897Smckusick 468*53897Smckusick xmit_error(lance, tmd) 469*53897Smckusick register Lance_chan *lance; 470*53897Smckusick register xmit_msg_desc *tmd; 471*53897Smckusick { 472*53897Smckusick register int status = tmd->tmd_error; 473*53897Smckusick register int chan = lance - lancesw; 474*53897Smckusick 475*53897Smckusick if (status & TMD_BUFF) 476*53897Smckusick printf("lance %d: xmit error: buffer\n", chan); 477*53897Smckusick if (status & TMD_UFLO) 478*53897Smckusick printf("lance %d: xmit error: underflow\n", chan); 479*53897Smckusick if (status & TMD_LCOL) { 480*53897Smckusick printf("lance %d: xmit error: late collision\n", chan); 481*53897Smckusick lance->lance_stats.ens_owcollis++; 482*53897Smckusick } 483*53897Smckusick if (status & TMD_LCAR) 484*53897Smckusick printf("lance %d: xmit error: loss of carrier\n", chan); 485*53897Smckusick if (status & TMD_RTRY) { 486*53897Smckusick printf("lance %d: xmit error: retry tdr=%d\n", 487*53897Smckusick chan, status & TMD_TDR); 488*53897Smckusick lance->lance_stats.ens_xcollis++; 489*53897Smckusick } 490*53897Smckusick } 491*53897Smckusick 492*53897Smckusick lance_write_reg(chan, reg, data) 493*53897Smckusick int chan, reg, data; 494*53897Smckusick { 495*53897Smckusick register Lance_reg *lance = lancesw[chan].lance_addr; 496*53897Smckusick register int s; 497*53897Smckusick 498*53897Smckusick s = spl7(); 499*53897Smckusick lance->rap = reg; 500*53897Smckusick lance->rdp = data; 501*53897Smckusick (void) splx(s); 502*53897Smckusick } 503*53897Smckusick 504*53897Smckusick lance_read_reg(chan, reg) 505*53897Smckusick int chan, reg; 506*53897Smckusick { 507*53897Smckusick register Lance_reg *lance = lancesw[chan].lance_addr; 508*53897Smckusick register int s, d; 509*53897Smckusick 510*53897Smckusick s = spl7(); 511*53897Smckusick lance->rap = reg; 512*53897Smckusick d = lance->rdp; 513*53897Smckusick (void) splx(s); 514*53897Smckusick 515*53897Smckusick return (d); 516*53897Smckusick } 517*53897Smckusick 518*53897Smckusick get_hard_addr(chan, addr) 519*53897Smckusick int chan; 520*53897Smckusick u_short *addr; 521*53897Smckusick { 522*53897Smckusick register unsigned char *p, *q; 523*53897Smckusick register int i; 524*53897Smckusick register Lance_chan *lance = &lancesw[chan]; 525*53897Smckusick unsigned char hard_addr[6]; 526*53897Smckusick 527*53897Smckusick p = (unsigned char *)lance->lance_rom + 16; 528*53897Smckusick q = hard_addr; 529*53897Smckusick for (i = 0; i < 6; i++) { 530*53897Smckusick *q = (*p++ & 0xf) << 4; 531*53897Smckusick *q++ |= *p++ & 0xf; 532*53897Smckusick } 533*53897Smckusick 534*53897Smckusick bcopy(hard_addr, (char *)addr, 6); 535*53897Smckusick } 536*53897Smckusick 537*53897Smckusick lance_led() 538*53897Smckusick { 539*53897Smckusick 540*53897Smckusick #ifdef news700 541*53897Smckusick *(u_char *)ETHER_LED = 1; 542*53897Smckusick *(u_char *)ETHER_LED = 0; 543*53897Smckusick #endif /* news700 */ 544*53897Smckusick } 545*53897Smckusick 546*53897Smckusick #if defined(mips) && defined(CPU_SINGLE) 547*53897Smckusick bxcopy(s, d, n) 548*53897Smckusick caddr_t s, d; 549*53897Smckusick int n; 550*53897Smckusick { 551*53897Smckusick 552*53897Smckusick if (n <= 0) 553*53897Smckusick return; 554*53897Smckusick switch ((((int)s & 03) << 2) + ((int)d & 03)) { 555*53897Smckusick 556*53897Smckusick case 0x0: 557*53897Smckusick blcopy((long *)s, (long *)d, n); 558*53897Smckusick return; 559*53897Smckusick 560*53897Smckusick case 0x5: 561*53897Smckusick *(char *)d = *(char *)s; 562*53897Smckusick blcopy((long *)(s + 1), (long *)(d + 1), n - 1); 563*53897Smckusick return; 564*53897Smckusick 565*53897Smckusick case 0xa: 566*53897Smckusick switch (n) { 567*53897Smckusick 568*53897Smckusick case 1: 569*53897Smckusick *(char *)d = *(char *)s; 570*53897Smckusick return; 571*53897Smckusick 572*53897Smckusick case 2: 573*53897Smckusick *(short *)d = *(short *)s; 574*53897Smckusick return; 575*53897Smckusick 576*53897Smckusick default: 577*53897Smckusick *(short *)d = *(short *)s; 578*53897Smckusick blcopy((long *)(s + 2), (long *)(d + 2), n - 2); 579*53897Smckusick return; 580*53897Smckusick } 581*53897Smckusick 582*53897Smckusick case 0xf: 583*53897Smckusick switch (n) { 584*53897Smckusick 585*53897Smckusick case 1: 586*53897Smckusick *(char *)d = *(char *)s; 587*53897Smckusick return; 588*53897Smckusick 589*53897Smckusick case 2: 590*53897Smckusick *(char *)d = *(char *)s; 591*53897Smckusick *(char *)(d + 1) = *(char *)(s + 1); 592*53897Smckusick return; 593*53897Smckusick 594*53897Smckusick case 3: 595*53897Smckusick *(char *)d = *(char *)s; 596*53897Smckusick *(short *)(d + 1) = *(short *)(s + 1); 597*53897Smckusick return; 598*53897Smckusick 599*53897Smckusick default: 600*53897Smckusick *(char *)d = *(char *)s; 601*53897Smckusick *(short *)(d + 1) = *(short *)(s + 1); 602*53897Smckusick blcopy((long *)(s + 3), (long *)(d + 3), n - 3); 603*53897Smckusick return; 604*53897Smckusick } 605*53897Smckusick 606*53897Smckusick case 0x7: 607*53897Smckusick case 0xd: 608*53897Smckusick switch (n) { 609*53897Smckusick 610*53897Smckusick case 1: 611*53897Smckusick *(char *)d = *(char *)s; 612*53897Smckusick return; 613*53897Smckusick 614*53897Smckusick case 2: 615*53897Smckusick *(char *)d = *(char *)s; 616*53897Smckusick *(char *)(d + 1) = *(char *)(s + 1); 617*53897Smckusick return; 618*53897Smckusick 619*53897Smckusick default: 620*53897Smckusick *(char *)d = *(char *)s; 621*53897Smckusick bwcopy((short *)(s + 1), (short *)(d + 1), n); 622*53897Smckusick return; 623*53897Smckusick } 624*53897Smckusick 625*53897Smckusick case 0x2: 626*53897Smckusick case 0x8: 627*53897Smckusick bwcopy((short *)s, (short *)d, n); 628*53897Smckusick return; 629*53897Smckusick 630*53897Smckusick default: 631*53897Smckusick bbcopy((char *)s, (char *)d, n); 632*53897Smckusick return; 633*53897Smckusick } 634*53897Smckusick } 635*53897Smckusick 636*53897Smckusick #define COPY(s, d, n, t) \ 637*53897Smckusick while ((n) >= 8 * sizeof (t)) { \ 638*53897Smckusick int t0, t1, t2, t3, t4, t5, t6, t7; \ 639*53897Smckusick t0 = (s)[0]; \ 640*53897Smckusick t1 = (s)[1]; \ 641*53897Smckusick t2 = (s)[2]; \ 642*53897Smckusick t3 = (s)[3]; \ 643*53897Smckusick t4 = (s)[4]; \ 644*53897Smckusick t5 = (s)[5]; \ 645*53897Smckusick t6 = (s)[6]; \ 646*53897Smckusick t7 = (s)[7]; \ 647*53897Smckusick (d)[0] = t0; \ 648*53897Smckusick (d)[1] = t1; \ 649*53897Smckusick (d)[2] = t2; \ 650*53897Smckusick (d)[3] = t3; \ 651*53897Smckusick (d)[4] = t4; \ 652*53897Smckusick (d)[5] = t5; \ 653*53897Smckusick (d)[6] = t6; \ 654*53897Smckusick (d)[7] = t7; \ 655*53897Smckusick (s) += 8; \ 656*53897Smckusick (d) += 8; \ 657*53897Smckusick (n) -= 8 * sizeof (t); \ 658*53897Smckusick } \ 659*53897Smckusick while ((n) >= sizeof (t)) { \ 660*53897Smckusick (d)[0] = (s)[0]; \ 661*53897Smckusick (s)++; \ 662*53897Smckusick (d)++; \ 663*53897Smckusick (n) -= sizeof (t); \ 664*53897Smckusick } 665*53897Smckusick 666*53897Smckusick blcopy(s, d, n) 667*53897Smckusick long *s, *d; 668*53897Smckusick int n; 669*53897Smckusick { 670*53897Smckusick 671*53897Smckusick COPY(s, d, n, long); 672*53897Smckusick switch (n) { 673*53897Smckusick 674*53897Smckusick case 0: 675*53897Smckusick return; 676*53897Smckusick 677*53897Smckusick case 1: 678*53897Smckusick *(char *)d = *(char *)s; 679*53897Smckusick return; 680*53897Smckusick 681*53897Smckusick case 2: 682*53897Smckusick *(short *)d = *(short *)s; 683*53897Smckusick return; 684*53897Smckusick 685*53897Smckusick case 3: 686*53897Smckusick *(short *)d = *(short *)s; 687*53897Smckusick *((char *)d + 2) = *((char *)s + 2); 688*53897Smckusick return; 689*53897Smckusick } 690*53897Smckusick } 691*53897Smckusick 692*53897Smckusick bwcopy(s, d, n) 693*53897Smckusick short *s, *d; 694*53897Smckusick int n; 695*53897Smckusick { 696*53897Smckusick 697*53897Smckusick COPY(s, d, n, short); 698*53897Smckusick if (n == 1) 699*53897Smckusick *(char *)d = *(char *)s; 700*53897Smckusick } 701*53897Smckusick 702*53897Smckusick bbcopy(s, d, n) 703*53897Smckusick char *s, *d; 704*53897Smckusick int n; 705*53897Smckusick { 706*53897Smckusick 707*53897Smckusick COPY(s, d, n, char); 708*53897Smckusick } 709*53897Smckusick #endif /* defined(mips) && defined(CPU_SINGLE) */ 710*53897Smckusick 711*53897Smckusick #endif /* NEN > 0 */ 712