⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i82586.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -