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

📄 net_3c59x.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* References: *  *   1. EtherLink(r) III Parallel Tasking(tm) ISA, EISA, Micro *      Channel(r), and PCMCIA Adapter Drivers Technical Reference *  * The current version of the driver has been tested only on 3c590XL. */#include <kerninc/kernel.hxx>#include <kerninc/Process.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/AutoConf.hxx>#include <kerninc/IntAction.hxx>#include <kerninc/IRQ.hxx>#include <kerninc/Machine.hxx>#include <kerninc/Thread.hxx>#include <kerninc/NetInterface.hxx>#include <kerninc/IoRegion.hxx>#include <kerninc/PhysMem.hxx>#include <kerninc/PCI.hxx>#include <kerninc/PCI-def.hxx>#include <eros/Device.h>#include <io.h>#include <eros/Invoke.h>#include <eros/memory.h>#include <eros/machine/endian.h>#include <kerninc/MsgLog.hxx>#include <kerninc/util.h>#include <arch-kerninc/Process.hxx>/* for fine-grain timing: */#include <../kernel/lostart.hxx>#define BOOMERANG/* #define USE_RX_RING *//* #define ENET_DEBUG * #define VERBOSE *//* The min/max packet sizes at the ethernet level are dictated by wire * timing, and are entirely independent of the encapsulation (RFC984 * v/s IEEE 802.2/802.3.  Both sizes exclude the CRC field, which is * automatically generated by the hardware (or if necessary by the * driver). *  * The true min packet size for ethernet, excluding CRC field, is 60 bytes * The true max packet size for ethernet, excluding CRC field, is 1514 bytes. *  */#define	MIN_ENET_PACKET_SZ   0X3C#define MAX_ENET_PACKET_SZ   0x05ea#define TX_FIFO_THRESH MAX_ENET_PACKET_SZ + 4 + 2static bool Probe(AutoConf *ac);static bool Attach(AutoConf *ac);struct Driver ac_3c59x = {  "3c59x", Probe, Attach} ;/* THEORY OF OPERATION: *  *  * The 3c59x is a true bus-mastering card.  Given half a chance, it * will contrive to do it's own DMA to/from memory. In general, we * wish to avoid marginal copy overhead by transferring the data * directly from/to the user-supplied buffer.  This complicates * things, as it imposes restrictions on alignment and forces us to * make tradeoffs regarding interrupt cost and copy cost. *  * *** Alignment *  * One problem with this is that the hardware requires the packet to * be a multiple of 4 bytes (zero padded if necessary), while the * enet spec allows the packet to be any desired length between min * and max.  *  * On the receive side, we therefore require that the user-supplied * buffer by aligned to a 32 bit boundary and ALSO multiple of 32 * bits.  This allows us to accept the padding bytes from the card * directly into the buffer and then report the true length to the * caller. *  * On the send side, we need to cope with short packets.  The options * would appear to be one of the following: *  *   1. Require the sent packet to be 32-bit aligned, handle the *      trailing bytes specially by copying if necessary.  *  *   2. Require the sent packet buffer to be BOTH 32-bit aligned and a *      multiple of 32-bits, obtaining the true packet length by *      parsing the outbound packet.  Unfortunately, this *      requires the driver to do some parsing to determine if this is *      an RFC894 packet or an IEEE 802.2/802.3 packet, so that is *      not a preferred solution. *  *   3. Require the sent packet buffer to be BOTH 32-bit aligned and a *      32-bit multiple, with the length prepended to the buffer. *  * There is a tradeoff here, as the marginal interrupt may cost more * than making the extra copy. *  * *** Normal State *  * Under normal operating conditions, the cards are left in register * window *7*.  This window holds all of the registers that are critical * to normal operation.  Some supporting routines adjust the * registers, but these are always careful to switch them back. *  * *** To Copy or Not To Copy *  * Assuming that the packet is suitably aligned, we have the option of * letting the card handle the DMA via it's bus-mastering feature. * Taking a simplistic view, we can simply pin the pages of the reader * (writer) in memory, mark the pages as "I/O involved", and de-pin * them when we get the completion interrupt. *  * If the user buffer is mis-aligned, we have something of a problem, * because the DMA engine on this card requires that the buffer be * aligned to a 64 bit boundary.  For the moment, strictly to keep * things simple, we require that the packet address supplied by the * user be quadword aligned.  If it is not, we return RC_RequestError. * The present driver will pin a maximum of two pages per request, to * allow the packet buffer to cross a page boundary. *  * Note that pinning a buffer does NOT prevent the user from modifying * it out from under us or from colliding with driver writes.  This is * okay.  Caveat emptor! *  * The current driver performs NO in-kernel buffering. Packets are * read directly into the user-provided buffer.  Indeed, we do not * even bother to enable RX interrupts unless somebody goes to read a * packet and discovers the RX FIFO to be empty.  This tends to give * us the best advantages of polling v/s interrupts, PROVIDED that the * RX FIFO is deep enough relative to the poll rate. *  * On the 10 Mbit cards, we get away with this because it takes a * relatively long time for the RX FIFO to overflow.  On the 100 Mbit * cards, I am concerned that the RX FIFO is in fact NOT deep enough, * in which case we may be forced to do something.  Some possible * options: *  *   1. Introduce a packet multiread operation. This is certainly the *      first thing to attempt. *  *   2. Extend the fifo into the kernel, eating the associated memory *      overhead. *  *   3. Export a kernel buffer to user land, raising risk of kernel *      compromise by queue mishandling. *  *   4. Have multiple packet readers in action simultaneously, and pin *      their pages in memory. *  * My basic view is to do the simple thing first and see how it goes. */#define MEDIA_AUTODETECT 1/* #define VORTEX_BUS_MASTER */#define TX_RING_SIZE	16#define RX_RING_SIZE	16#define PKT_BUF_SZ	1536	/* Size of each temporary Rx buffer.*//* Set the copy breakpoint for the copy-only-tiny-frames scheme.   Setting to > 1512 effectively disables this feature. */#define RX_COPYBREAK 200/* Number of times to check to see if the Tx FIFO has space, used in some   limited cases. */#define WAIT_TX_AVAIL 200static struct {  uint16_t prodId;  uint8_t ioSize;  uint32_t defaultOptions;  char * name;} product_info[] = {  { PCI_DEVICE_ID_3COM_3C590,      0x20, UINT32_MAX, "3c590 Vortex 10Mbps" },  { PCI_DEVICE_ID_3COM_3C595TX,    0x20, UINT32_MAX, "3c595 Vortex 100baseTX" },  { PCI_DEVICE_ID_3COM_3C595T4,    0x20, UINT32_MAX, "3c595 Vortex 100baseT4" },  { PCI_DEVICE_ID_3COM_3C595MII,   0x20, UINT32_MAX, "3c595 Vortex 100base-MII" },  { PCI_DEVICE_ID_3COM_3C900,      0x40, UINT32_MAX, "3c900 Boomerang 10baseT" },  { PCI_DEVICE_ID_3COM_3C900Combo, 0x40, UINT32_MAX, "3c900 Boomerang 10Mbps/Combo" },  { PCI_DEVICE_ID_3COM_3C905TX,    0x40, UINT32_MAX, "3c905 Boomerang 100baseTx" },  { PCI_DEVICE_ID_3COM_3C905T4,    0x40, UINT32_MAX, "3c905 Boomerang 100baseT4" },  { 0,                             0x20, UINT32_MAX, "3c592 EISA 10mbps Demon/Vortex"},  { 0,                             0x20, UINT32_MAX, "3c597 EISA Fast Demon/Vortex" },};  /* Register window offsets */enum {  El3Cmd = 0xe,			/* common to all windows */  El3Status = 0xe,		/* BYTE value */#if 0  El3Window = 0xf,		/* BYTE value */  El3EepromData = 0xc,  El3EepromCmd = 0xa,  El3RsrcConfig = 0x8,  El3AddrConfig = 0x6,  El3ConfigCtrl = 0x4,  El3ProductId = 0x2,  El3ManufacturerID = 0x0,#endif} ;enum {  GlobalReset        = 0u  << 11,  SelectWindow       = 1u  << 11,  StartCoax          = 2u  << 11,  RxDisable          = 3u  << 11,  RxEnable           = 4u  << 11,  RxReset            = 5u  << 11,  UpStall	     = 6u  << 11,  UpUnstall	     = (6u  << 11) + 1,  DownStall	     = (6u  << 11) + 2,  DownUnstall	     = (6u  << 11) + 3,  RxDiscard          = 8u  << 11,  TxEnable           = 9u  << 11,  TxDisable          = 10u << 11,  TxReset            = 11u << 11,  ReqIntr            = 12u << 11,  AckIntr            = 13u << 11,  SetIntrMask        = 14u << 11,  SetStatusMask      = 15u << 11,  SetRxFilter        = 16u << 11,  SetRxThresh        = 17u << 11, /* RX Early Threshold */  SetTxAvailThresh   = 18u << 11, /* TX Available Threshold */  SetTxStartThresh   = 19u << 11,  SetDmaUp           = 20u << 11,  StartDmaDown       = (20u << 11) + 1,  StatsEnable        = 21u << 11,  StatsDisable       = 22u << 11,  StopCoax           = 23u << 11,#if 0  SetTxReclaimThresh = 24u << 11,  PowerUp            = 27u << 11, /* 3c509b, 3c589b */  PowerDownFull      = 28u << 11, /* 3c509b, 3c589b */  PowerAuto          = 29u << 11, /* 3c509b, 3c589b */#endif};/* Commands: * Set RX filter command args: */enum {  RxIndividual = 0x1,  RxMulticast  = 0x2,  RxBroadcast  = 0x4,  RxPromisc    = 0x8,};/* Status register bits: */enum {#if 0  CurWindow    = 0xE000,	/* current window number */#endif  /* Intervening bits are reserved */  CmdInProgress= 0x1000,  DmaInProgress= 0x0800,  UpComplete   = 0x0400,  DownComplete = 0x0200,  DmaDone      = 0x0100,  UpdateStats  = 0x0080,	/* generates interrupt when set if not masked */  IntRequested = 0x0040,	/* generates interrupt when set if not masked */  RxEarly      = 0x0020,	/* generates interrupt when set if not masked */  RxComplete   = 0x0010,	/* generates interrupt when set if not masked */  TxAvail      = 0x0008,	/* generates interrupt when set if not masked */  TxComplete   = 0x0004,	/* generates interrupt when set if not masked */  AdapterFail  = 0x0002,	/* generates interrupt when set if not masked */  IntLatch     = 0x0001,};/* RX Status register values: (16-bit register) */enum {  RxsIncomplete = 0x8000u,	/* incomplete RX packet */  RxsError      = 0x4000,	/* error in RX packet */  Rxsuint8_ts      = 0x1fff,	/* RX packet len, excluding padding */#if 0  /* Only on 3c509!!!   * RX Error Type values:   */  RxsOverrun    = 0x0u << 11,  RxsOversize   = 0x1u << 11,	/* oversize packet (> 1514 bytes) */  RxsDribble    = 0x2u << 11,	/* The trouble with dribbles... */  RxsRunt       = 0x3u << 11,	/* small packet */  RxsAlignment  = 0x4u << 11,	/* framing error */  RxsCRC        = 0x5u << 11,#endif};/* TX Status register values: (8-bit register) */enum {  TxsComplete       = 0x80,  TxsIntReq         = 0x40,	/* interrupt on completion requested */  TxsJabber         = 0x20,	/* jabber error -- TP only; TX Reset required */  TxsUnderrun       = 0x10,	/* TX Reset required */  TxsCollisions     = 0x08,	/* Maximum collisions */  TxsStatusOverflow = 0x04,  TxsReclaim        = 0x02,	/* MCA only; else undefined */  /* bit 0 undefined */};/* Window 0 offsets: */enum {  Wn0EepromCmd  = 0x0a,  Wn0EepromData = 0x0c,};enum Win0_EEPROM_bits {  EEPROM_Read = 0x80,  EEPROM_WRITE = 0x40,  EEPROM_ERASE = 0xC0,  EEPROM_EWENB = 0x30,		/* Enable erasing/writing for 10 msec. */  EEPROM_EWDIS = 0x00,		/* Disable EWENB before 10 msec timeout. */};/* EEPROM locations. */enum eeprom_offset {  PhysAddr01=0,  PhysAddr23=1,  PhysAddr45=2,  ModelID=3,  EtherLink3ID=7,};/* Window 1 offsets -- on vortex, Window 1 is always visible in the * extended I/O space. */enum {  Wn1RxStatus   = 0x18,  Wn1Timer      = 0x1a,  Wn1TxStatus   = 0x1B,  Wn1RxFifo     = 0x10,  Wn1TxFifo     = 0x10,  Wn1TxFree     = 0x1c,  Wn1RxErrors   = 0x14,};#ifdef BOOMERANGenum {  Wn1DnStatus     = 0x20,  Wn1DnListPtr    = 0x24,  Wn1DnFragAddr   = 0x28,  Wn1DnFragLen    = 0x2C,  Wn1DnListOffset = 0x23,  Wn1TxFreeThresh = 0x2f,	/* maybe obsolete */  Wn1UpStatus     = 0x30,  Wn1FreeTimer    = 0x34,	/* free timer register */  Wn1DownTimer    = 0x36,	/* count-down timer register */  Wn1UpListPtr    = 0x38,};#endifenum Window3 {			/* Window 3: MAC/config bits. */  Wn3Config=0,  Wn3MacCtrl=6,  Wn3Options=8,};enum {  MacFullDuplex = 0x20,};union wn3_config {  int i;  struct w3_config_fields {    unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;    int pad8:8;    unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1;    int pad24:7;  } u;};/* Window 4 offsets: */enum {  Wn4NetDiag     = 0x06,  Wn4MediaType   = 0x0a,} ;enum Win4_Media_bits {  Media_SQE = 0x0008,		/* Enable SQE error counting for AUI. */  Media_10TP = 0x00C0,	/* Enable link beat and jabber for 10baseT. */  Media_Lnk = 0x0080,		/* Enable just link beat for 100TX/100FX. */  Media_LnkBeat = 0x0800,};enum Window7 {			/* Window 7: Bus Master control. */  Wn7MasterAddr   = 0,  Wn7MasterLen    = 6,  Wn7MasterStatus = 12,};/* Boomerang bus master control registers. */enum MasterCtrl {  PktStatus   = 0x20,  DownListPtr = 0x24,  FragAddr    = 0x28,  FragLen     = 0x2c,  TxFreeThreshold = 0x2f,  UpPktStatus = 0x30,  UpListPtr   = 0x38,};/* The Rx and Tx descriptor lists.   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte

⌨️ 快捷键说明

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