static int init586(struct net_device *dev) { void __iomem *ptr; int i, result = 0; struct priv *p = netdev_priv(dev); struct configure_cmd_struct __iomem *cfg_cmd; struct iasetup_cmd_struct __iomem *ias_cmd; struct tdr_cmd_struct __iomem *tdr_cmd; struct mcsetup_cmd_struct __iomem *mc_cmd; struct netdev_hw_addr *ha; int num_addrs = netdev_mc_count(dev); ptr = p->scb + 1; cfg_cmd = ptr; /* */ writew(0, &cfg_cmd->cmd_status); writew(CMD_CONFIGURE | CMD_LAST, &cfg_cmd->cmd_cmd); writew(0xFFFF, &cfg_cmd->cmd_link); /* */ writeb(0x0a, &cfg_cmd->byte_cnt); /* */ writeb(fifo, &cfg_cmd->fifo); /* */ writeb(0x40, &cfg_cmd->sav_bf); /* */ writeb(0x2e, &cfg_cmd->adr_len); writeb(0x00, &cfg_cmd->priority); writeb(0x60, &cfg_cmd->ifs); writeb(0x00, &cfg_cmd->time_low); writeb(0xf2, &cfg_cmd->time_high); writeb(0x00, &cfg_cmd->promisc); if (dev->flags & IFF_ALLMULTI) { int len = ((char __iomem *)p->iscp - (char __iomem *)ptr - 8) / 6; if (num_addrs > len) { printk(KERN_ERR "%s: switching to promisc. mode\n", dev->name); writeb(0x01, &cfg_cmd->promisc); } } if (dev->flags & IFF_PROMISC) writeb(0x01, &cfg_cmd->promisc); writeb(0x00, &cfg_cmd->carr_coll); writew(make16(cfg_cmd), &p->scb->cbl_offset); writeb(0, &p->scb->cmd_ruc); writeb(CUC_START, &p->scb->cmd_cuc); /* */ ni_attn586(); wait_for_stat_compl(cfg_cmd); if ((readw(&cfg_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) { printk(KERN_ERR "%s: configure command failed: %x\n", dev->name, readw(&cfg_cmd->cmd_status)); return 1; } /* */ ias_cmd = ptr; writew(0, &ias_cmd->cmd_status); writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd); writew(0xffff, &ias_cmd->cmd_link); memcpy_toio(&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN); writew(make16(ias_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); /* */ ni_attn586(); wait_for_stat_compl(ias_cmd); if ((readw(&ias_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) { printk(KERN_ERR "%s (ni52): individual address setup command failed: %04x\n", dev->name, readw(&ias_cmd->cmd_status)); return 1; } /* */ tdr_cmd = ptr; writew(0, &tdr_cmd->cmd_status); writew(CMD_TDR | CMD_LAST, &tdr_cmd->cmd_cmd); writew(0xffff, &tdr_cmd->cmd_link); writew(0, &tdr_cmd->status); writew(make16(tdr_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); /* */ ni_attn586(); wait_for_stat_compl(tdr_cmd); if (!(readw(&tdr_cmd->cmd_status) & STAT_COMPL)) printk(KERN_ERR "%s: Problems while running the TDR.\n", dev->name); else { udelay(16); result = readw(&tdr_cmd->status); writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); ni_attn586(); /* */ if (result & TDR_LNK_OK) ; else if (result & TDR_XCVR_PRB) printk(KERN_ERR "%s: TDR: Transceiver problem. Check the cable(s)!\n", dev->name); else if (result & TDR_ET_OPN) printk(KERN_ERR "%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); else if (result & TDR_ET_SRT) { /* */ if (result & TDR_TIMEMASK) printk(KERN_ERR "%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else printk(KERN_ERR "%s: TDR: Unknown status %04x\n", dev->name, result); } /* */ if (num_addrs && !(dev->flags & IFF_PROMISC)) { mc_cmd = ptr; writew(0, &mc_cmd->cmd_status); writew(CMD_MCSETUP | CMD_LAST, &mc_cmd->cmd_cmd); writew(0xffff, &mc_cmd->cmd_link); writew(num_addrs * 6, &mc_cmd->mc_cnt); i = 0; netdev_for_each_mc_addr(ha, dev) memcpy_toio(mc_cmd->mc_list[i++], ha->addr, 6); writew(make16(mc_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); wait_for_stat_compl(mc_cmd); if ((readw(&mc_cmd->cmd_status) & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK)) printk(KERN_ERR "%s: Can't apply multicast-address-list.\n", dev->name); } /* */ #if (NUM_XMIT_BUFFS == 1) for (i = 0; i < 2; i++) { p->nop_cmds[i] = ptr; writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); writew(0, &p->nop_cmds[i]->cmd_status); writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); ptr = ptr + sizeof(struct nop_cmd_struct); } #else for (i = 0; i < NUM_XMIT_BUFFS; i++) { p->nop_cmds[i] = ptr; writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); writew(0, &p->nop_cmds[i]->cmd_status); writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); ptr = ptr + sizeof(struct nop_cmd_struct); } #endif ptr = alloc_rfa(dev, ptr); /* */ /* */ for (i = 0; i < NUM_XMIT_BUFFS; i++) { /* */ p->xmit_cmds[i] = ptr; ptr = ptr + sizeof(struct transmit_cmd_struct); p->xmit_cbuffs[i] = ptr; /* */ ptr = ptr + XMIT_BUFF_SIZE; p->xmit_buffs[i] = ptr; /* */ ptr = ptr + sizeof(struct tbd_struct); if ((void __iomem *)ptr > (void __iomem *)p->iscp) { printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", dev->name); return 1; } memset_io(p->xmit_cmds[i], 0, sizeof(struct transmit_cmd_struct)); memset_io(p->xmit_buffs[i], 0, sizeof(struct tbd_struct)); writew(make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]), &p->xmit_cmds[i]->cmd_link); writew(STAT_COMPL, &p->xmit_cmds[i]->cmd_status); writew(CMD_XMIT|CMD_INT, &p->xmit_cmds[i]->cmd_cmd); writew(make16(p->xmit_buffs[i]), &p->xmit_cmds[i]->tbd_offset); writew(0xffff, &p->xmit_buffs[i]->next); writel(make24(p->xmit_cbuffs[i]), &p->xmit_buffs[i]->buffer); } p->xmit_count = 0; p->xmit_last = 0; #ifndef NO_NOPCOMMANDS p->nop_point = 0; #endif /* */ #ifndef NO_NOPCOMMANDS writew(make16(p->nop_cmds[0]), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); wait_for_scb_cmd(dev); #else writew(make16(p->xmit_cmds[0]), &p->xmit_cmds[0]->cmd_link); writew(CMD_XMIT | CMD_SUSPEND | CMD_INT, &p->xmit_cmds[0]->cmd_cmd); #endif /* */ writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); ni_attn586(); udelay(16); ni_enaint(); return 0; }
static int init586(struct net_device *dev) { void __iomem *ptr; int i, result = 0; struct priv *p = (struct priv *)dev->priv; struct configure_cmd_struct __iomem *cfg_cmd; struct iasetup_cmd_struct __iomem *ias_cmd; struct tdr_cmd_struct __iomem *tdr_cmd; struct mcsetup_cmd_struct __iomem *mc_cmd; struct dev_mc_list *dmi = dev->mc_list; int num_addrs = dev->mc_count; ptr = p->scb + 1; cfg_cmd = ptr; /* configure-command */ writew(0, &cfg_cmd->cmd_status); writew(CMD_CONFIGURE | CMD_LAST, &cfg_cmd->cmd_cmd); writew(0xFFFF, &cfg_cmd->cmd_link); /* number of cfg bytes */ writeb(0x0a, &cfg_cmd->byte_cnt); /* fifo-limit (8=tx:32/rx:64) */ writeb(fifo, &cfg_cmd->fifo); /* hold or discard bad recv frames (bit 7) */ writeb(0x40, &cfg_cmd->sav_bf); /* addr_len |!src_insert |pre-len |loopback */ writeb(0x2e, &cfg_cmd->adr_len); writeb(0x00, &cfg_cmd->priority); writeb(0x60, &cfg_cmd->ifs);; writeb(0x00, &cfg_cmd->time_low); writeb(0xf2, &cfg_cmd->time_high); writeb(0x00, &cfg_cmd->promisc);; if (dev->flags & IFF_ALLMULTI) { int len = ((char __iomem *)p->iscp - (char __iomem *)ptr - 8) / 6; if (num_addrs > len) { printk(KERN_ERR "%s: switching to promisc. mode\n", dev->name); dev->flags |= IFF_PROMISC; } } if (dev->flags & IFF_PROMISC) writeb(0x01, &cfg_cmd->promisc); writeb(0x00, &cfg_cmd->carr_coll); writew(make16(cfg_cmd), &p->scb->cbl_offset); writeb(0, &p->scb->cmd_ruc); writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ ni_attn586(); wait_for_stat_compl(cfg_cmd); if ((readw(&cfg_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) { printk(KERN_ERR "%s: configure command failed: %x\n", dev->name, readw(&cfg_cmd->cmd_status)); return 1; } /* * individual address setup */ ias_cmd = ptr; writew(0, &ias_cmd->cmd_status); writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd); writew(0xffff, &ias_cmd->cmd_link); memcpy_toio(&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN); writew(make16(ias_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ ni_attn586(); wait_for_stat_compl(ias_cmd); if ((readw(&ias_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) { printk(KERN_ERR "%s (ni52): individual address setup command failed: %04x\n", dev->name, readw(&ias_cmd->cmd_status)); return 1; } /* * TDR, wire check .. e.g. no resistor e.t.c */ tdr_cmd = ptr; writew(0, &tdr_cmd->cmd_status); writew(CMD_TDR | CMD_LAST, &tdr_cmd->cmd_cmd); writew(0xffff, &tdr_cmd->cmd_link); writew(0, &tdr_cmd->status); writew(make16(tdr_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ ni_attn586(); wait_for_stat_compl(tdr_cmd); if (!(readw(&tdr_cmd->cmd_status) & STAT_COMPL)) printk(KERN_ERR "%s: Problems while running the TDR.\n", dev->name); else { udelay(16); result = readw(&tdr_cmd->status); writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); ni_attn586(); /* ack the interrupts */ if (result & TDR_LNK_OK) ; else if (result & TDR_XCVR_PRB) printk(KERN_ERR "%s: TDR: Transceiver problem. Check the cable(s)!\n", dev->name); else if (result & TDR_ET_OPN) printk(KERN_ERR "%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); else if (result & TDR_ET_SRT) { /* time == 0 -> strange :-) */ if (result & TDR_TIMEMASK) printk(KERN_ERR "%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else printk(KERN_ERR "%s: TDR: Unknown status %04x\n", dev->name, result); } /* * Multicast setup */ if (num_addrs && !(dev->flags & IFF_PROMISC)) { mc_cmd = ptr; writew(0, &mc_cmd->cmd_status); writew(CMD_MCSETUP | CMD_LAST, &mc_cmd->cmd_cmd); writew(0xffff, &mc_cmd->cmd_link); writew(num_addrs * 6, &mc_cmd->mc_cnt); for (i = 0; i < num_addrs; i++, dmi = dmi->next) memcpy_toio(mc_cmd->mc_list[i], dmi->dmi_addr, 6); writew(make16(mc_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); wait_for_stat_compl(mc_cmd); if ((readw(&mc_cmd->cmd_status) & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK)) printk(KERN_ERR "%s: Can't apply multicast-address-list.\n", dev->name); } /* * alloc nop/xmit-cmds */ #if (NUM_XMIT_BUFFS == 1) for (i = 0; i < 2; i++) { p->nop_cmds[i] = ptr; writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); writew(0, &p->nop_cmds[i]->cmd_status); writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); ptr = ptr + sizeof(struct nop_cmd_struct); } #else for (i = 0; i < NUM_XMIT_BUFFS; i++) { p->nop_cmds[i] = ptr; writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); writew(0, &p->nop_cmds[i]->cmd_status); writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); ptr = ptr + sizeof(struct nop_cmd_struct); } #endif ptr = alloc_rfa(dev, ptr); /* init receive-frame-area */ /* * alloc xmit-buffs / init xmit_cmds */ for (i = 0; i < NUM_XMIT_BUFFS; i++) { /* Transmit cmd/buff 0 */ p->xmit_cmds[i] = ptr; ptr = ptr + sizeof(struct transmit_cmd_struct); p->xmit_cbuffs[i] = ptr; /* char-buffs */ ptr = ptr + XMIT_BUFF_SIZE; p->xmit_buffs[i] = ptr; /* TBD */ ptr = ptr + sizeof(struct tbd_struct); if ((void __iomem *)ptr > (void __iomem *)p->iscp) { printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", dev->name); return 1; } memset_io(p->xmit_cmds[i], 0, sizeof(struct transmit_cmd_struct)); memset_io(p->xmit_buffs[i], 0, sizeof(struct tbd_struct)); writew(make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]), &p->xmit_cmds[i]->cmd_link); writew(STAT_COMPL, &p->xmit_cmds[i]->cmd_status); writew(CMD_XMIT|CMD_INT, &p->xmit_cmds[i]->cmd_cmd); writew(make16(p->xmit_buffs[i]), &p->xmit_cmds[i]->tbd_offset); writew(0xffff, &p->xmit_buffs[i]->next); writel(make24(p->xmit_cbuffs[i]), &p->xmit_buffs[i]->buffer); } p->xmit_count = 0; p->xmit_last = 0; #ifndef NO_NOPCOMMANDS p->nop_point = 0; #endif /* * 'start transmitter' */ #ifndef NO_NOPCOMMANDS writew(make16(p->nop_cmds[0]), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); wait_for_scb_cmd(dev); #else writew(make16(p->xmit_cmds[0]), &p->xmit_cmds[0]->cmd_link); writew(CMD_XMIT | CMD_SUSPEND | CMD_INT, &p->xmit_cmds[0]->cmd_cmd); #endif /* * ack. interrupts */ writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); ni_attn586(); udelay(16); ni_enaint(); return 0; }