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

📄 lance.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 4 页
字号:
		printf("WERR\n");#endif                ec->eth_stat.ets_sendErr++;              }            if (isr & ISR_WINT)              {#if 0		printf("WINT\n");#endif		/* status check: restart if needed. */		status = lp->tx_ring[cur_tx_slot_nr].u.base;		/* ??? */		if (status & 0x40000000)		  {		    status = lp->tx_ring[cur_tx_slot_nr].misc;		    ec->eth_stat.ets_sendErr++;		    if (status & 0x0400)		      ec->eth_stat.ets_transAb++;		    if (status & 0x0800)		      ec->eth_stat.ets_carrSense++;		    if (status & 0x1000)		      ec->eth_stat.ets_OWC++;		    if (status & 0x4000)		      {			ec->eth_stat.ets_fifoUnder++;			must_restart=1;		      }		  }		else		  {		    if (status & 0x18000000)		      ec->eth_stat.ets_collision++;		    ec->eth_stat.ets_packetT++;		  }              }            /* transmit a packet on the next slot if it exists. */	    check = 0;	    if (isstored[cur_tx_slot_nr]==1)	      {		/* free the tx-slot just transmitted */		isstored[cur_tx_slot_nr]=0;		cur_tx_slot_nr = (++cur_tx_slot_nr) & TX_RING_MOD_MASK;				/* next tx-slot is ready? */		if (isstored[cur_tx_slot_nr]==1)		  check=1;		else		  check=0;	      }	    else	      {		panic( "lance", "got premature WINT...", NO_NUM);	      }	    if (check==1)	      {		lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;		out_word(ioaddr+LANCE_ADDR, 0x0000);		out_word(ioaddr+LANCE_DATA, 0x0048);	      }	    else	      if (check==-1)		continue;	    /* we set a buffered message in the slot if it exists. */	    /* and transmit it, if needed. */	    if (ec->flags & ECF_SEND_AVAIL)	      ec_send(ec);          }        if (isr & ISR_RINT)          {#if 0	    printf("RINT\n");#endif            ec_recv(ec);          }        if (isr & ISR_RST)          {            ec->flags = ECF_STOPPED;            break;          }        /* ??? cf. lance driver on linux */        if (must_restart == 1)          {#if 0	    printf("ETH: restarting...\n");#endif	    out_word(ioaddr+LANCE_ADDR, 0x0);	    (void)in_word(ioaddr+LANCE_ADDR);	    out_word(ioaddr+LANCE_DATA, 0x4);  /* stop */	    out_word(ioaddr+LANCE_DATA, 0x2);  /* start */          }      }        if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))      {#if 0	printf("ETH: resetting...\n");#endif        ec_reset(ec);      }}/*===========================================================================* *                              ec_reset                                     * *===========================================================================*/static void ec_reset(ec)ether_card_t *ec;{  /* Stop/start the chip, and clear all RX,TX-slots */  unsigned short ioaddr = ec->ec_port;  int i;    out_word(ioaddr+LANCE_ADDR, 0x0);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, 0x4);                      /* stop */  out_word(ioaddr+LANCE_DATA, 0x2);                      /* start */    /* purge Tx-ring */  tx_slot_nr = cur_tx_slot_nr = 0;  for (i=0; i<TX_RING_SIZE; i++) {    lp->tx_ring[i].u.base = 0;    isstored[i]=0;  }  /* re-init Rx-ring */  rx_slot_nr = 0;  for (i=0; i<RX_RING_SIZE; i++)     {      lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;      lp->rx_ring[i].u.addr[3] |= 0x80;    }  /* store a buffered message on the slot if exists */  ec_send(ec);  ec->flags &= ~ECF_STOPPED;}/*===========================================================================* *                              ec_send                                      * *===========================================================================*/static void ec_send(ec)ether_card_t *ec;{  /* from ec_check_ints() or ec_reset(). */  /* this function proccesses the buffered message. (slot/transmit) */  if (!(ec->flags & ECF_SEND_AVAIL))    return;    ec->flags &= ~ECF_SEND_AVAIL;  switch(ec->sendmsg.m_type)    {    case DL_WRITE:  do_vwrite(&ec->sendmsg, TRUE, FALSE);       break;    case DL_WRITEV: do_vwrite(&ec->sendmsg, TRUE, TRUE);        break;    default:      panic( "lance", "wrong type:", ec->sendmsg.m_type);      break;    }}/*===========================================================================* *                              do_vread                                     * *===========================================================================*/static void do_vread(mp, vectored)message *mp;int vectored;{  int port, count, size;  ether_card_t *ec;  port = mp->DL_PORT;  count = mp->DL_COUNT;  ec= &ec_table[port];  ec->client= mp->DL_PROC;  if (vectored)    {      get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,                   (count > IOVEC_NR ? IOVEC_NR : count) *                   sizeof(iovec_t), ec->read_iovec.iod_iovec);      ec->read_iovec.iod_iovec_s    = count;      ec->read_iovec.iod_proc_nr    = mp->DL_PROC;      ec->read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;            ec->tmp_iovec = ec->read_iovec;      size= calc_iovec_size(&ec->tmp_iovec);    }  else    {      ec->read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;      ec->read_iovec.iod_iovec[0].iov_size = mp->DL_COUNT;      ec->read_iovec.iod_iovec_s           = 1;      ec->read_iovec.iod_proc_nr           = mp->DL_PROC;      ec->read_iovec.iod_iovec_addr        = 0;      size= count;    }  ec->flags |= ECF_READING;  ec_recv(ec);  if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))    ec_reset(ec);  reply(ec, OK, FALSE);}/*===========================================================================* *                              ec_recv                                      * *===========================================================================*/static void ec_recv(ec)ether_card_t *ec;{  vir_bytes length;  int packet_processed;  int status;  unsigned short ioaddr = ec->ec_port;  if ((ec->flags & ECF_READING)==0)    return;  if (!(ec->flags & ECF_ENABLED))    return;  /* we check all the received slots until find a properly received packet */  packet_processed = FALSE;  while (!packet_processed)    {      status = lp->rx_ring[rx_slot_nr].u.base >> 24;      if ( (status & 0x80) == 0x00 )        {	  status = lp->rx_ring[rx_slot_nr].u.base >> 24;	  /* ??? */	  if (status != 0x03)	    {	      if (status & 0x01)		ec->eth_stat.ets_recvErr++;	      if (status & 0x04)		ec->eth_stat.ets_fifoOver++;	      if (status & 0x08)		ec->eth_stat.ets_CRCerr++;	      if (status & 0x10)		ec->eth_stat.ets_OVW++;	      if (status & 0x20)		ec->eth_stat.ets_frameAll++;	      length = 0;	    }	  else	    {	      ec->eth_stat.ets_packetR++;	      length = lp->rx_ring[rx_slot_nr].msg_length;	    }          if (length > 0)            {	      ec_nic2user(ec, (int)(lp->rbuf[rx_slot_nr]),			  &ec->read_iovec, 0, length);                            ec->read_s = length;              ec->flags |= ECF_PACK_RECV;              ec->flags &= ~ECF_READING;              packet_processed = TRUE;            }          /* set up this slot again, and we move to the next slot */	  lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN;	  lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80;	  out_word(ioaddr+LANCE_ADDR, 0x00);	  out_word(ioaddr+LANCE_DATA, 0x7940);	  rx_slot_nr = (++rx_slot_nr) & RX_RING_MOD_MASK;        }      else        break;    }}/*===========================================================================* *                              do_vwrite                                    * *===========================================================================*/static void do_vwrite(mp, from_int, vectored)message *mp;int from_int;int vectored;{  int port, count, check;  ether_card_t *ec;  unsigned short ioaddr;  port = mp->DL_PORT;  count = mp->DL_COUNT;  ec = &ec_table[port];  ec->client= mp->DL_PROC;  if (isstored[tx_slot_nr]==1)    {      /* all slots are used, so this message is buffered */      ec->sendmsg= *mp;      ec->flags |= ECF_SEND_AVAIL;      reply(ec, OK, FALSE);      return;    }  /* convert the message to write_iovec */  if (vectored)    {      get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,                   (count > IOVEC_NR ? IOVEC_NR : count) *                   sizeof(iovec_t), ec->write_iovec.iod_iovec);      ec->write_iovec.iod_iovec_s    = count;      ec->write_iovec.iod_proc_nr    = mp->DL_PROC;      ec->write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;      ec->tmp_iovec = ec->write_iovec;      ec->write_s = calc_iovec_size(&ec->tmp_iovec);    }  else    {        ec->write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;      ec->write_iovec.iod_iovec[0].iov_size = mp->DL_COUNT;      ec->write_iovec.iod_iovec_s    = 1;      ec->write_iovec.iod_proc_nr    = mp->DL_PROC;      ec->write_iovec.iod_iovec_addr = 0;      ec->write_s = mp->DL_COUNT;    }  /* copy write_iovec to the slot on DMA address */  ec_user2nic(ec, &ec->write_iovec, 0,              (int)(lp->tbuf[tx_slot_nr]), ec->write_s);  /* set-up for transmitting, and transmit it if needed. */  lp->tx_ring[tx_slot_nr].buf_length = -ec->write_s;  lp->tx_ring[tx_slot_nr].misc = 0x0;  lp->tx_ring[tx_slot_nr].u.base     = virt_to_bus(lp->tbuf[tx_slot_nr]) & 0xffffff;  isstored[tx_slot_nr]=1;  if (cur_tx_slot_nr == tx_slot_nr)    check=1;  else    check=0;  tx_slot_nr = (++tx_slot_nr) & TX_RING_MOD_MASK;  if (check == 1)    {      ioaddr = ec->ec_port;      lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;      out_word(ioaddr+LANCE_ADDR, 0x0000);      out_word(ioaddr+LANCE_DATA, 0x0048);    }          ec->flags |= ECF_PACK_SEND;  /* reply by calling do_int() if this function is called from interrupt. */  if (from_int)    return;  reply(ec, OK, FALSE);}/*===========================================================================* *                              get_userdata                                 * *===========================================================================*/static void get_userdata(user_proc, user_addr, count, loc_addr)int user_proc;vir_bytes user_addr;vir_bytes count;void *loc_addr;{	/*  phys_bytes src;  src = numap_local(user_proc, user_addr, count);  if (!src)    panic( "lance", "umap failed", NO_NUM);  phys_copy(src, vir2phys(loc_addr), (phys_bytes) count);  */	int cps;	cps = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes) loc_addr, count);	if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);}/*===========================================================================* *                              ec_user2nic                                  * *===========================================================================*/static void ec_user2nic(ec, iovp, offset, nic_addr, count)ether_card_t *ec;iovec_dat_t *iovp;vir_bytes offset;int nic_addr;vir_bytes count;{  /*phys_bytes phys_hw, phys_user;*/  int bytes, i, r;  /*  phys_hw = vir2phys(nic_addr);  */  i= 0;  while (count > 0)    {      if (i >= IOVEC_NR)        {          ec_next_iovec(iovp);          i= 0;          continue;        }      if (offset >= iovp->iod_iovec[i].iov_size)        {          offset -= iovp->iod_iovec[i].iov_size;          i++;          continue;        }      bytes = iovp->iod_iovec[i].iov_size - offset;      if (bytes > count)        bytes = count;            /*      phys_user = numap_local(iovp->iod_proc_nr,                        iovp->iod_iovec[i].iov_addr + offset, bytes);            phys_copy(phys_user, phys_hw, (phys_bytes) bytes);      */      if ( (r=sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset,      	SELF, nic_addr, count )) != OK )      	panic( "lance", "sys_datacopy failed", r );      	      count -= bytes;      nic_addr += bytes;      offset += bytes;    }}/*===========================================================================* *                              ec_nic2user                                  * *===========================================================================*/static void ec_nic2user(ec, nic_addr, iovp, offset, count)ether_card_t *ec;int nic_addr;iovec_dat_t *iovp;vir_bytes offset;vir_bytes count;{  /*phys_bytes phys_hw, phys_user;*/  int bytes, i, r;  /*phys_hw = vir2phys(nic_addr);*/  i= 0;  while (count > 0)    {      if (i >= IOVEC_NR)        {          ec_next_iovec(iovp);          i= 0;          continue;        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -