/* common ioctl handler. return: 0=ok, -1=error */ int etc_ioctl(etc_info_t *etc, int cmd, void *arg) { int error; int val; int *vec = (int*)arg; error = 0; val = arg ? *(int*)arg : 0; ET_TRACE(("et%d: etc_ioctl: cmd 0x%x\n", etc->unit, cmd)); switch (cmd) { case ETCUP: et_up(etc->et); break; case ETCDOWN: et_down(etc->et, TRUE); break; case ETCLOOP: etc_loopback(etc, val); break; case ETCDUMP: if (et_msg_level & 0x10000) bcmdumplog((char *)arg, 4096); break; case ETCSETMSGLEVEL: et_msg_level = val; break; case ETCPROMISC: etc_promisc(etc, val); break; case ETCQOS: etc_qos(etc, val); break; case ETCSPEED: if (val == ET_1000FULL) { etc->speed = 1000; etc->duplex = 1; } else if (val == ET_1000HALF) { etc->speed = 1000; etc->duplex = 0; } else if (val == ET_100FULL) { etc->speed = 100; etc->duplex = 1; } else if (val == ET_100HALF) { etc->speed = 100; etc->duplex = 0; } else if (val == ET_10FULL) { etc->speed = 10; etc->duplex = 1; } else if (val == ET_10HALF) { etc->speed = 10; etc->duplex = 0; } else if (val == ET_AUTO) ; else goto err; etc->forcespeed = val; /* explicitly reset the phy */ (*etc->chops->phyreset)(etc->ch, etc->phyaddr); /* request restart autonegotiation if we're reverting to adv mode */ if (etc->forcespeed == ET_AUTO) { etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); etc->advertise2 = ADV_1000FULL; etc->needautoneg = TRUE; } else { etc->advertise = etc->advertise2 = 0; etc->needautoneg = FALSE; } et_init(etc->et, ET_INIT_DEF_OPTIONS); break; case ETCPHYRD: if (vec) { vec[1] = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, vec[0]); ET_TRACE(("etc_ioctl: ETCPHYRD of reg 0x%x => 0x%x\n", vec[0], vec[1])); } break; case ETCPHYRD2: if (vec) { uint phyaddr, reg; phyaddr = vec[0] >> 16; if (phyaddr < MAXEPHY) { reg = vec[0] & 0xffff; vec[1] = (*etc->chops->phyrd)(etc->ch, phyaddr, reg); ET_TRACE(("etc_ioctl: ETCPHYRD2 of phy 0x%x, reg 0x%x => 0x%x\n", phyaddr, reg, vec[1])); } } break; case ETCPHYWR: if (vec) { ET_TRACE(("etc_ioctl: ETCPHYWR to reg 0x%x <= 0x%x\n", vec[0], vec[1])); (*etc->chops->phywr)(etc->ch, etc->phyaddr, vec[0], (uint16)vec[1]); } break; case ETCPHYWR2: if (vec) { uint phyaddr, reg; phyaddr = vec[0] >> 16; if (phyaddr < MAXEPHY) { reg = vec[0] & 0xffff; (*etc->chops->phywr)(etc->ch, phyaddr, reg, (uint16)vec[1]); ET_TRACE(("etc_ioctl: ETCPHYWR2 to phy 0x%x, reg 0x%x <= 0x%x\n", phyaddr, reg, vec[1])); } } break; #ifdef ETROBO case ETCROBORD: if (etc->robo && vec) { uint page, reg; uint16 val; robo_info_t *robo = (robo_info_t *)etc->robo; page = vec[0] >> 16; reg = vec[0] & 0xffff; val = -1; robo->ops->read_reg(etc->robo, page, reg, &val, 2); vec[1] = val; ET_TRACE(("etc_ioctl: ETCROBORD of page 0x%x, reg 0x%x => 0x%x\n", page, reg, val)); } break; case ETCROBOWR: if (etc->robo && vec) { uint page, reg; uint16 val; robo_info_t *robo = (robo_info_t *)etc->robo; page = vec[0] >> 16; reg = vec[0] & 0xffff; val = vec[1]; robo->ops->write_reg(etc->robo, page, vec[0], &val, 2); ET_TRACE(("etc_ioctl: ETCROBOWR to page 0x%x, reg 0x%x <= 0x%x\n", page, reg, val)); }
/* common ioctl handler. return: 0=ok, -1=error */ int etc_ioctl(etc_info_t *etc, int cmd, void *arg) { int error; int val; int *vec = (int*)arg; error = 0; val = arg? *(int*)arg: 0; ET_TRACE(("et%d: etc_ioctl: cmd 0x%x\n", etc->unit, cmd)); switch (cmd) { case ETCUP: et_up(etc->et); break; case ETCDOWN: et_down(etc->et, TRUE); break; case ETCLOOP: etc_loopback(etc, val); break; case ETCDUMP: if (et_msg_level & 0x10000) bcmdumplog((uchar*)arg, 4096); break; case ETCSETMSGLEVEL: et_msg_level = val; break; case ETCPROMISC: etc_promisc(etc, val); break; case ETCQOS: etc_qos(etc, val); break; case ETCSPEED: if ((val != ET_AUTO) && (val != ET_10HALF) && (val != ET_10FULL) && (val != ET_100HALF) && (val != ET_100FULL)) goto err; etc->forcespeed = val; /* explicitly reset the phy */ (*etc->chops->phyreset)(etc->ch, etc->phyaddr); /* request restart autonegotiation if we're reverting to adv mode */ if ((etc->forcespeed == ET_AUTO) & etc->advertise) etc->needautoneg = TRUE; et_init(etc->et); break; case ETCPHYRD: if (vec) vec[1] = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, vec[0]); break; case ETCPHYWR: if (vec) (*etc->chops->phywr)(etc->ch, etc->phyaddr, vec[0], (uint16) vec[1]); break; default: err: error = -1; } return (error); }