if_fxp.c

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

C
2,315
字号
/*- * Copyright (c) 1995, David Greenman * Copyright (c) 2001 Jonathan Lemon <jlemon@freebsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice unmodified, this list of conditions, and the following *    disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/fxp/if_fxp.c,v 1.118 2001/09/05 23:33:58 brooks Exp $ *//* * Intel EtherExpress Pro/100B PCI Fast Ethernet driver *//* * RTEMS Revision Preliminary History * * July XXX, 2002     W. Eric Norum <eric.norum@usask.ca> *     Placed in RTEMS CVS repository.  All further modifications will be *     noted in the CVS log and not in this comment. * * July 11, 2002     W. Eric Norum <eric.norum@usask.ca> *     Minor modifications to get driver working with NIC on VersaLogic *     Bobcat PC-104 single-board computer.  The Bobcat has no video *     driver so printf/printk calls are directed to COM2:.  This *     arrangement seems to require delays after the printk calls or *     else things lock up.  Perhaps the RTEMS pc386 console code *     should be modified to insert these delays itself. * * June 27, 2002     W. Eric Norum <eric.norum@usask.ca> *     Obtained from Thomas Doerfler <Thomas.Doerfler@imd-systems.de>. *     A big thank-you to Thomas for making this available. * * October 01, 2001  Thomas Doerfler <Thomas.Doerfler@imd-systems.de> *     Original RTEMS modifications. */#if defined(__i386__)/*#define DEBUG_OUT 0*/#include <rtems.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include <bsp.h>#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/sockio.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include <sys/malloc.h>#include <sys/systm.h>#include <bsp.h>#include <pcibios.h>#include <irq.h>#include "pci.h"#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif#include <net/bpf.h>#include <vm/vm.h>		/* for vtophys */#include <net/if_types.h>#include "if_fxpreg.h"#include "if_fxpvar.h"/* * some adaptation replacements for RTEMS */static rtems_interval fxp_ticksPerSecond;#define device_printf(device,format,args...) printk(format,## args)#define DELAY(n) rtems_task_wake_after(((n)*fxp_ticksPerSecond/1000000)+1)#ifdef DEBUG_OUT#define DBGLVL_PRINTK(LVL,format, args...)                   \if (DEBUG_OUT >= (LVL)) {                                    \  printk(format, ## args);                                   \}#else#define DBGLVL_PRINTK(LVL,format, args...)#endif/* * RTEMS event used by interrupt handler to signal driver tasks. * This must not be any of the events used by the network task synchronization. */#define INTERRUPT_EVENT	RTEMS_EVENT_1/* * remapping between PCI device and CPU memmory address view... */#if defined(__i386)#define vtophys(p) (u_int32_t)(p)#else#define vtophys(p) vtophys(p)#endif#define NFXPDRIVER 1static struct fxp_softc fxp_softc[NFXPDRIVER];static int fxp_is_verbose = TRUE;/* * NOTE!  On the Alpha, we have an alignment constraint.  The * card DMAs the packet immediately following the RFA.  However, * the first thing in the packet is a 14-byte Ethernet header. * This means that the packet is misaligned.  To compensate, * we actually offset the RFA 2 bytes into the cluster.  This * alignes the packet after the Ethernet header at a 32-bit * boundary.  HOWEVER!  This means that the RFA is misaligned! */#define	RFA_ALIGNMENT_FUDGE	2/* * Set initial transmit threshold at 64 (512 bytes). This is * increased by 64 (512 bytes) at a time, to maximum of 192 * (1536 bytes), if an underrun occurs. */static int tx_threshold = 64;/* * The configuration byte map has several undefined fields which * must be one or must be zero.  Set up a template for these bits * only, (assuming a 82557 chip) leaving the actual configuration * to fxp_init. * * See struct fxp_cb_config for the bit definitions. */static u_char fxp_cb_config_template[] = {	0x0, 0x0,		/* cb_status */	0x0, 0x0,		/* cb_command */	0x0, 0x0, 0x0, 0x0,	/* link_addr */	0x0,	/*  0 */	0x0,	/*  1 */	0x0,	/*  2 */	0x0,	/*  3 */	0x0,	/*  4 */	0x0,	/*  5 */	0x32,	/*  6 */	0x0,	/*  7 */	0x0,	/*  8 */	0x0,	/*  9 */	0x6,	/* 10 */	0x0,	/* 11 */	0x0,	/* 12 */	0x0,	/* 13 */	0xf2,	/* 14 */	0x48,	/* 15 */	0x0,	/* 16 */	0x40,	/* 17 */	0xf0,	/* 18 */	0x0,	/* 19 */	0x3f,	/* 20 */	0x5	/* 21 */};struct fxp_ident {	u_int16_t	devid;	char 		*name;	int			warn;};#define UNTESTED 1/* * Claim various Intel PCI device identifiers for this driver.  The * sub-vendor and sub-device field are extensively used to identify * particular variants, but we don't currently differentiate between * them. */static struct fxp_ident fxp_ident_table[] = {    { 0x1229,		"Intel Pro 10/100B/100+ Ethernet", UNTESTED },    { 0x2449,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1209,		"Intel Embedded 10/100 Ethernet", 0 },    { 0x1029,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1030,		"Intel Pro/100 Ethernet", 0 },    { 0x1031,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1032,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1033,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1034,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1035,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1036,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1037,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x1038,		"Intel Pro/100 Ethernet", UNTESTED },    { 0x103B,		"Intel Pro/100 Ethernet (82801BD PRO/100 VM (LOM))", 0 },    { 0,		NULL },};#if 0static int		fxp_probe(device_t dev);static int		fxp_attach(device_t dev);static int		fxp_detach(device_t dev);static int		fxp_shutdown(device_t dev);#endifint	fxp_output (struct ifnet *,	   struct mbuf *, struct sockaddr *, struct rtentry *);static rtems_isr        fxp_intr(rtems_vector_number v);static void 		fxp_init(void *xsc);static void 		fxp_tick(void *xsc);static void 		fxp_start(struct ifnet *ifp);static void		fxp_stop(struct fxp_softc *sc);static void 		fxp_release(struct fxp_softc *sc);static int		fxp_ioctl(struct ifnet *ifp, int command,			    caddr_t data);static void 		fxp_watchdog(struct ifnet *ifp);static int		fxp_add_rfabuf(struct fxp_softc *sc, struct mbuf *oldm);static void		fxp_mc_setup(struct fxp_softc *sc);static u_int16_t	fxp_eeprom_getword(struct fxp_softc *sc, int offset,			    int autosize);static void 		fxp_eeprom_putword(struct fxp_softc *sc, int offset,			    u_int16_t data);static void		fxp_autosize_eeprom(struct fxp_softc *sc);static void		fxp_read_eeprom(struct fxp_softc *sc, u_short *data,			    int offset, int words);static void		fxp_write_eeprom(struct fxp_softc *sc, u_short *data,			    int offset, int words);#ifdef NOTUSEDstatic int		fxp_ifmedia_upd(struct ifnet *ifp);static void		fxp_ifmedia_sts(struct ifnet *ifp,			    struct ifmediareq *ifmr);static int		fxp_serial_ifmedia_upd(struct ifnet *ifp);static void		fxp_serial_ifmedia_sts(struct ifnet *ifp,			    struct ifmediareq *ifmr);static volatile int	fxp_miibus_readreg(device_t dev, int phy, int reg);static void		fxp_miibus_writereg(device_t dev, int phy, int reg,			    int value);#endifstatic __inline void	fxp_lwcopy(volatile u_int32_t *src,			    volatile u_int32_t *dst);static __inline void 	fxp_scb_wait(struct fxp_softc *sc);static __inline void	fxp_scb_cmd(struct fxp_softc *sc, int cmd);static __inline void	fxp_dma_wait(volatile u_int16_t *status,			    struct fxp_softc *sc);/* * Inline function to copy a 16-bit aligned 32-bit quantity. */static __inline voidfxp_lwcopy(volatile u_int32_t *src, volatile u_int32_t *dst){#ifdef __i386__	*dst = *src;#else	volatile u_int16_t *a = (volatile u_int16_t *)src;	volatile u_int16_t *b = (volatile u_int16_t *)dst;	b[0] = a[0];	b[1] = a[1];#endif}/* * inline access functions to pci space registers */static __inline u_int8_t fxp_csr_read_1(struct fxp_softc *sc,int  reg) {  u_int8_t val;  if (sc->pci_regs_are_io) {    inport_byte(sc->pci_regs_base + reg,val);  }  else {    val = *(u_int8_t *)(sc->pci_regs_base+reg);  }  return val;}static __inline u_int32_t fxp_csr_read_2(struct fxp_softc *sc,int  reg) {  u_int16_t val;  if (sc->pci_regs_are_io) {    inport_word(sc->pci_regs_base + reg,val);  }  else {    val = *(u_int16_t *)(sc->pci_regs_base+reg);  }  return val;}static __inline u_int32_t fxp_csr_read_4(struct fxp_softc *sc,int  reg) {  u_int32_t val;  if (sc->pci_regs_are_io) {    inport_long(sc->pci_regs_base + reg,val);  }  else {    val = *(u_int32_t *)(sc->pci_regs_base+reg);  }  return val;}/* * Wait for the previous command to be accepted (but not necessarily * completed). */static __inline voidfxp_scb_wait(struct fxp_softc *sc){	int i = 10000;	while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i)		DELAY(2);	if (i == 0)		device_printf(sc->dev, "SCB timeout: 0x%x 0x%x 0x%x 0x%x\n",		    CSR_READ_1(sc, FXP_CSR_SCB_COMMAND),		    CSR_READ_1(sc, FXP_CSR_SCB_STATACK),		    CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS),		    CSR_READ_2(sc, FXP_CSR_FLOWCONTROL));}static __inline voidfxp_scb_cmd(struct fxp_softc *sc, int cmd){	if (cmd == FXP_SCB_COMMAND_CU_RESUME && sc->cu_resume_bug) {		CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_CB_COMMAND_NOP);		fxp_scb_wait(sc);	}	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, cmd);}static __inline voidfxp_dma_wait(volatile u_int16_t *status, struct fxp_softc *sc){	int i = 10000;	while (!(*status & FXP_CB_STATUS_C) && --i)		DELAY(2);	if (i == 0)		device_printf(sc->dev, "DMA timeout\n");}static __inline unsigned int pci_get_vendor(struct fxp_softc *sc) {  u_int16_t vendor;  pcib_conf_read16(sc->pci_signature,0,&vendor);  return vendor;}static __inline unsigned int pci_get_device(struct fxp_softc *sc) {  u_int16_t device;  pcib_conf_read16(sc->pci_signature,2,&device);  return device;}static __inline unsigned int pci_get_subvendor(struct fxp_softc *sc) {  u_int16_t subvendor;  pcib_conf_read16(sc->pci_signature,0x2c,&subvendor);  return subvendor;}static __inline unsigned int pci_get_subdevice(struct fxp_softc *sc) {  u_int16_t subdevice;  pcib_conf_read16(sc->pci_signature,0x2e,&subdevice);  return subdevice;}static __inline unsigned int pci_get_revid(struct fxp_softc *sc) {  u_int8_t revid;  pcib_conf_read8(sc->pci_signature,0x08,&revid);  return revid;}static void nopOn(const rtems_irq_connect_data* notUsed){  /*   * code should be moved from fxp_Enet_initialize_hardware   * to this location   */}static int fxpIsOn(const rtems_irq_connect_data* irq){  return BSP_irq_enabled_at_i8259s (irq->name);}intrtems_fxp_attach(struct rtems_bsdnet_ifconfig *config, int attaching){	int error = 0;	struct fxp_softc *sc;	struct ifnet *ifp;	u_int16_t val16;	u_int32_t val32;	u_int16_t data;	int i;	int s;	int unitNumber;	char *unitName;	u_int16_t dev_id;	u_int8_t interrupt;	int mtu;    /*     * Set up some timing values     */    rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &fxp_ticksPerSecond);	DBGLVL_PRINTK(1,"fxp_attach called\n");	/* 	 * Parse driver name	 */	if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)		return 0;		/*	 * Is driver free?	 */	if ((unitNumber <= 0) || (unitNumber > NFXPDRIVER)) {		device_printf(dev,"Bad FXP unit number.\n");		return 0;	}	sc = &fxp_softc[unitNumber - 1];	ifp = &sc->arpcom.ac_if;	if (ifp->if_softc != NULL) {		device_printf(dev,"FXP Driver already in use.\n");		return 0;	}	bzero(sc, sizeof(*sc));#ifdef NOTUSED	sc->dev = dev;	callout_handle_init(&sc->stat_ch);	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_DEF | MTX_RECURSE);#endif	s = splimp(); 	/*	 * init PCI Bios interface...	 */	i = pcib_init();	DBGLVL_PRINTK(2,"fxp_attach: pcib_init returned %d\n",i);	if (i != PCIB_ERR_SUCCESS) {	  device_printf(dev, "could not initialize pci bios interface\n");	  return 0;	}		/*	 * find device on pci bus	 */	    { int j;      for (j=0; fxp_ident_table[j].devid; j++ ) {

⌨️ 快捷键说明

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