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

📄 eepro100.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Shift the command bits out. */	do {		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;		outw(dataval, ee_addr); udelay(2);		outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);		retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);	} while (--cmd_len >= 0);	outw(EE_ENB, ee_addr); udelay(2);	/* Terminate the EEPROM access. */	outw(EE_ENB & ~EE_CS, ee_addr);	return retval;}static inline void whereami (const char *str){#if	0  printf ("%s\n", str);  sleep (2);#endif}/* function: eepro100_reset * resets the card. This is used to allow Etherboot to probe the card again * from a "virginal" state.... * Arguments: none * * returns:   void. */static void eepro100_reset(struct nic *nic){  outl(0, ioaddr + SCBPort);}/* function: eepro100_transmit * This transmits a packet. * * Arguments: char d[6]:          destination ethernet address. *            unsigned short t:   ethernet protocol type. *            unsigned short s:   size of the data-part of the packet. *            char *p:            the data for the packet. * returns:   void. */static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p){  struct eth_hdr {    unsigned char dst_addr[ETH_ALEN];    unsigned char src_addr[ETH_ALEN];    unsigned short type;  } hdr;  unsigned short status;  int to;  int s1, s2;  status = inw(ioaddr + SCBStatus);  /* Acknowledge all of the current interrupt sources ASAP. */  outw(status & 0xfc00, ioaddr + SCBStatus);#ifdef	DEBUG  printf ("transmitting type %hX packet (%d bytes). status = %hX, cmd=%hX\n",	  t, s, status, inw (ioaddr + SCBCmd));#endif  memcpy (&hdr.dst_addr, d, ETH_ALEN);  memcpy (&hdr.src_addr, nic->node_addr, ETH_ALEN);  hdr.type = htons (t);  txfd.status = 0;  txfd.command = CmdSuspend | CmdTx | CmdTxFlex;  txfd.link   = virt_to_bus (&txfd);  txfd.count   = 0x02208000;  txfd.tx_desc_addr = (u32)&txfd.tx_buf_addr0;  txfd.tx_buf_addr0 = virt_to_bus (&hdr);  txfd.tx_buf_size0 = sizeof (hdr);  txfd.tx_buf_addr1 = virt_to_bus (p);  txfd.tx_buf_size1 = s;#ifdef	DEBUG  printf ("txfd: \n");  hd (&txfd, sizeof (txfd));#endif  outl(virt_to_bus(&txfd), ioaddr + SCBPointer);  outw(INT_MASK | CU_START, ioaddr + SCBCmd);  wait_for_cmd_done(ioaddr + SCBCmd);  s1 = inw (ioaddr + SCBStatus);  load_timer2(10*TICKS_PER_MS);		/* timeout 10 ms for transmit */  while (!txfd.status && timer2_running())    /* Wait */;  s2 = inw (ioaddr + SCBStatus);#ifdef	DEBUG  printf ("s1 = %hX, s2 = %hX.\n", s1, s2);#endif}/* function: eepro100_poll / eth_poll * This recieves a packet from the network. * * Arguments: none * * returns:   1 if a packet was recieved. *            0 if no pacet was recieved. * side effects: *            returns the packet in the array nic->packet. *            returns the length of the packet in nic->packetlen. */static int eepro100_poll(struct nic *nic){  if (!ACCESS(rxfd)status)    return 0;  /* Ok. We got a packet. Now restart the reciever.... */  ACCESS(rxfd)status = 0;  ACCESS(rxfd)command = 0xc000;  outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);  outw(INT_MASK | RX_START, ioaddr + SCBCmd);  wait_for_cmd_done(ioaddr + SCBCmd);#ifdef	DEBUG  printf ("Got a packet: Len = %d.\n", ACCESS(rxfd)count & 0x3fff);#endif  nic->packetlen =  ACCESS(rxfd)count & 0x3fff;  memcpy (nic->packet, ACCESS(rxfd)packet, nic->packetlen);#ifdef	DEBUG  hd (nic->packet, 0x30);#endif  return 1;}static void eepro100_disable(struct nic *nic){    /* See if this PartialReset solves the problem with interfering with       kernel operation after Etherboot hands over. - Ken 20001102 */    outl(2, ioaddr + SCBPort);}/* exported function: eepro100_probe / eth_probe * initializes a card * * side effects: *            leaves the ioaddress of the 82557 chip in the variable ioaddr. *            leaves the 82557 initialized, and ready to recieve packets. */struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_device *p){	unsigned short sum = 0;	int i;	int read_cmd, ee_size;	unsigned short value;	int options;	int promisc;	/* we cache only the first few words of the EEPROM data	   be careful not to access beyond this array */	unsigned short eeprom[16];	if (probeaddrs == 0 || probeaddrs[0] == 0)		return 0;	ioaddr = probeaddrs[0] & ~3; /* Mask the bit that says "this is an io addr" */	adjust_pci_device(p);	if ((do_eeprom_cmd(EE_READ_CMD << 24, 27) & 0xffe0000)		== 0xffe0000) {		ee_size = 0x100;		read_cmd = EE_READ_CMD << 24;	} else {		ee_size = 0x40;		read_cmd = EE_READ_CMD << 22;	}	for (i = 0, sum = 0; i < ee_size; i++) {		unsigned short value = do_eeprom_cmd(read_cmd | (i << 16), 27);		if (i < (int)(sizeof(eeprom)/sizeof(eeprom[0])))			eeprom[i] = value;		sum += value;	}  for (i=0;i<ETH_ALEN;i++) {	nic->node_addr[i] =  (eeprom[i/2] >> (8*(i&1))) & 0xff;  }  printf ("Ethernet addr: %!\n", nic->node_addr);  if (sum != 0xBABA)	printf("eepro100: Invalid EEPROM checksum %#hX, "	       "check settings before activating this device!\n", sum);  outl(0, ioaddr + SCBPort);  udelay (10000);  whereami ("Got eeprom.");  outl(virt_to_bus(&lstats), ioaddr + SCBPointer);  outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd);  wait_for_cmd_done(ioaddr + SCBCmd);  whereami ("set stats addr.");  /* INIT RX stuff. */  /* Base = 0 */  outl(0, ioaddr + SCBPointer);  outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);  wait_for_cmd_done(ioaddr + SCBCmd);  whereami ("set rx base addr.");  ACCESS(rxfd)status  = 0x0001;  ACCESS(rxfd)command = 0x0000;  ACCESS(rxfd)link    = virt_to_bus(&(ACCESS(rxfd)status));  ACCESS(rxfd)rx_buf_addr = (int) &nic->packet;  ACCESS(rxfd)count   = 0;  ACCESS(rxfd)size    = 1528;  outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);  outw(INT_MASK | RX_START, ioaddr + SCBCmd);  wait_for_cmd_done(ioaddr + SCBCmd);  whereami ("started RX process.");  /* Start the reciever.... */  ACCESS(rxfd)status = 0;  ACCESS(rxfd)command = 0xc000;  outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);  outw(INT_MASK | RX_START, ioaddr + SCBCmd);  /* INIT TX stuff. */  /* Base = 0 */  outl(0, ioaddr + SCBPointer);  outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd);  wait_for_cmd_done(ioaddr + SCBCmd);  whereami ("set TX base addr.");  txfd.command      = (CmdIASetup);  txfd.status       = 0x0000;  txfd.link         = virt_to_bus (&confcmd);  {	char *t = (char *)&txfd.tx_desc_addr;	for (i=0;i<ETH_ALEN;i++)		t[i] = nic->node_addr[i];  }#ifdef	DEBUG  printf ("Setup_eaddr:\n");  hd (&txfd, 0x20);#endif  /*      options = 0x40; */ /* 10mbps half duplex... */  options = 0x00;            /* Autosense */  promisc = 0;  if (   ((eeprom[6]>>8) & 0x3f) == DP83840	  || ((eeprom[6]>>8) & 0x3f) == DP83840A) {	int mdi_reg23 = mdio_read(eeprom[6] & 0x1f, 23) | 0x0422;	if (congenb)	  mdi_reg23 |= 0x0100;	printf("  DP83840 specific setup, setting register 23 to %hX.\n",	       mdi_reg23);	mdio_write(eeprom[6] & 0x1f, 23, mdi_reg23);  }  whereami ("Done DP8340 special setup.");  if (options != 0) {	mdio_write(eeprom[6] & 0x1f, 0,		   ((options & 0x20) ? 0x2000 : 0) |    /* 100mbps? */		   ((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */	whereami ("set mdio_register.");  }  confcmd.command  = CmdSuspend | CmdConfigure;  confcmd.status   = 0x0000;  confcmd.link     = virt_to_bus (&txfd);  confcmd.data[1]  = (txfifo << 4) | rxfifo;  confcmd.data[4]  = rxdmacount;  confcmd.data[5]  = txdmacount + 0x80;  confcmd.data[15] = promisc ? 0x49: 0x48;  confcmd.data[19] = (options & 0x10) ? 0xC0 : 0x80;  confcmd.data[21] = promisc ? 0x0D: 0x05;  outl(virt_to_bus(&txfd), ioaddr + SCBPointer);  outw(INT_MASK | CU_START, ioaddr + SCBCmd);  wait_for_cmd_done(ioaddr + SCBCmd);  whereami ("started TX thingy (config, iasetup).");  load_timer2(10*TICKS_PER_MS);  while (!txfd.status && timer2_running())	/* Wait */;  nic->reset = eepro100_reset;  nic->poll = eepro100_poll;  nic->transmit = eepro100_transmit;  nic->disable = eepro100_disable;  return nic;}/*********************************************************************/#ifdef	DEBUG/* Hexdump a number of bytes from memory... */void hd (void *where, int n){  int i;  while (n > 0) {    printf ("%X ", where);    for (i=0;i < ( (n>16)?16:n);i++)      printf (" %hhX", ((char *)where)[i]);    printf ("\n");    n -= 16;    where += 16;  }}#endif

⌨️ 快捷键说明

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