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

📄 lance.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 4 页
字号:
  message mess;  int i;  for (i= 0; i<EC_PORT_NR_MAX; i++)    {      if (ec_table[i].mode != EC_ENABLED)	continue;      mess.m_type= DL_STOP;      mess.DL_PORT= i;      do_stop(&mess);    }      	/*printf("LANCE driver stopped.\n");*/  	  	sys_exit( 0 );}/*===========================================================================* *                              do_init                                      * *===========================================================================*/static void do_init(mp)message *mp;{  int port;  ether_card_t *ec;  message reply_mess;pci_init();  port = mp->DL_PORT;  if (port < 0 || port >= EC_PORT_NR_MAX)    {      reply_mess.m_type= DL_INIT_REPLY;      reply_mess.m3_i1= ENXIO;      mess_reply(mp, &reply_mess);      return;    }  ec= &ec_table[port];  strcpy(ec->port_name, "eth_card#0");  ec->port_name[9] += port;  if (ec->mode == EC_DISABLED)    {      /* This is the default, try to (re)locate the device. */      /* only try to enable if memory is correct for DMA */	  if ( CORRECT_DMA_MEM() )	  {		conf_hw(ec);	  }	  else	  {	  	report( "LANCE", "DMA denied because address out of range", NO_NUM );	  }	        if (ec->mode == EC_DISABLED)	{	  /* Probe failed, or the device is configured off. */	  reply_mess.m_type= DL_INIT_REPLY;	  reply_mess.m3_i1= ENXIO;	  mess_reply(mp, &reply_mess);	  return;	}      if (ec->mode == EC_ENABLED)	ec_init(ec);    }  if (ec->mode == EC_SINK)    {      ec->mac_address.ea_addr[0] = 	ec->mac_address.ea_addr[1] = 	ec->mac_address.ea_addr[2] = 	ec->mac_address.ea_addr[3] = 	ec->mac_address.ea_addr[4] = 	ec->mac_address.ea_addr[5] = 0;      ec_confaddr(ec);      reply_mess.m_type = DL_INIT_REPLY;      reply_mess.m3_i1 = mp->DL_PORT;      reply_mess.m3_i2 = EC_PORT_NR_MAX;      *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;      mess_reply(mp, &reply_mess);      return;    }  assert(ec->mode == EC_ENABLED);  assert(ec->flags & ECF_ENABLED);  ec->flags &= ~(ECF_PROMISC | ECF_MULTI | ECF_BROAD);  if (mp->DL_MODE & DL_PROMISC_REQ)    ec->flags |= ECF_PROMISC | ECF_MULTI | ECF_BROAD;  if (mp->DL_MODE & DL_MULTI_REQ)    ec->flags |= ECF_MULTI;  if (mp->DL_MODE & DL_BROAD_REQ)    ec->flags |= ECF_BROAD;  ec->client = mp->m_source;  ec_reinit(ec);  reply_mess.m_type = DL_INIT_REPLY;  reply_mess.m3_i1 = mp->DL_PORT;  reply_mess.m3_i2 = EC_PORT_NR_MAX;  *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;  mess_reply(mp, &reply_mess);}/*===========================================================================* *                              do_int                                       * *===========================================================================*/static void do_int(ec)ether_card_t *ec;{  if (ec->flags & (ECF_PACK_SEND | ECF_PACK_RECV))    reply(ec, OK, TRUE);}#if 0/*===========================================================================* *                              ec_handler                                   * *===========================================================================*/static int ec_handler(hook)irq_hook_t *hook;{  /* LANCE interrupt, send message and reenable interrupts. */#if 0  printf(">> ec_handler(): \n");#endif  structof(ether_card_t, ec_hook, hook)->ec_int_pending= 1;  notify(eth_tasknr);  return 0;}#endif/*===========================================================================* *                              conf_hw                                      * *===========================================================================*/static void conf_hw(ec)ether_card_t *ec;{  static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0        /* ,... */ };  int ifnr;  ec_conf_t *ecp;  ec->mode= EC_DISABLED;     /* Superfluous */  ifnr= ec-ec_table;  ecp= &ec_conf[ifnr];  update_conf(ec, ecp);  if (ec->mode != EC_ENABLED)    return;  if (!lance_probe(ec))    {      printf("%s: No ethernet card found on PCI-BIOS info.\n", 	     ec->port_name);      ec->mode= EC_DISABLED;      return;    }  /* Allocate a memory segment, programmed I/O should set the   * memory segment (linmem) to zero.   */  if (ec->ec_linmem != 0)    {    	assert( 0 );      	/*phys2seg(&ec->ec_memseg, &ec->ec_memoff, ec->ec_linmem);*/    }/* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000;  ec->flags = ECF_EMPTY;  ec->eth_stat = empty_stat;}/*===========================================================================* *                              update_conf                                  * *===========================================================================*/static void update_conf(ec, ecp)ether_card_t *ec;ec_conf_t *ecp;{  long v;  static char ec_fmt[] = "x:d:x:x";  /* Get the default settings and modify them from the environment. */  ec->mode= EC_SINK;  v= ecp->ec_port;  switch (env_parse(ecp->ec_envvar, ec_fmt, 0, &v, 0x0000L, 0xFFFFL)) {  case EP_OFF:    ec->mode= EC_DISABLED;    break;  case EP_ON:  case EP_SET:    ec->mode= EC_ENABLED;      /* Might become disabled if 				* all probes fail */    break;  }    ec->ec_port= v;  v= ecp->ec_irq | DEI_DEFAULT;  (void) env_parse(ecp->ec_envvar, ec_fmt, 1, &v, 0L,		   (long) NR_IRQ_VECTORS - 1);  ec->ec_irq= v;    v= ecp->ec_mem;  (void) env_parse(ecp->ec_envvar, ec_fmt, 2, &v, 0L, 0xFFFFFL);  ec->ec_linmem= v;    v= 0;  (void) env_parse(ecp->ec_envvar, ec_fmt, 3, &v, 0x2000L, 0x8000L);  ec->ec_ramsize= v;}/*===========================================================================* *                              ec_init                                      * *===========================================================================*/static void ec_init(ec)ether_card_t *ec;{  int i, r;  /* General initialization */  ec->flags = ECF_EMPTY;  /*disable_irq(ec->ec_irq);*/  lance_init_card(ec); /* Get mac_address, etc ...*/  ec_confaddr(ec);#if VERBOSE  printf("%s: Ethernet address ", ec->port_name);  for (i= 0; i < 6; i++)    printf("%x%c", ec->mac_address.ea_addr[i],	   i < 5 ? ':' : '\n');#endif  /* Finish the initialization */  ec->flags |= ECF_ENABLED;  /* Set the interrupt handler */  /*put_irq_handler(&ec->ec_hook, ec->ec_irq, ec_handler);*/  ec->ec_hook = ec->ec_irq;  	if ((r=sys_irqsetpolicy(ec->ec_irq, 0, &ec->ec_hook)) != OK)		printf("lance: error, couldn't set IRQ policy: %d\n", r);/*  enable_irq(ec->ec_irq); *//*  enter_kdebug(">> ec_init():"); */  return;}/*===========================================================================* *                              reply                                        * *===========================================================================*/static void reply(ec, err, may_block)ether_card_t *ec;int err;int may_block;{  message reply;  int status,r;  clock_t now;  status = 0;  if (ec->flags & ECF_PACK_SEND)    status |= DL_PACK_SEND;  if (ec->flags & ECF_PACK_RECV)    status |= DL_PACK_RECV;  reply.m_type   = DL_TASK_REPLY;  reply.DL_PORT  = ec - ec_table;  reply.DL_PROC  = ec->client;  reply.DL_STAT  = status | ((u32_t) err << 16);  reply.DL_COUNT = ec->read_s;#if 1  if ((r=getuptime(&now)) != OK)	panic("lance", "getuptime() failed:", r);  reply.DL_CLCK = now; #else  reply.DL_CLCK = 0;#endif  r = send(ec->client, &reply);#if 1  if (r == ELOCKED && may_block)    {/*     enter_kdebug(">> lance_task: ELOCKED!"); */      return;    }#endif  if (r < 0)    panic( "lance", "send failed:", r);  ec->read_s = 0;  ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV);}/*===========================================================================* *                              mess_reply                                   * *===========================================================================*/static void mess_reply(req, reply_mess)message *req;message *reply_mess;{  if (send(req->m_source, reply_mess) != OK)    panic( "lance", "unable to mess_reply", NO_NUM);}/*===========================================================================* *                              ec_confaddr                                  * *===========================================================================*/static void ec_confaddr(ec)ether_card_t *ec;{  int i;  char eakey[16];  static char eafmt[]= "x:x:x:x:x:x";  long v;  /* User defined ethernet address? */  strcpy(eakey, ec_conf[ec-ec_table].ec_envvar);  strcat(eakey, "_EA");  for (i= 0; i < 6; i++)    {      v= ec->mac_address.ea_addr[i];      if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)	break;      ec->mac_address.ea_addr[i]= v;    }    if (i != 0 && i != 6)    {      /* It's all or nothing; force a panic. */      (void) env_parse(eakey, "?", 0, &v, 0L, 0L);    }}/*===========================================================================* *                              ec_reinit                                    * *===========================================================================*/static void ec_reinit(ec)ether_card_t *ec;{  int i;  unsigned short ioaddr = ec->ec_port;  out_word(ioaddr+LANCE_ADDR, 0x0);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, 0x4);           /* stop */  /* 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;    }  /* Set 'Receive Mode' */  if (ec->flags & ECF_PROMISC)    {      out_word(ioaddr+LANCE_ADDR, 0xf);      out_word(ioaddr+LANCE_DATA, 0x8000);    }  else    {      if (ec->flags & (ECF_BROAD | ECF_MULTI))        {          out_word(ioaddr+LANCE_ADDR, 0xf);          out_word(ioaddr+LANCE_DATA, 0x0000);        }      else        {          out_word(ioaddr+LANCE_ADDR, 0xf);          out_word(ioaddr+LANCE_DATA, 0x4000);        }    }  out_word(ioaddr+LANCE_ADDR, 0x0);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, 0x142);   /* start && enable interrupt */  return;}/*===========================================================================* *                              ec_check_ints                                * *===========================================================================*/static void ec_check_ints(ec)ether_card_t *ec;{  int must_restart=0;  int check,status;  int isr=0x0000;  unsigned short ioaddr = ec->ec_port;  if (!(ec->flags & ECF_ENABLED))    panic( "lance", "got premature interrupt", NO_NUM);    for (;;)      {#if 0	printf("ETH: Reading ISR...");#endif	out_word(ioaddr+LANCE_ADDR, 0x00);	isr=in_word(ioaddr+LANCE_DATA);	if (isr & 0x8600)	  out_word( ioaddr+LANCE_DATA, isr & ~0x004f);	out_word(ioaddr+LANCE_DATA, 0x7940);#if 0	printf("ISR=0x%x...",in_word(ioaddr+LANCE_DATA));#endif#define ISR_WINT 0x0200#define ISR_RINT 0x0400#define ISR_RERR 0x1000#define ISR_WERR 0x4000#define ISR_ERR  0x8000#define ISR_RST  0x0000        if ((isr & (ISR_WINT|ISR_RINT|ISR_RERR|ISR_WERR|ISR_ERR)) == 0x0000)          {#if 0	    printf("OK\n");#endif            break;          }        if (isr & ISR_RERR)          {#if 0	    printf("RERR\n");#endif            ec->eth_stat.ets_recvErr++;          }        if ((isr & ISR_WERR) || (isr & ISR_WINT))          {            if (isr & ISR_WERR)              {#if 0

⌨️ 快捷键说明

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