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 + -
显示快捷键?