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

📄 lance.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 4 页
字号:
      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_hw, phys_user, (phys_bytes) bytes);      */      if ( (r=sys_datacopy( SELF, nic_addr, iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, bytes )) != OK )      	panic( "lance", "sys_datacopy failed: ", r );            count -= bytes;      nic_addr += bytes;      offset += bytes;    }}/*===========================================================================* *                              calc_iovec_size                              * *===========================================================================*/static int calc_iovec_size(iovp)iovec_dat_t *iovp;{  int size,i;  size = i = 0;          while (i < iovp->iod_iovec_s)    {      if (i >= IOVEC_NR)        {          ec_next_iovec(iovp);          i= 0;          continue;        }      size += iovp->iod_iovec[i].iov_size;      i++;    }  return size;}/*===========================================================================* *                           ec_next_iovec                                   * *===========================================================================*/static void ec_next_iovec(iovp)iovec_dat_t *iovp;{  iovp->iod_iovec_s -= IOVEC_NR;  iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);  get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,                (iovp->iod_iovec_s > IOVEC_NR ?                 IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_t),                iovp->iod_iovec); }/*===========================================================================* *                              do_getstat                                   * *===========================================================================*/static void do_getstat(mp)message *mp;{  int port;  ether_card_t *ec;  port = mp->DL_PORT;  if (port < 0 || port >= EC_PORT_NR_MAX)    panic( "lance", "illegal port", port);  ec= &ec_table[port];  ec->client= mp->DL_PROC;  put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,               (vir_bytes) sizeof(ec->eth_stat), &ec->eth_stat);  reply(ec, OK, FALSE);}/*===========================================================================* *                              put_userdata                                 * *===========================================================================*/static void put_userdata(user_proc, user_addr, count, loc_addr)int user_proc;vir_bytes user_addr;vir_bytes count;void *loc_addr;{  /*phys_bytes dst;  dst = numap_local(user_proc, user_addr, count);  if (!dst)    panic( "lance", "umap failed", NO_NUM);  phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count);  */	int cps;	cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);	if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);}/*===========================================================================* *                              do_stop                                      * *===========================================================================*/static void do_stop(mp)message *mp;{  int port;  ether_card_t *ec;  unsigned short ioaddr;  port = mp->DL_PORT;  if (port < 0 || port >= EC_PORT_NR_MAX)    panic( "lance", "illegal port", port);  ec = &ec_table[port];  if (!(ec->flags & ECF_ENABLED))    return;  ioaddr = ec->ec_port;    out_word(ioaddr+LANCE_ADDR, 0x0);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, 0x4);                          /* stop */  out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* reset */  ec->flags = ECF_EMPTY;}static void getAddressing(devind, ec)int devind;ether_card_t *ec;{	unsigned int      membase, ioaddr;	int reg, irq;	for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4)	{          ioaddr = pci_attr_r32(devind, reg);          if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0               || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0)            continue;          /* Strip the I/O address out of the returned value */          ioaddr &= PCI_BASE_ADDRESS_IO_MASK;          /* Get the memory base address */          membase = pci_attr_r32(devind, PCI_BASE_ADDRESS_1);          /* KK: Get the IRQ number */          irq = pci_attr_r8(devind, PCI_INTERRUPT_PIN);          if (irq)            irq = pci_attr_r8(devind, PCI_INTERRUPT_LINE);          /* Get the ROM base address */          /*pci_attr_r32(devind, PCI_ROM_ADDRESS, &romaddr);          romaddr >>= 10;*/          /* Take the first one or the one that matches in boot ROM address */          /*if (pci_ioaddr == 0               || romaddr == ((unsigned long) rom.rom_segment << 4)) {*/            ec->ec_linmem = membase;            ec->ec_port = ioaddr;            ec->ec_irq = irq;          /*}*/	}}/*===========================================================================* *                            lance_probe                                    * *===========================================================================*/static int lance_probe(ec)ether_card_t *ec;{  unsigned short    pci_cmd, attached = 0;  unsigned short    ioaddr;  int               lance_version, chip_version;	int devind, just_one, i, r;		u16_t vid, did;	u32_t bar;	u8_t ilr;	char *dname;	if ((ec->ec_pcibus | ec->ec_pcidev | ec->ec_pcifunc) != 0)	{		/* Look for specific PCI device */		r= pci_find_dev(ec->ec_pcibus, ec->ec_pcidev,			ec->ec_pcifunc, &devind);		if (r == 0)		{			printf("%s: no PCI found at %d.%d.%d\n",				ec->port_name, ec->ec_pcibus,				ec->ec_pcidev, ec->ec_pcifunc);			return 0;		}		pci_ids(devind, &vid, &did);		just_one= TRUE;	}	else	{		r= pci_first_dev(&devind, &vid, &did);		if (r == 0)			return 0;		just_one= FALSE;	}	for(;;)	{		for (i= 0; pcitab[i].vid != 0; i++)		{			if (pcitab[i].vid != vid)				continue;			if (pcitab[i].did != did)				continue;			if (pcitab[i].checkclass)			{			  panic("lance",			    "class check not implemented", NO_NUM);			}			break;		}		if (pcitab[i].vid != 0)			break;		if (just_one)		{			printf(		"%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",				ec->port_name, vid, did,				ec->ec_pcibus,				ec->ec_pcidev, ec->ec_pcifunc);			return 0;		}		r= pci_next_dev(&devind, &vid, &did);		if (!r)			return 0;	}	dname= pci_dev_name(vid, did);	if (!dname)		dname= "unknown device";		/*	printf("%s: ", ec->port_name);	printf("%s ", dname);	printf("(%x/", vid);	printf("%x) ", did);	printf("at %s\n", pci_slot_name(devind));	*/	pci_reserve(devind);		/*  for (i = 0; pci_dev_list[i].vendor != 0; i++) {    if (pci_dev_list[i].suffix == 1)      {	ec->ec_port   = pci_dev_list[i].ioaddr;	ec->ec_irq    = pci_dev_list[i].irq;	ec->ec_linmem = pci_dev_list[i].membase;	ec->ec_bus    = pci_dev_list[i].bus;	ec->ec_dev    = pci_dev_list[i].devfn;	ec->ec_fnc    =	pci_dev_list[i].suffix = -1;	attached = 1;	break;      }  }  if (attached == 0)    return 0; */	getAddressing(devind, ec);  /* ===== Bus Master ? ===== */  /*pcibios_read_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, &pci_cmd);*/  pci_cmd = pci_attr_r32(devind, PCI_CR);  if (!(pci_cmd & PCI_COMMAND_MASTER)) {    pci_cmd |= PCI_COMMAND_MASTER;    /*pcibios_write_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, pci_cmd);*/    pci_attr_w32(devind, PCI_CR, pci_cmd);  }  /* ===== Probe Details ===== */  ioaddr = ec->ec_port;  out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* Reset */  out_word(ioaddr+LANCE_ADDR, 0x0);                          /* Sw to win 0 */  if (in_word(ioaddr+LANCE_DATA) != 0x4)    {      ec->mode=EC_DISABLED;    }  /* Probe Chip Version */  out_word(ioaddr+LANCE_ADDR, 88);     /* Get the version of the chip */  if (in_word(ioaddr+LANCE_ADDR) != 88)    lance_version = 0;  else    {      chip_version = in_word(ioaddr+LANCE_DATA);      out_word(ioaddr+LANCE_ADDR, 89);      chip_version |= in_word(ioaddr+LANCE_DATA) << 16;      if ((chip_version & 0xfff) != 0x3)        {          ec->mode=EC_DISABLED;        }      chip_version = (chip_version >> 12) & 0xffff;      for (lance_version = 1; chip_table[lance_version].id_number != 0;           ++lance_version)        if (chip_table[lance_version].id_number == chip_version)          break;    }#if 0  printf("%s: %s at %X:%d\n",	 ec->port_name, chip_table[lance_version].name,	 ec->ec_port, ec->ec_irq);#endif  return lance_version;}/*===========================================================================* *				do_getname				     * *===========================================================================*/static void do_getname(mp)message *mp;{	int r;	strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));	mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';	mp->m_type= DL_NAME_REPLY;	r= send(mp->m_source, mp);	if (r != OK)		panic("LANCE", "do_getname: send failed", r);}/*===========================================================================* *                            lance_init_card                                * *===========================================================================*/static void lance_init_card(ec)ether_card_t *ec;{  int i;  Address l;  unsigned short ioaddr = ec->ec_port;  /* ============= setup init_block(cf. lance_probe1) ================ */  /* make sure data structure is 8-byte aligned */  l = ((Address)lance + 7) & ~7;  lp = (struct lance_interface *)l;  lp->init_block.mode = 0x3;      /* disable Rx and Tx */  lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;  /* using multiple Rx/Tx buffer */  lp->init_block.rx_ring     = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;  lp->init_block.tx_ring     = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;  l = virt_to_bus(&lp->init_block);  out_word(ioaddr+LANCE_ADDR, 0x1);   (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, (unsigned short)l);  out_word(ioaddr+LANCE_ADDR, 0x2);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, (unsigned short)(l >> 16));  out_word(ioaddr+LANCE_ADDR, 0x4);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, 0x915);  out_word(ioaddr+LANCE_ADDR, 0x0);  (void)in_word(ioaddr+LANCE_ADDR);  /* ============= Get MAC address (cf. lance_probe1) ================ */  for (i = 0; i < 6; ++i)    ec->mac_address.ea_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i);  /* ============ (re)start init_block(cf. lance_reset) =============== */  /* Reset the LANCE */  (void)in_word(ioaddr+LANCE_RESET);  /* ----- Re-initialize the LANCE ----- */  /* Set station address */  for (i = 0; i < 6; ++i)    lp->init_block.phys_addr[i] = ec->mac_address.ea_addr[i];  /* Preset the receive ring headers */  for (i=0; i<RX_RING_SIZE; i++) {    lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;    /* OWN */    lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;    /* we set the top byte as the very last thing */    lp->rx_ring[i].u.addr[3] = 0x80;  }  /* Preset the transmitting ring headers */  for (i=0; i<TX_RING_SIZE; i++) {    lp->tx_ring[i].u.base = 0;    isstored[i] = 0;  }  lp->init_block.mode = 0x0;      /* enable Rx and Tx */  l = (Address)virt_to_bus(&lp->init_block);  out_word(ioaddr+LANCE_ADDR, 0x1);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, (short)l);  out_word(ioaddr+LANCE_ADDR, 0x2);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, (short)(l >> 16));  out_word(ioaddr+LANCE_ADDR, 0x4);  (void)in_word(ioaddr+LANCE_ADDR);  out_word(ioaddr+LANCE_DATA, 0x915);  out_word(ioaddr+LANCE_ADDR, 0x0);  (void)in_word(ioaddr+LANCE_ADDR);  /* ----- start when init done. ----- */  out_word(ioaddr+LANCE_DATA, 0x4);           /* stop */  out_word(ioaddr+LANCE_DATA, 0x1);           /* init */  for (i = 10000; i > 0; --i)    if (in_word(ioaddr+LANCE_DATA) & 0x100)      break;  /* Set 'Multicast Table' */  for (i=0;i<4;++i)    {      out_word(ioaddr+LANCE_ADDR, 0x8 + i);      out_word(ioaddr+LANCE_DATA, 0xffff);    }  /* 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;}

⌨️ 快捷键说明

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