if_fxp.c

来自「RTEMS (Real-Time Executive for Multiproc」· C语言 代码 · 共 2,315 行 · 第 1/5 页

C
2,315
字号
		i = pcib_find_by_devid( 0x8086,								fxp_ident_table[j].devid,								unitNumber-1,			       				&(sc->pci_signature));		DBGLVL_PRINTK(2,"fxp_attach: find_devid returned %d "		      "and pci signature 0x%x\n",		      i,sc->pci_signature);        if (PCIB_ERR_SUCCESS == i) {			if ( UNTESTED == fxp_ident_table[j].warn ) {				device_printf(dev,"WARNING: this chip version has NOT been reported to work under RTEMS yet.\n");				device_printf(dev,"         If it works OK, report it as tested in 'c/src/libchip/network/if_fxp.c'\n");			}			break;		}	  }				}	/*	 * FIXME: add search for more device types...	 */	if (i != PCIB_ERR_SUCCESS) {	  device_printf(dev, "could not find 82559ER device\n");	  return 0;	}	  	/*	 * Enable bus mastering. Enable memory space too, in case	 * BIOS/Prom forgot about it.	 */	pcib_conf_read16(sc->pci_signature, PCI_COMMAND,&val16);	val16 |= (PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER);	pcib_conf_write16(sc->pci_signature, PCI_COMMAND, val16);	DBGLVL_PRINTK(3,"fxp_attach: PCI_COMMAND_write = 0x%x\n",val16);	pcib_conf_read16(sc->pci_signature, PCI_COMMAND,&val16);	DBGLVL_PRINTK(4,"fxp_attach: PCI_COMMAND_read  = 0x%x\n",val16);	/*	 * Figure out which we should try first - memory mapping or i/o mapping?	 * We default to memory mapping. Then we accept an override from the	 * command line. Then we check to see which one is enabled.	 */#ifdef NOTUSED	m1 = PCI_COMMAND_MEMORY;	m2 = PCI_COMMAND_IO;	prefer_iomap = 0;	if (resource_int_value(device_get_name(dev), device_get_unit(dev),	    "prefer_iomap", &prefer_iomap) == 0 && prefer_iomap != 0) {		m1 = PCI_COMMAND_IO;		m2 = PCI_COMMAND_MEMORY;	}	if (val & m1) {		sc->rtp = ((m1 == PCI_COMMAND_MEMORY)			   ? SYS_RES_MEMORY : SYS_RES_IOPORT);		sc->rgd = ((m1 == PCI_COMMAND_MEMORY)			   ? FXP_PCI_MMBA   : FXP_PCI_IOBA);		sc->mem = bus_alloc_resource(dev, sc->rtp, &sc->rgd,	                                     0, ~0, 1, RF_ACTIVE);	}	if (sc->mem == NULL && (val & m2)) {		sc->rtp = ((m2 == PCI_COMMAND_MEMORY)			   ? SYS_RES_MEMORY : SYS_RES_IOPORT);		sc->rgd = ((m2 == PCI_COMMAND_MEMORY)			   ? FXP_PCI_MMBA : FXP_PCI_IOBA);		sc->mem = bus_alloc_resource(dev, sc->rtp, &sc->rgd,                                            0, ~0, 1, RF_ACTIVE);	}	if (!sc->mem) {		device_printf(dev, "could not map device registers\n");		error = ENXIO;		goto fail;        }	if (fxp_is_verbose) {		device_printf(dev, "using %s space register mapping\n",		   sc->rtp == SYS_RES_MEMORY? "memory" : "I/O");	}	sc->sc_st = rman_get_bustag(sc->mem);	sc->sc_sh = rman_get_bushandle(sc->mem);	/*	 * Allocate our interrupt.	 */	rid = 0;	sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,				 RF_SHAREABLE | RF_ACTIVE);	if (sc->irq == NULL) {		device_printf(dev, "could not map interrupt\n");		error = ENXIO;		goto fail;	}	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,			       fxp_intr, sc, &sc->ih);	if (error) {		device_printf(dev, "could not setup irq\n");		goto fail;	}#endif	/*	 * get mapping and base address of registers	 */	pcib_conf_read16(sc->pci_signature, PCI_COMMAND,&val16);	DBGLVL_PRINTK(4,"fxp_attach: PCI_COMMAND_read  = 0x%x\n",val16);	if((val16 & PCI_COMMAND_IO) != 0) {	  sc->pci_regs_are_io = TRUE;	  pcib_conf_read32(sc->pci_signature,			   PCI_BASE_ADDRESS_1,			   &val32);	  	  sc->pci_regs_base = val32 & PCI_BASE_ADDRESS_IO_MASK;	}	else {	  sc->pci_regs_are_io = FALSE;	  pcib_conf_read32(sc->pci_signature,			   PCI_BASE_ADDRESS_0,			   &val32);	  sc->pci_regs_base = val32 & PCI_BASE_ADDRESS_MEM_MASK;	}	DBGLVL_PRINTK(3,"fxp_attach: CSR registers are mapped in %s space"		      " at address 0x%x\n",		      sc->pci_regs_are_io ? "I/O" : "MEM",		      sc->pci_regs_base);	/*	 * get interrupt level to be used	 */	pcib_conf_read8(sc->pci_signature, 60, &interrupt);	DBGLVL_PRINTK(3,"fxp_attach: interrupt = 0x%x\n",interrupt);	sc->irqInfo.name = (rtems_irq_symbolic_name)interrupt;	/*	 * Set up interrupts	 */	sc->irqInfo.hdl = (rtems_irq_hdl)fxp_intr;	sc->irqInfo.on  = nopOn;	sc->irqInfo.off = nopOn;	sc->irqInfo.isOn = fxpIsOn;  	s = BSP_install_rtems_irq_handler (&sc->irqInfo);	if (!s)	  rtems_panic ("Can't attach fxp interrupt handler for irq %d\n",		       sc->irqInfo.name);	/*	 * Reset to a stable state.	CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);	 */	CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET);	DELAY(10);	sc->cbl_base = malloc(sizeof(struct fxp_cb_tx) * FXP_NTXCB,	    M_DEVBUF, M_NOWAIT);	DBGLVL_PRINTK(3,"fxp_attach: sc->cbl_base = 0x%x\n",sc->cbl_base);	if (sc->cbl_base == NULL)		goto failmem;	else 	        bzero(sc->cbl_base,sizeof(struct fxp_cb_tx) * FXP_NTXCB);	sc->fxp_stats = malloc(sizeof(struct fxp_stats), M_DEVBUF,	    M_NOWAIT);	DBGLVL_PRINTK(3,"fxp_attach: sc->fxp_stats = 0x%x\n",sc->fxp_stats);	if (sc->fxp_stats == NULL)		goto failmem;	else	        bzero(sc->fxp_stats,sizeof(struct fxp_stats));	sc->mcsp = malloc(sizeof(struct fxp_cb_mcs), M_DEVBUF, M_NOWAIT);	DBGLVL_PRINTK(3,"fxp_attach: sc->mcsp = 0x%x\n",sc->mcsp);	if (sc->mcsp == NULL)		goto failmem;	/*	 * Pre-allocate our receive buffers.	 */	for (i = 0; i < FXP_NRFABUFS; i++) {		if (fxp_add_rfabuf(sc, NULL) != 0) {			goto failmem;		}	}	/*	 * Find out how large of an SEEPROM we have.	 */	DBGLVL_PRINTK(3,"fxp_attach: calling fxp_autosize_eeprom\n");	fxp_autosize_eeprom(sc);	/*	 * Determine whether we must use the 503 serial interface.	 */	fxp_read_eeprom(sc, &data, 6, 1);	if ((data & FXP_PHY_DEVICE_MASK) != 0 &&	    (data & FXP_PHY_SERIAL_ONLY))		sc->flags |= FXP_FLAG_SERIAL_MEDIA;	/*	 * Find out the basic controller type; we currently only	 * differentiate between a 82557 and greater.	 */	fxp_read_eeprom(sc, &data, 5, 1);	if ((data >> 8) == 1)		sc->chip = FXP_CHIP_82557;	DBGLVL_PRINTK(3,"fxp_attach: sc->chip = %d\n",sc->chip);	/*	 * Enable workarounds for certain chip revision deficiencies.	 *	 * Systems based on the ICH2/ICH2-M chip from Intel have a defect	 * where the chip can cause a PCI protocol violation if it receives	 * a CU_RESUME command when it is entering the IDLE state.  The 	 * workaround is to disable Dynamic Standby Mode, so the chip never	 * deasserts CLKRUN#, and always remains in an active state.	 *	 * See Intel 82801BA/82801BAM Specification Update, Errata #30.	 */#ifdef NOTUSED	i = pci_get_device(dev);#else	pcib_conf_read16(sc->pci_signature,2,&dev_id);	DBGLVL_PRINTK(3,"fxp_attach: device id = 0x%x\n",dev_id);#endif	if (dev_id == 0x2449 || (dev_id > 0x1030 && dev_id < 0x1039)) {        device_printf(dev, "*** See Intel 82801BA/82801BAM Specification Update, Errata #30. ***\n");		fxp_read_eeprom(sc, &data, 10, 1);		if (data & 0x02) {			/* STB enable */			u_int16_t cksum;			int i;			device_printf(dev,		    "*** DISABLING DYNAMIC STANDBY MODE IN EEPROM ***\n");			data &= ~0x02;			fxp_write_eeprom(sc, &data, 10, 1);			device_printf(dev, "New EEPROM ID: 0x%x\n", data);			cksum = 0;			for (i = 0; i < (1 << sc->eeprom_size) - 1; i++) {				fxp_read_eeprom(sc, &data, i, 1);				cksum += data;			}			i = (1 << sc->eeprom_size) - 1;			cksum = 0xBABA - cksum;			fxp_read_eeprom(sc, &data, i, 1);			fxp_write_eeprom(sc, &cksum, i, 1);			device_printf(dev,			    "EEPROM checksum @ 0x%x: 0x%x -> 0x%x\n",			    i, data, cksum);			/*			 * We need to do a full PCI reset here.  A software 			 * reset to the port doesn't cut it, but let's try			 * anyway.			 */			CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET);			DELAY(50);			device_printf(dev,	    "*** PLEASE REBOOT THE SYSTEM NOW FOR CORRECT OPERATION ***\n");#if 1			/*			 * If the user elects to continue, try the software			 * workaround, as it is better than nothing.			 */			sc->flags |= FXP_FLAG_CU_RESUME_BUG;#endif		}	}	/*	 * If we are not a 82557 chip, we can enable extended features.	 */	if (sc->chip != FXP_CHIP_82557) {	  u_int8_t tmp_val;		/*		 * If MWI is enabled in the PCI configuration, and there		 * is a valid cacheline size (8 or 16 dwords), then tell		 * the board to turn on MWI.		 */	        pcib_conf_read8(sc->pci_signature,				PCI_CACHE_LINE_SIZE,&tmp_val);		DBGLVL_PRINTK(3,"fxp_attach: CACHE_LINE_SIZE = %d\n",tmp_val);		if (val16 & PCI_COMMAND_MEMORY &&		    tmp_val != 0)			sc->flags |= FXP_FLAG_MWI_ENABLE;		/* turn on the extended TxCB feature */		sc->flags |= FXP_FLAG_EXT_TXCB;		/* enable reception of long frames for VLAN */		sc->flags |= FXP_FLAG_LONG_PKT_EN;		DBGLVL_PRINTK(3,"fxp_attach: sc->flags = 0x%x\n",			      sc->flags);	}	/*	 * Read MAC address.	 */	fxp_read_eeprom(sc, (u_int16_t *)sc->arpcom.ac_enaddr, 0, 3);	if (fxp_is_verbose) {	    device_printf(dev, "Ethernet address %x:%x:%x:%x:%x:%x %s \n",	        ((u_int8_t *)sc->arpcom.ac_enaddr)[0],	        ((u_int8_t *)sc->arpcom.ac_enaddr)[1],    	    ((u_int8_t *)sc->arpcom.ac_enaddr)[2],    	    ((u_int8_t *)sc->arpcom.ac_enaddr)[3],    	    ((u_int8_t *)sc->arpcom.ac_enaddr)[4],    	    ((u_int8_t *)sc->arpcom.ac_enaddr)[5],    	    sc->flags & FXP_FLAG_SERIAL_MEDIA ? ", 10Mbps" : "");		device_printf(dev, "PCI IDs: 0x%x 0x%x 0x%x 0x%x 0x%x\n",		    pci_get_vendor(sc), pci_get_device(sc),		    pci_get_subvendor(sc), pci_get_subdevice(sc),		    pci_get_revid(sc));		device_printf(dev, "Chip Type: %d\n", sc->chip);	}#ifdef NOTUSED /* do not set up interface at all... */	/*	 * If this is only a 10Mbps device, then there is no MII, and	 * the PHY will use a serial interface instead.	 *	 * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter	 * doesn't have a programming interface of any sort.  The	 * media is sensed automatically based on how the link partner	 * is configured.  This is, in essence, manual configuration.	 */	if (sc->flags & FXP_FLAG_SERIAL_MEDIA) {		ifmedia_init(&sc->sc_media, 0, fxp_serial_ifmedia_upd,		    fxp_serial_ifmedia_sts);		ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);		ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);	} else {		if (mii_phy_probe(dev, &sc->miibus, fxp_ifmedia_upd,		    fxp_ifmedia_sts)) {	                device_printf(dev, "MII without any PHY!\n");			error = ENXIO;			goto fail;		}	}#endif	if (config->mtu)		mtu = config->mtu;	else		mtu = ETHERMTU;	ifp->if_softc = sc;	ifp->if_unit = unitNumber;	ifp->if_name = unitName;	ifp->if_mtu  = mtu;	ifp->if_baudrate = 100000000;	ifp->if_init = fxp_init;	ifp->if_ioctl = fxp_ioctl;	ifp->if_start = fxp_start;	ifp->if_output = ether_output;	ifp->if_watchdog = fxp_watchdog;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX /*| IFF_MULTICAST*/;	if (ifp->if_snd.ifq_maxlen == 0)		ifp->if_snd.ifq_maxlen = ifqmaxlen;	/*	 * Attach the interface.	 */	DBGLVL_PRINTK(3,"fxp_attach: calling if_attach\n");	if_attach (ifp);	DBGLVL_PRINTK(3,"fxp_attach: calling ether_if_attach\n");	ether_ifattach(ifp);	DBGLVL_PRINTK(3,"fxp_attach: return from ether_if_attach\n");#ifdef NOTUSED	/*	 * Tell the upper layer(s) we support long frames.	 */	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);#endif	/*	 * Let the system queue as many packets as we have available	 * TX descriptors.	 */	ifp->if_snd.ifq_maxlen = FXP_NTXCB - 1;	splx(s);	return (0);failmem:	device_printf(dev, "Failed to malloc memory\n");	error = ENOMEM;#ifdef NOTUSEDfail:#endif	splx(s);	fxp_release(sc);	return (error);}/* * release all resources */static voidfxp_release(struct fxp_softc *sc){#ifdef NOTUSED	bus_generic_detach(sc->dev);	if (sc->miibus)		device_delete_child(sc->dev, sc->miibus);#endif	if (sc->cbl_base)		free(sc->cbl_base, M_DEVBUF);	if (sc->fxp_stats)		free(sc->fxp_stats, M_DEVBUF);	if (sc->mcsp)		free(sc->mcsp, M_DEVBUF);	if (sc->rfa_headm)		m_freem(sc->rfa_headm);#ifdef NOTUSED	if (sc->ih)		bus_teardown_intr(sc->dev, sc->irq, sc->ih);	if (sc->irq)		bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->irq);	if (sc->mem)		bus_release_resource(sc->dev, sc->rtp, sc->rgd, sc->mem);	mtx_destroy(&sc->sc_mtx);#endif}#if NOTUSED/* * Detach interface. */static intfxp_detach(device_t dev){	struct fxp_softc *sc = device_get_softc(dev);	int s;	/* disable interrupts */	CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE);	s = splimp();	/*	 * Stop DMA and drop transmit queue.	 */	fxp_stop(sc);	/*	 * Close down routes etc.	 */	ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);	/*	 * Free all media structures.	 */	ifmedia_removeall(&sc->sc_media);	splx(s);	/* Release our allocated resources. */	fxp_release(sc);	return (0);}/* * Device shutdown routine. Called at system shutdown after sync. The * main purpose of this routine is to shut off receiver DMA so that * kernel memory doesn't get clobbered during warmboot. */static int

⌨️ 快捷键说明

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