📄 i82586.c
字号:
sc->ie_bus_write16(sc, IE_RFRAME_LAST(sc->rframes,n), ((m==0)? (IE_FD_EOL|IE_FD_SUSP) : 0)); } /* * step 3: link the RBDs and set EOL on last one */ for (n = 0; n < sc->nrxbuf; n++) { int m = (n == sc->nrxbuf - 1) ? 0 : n + 1; /* Clear status */ sc->ie_bus_write16(sc, IE_RBD_STATUS(sc->rbds,n), 0); /* Make a circular list */ sc->ie_bus_write16(sc, IE_RBD_NEXT(sc->rbds,n), IE_RBD_ADDR(sc->rbds,m)); /* Link to data buffers */ sc->ie_bus_write24(sc, IE_RBD_BUFADDR(sc->rbds, n), IE_RBUF_ADDR(sc, n)); sc->ie_bus_write16(sc, IE_RBD_BUFLEN(sc->rbds,n), IE_RBUF_SIZE | ((m==0)?IE_RBD_EOL:0)); } /* * step 4: all xmit no-op commands loopback onto themselves */ for (n = 0; n < NTXBUF; n++) { sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, n), 0); sc->ie_bus_write16(sc, IE_CMD_NOP_CMD(sc->nop_cmds, n), IE_CMD_NOP); sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, n), IE_CMD_NOP_ADDR(sc->nop_cmds, n)); } /* * step 6: set the head and tail pointers on receive to keep track of * the order in which RFDs and RBDs are used. */ /* Pointers to last packet sent and next available transmit buffer. */ sc->xchead = sc->xctail = 0; /* Clear transmit-busy flag and set number of free transmit buffers. */ sc->xmit_busy = 0; /* * Pointers to first and last receive frame. * The RFD pointed to by rftail is the only one that has EOL set. */ sc->rfhead = 0; sc->rftail = sc->nframes - 1; /* * Pointers to first and last receive descriptor buffer. * The RBD pointed to by rbtail is the only one that has EOL set. */ sc->rbhead = 0; sc->rbtail = sc->nrxbuf - 1;/* link in recv frames * and buffer into the scb. */#if I82586_DEBUG printf("%s: reserved %d bytes\n", sc->arpcom.ac_if.if_name, ptr - sc->buf_area);#endif}static intie_cfg_setup(struct ie_softc *sc, int cmd, int promiscuous, int manchester){ int cmdresult, status; u_int8_t buf[IE_CMD_CFG_SZ]; /* XXX malloc? */ *IE_CMD_CFG_CNT(buf) = 0x0c; *IE_CMD_CFG_FIFO(buf) = 8; *IE_CMD_CFG_SAVEBAD(buf) = 0x40; *IE_CMD_CFG_ADDRLEN(buf) = 0x2e; *IE_CMD_CFG_PRIORITY(buf) = 0; *IE_CMD_CFG_IFS(buf) = 0x60; *IE_CMD_CFG_SLOT_LOW(buf) = 0; *IE_CMD_CFG_SLOT_HIGH(buf) = 0xf2; *IE_CMD_CFG_PROMISC(buf) = !!promiscuous | manchester << 2; *IE_CMD_CFG_CRSCDT(buf) = 0; *IE_CMD_CFG_MINLEN(buf) = 64; *IE_CMD_CFG_JUNK(buf) = 0xff; sc->memcopyout(sc, buf, cmd, IE_CMD_CFG_SZ); setup_simple_command(sc, IE_CMD_CONFIG, cmd); IE_BUS_BARRIER(sc, cmd, IE_CMD_CFG_SZ, BUS_SPACE_BARRIER_WRITE); cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0); status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)); if (cmdresult != 0) { printf("%s: configure command timed out; status %x\n", sc->arpcom.ac_if.if_name, status); return (0); } if ((status & IE_STAT_OK) == 0) { printf("%s: configure command failed; status %x\n", sc->arpcom.ac_if.if_name, status); return (0); } /* Squash any pending interrupts */ ie_ack(sc, IE_ST_WHENCE); return (1);}static intie_ia_setup(struct ie_softc *sc, int cmdbuf){ int cmdresult, status; setup_simple_command(sc, IE_CMD_IASETUP, cmdbuf); (sc->memcopyout)(sc, sc->arpcom.ac_enaddr, IE_CMD_IAS_EADDR(cmdbuf), ETHER_ADDR_LEN); cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0); status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf)); if (cmdresult != 0) { printf("%s: individual address command timed out; status %x\n", sc->arpcom.ac_if.if_name, status); return (0); } if ((status & IE_STAT_OK) == 0) { printf("%s: individual address command failed; status %x\n", sc->arpcom.ac_if.if_name, status); return (0); } /* Squash any pending interrupts */ ie_ack(sc, IE_ST_WHENCE); return (1);}/* * Run the multicast setup command. * Called at splnet(). */static intie_mc_setup(struct ie_softc *sc, int cmdbuf){ int cmdresult, status; if (sc->mcast_count == 0) return (1); setup_simple_command(sc, IE_CMD_MCAST, cmdbuf); (sc->memcopyout)(sc, (caddr_t)sc->mcast_addrs, IE_CMD_MCAST_MADDR(cmdbuf), sc->mcast_count * ETHER_ADDR_LEN); sc->ie_bus_write16(sc, IE_CMD_MCAST_BYTES(cmdbuf), sc->mcast_count * ETHER_ADDR_LEN); /* Start the command */ cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0); status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf)); if (cmdresult != 0) { printf("%s: multicast setup command timed out; status %x\n", sc->arpcom.ac_if.if_name, status); return (0); } if ((status & IE_STAT_OK) == 0) { printf("%s: multicast setup command failed; status %x\n", sc->arpcom.ac_if.if_name, status); return (0); } /* Squash any pending interrupts */ ie_ack(sc, IE_ST_WHENCE); return (1);}/* * This routine takes the environment generated by check_ie_present() and adds * to it all the other structures we need to operate the adapter. This * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting * the receiver unit, and clearing interrupts. * * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER. */voidi82586_init(void *arg){ struct ie_softc *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; int cmd; sc->async_cmd_inprogress = 0; sc->xmit_busy = 0;#if I82586_DEBUG memset(sc->trace_flow, 0, sizeof(sc->trace_flow)); sc->trace_flow_wrap = 0;#endif sc->trace_flow_in = 0; cmd = sc->buf_area; #if I82586_DEBUG printf ("%s: sc_debug at 0x%08x\n", sc->arpcom.ac_if.if_name, (unsigned int) &sc->sc_debug);#endif /* * Send the configure command first. */ if (ie_cfg_setup(sc, cmd, sc->promisc, 0) == 0) return; /* * Send the Individual Address Setup command. */ if (ie_ia_setup(sc, cmd) == 0) return; /* * Run the time-domain reflectometer. */ ie_run_tdr(sc, cmd); /* * Set the multi-cast filter, if any */ if (ie_mc_setup(sc, cmd) == 0) return; /* * If no tasks exist, create them. Need to add something to allow * different names for the different devices. */ if (sc->intr_task == 0) sc->intr_task = rtems_bsdnet_newproc ("IEi0", 2048, i82586_intr_task, sc); if (sc->tx_task == 0) sc->tx_task = rtems_bsdnet_newproc ("IEt0", 2048, i82586_tx_task, sc); /* * Acknowledge any interrupts we have generated thus far. */ ie_ack(sc, IE_ST_WHENCE); /* * Set up the transmit and recv buffers. */ i82586_setup_bufs(sc); if (sc->hwinit) (sc->hwinit)(sc); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; if (NTXBUF < 2) sc->do_xmitnopchain = 0; i82586_start_transceiver(sc);}/* * Start the RU and possibly the CU unit */static voidi82586_start_transceiver(struct ie_softc *sc){#if I82586_DEBUG I82586_TRACE(sc, I82586_RX_START, 0);#endif /* * Start RU at current position in frame & RBD lists. */ sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,sc->rfhead), IE_RBD_ADDR(sc->rbds, sc->rbhead)); sc->ie_bus_write16(sc, IE_SCB_RCVLST(sc->scb), IE_RFRAME_ADDR(sc->rframes,sc->rfhead)); if (sc->do_xmitnopchain) { /* Stop transmit command chain */ if (i82586_start_cmd(sc, IE_CUC_SUSPEND|IE_RUC_SUSPEND, 0, 0, 0)) printf("%s: CU/RU stop command timed out\n", sc->arpcom.ac_if.if_name); /* Start the receiver & transmitter chain */ /* sc->scb->ie_command_list = IEADDR(sc->nop_cmds[(sc->xctail+NTXBUF-1) % NTXBUF]);*/ sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), IE_CMD_NOP_ADDR( sc->nop_cmds, (sc->xctail + NTXBUF - 1) % NTXBUF)); if (i82586_start_cmd(sc, IE_CUC_START|IE_RUC_START, 0, 0, 0)) printf("%s: CU/RU command timed out\n", sc->arpcom.ac_if.if_name); } else { if (i82586_start_cmd(sc, IE_RUC_START, 0, 0, 0)) printf("%s: RU command timed out\n", sc->arpcom.ac_if.if_name); }}voidi82586_stop(struct ifnet *ifp, int disable){ struct ie_softc *sc = ifp->if_softc; if (i82586_start_cmd(sc, IE_RUC_SUSPEND | IE_CUC_SUSPEND, 0, 0, 0)) printf("%s: iestop: disable commands timed out\n", sc->arpcom.ac_if.if_name);}inti82586_ioctl(struct ifnet *ifp, int cmd, caddr_t data){ struct ie_softc *sc = ifp->if_softc;/* struct ifreq *ifr = (struct ifreq *)data; */ int s; int error = 0; s = splnet(); switch(cmd) { case SIOCGIFMEDIA: case SIOCSIFMEDIA: break; case SIO_RTEMS_SHOW_STATS:#if I82586_DEBUG print_softie(sc);#endif break; default: error = ether_ioctl(ifp, cmd, data); if (error == ENETRESET) { /* * Multicast list has changed; set the hardware filter * accordingly. */ ie_mc_reset(sc); error = 0; } break; }#if I82586_DEBUG if (cmd == SIOCSIFFLAGS) sc->sc_debug = (ifp->if_flags & IFF_DEBUG) ? IED_ALL : 0;#endif splx(s); return (error);}static voidie_mc_reset(struct ie_softc *sc){ struct ether_multi *enm; struct ether_multistep step; int size; /* * Step through the list of addresses. */ again: size = 0; sc->mcast_count = 0; ETHER_FIRST_MULTI(step, &sc->arpcom, enm); while (enm) { size += 6; if (sc->mcast_count >= IE_MAXMCAST || memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { sc->arpcom.ac_if.if_flags |= IFF_ALLMULTI; i82586_ioctl(&sc->arpcom.ac_if, SIOCSIFFLAGS, (void *)0); return; } ETHER_NEXT_MULTI(step, enm); } if (size > sc->mcast_addrs_size) { /* Need to allocate more space */ if (sc->mcast_addrs_size) free(sc->mcast_addrs, M_IPMADDR); sc->mcast_addrs = (char *) malloc(size, M_IPMADDR, M_WAITOK); sc->mcast_addrs_size = size; } /* * We've got the space; now copy the addresses */ ETHER_FIRST_MULTI(step, &sc->arpcom, enm); while (enm) { if (sc->mcast_count >= IE_MAXMCAST) goto again; /* Just in case */ memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo, 6); sc->mcast_count++; ETHER_NEXT_MULTI(step, enm); } sc->want_mcsetup = 1;}/* * Media change callback. */inti82586_mediachange(struct ifnet *ifp){ struct ie_softc *sc = ifp->if_softc; if (sc->sc_mediachange) return ((*sc->sc_mediachange)(sc)); return (0);}/* * Media status callback. */voidi82586_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr){ struct ie_softc *sc = ifp->if_softc; if (sc->sc_mediastatus) (*sc->sc_mediastatus)(sc, ifmr);}#if I82586_DEBUGstatic voidprint_softie(struct ie_softc *sc){ static char *trace_labels[] = { "INTS_REQ", "INTS_IN", "INTS_LOOPS", "INTS_OUT", "RX_INT", "RX_DROP", "RX_ERR", "RX_OK", "RX_START", "START_TX", "TX_START", "TX_INT", "TX_REQ", "TX_EVT", "TX_EMIT", "TX_BAD", "TX_ACTIVE", "TRACE_CNT" }; int i; printf("i82586 %s:\n", sc->arpcom.ac_if.if_name); printf(" iobase=%p\n", sc->sc_iobase); printf(" scp=0x%08x\t\tiscp=0x%08x\t\tscb=0x%08x\n", sc->scp, sc->iscp, sc->scb); printf(" buf_area=0x%08x\tbuf_area_sz=0x%08x\n", sc->buf_area, sc->buf_area_sz); printf(" rframes=0x%08x\trbds=0x%08x\t\trbufs=0x%08x\n", sc->rframes, sc->rbds, sc->rbufs); printf(" nop_cmds=0x%08x\txmit_cmds=0x%08x\n", sc->nop_cmds, sc->xmit_cmds); printf(" xbds=0x%08x\txbufs=0x%08x\n\n", sc->xbds, sc->xbufs); printf(" rfhead=%d\trftail=%d\n", sc->rfhead, sc->rftail); printf(" rbhead=%d\trbtail=%d\n", sc->rbhead, sc->rbtail); printf(" nframes=%d\tnrxbuf=%d\trnr_expect=%d\n", sc->nframes, sc->nrxbuf, sc->rnr_expect); printf(" xchead=%d\txctail=%d\n", sc->xchead, sc->xctail); printf(" xmit_busy=%d\txmit_req=%d\tdo_xmitnopchain=%d\n", sc->xmit_busy, sc->xmit_req, sc->do_xmitnopchain); printf(" promisc=%d\tasync_cmd_inprogress=%d\n\n", sc->promisc, sc->async_cmd_inprogress); { int cnt; int in; int lfdone = 0; char *tabs; if (!sc->trace_flow_wrap) { cnt = sc->trace_flow_in; in = 0; } else { cnt = I82586_TRACE_FLOW; in = sc->trace_flow_in; } sc->trace_flow_in = sc->trace_flow_wrap = 0; cnt /= 2; for (i = 0; i < cnt; i++) { if (!lfdone) { switch (sc->trace_flow[in]) { case I82586_INTS_REQ: case I82586_INTS_IN: printf("\n"); } } lfdone = 0; if (strlen(trace_labels[sc->trace_flow[in]]) < 8) tabs = "\t\t"; else tabs = "\t"; printf(" %d\t%s%s0x%08x (%d)\n", i, trace_labels[sc->trace_flow[in]], tabs, sc->trace_flow[in + 1], sc->trace_flow[in + 1]); switch (sc->trace_flow[in]) { case I82586_INTS_REQ: case I82586_INTS_OUT: lfdone = 1; printf("\n"); } in += 2; if (in >= I82586_TRACE_FLOW) in = 0; } }}static voidprint_rbd(struct ie_softc *sc, int n){ printf("RBD at %08x:\n status %04x, next %04x, buffer %lx\n" "length/EOL %04x\n", IE_RBD_ADDR(sc->rbds,n), sc->ie_bus_read16(sc, IE_RBD_STATUS(sc->rbds,n)), sc->ie_bus_read16(sc, IE_RBD_NEXT(sc->rbds,n)), (u_long)0,/*bus_space_read_4(sc->bt, sc->bh, IE_RBD_BUFADDR(sc->rbds,n)),-* XXX */ sc->ie_bus_read16(sc, IE_RBD_BUFLEN(sc->rbds,n)));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -