summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/3c589.h435
-rw-r--r--drivers/5701rls.c46
-rw-r--r--drivers/5701rls.h198
-rw-r--r--drivers/bcm570x_autoneg.h415
-rw-r--r--drivers/bcm570x_debug.h111
-rw-r--r--drivers/bcm570x_lm.h469
-rw-r--r--drivers/bcm570x_mm.h160
-rw-r--r--drivers/bcm570x_queue.h399
-rw-r--r--drivers/cfb_console.c912
-rw-r--r--drivers/cs8900.c235
-rw-r--r--drivers/ct69000.c1484
-rw-r--r--drivers/dc2114x.c720
-rw-r--r--drivers/i8042.c655
-rw-r--r--drivers/ns87308.c121
-rw-r--r--drivers/pci.c503
-rw-r--r--drivers/pci_auto.c319
-rw-r--r--drivers/pcnet.c526
-rw-r--r--drivers/smiLynxEM.c1059
-rw-r--r--drivers/tigon3.c6222
-rw-r--r--drivers/tigon3.h3469
20 files changed, 18458 insertions, 0 deletions
diff --git a/drivers/3c589.h b/drivers/3c589.h
new file mode 100644
index 0000000..00e7f7c
--- /dev/null
+++ b/drivers/3c589.h
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) 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, this list of conditions and the following disclaimer. 2. The name
+ * of the author may not be used to endorse or promote products derived from
+ * this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ October 2, 1994
+
+ Modified by: Andres Vega Garcia
+
+ INRIA - Sophia Antipolis, France
+ e-mail: avega@sophia.inria.fr
+ finger: avega@pax.inria.fr
+
+ */
+
+/*
+ * Created from if_epreg.h by Fred Gray (fgray@rice.edu) to support the
+ * 3c590 family.
+ */
+
+/*
+ * Modified by Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
+ * for etherboot
+ * Mar. 14, 2000
+*/
+
+/*
+ * Ethernet software status per interface.
+ */
+
+/*
+ * Some global constants
+ */
+
+#define TX_INIT_RATE 16
+#define TX_INIT_MAX_RATE 64
+#define RX_INIT_LATENCY 64
+#define RX_INIT_EARLY_THRESH 64
+#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */
+#define MIN_RX_EARLY_THRESHL 4
+
+#define EEPROMSIZE 0x40
+#define MAX_EEPROMBUSY 1000
+#define VX_LAST_TAG 0xd7
+#define VX_MAX_BOARDS 16
+#define VX_ID_PORT 0x100
+
+/*
+ * some macros to acces long named fields
+ */
+#define BASE (EL_BASE_ADDR)
+
+/*
+ * Commands to read/write EEPROM trough EEPROM command register (Window 0,
+ * Offset 0xa)
+ */
+#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */
+#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */
+#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */
+#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */
+
+#define EEPROM_BUSY (1<<15)
+
+/*
+ * Some short functions, worth to let them be a macro
+ */
+
+/**************************************************************************
+ * *
+ * These define the EEPROM data structure. They are used in the probe
+ * function to verify the existence of the adapter after having sent
+ * the ID_Sequence.
+ *
+ * There are others but only the ones we use are defined here.
+ *
+ **************************************************************************/
+
+#define EEPROM_NODE_ADDR_0 0x0 /* Word */
+#define EEPROM_NODE_ADDR_1 0x1 /* Word */
+#define EEPROM_NODE_ADDR_2 0x2 /* Word */
+#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */
+#define EEPROM_MFG_ID 0x7 /* 0x6d50 */
+#define EEPROM_ADDR_CFG 0x8 /* Base addr */
+#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */
+#define EEPROM_OEM_ADDR_0 0xa /* Word */
+#define EEPROM_OEM_ADDR_1 0xb /* Word */
+#define EEPROM_OEM_ADDR_2 0xc /* Word */
+#define EEPROM_SOFT_INFO_2 0xf /* Software information 2 */
+
+#define NO_RX_OVN_ANOMALY (1<<5)
+
+/**************************************************************************
+ * *
+ * These are the registers for the 3Com 3c509 and their bit patterns when *
+ * applicable. They have been taken out the the "EtherLink III Parallel *
+ * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual *
+ * from 3com. *
+ * *
+ **************************************************************************/
+
+#define VX_COMMAND 0x0e /* Write. BASE+0x0e is always a
+ * command reg. */
+#define VX_STATUS 0x0e /* Read. BASE+0x0e is always status
+ * reg. */
+#define VX_WINDOW 0x0f /* Read. BASE+0x0f is always window
+ * reg. */
+/*
+ * Window 0 registers. Setup.
+ */
+/* Write */
+#define VX_W0_EEPROM_DATA 0x0c
+#define VX_W0_EEPROM_COMMAND 0x0a
+#define VX_W0_RESOURCE_CFG 0x08
+#define VX_W0_ADDRESS_CFG 0x06
+#define VX_W0_CONFIG_CTRL 0x04
+ /* Read */
+#define VX_W0_PRODUCT_ID 0x02
+#define VX_W0_MFG_ID 0x00
+
+
+/*
+ * Window 1 registers. Operating Set.
+ */
+/* Write */
+#define VX_W1_TX_PIO_WR_2 0x02
+#define VX_W1_TX_PIO_WR_1 0x00
+/* Read */
+#define VX_W1_FREE_TX 0x0c
+#define VX_W1_TX_STATUS 0x0b /* byte */
+#define VX_W1_TIMER 0x0a /* byte */
+#define VX_W1_RX_STATUS 0x08
+#define VX_W1_RX_PIO_RD_2 0x02
+#define VX_W1_RX_PIO_RD_1 0x00
+
+/*
+ * Window 2 registers. Station Address Setup/Read
+ */
+/* Read/Write */
+#define VX_W2_ADDR_5 0x05
+#define VX_W2_ADDR_4 0x04
+#define VX_W2_ADDR_3 0x03
+#define VX_W2_ADDR_2 0x02
+#define VX_W2_ADDR_1 0x01
+#define VX_W2_ADDR_0 0x00
+
+/*
+ * Window 3 registers. FIFO Management.
+ */
+/* Read */
+#define VX_W3_INTERNAL_CFG 0x00
+#define VX_W3_RESET_OPT 0x08
+#define VX_W3_FREE_TX 0x0c
+#define VX_W3_FREE_RX 0x0a
+
+/*
+ * Window 4 registers. Diagnostics.
+ */
+/* Read/Write */
+#define VX_W4_MEDIA_TYPE 0x0a
+#define VX_W4_CTRLR_STATUS 0x08
+#define VX_W4_NET_DIAG 0x06
+#define VX_W4_FIFO_DIAG 0x04
+#define VX_W4_HOST_DIAG 0x02
+#define VX_W4_TX_DIAG 0x00
+
+/*
+ * Window 5 Registers. Results and Internal status.
+ */
+/* Read */
+#define VX_W5_READ_0_MASK 0x0c
+#define VX_W5_INTR_MASK 0x0a
+#define VX_W5_RX_FILTER 0x08
+#define VX_W5_RX_EARLY_THRESH 0x06
+#define VX_W5_TX_AVAIL_THRESH 0x02
+#define VX_W5_TX_START_THRESH 0x00
+
+/*
+ * Window 6 registers. Statistics.
+ */
+/* Read/Write */
+#define TX_TOTAL_OK 0x0c
+#define RX_TOTAL_OK 0x0a
+#define TX_DEFERRALS 0x08
+#define RX_FRAMES_OK 0x07
+#define TX_FRAMES_OK 0x06
+#define RX_OVERRUNS 0x05
+#define TX_COLLISIONS 0x04
+#define TX_AFTER_1_COLLISION 0x03
+#define TX_AFTER_X_COLLISIONS 0x02
+#define TX_NO_SQE 0x01
+#define TX_CD_LOST 0x00
+
+/****************************************
+ *
+ * Register definitions.
+ *
+ ****************************************/
+
+/*
+ * Command register. All windows.
+ *
+ * 16 bit register.
+ * 15-11: 5-bit code for command to be executed.
+ * 10-0: 11-bit arg if any. For commands with no args;
+ * this can be set to anything.
+ */
+#define GLOBAL_RESET (unsigned short) 0x0000 /* Wait at least 1ms
+ * after issuing */
+#define WINDOW_SELECT (unsigned short) (0x1<<11)
+#define START_TRANSCEIVER (unsigned short) (0x2<<11) /* Read ADDR_CFG reg to
+ * determine whether
+ * this is needed. If
+ * so; wait 800 uSec
+ * before using trans-
+ * ceiver. */
+#define RX_DISABLE (unsigned short) (0x3<<11) /* state disabled on
+ * power-up */
+#define RX_ENABLE (unsigned short) (0x4<<11)
+#define RX_RESET (unsigned short) (0x5<<11)
+#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11)
+#define TX_ENABLE (unsigned short) (0x9<<11)
+#define TX_DISABLE (unsigned short) (0xa<<11)
+#define TX_RESET (unsigned short) (0xb<<11)
+#define REQ_INTR (unsigned short) (0xc<<11)
+/*
+ * The following C_* acknowledge the various interrupts. Some of them don't
+ * do anything. See the manual.
+ */
+#define ACK_INTR (unsigned short) (0x6800)
+# define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1)
+# define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2)
+# define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4)
+# define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8)
+# define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10)
+# define C_RX_EARLY (unsigned short) (ACK_INTR|0x20)
+# define C_INT_RQD (unsigned short) (ACK_INTR|0x40)
+# define C_UPD_STATS (unsigned short) (ACK_INTR|0x80)
+#define SET_INTR_MASK (unsigned short) (0xe<<11)
+#define SET_RD_0_MASK (unsigned short) (0xf<<11)
+#define SET_RX_FILTER (unsigned short) (0x10<<11)
+# define FIL_INDIVIDUAL (unsigned short) (0x1)
+# define FIL_MULTICAST (unsigned short) (0x02)
+# define FIL_BRDCST (unsigned short) (0x04)
+# define FIL_PROMISC (unsigned short) (0x08)
+#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11)
+#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11)
+#define SET_TX_START_THRESH (unsigned short) (0x13<<11)
+#define STATS_ENABLE (unsigned short) (0x15<<11)
+#define STATS_DISABLE (unsigned short) (0x16<<11)
+#define STOP_TRANSCEIVER (unsigned short) (0x17<<11)
+
+/*
+ * Status register. All windows.
+ *
+ * 15-13: Window number(0-7).
+ * 12: Command_in_progress.
+ * 11: reserved.
+ * 10: reserved.
+ * 9: reserved.
+ * 8: reserved.
+ * 7: Update Statistics.
+ * 6: Interrupt Requested.
+ * 5: RX Early.
+ * 4: RX Complete.
+ * 3: TX Available.
+ * 2: TX Complete.
+ * 1: Adapter Failure.
+ * 0: Interrupt Latch.
+ */
+#define S_INTR_LATCH (unsigned short) (0x1)
+#define S_CARD_FAILURE (unsigned short) (0x2)
+#define S_TX_COMPLETE (unsigned short) (0x4)
+#define S_TX_AVAIL (unsigned short) (0x8)
+#define S_RX_COMPLETE (unsigned short) (0x10)
+#define S_RX_EARLY (unsigned short) (0x20)
+#define S_INT_RQD (unsigned short) (0x40)
+#define S_UPD_STATS (unsigned short) (0x80)
+#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000)
+
+#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS)
+
+/* Address Config. Register.
+ * Window 0/Port 06
+ */
+
+#define ACF_CONNECTOR_BITS 14
+#define ACF_CONNECTOR_UTP 0
+#define ACF_CONNECTOR_AUI 1
+#define ACF_CONNECTOR_BNC 3
+
+#define INTERNAL_CONNECTOR_BITS 20
+#define INTERNAL_CONNECTOR_MASK 0x01700000
+
+/*
+ * FIFO Registers. RX Status.
+ *
+ * 15: Incomplete or FIFO empty.
+ * 14: 1: Error in RX Packet 0: Incomplete or no error.
+ * 13-11: Type of error.
+ * 1000 = Overrun.
+ * 1011 = Run Packet Error.
+ * 1100 = Alignment Error.
+ * 1101 = CRC Error.
+ * 1001 = Oversize Packet Error (>1514 bytes)
+ * 0010 = Dribble Bits.
+ * (all other error codes, no errors.)
+ *
+ * 10-0: RX Bytes (0-1514)
+ */
+#define ERR_INCOMPLETE (unsigned short) (0x8000)
+#define ERR_RX (unsigned short) (0x4000)
+#define ERR_MASK (unsigned short) (0x7800)
+#define ERR_OVERRUN (unsigned short) (0x4000)
+#define ERR_RUNT (unsigned short) (0x5800)
+#define ERR_ALIGNMENT (unsigned short) (0x6000)
+#define ERR_CRC (unsigned short) (0x6800)
+#define ERR_OVERSIZE (unsigned short) (0x4800)
+#define ERR_DRIBBLE (unsigned short) (0x1000)
+
+/*
+ * TX Status.
+ *
+ * Reports the transmit status of a completed transmission. Writing this
+ * register pops the transmit completion stack.
+ *
+ * Window 1/Port 0x0b.
+ *
+ * 7: Complete
+ * 6: Interrupt on successful transmission requested.
+ * 5: Jabber Error (TP Only, TX Reset required. )
+ * 4: Underrun (TX Reset required. )
+ * 3: Maximum Collisions.
+ * 2: TX Status Overflow.
+ * 1-0: Undefined.
+ *
+ */
+#define TXS_COMPLETE 0x80
+#define TXS_INTR_REQ 0x40
+#define TXS_JABBER 0x20
+#define TXS_UNDERRUN 0x10
+#define TXS_MAX_COLLISION 0x8
+#define TXS_STATUS_OVERFLOW 0x4
+
+#define RS_AUI (1<<5)
+#define RS_BNC (1<<4)
+#define RS_UTP (1<<3)
+#define RS_T4 (1<<0)
+#define RS_TX (1<<1)
+#define RS_FX (1<<2)
+#define RS_MII (1<<6)
+
+
+/*
+ * FIFO Status (Window 4)
+ *
+ * Supports FIFO diagnostics
+ *
+ * Window 4/Port 0x04.1
+ *
+ * 15: 1=RX receiving (RO). Set when a packet is being received
+ * into the RX FIFO.
+ * 14: Reserved
+ * 13: 1=RX underrun (RO). Generates Adapter Failure interrupt.
+ * Requires RX Reset or Global Reset command to recover.
+ * It is generated when you read past the end of a packet -
+ * reading past what has been received so far will give bad
+ * data.
+ * 12: 1=RX status overrun (RO). Set when there are already 8
+ * packets in the RX FIFO. While this bit is set, no additional
+ * packets are received. Requires no action on the part of
+ * the host. The condition is cleared once a packet has been
+ * read out of the RX FIFO.
+ * 11: 1=RX overrun (RO). Set when the RX FIFO is full (there
+ * may not be an overrun packet yet). While this bit is set,
+ * no additional packets will be received (some additional
+ * bytes can still be pending between the wire and the RX
+ * FIFO). Requires no action on the part of the host. The
+ * condition is cleared once a few bytes have been read out
+ * from the RX FIFO.
+ * 10: 1=TX overrun (RO). Generates adapter failure interrupt.
+ * Requires TX Reset or Global Reset command to recover.
+ * Disables Transmitter.
+ * 9-8: Unassigned.
+ * 7-0: Built in self test bits for the RX and TX FIFO's.
+ */
+#define FIFOS_RX_RECEIVING (unsigned short) 0x8000
+#define FIFOS_RX_UNDERRUN (unsigned short) 0x2000
+#define FIFOS_RX_STATUS_OVERRUN (unsigned short) 0x1000
+#define FIFOS_RX_OVERRUN (unsigned short) 0x0800
+#define FIFOS_TX_OVERRUN (unsigned short) 0x0400
+
+/*
+ * Misc defines for various things.
+ */
+#define TAG_ADAPTER 0xd0
+#define ACTIVATE_ADAPTER_TO_CONFIG 0xff
+#define ENABLE_DRQ_IRQ 0x0001
+#define MFG_ID 0x506d /* `TCM' */
+#define PROD_ID 0x5090
+#define GO_WINDOW(x) outw(WINDOW_SELECT|(x),BASE+VX_COMMAND)
+#define JABBER_GUARD_ENABLE 0x40
+#define LINKBEAT_ENABLE 0x80
+#define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE)
+#define DISABLE_UTP 0x0
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+#define RX_ERROR 0x4000
+#define RX_INCOMPLETE 0x8000
+#define TX_INDICATE 1<<15
+#define is_eeprom_busy(b) (inw((b)+VX_W0_EEPROM_COMMAND)&EEPROM_BUSY)
+
+#define VX_IOSIZE 0x20
+
+#define VX_CONNECTORS 8
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/5701rls.c b/drivers/5701rls.c
new file mode 100644
index 0000000..c4409e4
--- /dev/null
+++ b/drivers/5701rls.c
@@ -0,0 +1,46 @@
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/* History: */
+/* */
+/******************************************************************************/
+
+#if INCLUDE_5701_AX_FIX
+
+#include "bcm570x_mm.h"
+#include "5701rls.h"
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice)
+{
+ T3_FWIMG_INFO FwImgInfo;
+
+ FwImgInfo.StartAddress = t3FwStartAddr;
+ FwImgInfo.Text.Buffer = (PLM_UINT8)t3FwText;
+ FwImgInfo.Text.Offset = t3FwTextAddr;
+ FwImgInfo.Text.Length = t3FwTextLen;
+ FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3FwRodata;
+ FwImgInfo.ROnlyData.Offset = t3FwRodataAddr;
+ FwImgInfo.ROnlyData.Length = t3FwRodataLen;
+ FwImgInfo.Data.Buffer = (PLM_UINT8)t3FwData;
+ FwImgInfo.Data.Offset = t3FwDataAddr;
+ FwImgInfo.Data.Length = t3FwDataLen;
+
+ if (LM_LoadFirmware(pDevice,
+ &FwImgInfo,
+ T3_RX_CPU_ID | T3_TX_CPU_ID,
+ T3_RX_CPU_ID) != LM_STATUS_SUCCESS)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ return LM_STATUS_SUCCESS;
+}
+
+#endif /* INCLUDE_5701_AX_FIX */
diff --git a/drivers/5701rls.h b/drivers/5701rls.h
new file mode 100644
index 0000000..30b127a
--- /dev/null
+++ b/drivers/5701rls.h
@@ -0,0 +1,198 @@
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/* History: */
+/******************************************************************************/
+
+typedef unsigned long U32;
+int t3FwReleaseMajor = 0x0;
+int t3FwReleaseMinor = 0x0;
+int t3FwReleaseFix = 0x0;
+U32 t3FwStartAddr = 0x08000000;
+U32 t3FwTextAddr = 0x08000000;
+int t3FwTextLen = 0x9c0;
+U32 t3FwRodataAddr = 0x080009c0;
+int t3FwRodataLen = 0x60;
+U32 t3FwDataAddr = 0x08000a40;
+int t3FwDataLen = 0x20;
+U32 t3FwSbssAddr = 0x08000a60;
+int t3FwSbssLen = 0xc;
+U32 t3FwBssAddr = 0x08000a70;
+int t3FwBssLen = 0x10;
+U32 t3FwText[(0x9c0/4) + 1] = {
+0x0,
+0x10000003, 0x0, 0xd, 0xd,
+0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800,
+0x26100000, 0xe000018, 0x0, 0xd,
+0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800,
+0x26100034, 0xe00021c, 0x0, 0xd,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0x3c1cc000, 0xafbf0018, 0xaf80680c, 0xe00004c,
+0x241b2105, 0x97850000, 0x97870002, 0x9782002c,
+0x9783002e, 0x3c040800, 0x248409c0, 0xafa00014,
+0x21400, 0x621825, 0x52c00, 0xafa30010,
+0x8f860010, 0xe52825, 0xe000060, 0x24070102,
+0x3c02ac00, 0x34420100, 0x3c03ac01, 0x34630100,
+0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498,
+0xaf82049c, 0x24020001, 0xaf825ce0, 0xe00003f,
+0xaf825d00, 0xe000140, 0x0, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x2402ffff, 0xaf825404,
+0x8f835400, 0x34630400, 0xaf835400, 0xaf825404,
+0x3c020800, 0x24420034, 0xaf82541c, 0x3e00008,
+0xaf805400, 0x0, 0x0, 0x3c020800,
+0x34423000, 0x3c030800, 0x34633000, 0x3c040800,
+0x348437ff, 0x3c010800, 0xac220a64, 0x24020040,
+0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60,
+0xac600000, 0x24630004, 0x83102b, 0x5040fffd,
+0xac600000, 0x3e00008, 0x0, 0x804821,
+0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800,
+0x8c840a68, 0x8fab0014, 0x24430001, 0x44102b,
+0x3c010800, 0xac230a60, 0x14400003, 0x4021,
+0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60,
+0x3c030800, 0x8c630a64, 0x91240000, 0x21140,
+0x431021, 0x481021, 0x25080001, 0xa0440000,
+0x29020008, 0x1440fff4, 0x25290001, 0x3c020800,
+0x8c420a60, 0x3c030800, 0x8c630a64, 0x8f84680c,
+0x21140, 0x431021, 0xac440008, 0xac45000c,
+0xac460010, 0xac470014, 0xac4a0018, 0x3e00008,
+0xac4b001c, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x2000008,
+0x0, 0xa0001e3, 0x3c0a0001, 0xa0001e3,
+0x3c0a0002, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x3c0a0007, 0xa0001e3, 0x3c0a0008, 0xa0001e3,
+0x3c0a0009, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x3c0a000b, 0xa0001e3,
+0x3c0a000c, 0xa0001e3, 0x3c0a000d, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x3c0a000e, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x0, 0xa0001e3,
+0x0, 0xa0001e3, 0x3c0a0013, 0xa0001e3,
+0x3c0a0014, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0x1821, 0x1021, 0xafbf0018, 0xafb10014,
+0xafb00010, 0x3c010800, 0x220821, 0xac200a70,
+0x3c010800, 0x220821, 0xac200a74, 0x3c010800,
+0x220821, 0xac200a78, 0x24630001, 0x1860fff5,
+0x2442000c, 0x24110001, 0x8f906810, 0x32020004,
+0x14400005, 0x24040001, 0x3c020800, 0x8c420a78,
+0x18400003, 0x2021, 0xe000182, 0x0,
+0x32020001, 0x10400003, 0x0, 0xe000169,
+0x0, 0xa000153, 0xaf915028, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
+0x3c050800, 0x8ca50a70, 0x3c060800, 0x8cc60a80,
+0x3c070800, 0x8ce70a78, 0x27bdffe0, 0x3c040800,
+0x248409d0, 0xafbf0018, 0xafa00010, 0xe000060,
+0xafa00014, 0xe00017b, 0x2021, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x24020001, 0x8f836810,
+0x821004, 0x21027, 0x621824, 0x3e00008,
+0xaf836810, 0x27bdffd8, 0xafbf0024, 0x1080002e,
+0xafb00020, 0x8f825cec, 0xafa20018, 0x8f825cec,
+0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000,
+0xaf825cec, 0x8e020000, 0x18400016, 0x0,
+0x3c020800, 0x94420a74, 0x8fa3001c, 0x221c0,
+0xac830004, 0x8fa2001c, 0x3c010800, 0xe000201,
+0xac220a74, 0x10400005, 0x0, 0x8e020000,
+0x24420001, 0xa0001df, 0xae020000, 0x3c020800,
+0x8c420a70, 0x21c02, 0x321c0, 0xa0001c5,
+0xafa2001c, 0xe000201, 0x0, 0x1040001f,
+0x0, 0x8e020000, 0x8fa3001c, 0x24420001,
+0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74,
+0xa0001df, 0xae020000, 0x3c100800, 0x26100a78,
+0x8e020000, 0x18400028, 0x0, 0xe000201,
+0x0, 0x14400024, 0x0, 0x8e020000,
+0x3c030800, 0x8c630a70, 0x2442ffff, 0xafa3001c,
+0x18400006, 0xae020000, 0x31402, 0x221c0,
+0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e,
+0x2442ff00, 0x2c420300, 0x1440000b, 0x24024000,
+0x3c040800, 0x248409dc, 0xafa00010, 0xafa00014,
+0x8fa6001c, 0x24050008, 0xe000060, 0x3821,
+0xa0001df, 0x0, 0xaf825cf8, 0x3c020800,
+0x8c420a40, 0x8fa3001c, 0x24420001, 0xaf835cf8,
+0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020,
+0x3e00008, 0x27bd0028, 0x27bdffe0, 0x3c040800,
+0x248409e8, 0x2821, 0x3021, 0x3821,
+0xafbf0018, 0xafa00010, 0xe000060, 0xafa00014,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f82680c,
+0x8f85680c, 0x21827, 0x3182b, 0x31823,
+0x431024, 0x441021, 0xa2282b, 0x10a00006,
+0x0, 0x401821, 0x8f82680c, 0x43102b,
+0x1440fffd, 0x0, 0x3e00008, 0x0,
+0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40,
+0x64102b, 0x54400002, 0x831023, 0x641023,
+0x2c420008, 0x3e00008, 0x38420001, 0x27bdffe0,
+0x802821, 0x3c040800, 0x24840a00, 0x3021,
+0x3821, 0xafbf0018, 0xafa00010, 0xe000060,
+0xafa00014, 0xa000216, 0x0, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x0, 0x27bdffe0,
+0x3c1cc000, 0xafbf0018, 0xe00004c, 0xaf80680c,
+0x3c040800, 0x24840a10, 0x3802821, 0x3021,
+0x3821, 0xafa00010, 0xe000060, 0xafa00014,
+0x2402ffff, 0xaf825404, 0x3c0200aa, 0xe000234,
+0xaf825434, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x0, 0x0, 0x0, 0x27bdffe8,
+0xafb00010, 0x24100001, 0xafbf0014, 0x3c01c003,
+0xac200000, 0x8f826810, 0x30422000, 0x10400003,
+0x0, 0xe000246, 0x0, 0xa00023a,
+0xaf905428, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x27bdfff8, 0x8f845d0c, 0x3c0200ff,
+0x3c030800, 0x8c630a50, 0x3442fff8, 0x821024,
+0x1043001e, 0x3c0500ff, 0x34a5fff8, 0x3c06c003,
+0x3c074000, 0x851824, 0x8c620010, 0x3c010800,
+0xac230a50, 0x30420008, 0x10400005, 0x871025,
+0x8cc20000, 0x24420001, 0xacc20000, 0x871025,
+0xaf825d0c, 0x8fa20000, 0x24420001, 0xafa20000,
+0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000,
+0x8fa20000, 0x8f845d0c, 0x3c030800, 0x8c630a50,
+0x851024, 0x1443ffe8, 0x851824, 0x27bd0008,
+0x3e00008, 0x0, 0x0, 0x0 };
+U32 t3FwRodata[(0x60/4) + 1] = {
+0x35373031, 0x726c7341, 0x0,
+0x0, 0x53774576, 0x656e7430, 0x0,
+0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e,
+0x45766e74, 0x0, 0x0, 0x0,
+0x0, 0x66617461, 0x6c457272, 0x0,
+0x0, 0x4d61696e, 0x43707542, 0x0,
+0x0, 0x0 };
+U32 t3FwData[(0x20/4) + 1] = {
+0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0 };
diff --git a/drivers/bcm570x_autoneg.h b/drivers/bcm570x_autoneg.h
new file mode 100644
index 0000000..95fcc07
--- /dev/null
+++ b/drivers/bcm570x_autoneg.h
@@ -0,0 +1,415 @@
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/* History: */
+/******************************************************************************/
+
+
+#ifndef AUTONEG_H
+#define AUTONEG_H
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+#define AN_LINK_TIMER_INTERVAL_US 9000 /* 10ms */
+
+/* TRUE, FALSE */
+#define AN_TRUE 1
+#define AN_FALSE 0
+
+
+
+/******************************************************************************/
+/* Main data structure for keeping track of 802.3z auto-negotation state */
+/* variables as shown in Figure 37-6 of the IEEE 802.3z specification. */
+/******************************************************************************/
+
+typedef struct
+{
+ /* Current auto-negotiation state. */
+ unsigned long State;
+ #define AN_STATE_UNKNOWN 0
+ #define AN_STATE_AN_ENABLE 1
+ #define AN_STATE_AN_RESTART_INIT 2
+ #define AN_STATE_AN_RESTART 3
+ #define AN_STATE_DISABLE_LINK_OK 4
+ #define AN_STATE_ABILITY_DETECT_INIT 5
+ #define AN_STATE_ABILITY_DETECT 6
+ #define AN_STATE_ACK_DETECT_INIT 7
+ #define AN_STATE_ACK_DETECT 8
+ #define AN_STATE_COMPLETE_ACK_INIT 9
+ #define AN_STATE_COMPLETE_ACK 10
+ #define AN_STATE_IDLE_DETECT_INIT 11
+ #define AN_STATE_IDLE_DETECT 12
+ #define AN_STATE_LINK_OK 13
+ #define AN_STATE_NEXT_PAGE_WAIT_INIT 14
+ #define AN_STATE_NEXT_PAGE_WAIT 16
+
+ /* Link timer. */
+ unsigned long LinkTime_us;
+
+ /* Current time. */
+ unsigned long CurrentTime_us;
+
+ /* Need these values for consistency check. */
+ unsigned short AbilityMatchCfg;
+
+ /* Ability, idle, and ack match functions. */
+ unsigned long AbilityMatchCnt;
+ char AbilityMatch;
+ char IdleMatch;
+ char AckMatch;
+
+ /* Tx config data */
+ union
+ {
+ /* The TxConfig register is arranged as follows: */
+ /* */
+ /* MSB LSB */
+ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */
+ /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8| */
+ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */
+ struct
+ {
+#ifdef BIG_ENDIAN_HOST
+ unsigned int D7:1; /* PS1 */
+ unsigned int D6:1; /* HD */
+ unsigned int D5:1; /* FD */
+ unsigned int D4:1;
+ unsigned int D3:1;
+ unsigned int D2:1;
+ unsigned int D1:1;
+ unsigned int D0:1;
+ unsigned int D15:1; /* NP */
+ unsigned int D14:1; /* ACK */
+ unsigned int D13:1; /* RF2 */
+ unsigned int D12:1; /* RF1 */
+ unsigned int D11:1;
+ unsigned int D10:1;
+ unsigned int D9:1;
+ unsigned int D8:1; /* PS2 */
+#else /* BIG_ENDIAN_HOST */
+ unsigned int D8:1; /* PS2 */
+ unsigned int D9:1;
+ unsigned int D10:1;
+ unsigned int D11:1;
+ unsigned int D12:1; /* RF1 */
+ unsigned int D13:1; /* RF2 */
+ unsigned int D14:1; /* ACK */
+ unsigned int D15:1; /* NP */
+ unsigned int D0:1;
+ unsigned int D1:1;
+ unsigned int D2:1;
+ unsigned int D3:1;
+ unsigned int D4:1;
+ unsigned int D5:1; /* FD */
+ unsigned int D6:1; /* HD */
+ unsigned int D7:1; /* PS1 */
+#endif
+ } bits;
+
+ unsigned short AsUSHORT;
+
+ #define D8_PS2 bits.D8
+ #define D12_RF1 bits.D12
+ #define D13_RF2 bits.D13
+ #define D14_ACK bits.D14
+ #define D15_NP bits.D15
+ #define D5_FD bits.D5
+ #define D6_HD bits.D6
+ #define D7_PS1 bits.D7
+ } TxConfig;
+
+ /* Rx config data */
+ union
+ {
+ /* The RxConfig register is arranged as follows: */
+ /* */
+ /* MSB LSB */
+ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */
+ /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8| */
+ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */
+ struct
+ {
+#ifdef BIG_ENDIAN_HOST
+ unsigned int D7:1; /* PS1 */
+ unsigned int D6:1; /* HD */
+ unsigned int D5:1; /* FD */
+ unsigned int D4:1;
+ unsigned int D3:1;
+ unsigned int D2:1;
+ unsigned int D1:1;
+ unsigned int D0:1;
+ unsigned int D15:1; /* NP */
+ unsigned int D14:1; /* ACK */
+ unsigned int D13:1; /* RF2 */
+ unsigned int D12:1; /* RF1 */
+ unsigned int D11:1;
+ unsigned int D10:1;
+ unsigned int D9:1;
+ unsigned int D8:1; /* PS2 */
+#else /* BIG_ENDIAN_HOST */
+ unsigned int D8:1; /* PS2 */
+ unsigned int D9:1;
+ unsigned int D10:1;
+ unsigned int D11:1;
+ unsigned int D12:1; /* RF1 */
+ unsigned int D13:1; /* RF2 */
+ unsigned int D14:1; /* ACK */
+ unsigned int D15:1; /* NP */
+ unsigned int D0:1;
+ unsigned int D1:1;
+ unsigned int D2:1;
+ unsigned int D3:1;
+ unsigned int D4:1;
+ unsigned int D5:1; /* FD */
+ unsigned int D6:1; /* HD */
+ unsigned int D7:1; /* PS1 */
+#endif
+ } bits;
+
+ unsigned short AsUSHORT;
+ } RxConfig;
+
+ #define AN_CONFIG_NP 0x0080
+ #define AN_CONFIG_ACK 0x0040
+ #define AN_CONFIG_RF2 0x0020
+ #define AN_CONFIG_RF1 0x0010
+ #define AN_CONFIG_PS2 0x0001
+ #define AN_CONFIG_PS1 0x8000
+ #define AN_CONFIG_HD 0x4000
+ #define AN_CONFIG_FD 0x2000
+
+
+ /* Management registers. */
+
+ /* Control register. */
+ union
+ {
+ struct
+ {
+ unsigned int an_enable:1;
+ unsigned int loopback:1;
+ unsigned int reset:1;
+ unsigned int restart_an:1;
+ } bits;
+
+ unsigned short AsUSHORT;
+
+ #define mr_an_enable Mr0.bits.an_enable
+ #define mr_loopback Mr0.bits.loopback
+ #define mr_main_reset Mr0.bits.reset
+ #define mr_restart_an Mr0.bits.restart_an
+ } Mr0;
+
+ /* Status register. */
+ union
+ {
+ struct
+ {
+ unsigned int an_complete:1;
+ unsigned int link_ok:1;
+ } bits;
+
+ unsigned short AsUSHORT;
+
+ #define mr_an_complete Mr1.bits.an_complete
+ #define mr_link_ok Mr1.bits.link_ok
+ } Mr1;
+
+ /* Advertisement register. */
+ union
+ {
+ struct
+ {
+ unsigned int reserved_4:5;
+ unsigned int full_duplex:1;
+ unsigned int half_duplex:1;
+ unsigned int sym_pause:1;
+ unsigned int asym_pause:1;
+ unsigned int reserved_11:3;
+ unsigned int remote_fault1:1;
+ unsigned int remote_fault2:1;
+ unsigned int reserved_14:1;
+ unsigned int next_page:1;
+ } bits;
+
+ unsigned short AsUSHORT;
+
+ #define mr_adv_full_duplex Mr4.bits.full_duplex
+ #define mr_adv_half_duplex Mr4.bits.half_duplex
+ #define mr_adv_sym_pause Mr4.bits.sym_pause
+ #define mr_adv_asym_pause Mr4.bits.asym_pause
+ #define mr_adv_remote_fault1 Mr4.bits.remote_fault1
+ #define mr_adv_remote_fault2 Mr4.bits.remote_fault2
+ #define mr_adv_next_page Mr4.bits.next_page
+ } Mr4;
+
+ /* Link partner advertisement register. */
+ union
+ {
+ struct
+ {
+ unsigned int reserved_4:5;
+ unsigned int lp_full_duplex:1;
+ unsigned int lp_half_duplex:1;
+ unsigned int lp_sym_pause:1;
+ unsigned int lp_asym_pause:1;
+ unsigned int reserved_11:3;
+ unsigned int lp_remote_fault1:1;
+ unsigned int lp_remote_fault2:1;
+ unsigned int lp_ack:1;
+ unsigned int lp_next_page:1;
+ } bits;
+
+ unsigned short AsUSHORT;
+
+ #define mr_lp_adv_full_duplex Mr5.bits.lp_full_duplex
+ #define mr_lp_adv_half_duplex Mr5.bits.lp_half_duplex
+ #define mr_lp_adv_sym_pause Mr5.bits.lp_sym_pause
+ #define mr_lp_adv_asym_pause Mr5.bits.lp_asym_pause
+ #define mr_lp_adv_remote_fault1 Mr5.bits.lp_remote_fault1
+ #define mr_lp_adv_remote_fault2 Mr5.bits.lp_remote_fault2
+ #define mr_lp_adv_next_page Mr5.bits.lp_next_page
+ } Mr5;
+
+ /* Auto-negotiation expansion register. */
+ union
+ {
+ struct
+ {
+ unsigned int reserved_0:1;
+ unsigned int page_received:1;
+ unsigned int next_pageable:1;
+ unsigned int reserved_15:13;
+ } bits;
+
+ unsigned short AsUSHORT;
+ } Mr6;
+
+ /* Auto-negotiation next page transmit register. */
+ union
+ {
+ struct
+ {
+ unsigned int code_field:11;
+ unsigned int toggle:1;
+ unsigned int ack2:1;
+ unsigned int message_page:1;
+ unsigned int reserved_14:1;
+ unsigned int next_page:1;
+ } bits;
+
+ unsigned short AsUSHORT;
+
+ #define mr_np_tx Mr7.AsUSHORT
+ } Mr7;
+
+ /* Auto-negotiation link partner ability register. */
+ union
+ {
+ struct
+ {
+ unsigned int code_field:11;
+ unsigned int toggle:1;
+ unsigned int ack2:1;
+ unsigned int message_page:1;
+ unsigned int ack:1;
+ unsigned int next_page:1;
+ } bits;
+
+ unsigned short AsUSHORT;
+
+ #define mr_lp_np_rx Mr8.AsUSHORT
+ } Mr8;
+
+ /* Extended status register. */
+ union
+ {
+ struct
+ {
+ unsigned int reserved_11:12;
+ unsigned int base1000_t_hd:1;
+ unsigned int base1000_t_fd:1;
+ unsigned int base1000_x_hd:1;
+ unsigned int base1000_x_fd:1;
+ } bits;
+
+ unsigned short AsUSHORT;
+ } Mr15;
+
+ /* Miscellaneous state variables. */
+ union
+ {
+ struct
+ {
+ unsigned int toggle_tx:1;
+ unsigned int toggle_rx:1;
+ unsigned int np_rx:1;
+ unsigned int page_rx:1;
+ unsigned int np_loaded:1;
+ } bits;
+
+ unsigned short AsUSHORT;
+
+ #define mr_toggle_tx MrMisc.bits.toggle_tx
+ #define mr_toggle_rx MrMisc.bits.toggle_rx
+ #define mr_np_rx MrMisc.bits.np_rx
+ #define mr_page_rx MrMisc.bits.page_rx
+ #define mr_np_loaded MrMisc.bits.np_loaded
+ } MrMisc;
+
+
+ /* Implement specifics */
+
+ /* Pointer to the operating system specific data structure. */
+ void *pContext;
+} AN_STATE_INFO, *PAN_STATE_INFO;
+
+
+
+/******************************************************************************/
+/* Return code of Autoneg8023z. */
+/******************************************************************************/
+
+typedef enum
+{
+ AUTONEG_STATUS_OK = 0,
+ AUTONEG_STATUS_DONE = 1,
+ AUTONEG_STATUS_TIMER_ENABLED = 2,
+ AUTONEG_STATUS_FAILED = 0xfffffff
+} AUTONEG_STATUS, *PAUTONEG_STATUS;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+AUTONEG_STATUS Autoneg8023z(PAN_STATE_INFO pAnInfo);
+void AutonegInit(PAN_STATE_INFO pAnInfo);
+
+
+
+/******************************************************************************/
+/* The following functions are defined in the os-dependent module. */
+/******************************************************************************/
+
+void MM_AnTxConfig(PAN_STATE_INFO pAnInfo);
+void MM_AnTxIdle(PAN_STATE_INFO pAnInfo);
+char MM_AnRxConfig(PAN_STATE_INFO pAnInfo, unsigned short *pRxConfig);
+
+
+
+#endif /* AUTONEG_H */
+
diff --git a/drivers/bcm570x_debug.h b/drivers/bcm570x_debug.h
new file mode 100644
index 0000000..0a688cf
--- /dev/null
+++ b/drivers/bcm570x_debug.h
@@ -0,0 +1,111 @@
+
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/* History: */
+/* 02/25/00 Hav Khauv Initial version. */
+/******************************************************************************/
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#ifdef VXWORKS
+#include <vxWorks.h>
+#endif
+
+/******************************************************************************/
+/* Debug macros */
+/******************************************************************************/
+
+/* Code path for controlling output debug messages. */
+/* Define your code path here. */
+#define CP_INIT 0x010000
+#define CP_SEND 0x020000
+#define CP_RCV 0x040000
+#define CP_INT 0x080000
+#define CP_UINIT 0x100000
+#define CP_RESET 0x200000
+
+#define CP_ALL (CP_INIT | CP_SEND | CP_RCV | CP_INT | \
+ CP_RESET | CP_UINIT)
+
+#define CP_MASK 0xffff0000
+
+
+/* Debug message levels. */
+#define LV_VERBOSE 0x03
+#define LV_INFORM 0x02
+#define LV_WARN 0x01
+#define LV_FATAL 0x00
+
+#define LV_MASK 0xffff
+
+
+/* Code path and messsage level combined. These are the first argument of */
+/* the DbgMessage macro. */
+#define INIT_V (CP_INIT | LV_VERBOSE)
+#define INIT_I (CP_INIT | LV_INFORM)
+#define INIT_W (CP_INIT | LV_WARN)
+#define SEND_V (CP_SEND | LV_VERBOSE)
+#define SEND_I (CP_SEND | LV_INFORM)
+#define SEND_W (CP_SEND | LV_WARN)
+#define RCV_V (CP_RCV | LV_VERBOSE)
+#define RCV_I (CP_RCV | LV_INFORM)
+#define RCV_W (CP_RCV | LV_WARN)
+#define INT_V (CP_INT | LV_VERBOSE)
+#define INT_I (CP_INT | LV_INFORM)
+#define INT_W (CP_INT | LV_WARN)
+#define UINIT_V (CP_UINIT | LV_VERBOSE)
+#define UINIT_I (CP_UINIT | LV_INFORM)
+#define UINIT_W (CP_UINIT | LV_WARN)
+#define RESET_V (CP_RESET | LV_VERBOSE)
+#define RESET_I (CP_RESET | LV_INFORM)
+#define RESET_W (CP_RESET | LV_WARN)
+#define CPALL_V (CP_ALL | LV_VERBOSE)
+#define CPALL_I (CP_ALL | LV_INFORM)
+#define CPALL_W (CP_ALL | LV_WARN)
+
+
+/* All code path message levels. */
+#define FATAL (CP_ALL | LV_FATAL)
+#define WARN (CP_ALL | LV_WARN)
+#define INFORM (CP_ALL | LV_INFORM)
+#define VERBOSE (CP_ALL | LV_VERBOSE)
+
+
+/* These constants control the message output. */
+/* Set your debug message output level and code path here. */
+#ifndef DBG_MSG_CP
+#define DBG_MSG_CP CP_ALL /* Where to output messages. */
+#endif
+
+#ifndef DBG_MSG_LV
+#define DBG_MSG_LV LV_VERBOSE /* Level of message output. */
+#endif
+
+/* DbgMessage macro. */
+#if DBG
+#define DbgMessage(CNTRL, MESSAGE) \
+ if((CNTRL & DBG_MSG_CP) && ((CNTRL & LV_MASK) <= DBG_MSG_LV)) \
+ printf MESSAGE
+#define DbgBreak() DbgBreakPoint()
+#undef STATIC
+#define STATIC
+#else
+#define DbgMessage(CNTRL, MESSAGE)
+#define DbgBreak()
+#undef STATIC
+#define STATIC static
+#endif /* DBG */
+
+
+
+#endif /* DEBUG_H */
+
diff --git a/drivers/bcm570x_lm.h b/drivers/bcm570x_lm.h
new file mode 100644
index 0000000..79073a8
--- /dev/null
+++ b/drivers/bcm570x_lm.h
@@ -0,0 +1,469 @@
+
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/* History: */
+/* 02/25/00 Hav Khauv Initial version. */
+/******************************************************************************/
+
+#ifndef LM_H
+#define LM_H
+
+#include "bcm570x_queue.h"
+#include "bcm570x_bits.h"
+
+
+
+/******************************************************************************/
+/* Basic types. */
+/******************************************************************************/
+
+typedef char LM_CHAR, *PLM_CHAR;
+typedef unsigned int LM_UINT, *PLM_UINT;
+typedef unsigned char LM_UINT8, *PLM_UINT8;
+typedef unsigned short LM_UINT16, *PLM_UINT16;
+typedef unsigned int LM_UINT32, *PLM_UINT32;
+typedef unsigned int LM_COUNTER, *PLM_COUNTER;
+typedef void LM_VOID, *PLM_VOID;
+typedef char LM_BOOL, *PLM_BOOL;
+
+/* 64bit value. */
+typedef struct {
+#ifdef BIG_ENDIAN_HOST
+ LM_UINT32 High;
+ LM_UINT32 Low;
+#else /* BIG_ENDIAN_HOST */
+ LM_UINT32 Low;
+ LM_UINT32 High;
+#endif /* !BIG_ENDIAN_HOST */
+} LM_UINT64, *PLM_UINT64;
+
+typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS;
+
+/* void LM_INC_PHYSICAL_ADDRESS(PLM_PHYSICAL_ADDRESS pAddr,LM_UINT32 IncSize) */
+#define LM_INC_PHYSICAL_ADDRESS(pAddr, IncSize) \
+ { \
+ LM_UINT32 OrgLow; \
+ \
+ OrgLow = (pAddr)->Low; \
+ (pAddr)->Low += IncSize; \
+ if((pAddr)->Low < OrgLow) { \
+ (pAddr)->High++; /* Wrap around. */ \
+ } \
+ }
+
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif /* NULL */
+
+#ifndef OFFSETOF
+#define OFFSETOF(_s, _m) (MM_UINT_PTR(&(((_s *) 0)->_m)))
+#endif /* OFFSETOF */
+
+
+
+/******************************************************************************/
+/* Simple macros. */
+/******************************************************************************/
+
+#define IS_ETH_BROADCAST(_pEthAddr) \
+ (((unsigned char *) (_pEthAddr))[0] == ((unsigned char) 0xff))
+
+#define IS_ETH_MULTICAST(_pEthAddr) \
+ (((unsigned char *) (_pEthAddr))[0] & ((unsigned char) 0x01))
+
+#define IS_ETH_ADDRESS_EQUAL(_pEtherAddr1, _pEtherAddr2) \
+ ((((unsigned char *) (_pEtherAddr1))[0] == \
+ ((unsigned char *) (_pEtherAddr2))[0]) && \
+ (((unsigned char *) (_pEtherAddr1))[1] == \
+ ((unsigned char *) (_pEtherAddr2))[1]) && \
+ (((unsigned char *) (_pEtherAddr1))[2] == \
+ ((unsigned char *) (_pEtherAddr2))[2]) && \
+ (((unsigned char *) (_pEtherAddr1))[3] == \
+ ((unsigned char *) (_pEtherAddr2))[3]) && \
+ (((unsigned char *) (_pEtherAddr1))[4] == \
+ ((unsigned char *) (_pEtherAddr2))[4]) && \
+ (((unsigned char *) (_pEtherAddr1))[5] == \
+ ((unsigned char *) (_pEtherAddr2))[5]))
+
+#define COPY_ETH_ADDRESS(_Src, _Dst) \
+ ((unsigned char *) (_Dst))[0] = ((unsigned char *) (_Src))[0]; \
+ ((unsigned char *) (_Dst))[1] = ((unsigned char *) (_Src))[1]; \
+ ((unsigned char *) (_Dst))[2] = ((unsigned char *) (_Src))[2]; \
+ ((unsigned char *) (_Dst))[3] = ((unsigned char *) (_Src))[3]; \
+ ((unsigned char *) (_Dst))[4] = ((unsigned char *) (_Src))[4]; \
+ ((unsigned char *) (_Dst))[5] = ((unsigned char *) (_Src))[5];
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+#define ETHERNET_ADDRESS_SIZE 6
+#define ETHERNET_PACKET_HEADER_SIZE 14
+#define MIN_ETHERNET_PACKET_SIZE 64 /* with 4 byte crc. */
+#define MAX_ETHERNET_PACKET_SIZE 1518 /* with 4 byte crc. */
+#define MIN_ETHERNET_PACKET_SIZE_NO_CRC 60
+#define MAX_ETHERNET_PACKET_SIZE_NO_CRC 1514
+#define MAX_ETHERNET_PACKET_BUFFER_SIZE 1536 /* A nice even number. */
+
+#ifndef LM_MAX_MC_TABLE_SIZE
+#define LM_MAX_MC_TABLE_SIZE 32
+#endif /* LM_MAX_MC_TABLE_SIZE */
+#define LM_MC_ENTRY_SIZE (ETHERNET_ADDRESS_SIZE+1)
+#define LM_MC_INSTANCE_COUNT_INDEX (LM_MC_ENTRY_SIZE-1)
+
+
+/* Receive filter masks. */
+#define LM_ACCEPT_UNICAST 0x0001
+#define LM_ACCEPT_MULTICAST 0x0002
+#define LM_ACCEPT_ALL_MULTICAST 0x0004
+#define LM_ACCEPT_BROADCAST 0x0008
+#define LM_ACCEPT_ERROR_PACKET 0x0010
+
+#define LM_PROMISCUOUS_MODE 0x10000
+
+
+
+/******************************************************************************/
+/* PCI registers. */
+/******************************************************************************/
+
+#define PCI_VENDOR_ID_REG 0x00
+#define PCI_DEVICE_ID_REG 0x02
+
+#define PCI_COMMAND_REG 0x04
+#define PCI_IO_SPACE_ENABLE 0x0001
+#define PCI_MEM_SPACE_ENABLE 0x0002
+#define PCI_BUSMASTER_ENABLE 0x0004
+#define PCI_MEMORY_WRITE_INVALIDATE 0x0010
+#define PCI_PARITY_ERROR_ENABLE 0x0040
+#define PCI_SYSTEM_ERROR_ENABLE 0x0100
+#define PCI_FAST_BACK_TO_BACK_ENABLE 0x0200
+
+#define PCI_STATUS_REG 0x06
+#define PCI_REV_ID_REG 0x08
+
+#define PCI_CACHE_LINE_SIZE_REG 0x0c
+
+#define PCI_IO_BASE_ADDR_REG 0x10
+#define PCI_IO_BASE_ADDR_MASK 0xfffffff0
+
+#define PCI_MEM_BASE_ADDR_LOW 0x10
+#define PCI_MEM_BASE_ADDR_HIGH 0x14
+
+#define PCI_SUBSYSTEM_VENDOR_ID_REG 0x2c
+#define PCI_SUBSYSTEM_ID_REG 0x2e
+#define PCI_INT_LINE_REG 0x3c
+
+#define PCIX_CAP_REG 0x40
+#define PCIX_ENABLE_RELAXED_ORDERING BIT_17
+
+/******************************************************************************/
+/* Fragment structure. */
+/******************************************************************************/
+
+typedef struct {
+ LM_UINT32 FragSize;
+ LM_PHYSICAL_ADDRESS FragBuf;
+} LM_FRAG, *PLM_FRAG;
+
+typedef struct {
+ /* FragCount is initialized for the caller to the maximum array size, on */
+ /* return FragCount is the number of the actual fragments in the array. */
+ LM_UINT32 FragCount;
+
+ /* Total buffer size. */
+ LM_UINT32 TotalSize;
+
+ /* Fragment array buffer. */
+ LM_FRAG Fragments[1];
+} LM_FRAG_LIST, *PLM_FRAG_LIST;
+
+#define DECLARE_FRAG_LIST_BUFFER_TYPE(_FRAG_LIST_TYPE_NAME, _MAX_FRAG_COUNT) \
+ typedef struct { \
+ LM_FRAG_LIST FragList; \
+ LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1]; \
+ } _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME
+
+
+
+/******************************************************************************/
+/* Status codes. */
+/******************************************************************************/
+
+#define LM_STATUS_SUCCESS 0
+#define LM_STATUS_FAILURE 1
+
+#define LM_STATUS_INTERRUPT_ACTIVE 2
+#define LM_STATUS_INTERRUPT_NOT_ACTIVE 3
+
+#define LM_STATUS_LINK_ACTIVE 4
+#define LM_STATUS_LINK_DOWN 5
+#define LM_STATUS_LINK_SETTING_MISMATCH 6
+
+#define LM_STATUS_TOO_MANY_FRAGMENTS 7
+#define LM_STATUS_TRANSMIT_ABORTED 8
+#define LM_STATUS_TRANSMIT_ERROR 9
+#define LM_STATUS_RECEIVE_ABORTED 10
+#define LM_STATUS_RECEIVE_ERROR 11
+#define LM_STATUS_INVALID_PACKET_SIZE 12
+#define LM_STATUS_OUT_OF_MAP_REGISTERS 13
+#define LM_STATUS_UNKNOWN_ADAPTER 14
+
+typedef LM_UINT LM_STATUS, *PLM_STATUS;
+
+
+
+/******************************************************************************/
+/* Requested media type. */
+/******************************************************************************/
+
+#define LM_REQUESTED_MEDIA_TYPE_AUTO 0
+#define LM_REQUESTED_MEDIA_TYPE_BNC 1
+#define LM_REQUESTED_MEDIA_TYPE_UTP_AUTO 2
+#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS 3
+#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX 4
+#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS 5
+#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX 6
+#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS 7
+#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX 8
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS 9
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX 10
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS 11
+#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX 12
+#define LM_REQUESTED_MEDIA_TYPE_MAC_LOOPBACK 0xfffe
+#define LM_REQUESTED_MEDIA_TYPE_PHY_LOOPBACK 0xffff
+
+typedef LM_UINT32 LM_REQUESTED_MEDIA_TYPE, *PLM_REQUESTED_MEDIA_TYPE;
+
+
+
+/******************************************************************************/
+/* Media type. */
+/******************************************************************************/
+
+#define LM_MEDIA_TYPE_UNKNOWN -1
+#define LM_MEDIA_TYPE_AUTO 0
+#define LM_MEDIA_TYPE_UTP 1
+#define LM_MEDIA_TYPE_BNC 2
+#define LM_MEDIA_TYPE_AUI 3
+#define LM_MEDIA_TYPE_FIBER 4
+
+typedef LM_UINT32 LM_MEDIA_TYPE, *PLM_MEDIA_TYPE;
+
+
+
+/******************************************************************************/
+/* Line speed. */
+/******************************************************************************/
+
+#define LM_LINE_SPEED_UNKNOWN 0
+#define LM_LINE_SPEED_10MBPS 1
+#define LM_LINE_SPEED_100MBPS 2
+#define LM_LINE_SPEED_1000MBPS 3
+
+typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED;
+
+
+
+/******************************************************************************/
+/* Duplex mode. */
+/******************************************************************************/
+
+#define LM_DUPLEX_MODE_UNKNOWN 0
+#define LM_DUPLEX_MODE_HALF 1
+#define LM_DUPLEX_MODE_FULL 2
+
+typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE;
+
+
+
+/******************************************************************************/
+/* Power state. */
+/******************************************************************************/
+
+#define LM_POWER_STATE_D0 0
+#define LM_POWER_STATE_D1 1
+#define LM_POWER_STATE_D2 2
+#define LM_POWER_STATE_D3 3
+
+typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE;
+
+
+
+/******************************************************************************/
+/* Task offloading. */
+/******************************************************************************/
+
+#define LM_TASK_OFFLOAD_NONE 0x0000
+#define LM_TASK_OFFLOAD_TX_IP_CHECKSUM 0x0001
+#define LM_TASK_OFFLOAD_RX_IP_CHECKSUM 0x0002
+#define LM_TASK_OFFLOAD_TX_TCP_CHECKSUM 0x0004
+#define LM_TASK_OFFLOAD_RX_TCP_CHECKSUM 0x0008
+#define LM_TASK_OFFLOAD_TX_UDP_CHECKSUM 0x0010
+#define LM_TASK_OFFLOAD_RX_UDP_CHECKSUM 0x0020
+#define LM_TASK_OFFLOAD_TCP_SEGMENTATION 0x0040
+
+typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD;
+
+
+
+/******************************************************************************/
+/* Flow control. */
+/******************************************************************************/
+
+#define LM_FLOW_CONTROL_NONE 0x00
+#define LM_FLOW_CONTROL_RECEIVE_PAUSE 0x01
+#define LM_FLOW_CONTROL_TRANSMIT_PAUSE 0x02
+#define LM_FLOW_CONTROL_RX_TX_PAUSE (LM_FLOW_CONTROL_RECEIVE_PAUSE | \
+ LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+
+/* This value can be or-ed with RECEIVE_PAUSE and TRANSMIT_PAUSE. If the */
+/* auto-negotiation is disabled and the RECEIVE_PAUSE and TRANSMIT_PAUSE */
+/* bits are set, then flow control is enabled regardless of link partner's */
+/* flow control capability. */
+#define LM_FLOW_CONTROL_AUTO_PAUSE 0x80000000
+
+typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL;
+
+
+
+/******************************************************************************/
+/* Wake up mode. */
+/******************************************************************************/
+
+#define LM_WAKE_UP_MODE_NONE 0
+#define LM_WAKE_UP_MODE_MAGIC_PACKET 1
+#define LM_WAKE_UP_MODE_NWUF 2
+#define LM_WAKE_UP_MODE_LINK_CHANGE 4
+
+typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE;
+
+
+
+/******************************************************************************/
+/* Counters. */
+/******************************************************************************/
+
+#define LM_COUNTER_FRAMES_XMITTED_OK 0
+#define LM_COUNTER_FRAMES_RECEIVED_OK 1
+#define LM_COUNTER_ERRORED_TRANSMIT_COUNT 2
+#define LM_COUNTER_ERRORED_RECEIVE_COUNT 3
+#define LM_COUNTER_RCV_CRC_ERROR 4
+#define LM_COUNTER_ALIGNMENT_ERROR 5
+#define LM_COUNTER_SINGLE_COLLISION_FRAMES 6
+#define LM_COUNTER_MULTIPLE_COLLISION_FRAMES 7
+#define LM_COUNTER_FRAMES_DEFERRED 8
+#define LM_COUNTER_MAX_COLLISIONS 9
+#define LM_COUNTER_RCV_OVERRUN 10
+#define LM_COUNTER_XMIT_UNDERRUN 11
+#define LM_COUNTER_UNICAST_FRAMES_XMIT 12
+#define LM_COUNTER_MULTICAST_FRAMES_XMIT 13
+#define LM_COUNTER_BROADCAST_FRAMES_XMIT 14
+#define LM_COUNTER_UNICAST_FRAMES_RCV 15
+#define LM_COUNTER_MULTICAST_FRAMES_RCV 16
+#define LM_COUNTER_BROADCAST_FRAMES_RCV 17
+
+typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE;
+
+
+
+/******************************************************************************/
+/* Forward definition. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK *PLM_DEVICE_BLOCK;
+typedef struct _LM_PACKET *PLM_PACKET;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+LM_STATUS LM_GetAdapterInfo(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_InitializeAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_ResetAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_DisableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_EnableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS LM_ServiceInterrupts(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask);
+LM_STATUS LM_Halt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_MulticastAdd(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS LM_MulticastDel(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS LM_MulticastClear(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetMacAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress);
+LM_STATUS LM_LoopbackAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pAddress);
+
+LM_UINT32 LM_GetCrcCounter(PLM_DEVICE_BLOCK pDevice);
+
+LM_WAKE_UP_MODE LM_PMCapabilities(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_NwufAdd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize,
+ LM_UINT8 *pByteMask, LM_UINT8 *pPattern);
+LM_STATUS LM_NwufRemove(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize,
+ LM_UINT8 *pByteMask, LM_UINT8 *pPattern);
+LM_STATUS LM_SetPowerState(PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel);
+
+LM_VOID LM_ReadPhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+ PLM_UINT32 pData32);
+LM_VOID LM_WritePhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+ LM_UINT32 Data32);
+
+LM_STATUS LM_ControlLoopBack(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Control);
+LM_STATUS LM_SetupPhy(PLM_DEVICE_BLOCK pDevice);
+int LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration);
+
+
+
+/******************************************************************************/
+/* These are the OS specific functions called by LMAC. */
+/******************************************************************************/
+
+LM_STATUS MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+ LM_UINT16 *pValue16);
+LM_STATUS MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+ LM_UINT16 Value16);
+LM_STATUS MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+ LM_UINT32 *pValue32);
+LM_STATUS MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+ LM_UINT32 Value32);
+LM_STATUS MM_MapMemBase(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_MapIoBase(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+ PLM_VOID *pMemoryBlockVirt);
+LM_STATUS MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+ PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
+ LM_BOOL Cached);
+LM_STATUS MM_GetConfig(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status);
+LM_STATUS MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS LM_MbufWorkAround(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetLinkSpeed(PLM_DEVICE_BLOCK pDevice,
+ LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+
+#if INCLUDE_5703_A0_FIX
+LM_STATUS LM_Load5703DmaWFirmware(PLM_DEVICE_BLOCK pDevice);
+#endif
+
+
+#endif /* LM_H */
+
diff --git a/drivers/bcm570x_mm.h b/drivers/bcm570x_mm.h
new file mode 100644
index 0000000..badd0d2
--- /dev/null
+++ b/drivers/bcm570x_mm.h
@@ -0,0 +1,160 @@
+
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/******************************************************************************/
+
+#ifndef MM_H
+#define MM_H
+
+#define __raw_readl readl
+#define __raw_writel writel
+
+#define BIG_ENDIAN_HOST 1
+#define readl(addr) (*(volatile unsigned int*)(addr))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+
+/* Define memory barrier function here if needed */
+#define wmb()
+#define membar()
+#include <common.h>
+#include <asm/types.h>
+#include "bcm570x_lm.h"
+#include "bcm570x_queue.h"
+#include "tigon3.h"
+#include <pci.h>
+
+#define FALSE 0
+#define TRUE 1
+#define ERROR -1
+
+#if DBG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+extern int MM_Packet_Desc_Size;
+
+#define MM_PACKET_DESC_SIZE MM_Packet_Desc_Size
+
+DECLARE_QUEUE_TYPE(UM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT+1);
+
+#define MAX_MEM 16
+
+/* Synch */
+typedef int mutex_t;
+typedef int spinlock_t;
+
+/* Embedded device control */
+typedef struct _UM_DEVICE_BLOCK {
+ LM_DEVICE_BLOCK lm_dev;
+ pci_dev_t pdev;
+ char *name;
+ void *mem_list[MAX_MEM];
+ dma_addr_t dma_list[MAX_MEM];
+ int mem_size_list[MAX_MEM];
+ int mem_list_num;
+ int mtu;
+ int index;
+ int opened;
+ int delayed_link_ind; /* Delay link status during initial load */
+ int adapter_just_inited; /* the first few seconds after init. */
+ int spurious_int; /* new -- unsupported */
+ int timer_interval;
+ int adaptive_expiry;
+ int crc_counter_expiry; /* new -- unsupported */
+ int poll_tib_expiry; /* new -- unsupported */
+ int tx_full;
+ int tx_queued;
+ int line_speed; /* in Mbps, 0 if link is down */
+ UM_RX_PACKET_Q rx_out_of_buf_q;
+ int rx_out_of_buf;
+ int rx_low_buf_thresh; /* changed to rx_buf_repl_thresh */
+ int rx_buf_repl_panic_thresh;
+ int rx_buf_align; /* new -- unsupported */
+ int do_global_lock;
+ mutex_t global_lock;
+ mutex_t undi_lock;
+ long undi_flags;
+ volatile int interrupt;
+ int tasklet_pending;
+ int tasklet_busy; /* new -- unsupported */
+ int rx_pkt;
+ int tx_pkt;
+#ifdef NICE_SUPPORT /* unsupported, this is a linux ioctl */
+ void (*nice_rx)(void*, void* );
+ void* nice_ctx;
+#endif /* NICE_SUPPORT */
+ int rx_adaptive_coalesce;
+ unsigned int rx_last_cnt;
+ unsigned int tx_last_cnt;
+ unsigned int rx_curr_coalesce_frames;
+ unsigned int rx_curr_coalesce_ticks;
+ unsigned int tx_curr_coalesce_frames; /* new -- unsupported */
+#if TIGON3_DEBUG /* new -- unsupported */
+ uint tx_zc_count;
+ uint tx_chksum_count;
+ uint tx_himem_count;
+ uint rx_good_chksum_count;
+#endif
+ unsigned int rx_bad_chksum_count; /* new -- unsupported */
+ unsigned int rx_misc_errors; /* new -- unsupported */
+} UM_DEVICE_BLOCK, *PUM_DEVICE_BLOCK;
+
+
+/* Physical/PCI DMA address */
+typedef union {
+ dma_addr_t dma_map;
+} dma_map_t;
+
+/* Packet */
+typedef struct
+_UM_PACKET {
+ LM_PACKET lm_packet;
+ void* skbuff; /* Address of packet buffer */
+} UM_PACKET, *PUM_PACKET;
+
+#define MM_ACQUIRE_UNDI_LOCK(_pDevice)
+#define MM_RELEASE_UNDI_LOCK(_pDevice)
+#define MM_ACQUIRE_INT_LOCK(_pDevice)
+#define MM_RELEASE_INT_LOCK(_pDevice)
+#define MM_UINT_PTR(_ptr) ((unsigned long) (_ptr))
+
+/* Macro for setting 64bit address struct */
+#define set_64bit_addr(paddr, low, high) \
+ (paddr)->Low = low; \
+ (paddr)->High = high;
+
+/* Assume that PCI controller's view of host memory is same as host */
+
+#define MEM_TO_PCI_PHYS(addr) (addr)
+
+extern void MM_SetAddr (LM_PHYSICAL_ADDRESS *paddr, dma_addr_t addr);
+extern void MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr);
+extern void MM_MapTxDma (PLM_DEVICE_BLOCK pDevice,
+ struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR *paddr,
+ LM_UINT32 *len, int frag);
+extern void MM_MapRxDma ( PLM_DEVICE_BLOCK pDevice,
+ struct _LM_PACKET *pPacket,
+ T3_64BIT_HOST_ADDR *paddr);
+
+
+/* BSP needs to provide sysUsecDelay and sysSerialPrintString */
+extern void sysSerialPrintString (char *s);
+#define MM_Wait(usec) udelay(usec)
+
+/* Define memory barrier function here if needed */
+#define wmb()
+
+#if 0
+#define cpu_to_le32(val) LONGSWAP(val)
+#endif
+#endif /* MM_H */
diff --git a/drivers/bcm570x_queue.h b/drivers/bcm570x_queue.h
new file mode 100644
index 0000000..bc32ad7
--- /dev/null
+++ b/drivers/bcm570x_queue.h
@@ -0,0 +1,399 @@
+
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/* Queue functions. */
+/* void QQ_InitQueue(PQQ_CONTAINER pQueue) */
+/* char QQ_Full(PQQ_CONTAINER pQueue) */
+/* char QQ_Empty(PQQ_CONTAINER pQueue) */
+/* unsigned int QQ_GetSize(PQQ_CONTAINER pQueue) */
+/* unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue) */
+/* char QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */
+/* char QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */
+/* PQQ_ENTRY QQ_PopHead(PQQ_CONTAINER pQueue) */
+/* PQQ_ENTRY QQ_PopTail(PQQ_CONTAINER pQueue) */
+/* PQQ_ENTRY QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx) */
+/* PQQ_ENTRY QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx) */
+/* */
+/* */
+/* History: */
+/* 02/25/00 Hav Khauv Initial version. */
+/******************************************************************************/
+
+#ifndef BCM_QUEUE_H
+#define BCM_QUEUE_H
+#ifndef EMBEDDED
+#define EMBEDDED 1
+#endif
+
+/******************************************************************************/
+/* Queue definitions. */
+/******************************************************************************/
+
+/* Entry for queueing. */
+typedef void *PQQ_ENTRY;
+
+/* Linux Atomic Ops support */
+typedef struct { int counter; } atomic_t;
+
+
+/*
+ * This combination of `inline' and `extern' has almost the effect of a
+ * macro. The way to use it is to put a function definition in a header
+ * file with these keywords, and put another copy of the definition
+ * (lacking `inline' and `extern') in a library file. The definition in
+ * the header file will cause most calls to the function to be inlined.
+ * If any uses of the function remain, they will refer to the single copy
+ * in the library.
+ */
+extern __inline void
+atomic_set(atomic_t* entry, int val)
+{
+ entry->counter = val;
+}
+extern __inline int
+atomic_read(atomic_t* entry)
+{
+ return entry->counter;
+}
+extern __inline void
+atomic_inc(atomic_t* entry)
+{
+ if(entry)
+ entry->counter++;
+}
+
+extern __inline void
+atomic_dec(atomic_t* entry)
+{
+ if(entry)
+ entry->counter--;
+}
+
+extern __inline void
+atomic_sub(int a, atomic_t* entry)
+{
+ if(entry)
+ entry->counter -= a;
+}
+extern __inline void
+atomic_add(int a, atomic_t* entry)
+{
+ if(entry)
+ entry->counter += a;
+}
+
+
+/* Queue header -- base type. */
+typedef struct {
+ unsigned int Head;
+ unsigned int Tail;
+ unsigned int Size;
+ atomic_t EntryCnt;
+ PQQ_ENTRY Array[1];
+} QQ_CONTAINER, *PQQ_CONTAINER;
+
+
+/* Declare queue type macro. */
+#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE) \
+ \
+ typedef struct { \
+ QQ_CONTAINER Container; \
+ PQQ_ENTRY EntryBuffer[_QUEUE_SIZE]; \
+ } _QUEUE_TYPE, *P##_QUEUE_TYPE
+
+
+
+/******************************************************************************/
+/* Compilation switches. */
+/******************************************************************************/
+
+#if DBG
+#undef QQ_NO_OVERFLOW_CHECK
+#undef QQ_NO_UNDERFLOW_CHECK
+#endif /* DBG */
+
+#ifdef QQ_USE_MACROS
+/* notdone */
+#else
+
+#ifdef QQ_NO_INLINE
+#define __inline
+#endif /* QQ_NO_INLINE */
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline void
+QQ_InitQueue(
+PQQ_CONTAINER pQueue,
+unsigned int QueueSize) {
+ pQueue->Head = 0;
+ pQueue->Tail = 0;
+ pQueue->Size = QueueSize+1;
+ atomic_set(&pQueue->EntryCnt, 0);
+} /* QQ_InitQueue */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline char
+QQ_Full(
+PQQ_CONTAINER pQueue) {
+ unsigned int NewHead;
+
+ NewHead = (pQueue->Head + 1) % pQueue->Size;
+
+ return(NewHead == pQueue->Tail);
+} /* QQ_Full */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline char
+QQ_Empty(
+PQQ_CONTAINER pQueue) {
+ return(pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline unsigned int
+QQ_GetSize(
+PQQ_CONTAINER pQueue) {
+ return pQueue->Size;
+} /* QQ_GetSize */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline unsigned int
+QQ_GetEntryCnt(
+PQQ_CONTAINER pQueue) {
+ return atomic_read(&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/* TRUE entry was added successfully. */
+/* FALSE queue is full. */
+/******************************************************************************/
+extern __inline char
+QQ_PushHead(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+ unsigned int Head;
+
+ Head = (pQueue->Head + 1) % pQueue->Size;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+ if(Head == pQueue->Tail) {
+ return 0;
+ } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+ pQueue->Array[pQueue->Head] = pEntry;
+ wmb();
+ pQueue->Head = Head;
+ atomic_inc(&pQueue->EntryCnt);
+
+ return -1;
+} /* QQ_PushHead */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/* TRUE entry was added successfully. */
+/* FALSE queue is full. */
+/******************************************************************************/
+extern __inline char
+QQ_PushTail(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+ unsigned int Tail;
+
+ Tail = pQueue->Tail;
+ if(Tail == 0) {
+ Tail = pQueue->Size;
+ } /* if */
+ Tail--;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+ if(Tail == pQueue->Head) {
+ return 0;
+ } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+ pQueue->Array[Tail] = pEntry;
+ wmb();
+ pQueue->Tail = Tail;
+ atomic_inc(&pQueue->EntryCnt);
+
+ return -1;
+} /* QQ_PushTail */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_PopHead(
+PQQ_CONTAINER pQueue) {
+ unsigned int Head;
+ PQQ_ENTRY Entry;
+
+ Head = pQueue->Head;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+ if(Head == pQueue->Tail) {
+ return (PQQ_ENTRY) 0;
+ } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+ if(Head == 0) {
+ Head = pQueue->Size;
+ } /* if */
+ Head--;
+
+ Entry = pQueue->Array[Head];
+#ifdef EMBEDDED
+ membar();
+#else
+ mb();
+#endif
+ pQueue->Head = Head;
+ atomic_dec(&pQueue->EntryCnt);
+
+ return Entry;
+} /* QQ_PopHead */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_PopTail(
+PQQ_CONTAINER pQueue) {
+ unsigned int Tail;
+ PQQ_ENTRY Entry;
+
+ Tail = pQueue->Tail;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+ if(Tail == pQueue->Head) {
+ return (PQQ_ENTRY) 0;
+ } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+ Entry = pQueue->Array[Tail];
+#ifdef EMBEDDED
+ membar();
+#else
+ mb();
+#endif
+ pQueue->Tail = (Tail + 1) % pQueue->Size;
+ atomic_dec(&pQueue->EntryCnt);
+
+ return Entry;
+} /* QQ_PopTail */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_GetHead(
+ PQQ_CONTAINER pQueue,
+ unsigned int Idx)
+{
+ if(Idx >= atomic_read(&pQueue->EntryCnt))
+ {
+ return (PQQ_ENTRY) 0;
+ }
+
+ if(pQueue->Head > Idx)
+ {
+ Idx = pQueue->Head - Idx;
+ }
+ else
+ {
+ Idx = pQueue->Size - (Idx - pQueue->Head);
+ }
+ Idx--;
+
+ return pQueue->Array[Idx];
+}
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+extern __inline PQQ_ENTRY
+QQ_GetTail(
+ PQQ_CONTAINER pQueue,
+ unsigned int Idx)
+{
+ if(Idx >= atomic_read(&pQueue->EntryCnt))
+ {
+ return (PQQ_ENTRY) 0;
+ }
+
+ Idx += pQueue->Tail;
+ if(Idx >= pQueue->Size)
+ {
+ Idx = Idx - pQueue->Size;
+ }
+
+ return pQueue->Array[Idx];
+}
+
+#endif /* QQ_USE_MACROS */
+
+
+
+#endif /* QUEUE_H */
diff --git a/drivers/cfb_console.c b/drivers/cfb_console.c
new file mode 100644
index 0000000..ee2fa9c
--- /dev/null
+++ b/drivers/cfb_console.c
@@ -0,0 +1,912 @@
+/*
+ * (C) Copyright 2002 ELTEC Elektronik AG
+ * Frank Gottschling <fgottschling@eltec.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cfb_console.c
+ *
+ * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel.
+ *
+ * At the moment only the 8x16 font is tested and the font fore- and
+ * background color is limited to black/white/gray colors. The Linux
+ * logo can be placed in the upper left corner and additional board
+ * information strings (that normaly goes to serial port) can be drawed.
+ *
+ * The console driver can use the standard PC keyboard interface (i8042)
+ * for character input. Character output goes to a memory mapped video
+ * framebuffer with little or big-endian organisation.
+ * With environment setting 'console=serial' the console i/o can be
+ * forced to serial port.
+
+ The driver uses graphic specific defines/parameters/functions:
+
+ (for SMI LynxE graphic chip)
+
+ CONFIG_VIDEO_SMI_LYNXEM - use graphic driver for SMI 710,712,810
+ VIDEO_FB_LITTLE_ENDIAN - framebuffer organisation default: big endian
+ VIDEO_HW_RECTFILL - graphic driver supports hardware rectangle fill
+ VIDEO_HW_BITBLT - graphic driver supports hardware bit blt
+
+ Console Parameters are set by graphic drivers global struct:
+
+ VIDEO_VISIBLE_COLS - x resolution
+ VIDEO_VISIBLE_ROWS - y resolution
+ VIDEO_PIXEL_SIZE - storage size in byte per pixel
+ VIDEO_DATA_FORMAT - graphical data format GDF
+ VIDEO_FB_ADRS - start of video memory
+
+ CONFIG_I8042_KBD - AT Keyboard driver for i8042
+ VIDEO_KBD_INIT_FCT - init function for keyboard
+ VIDEO_TSTC_FCT - keyboard_tstc function
+ VIDEO_GETC_FCT - keyboard_getc function
+
+ CONFIG_CONSOLE_CURSOR - on/off drawing cursor is done with delay
+ loop in VIDEO_TSTC_FCT (i8042)
+ CFG_CONSOLE_BLINK_COUNT - value for delay loop - blink rate
+ CONFIG_CONSOLE_TIME - display time/date in upper right corner,
+ needs CFG_CMD_DATE and CONFIG_CONSOLE_CURSOR
+ CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner
+ CONFIG_CONSOLE_EXTRA_INFO - display additional board information strings
+ that normaly goes to serial port. This define
+ requires a board specific function:
+ video_drawstring (VIDEO_INFO_X,
+ VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
+ info);
+ that fills a info buffer at i=row.
+ s.a: board/eltec/bab7xx.
+CONFIG_VGA_AS_SINGLE_DEVICE - If set the framebuffer device will be initialised
+ as an output only device. The Keyboard driver
+ will not be set-up. This may be used, if you
+ have none or more than one Keyboard devices
+ (USB Keyboard, AT Keyboard).
+
+CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last character. No
+ blinking is provided. Uses the macros CURSOR_SET
+ and CURSOR_OFF.
+CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability of the
+ graphic chip. Uses the macro CURSOR_SET.
+ ATTENTION: If booting an OS, the display driver
+ must disable the hardware register of the graphic
+ chip. Otherwise a blinking field is displayed
+*/
+
+#include <common.h>
+
+#ifdef CONFIG_CFB_CONSOLE
+
+/*****************************************************************************/
+/* Console device defines with SMI graphic */
+/* Any other graphic must change this section */
+/*****************************************************************************/
+
+#ifdef CONFIG_VIDEO_SMI_LYNXEM
+
+#define VIDEO_FB_LITTLE_ENDIAN
+#define VIDEO_HW_RECTFILL
+#define VIDEO_HW_BITBLT
+#endif
+
+/*****************************************************************************/
+/* Defines for the CT69000 driver */
+/*****************************************************************************/
+#ifdef CONFIG_VIDEO_CT69000
+
+#define VIDEO_FB_LITTLE_ENDIAN
+#define VIDEO_HW_RECTFILL
+#define VIDEO_HW_BITBLT
+#endif
+
+/*****************************************************************************/
+/* Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc */
+/*****************************************************************************/
+#include <video_fb.h>
+
+/*****************************************************************************/
+/* some Macros */
+/*****************************************************************************/
+#define VIDEO_VISIBLE_COLS (pGD->winSizeX)
+#define VIDEO_VISIBLE_ROWS (pGD->winSizeY)
+#define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP)
+#define VIDEO_DATA_FORMAT (pGD->gdfIndex)
+#define VIDEO_FB_ADRS (pGD->frameAdrs)
+
+/*****************************************************************************/
+/* Console device defines with i8042 keyboard controller */
+/* Any other keyboard controller must change this section */
+/*****************************************************************************/
+
+#ifdef CONFIG_I8042_KBD
+#include <i8042.h>
+
+#define VIDEO_KBD_INIT_FCT i8042_kbd_init()
+#define VIDEO_TSTC_FCT i8042_tstc
+#define VIDEO_GETC_FCT i8042_getc
+#endif
+
+/*****************************************************************************/
+/* Console device */
+/*****************************************************************************/
+
+#include <version.h>
+#include <linux/types.h>
+#include <devices.h>
+#include <video_font.h>
+#ifdef CFG_CMD_DATE
+#include <rtc.h>
+
+#endif
+
+/*****************************************************************************/
+/* Cursor definition: */
+/* CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/i8042.c) to */
+/* let the cursor blink. Uses the macros CURSOR_OFF */
+/* and CURSOR_ON. */
+/* CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No */
+/* blinking is provided. Uses the macros CURSOR_SET */
+/* and CURSOR_OFF. */
+/* CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the */
+/* graphic chip. Uses the macro CURSOR_SET. */
+/* ATTENTION: If booting an OS, the display driver */
+/* must disable the hardware register of the graphic */
+/* chip. Otherwise a blinking field is displayed */
+/*****************************************************************************/
+#if !defined(CONFIG_CONSOLE_CURSOR) && \
+ !defined(CONFIG_VIDEO_SW_CURSOR) && \
+ !defined(CONFIG_VIDEO_HW_CURSOR)
+/* no Cursor defined */
+#define CURSOR_ON
+#define CURSOR_OFF
+#define CURSOR_SET
+#endif
+
+#ifdef CONFIG_CONSOLE_CURSOR
+#ifdef CURSOR_ON
+#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+void console_cursor (int state);
+#define CURSOR_ON console_cursor(1);
+#define CURSOR_OFF console_cursor(0);
+#define CURSOR_SET
+#ifndef CONFIG_I8042_KBD
+#warning Cursor drawing on/off needs timer function s.a. drivers/i8042.c
+#endif
+#else
+#ifdef CONFIG_CONSOLE_TIME
+#error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
+#endif
+#endif /* CONFIG_CONSOLE_CURSOR */
+
+#ifdef CONFIG_VIDEO_SW_CURSOR
+#ifdef CURSOR_ON
+#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+#define CURSOR_ON
+#define CURSOR_OFF video_putchar(console_col * VIDEO_FONT_WIDTH,\
+ console_row * VIDEO_FONT_HEIGHT, ' ');
+#define CURSOR_SET video_set_cursor();
+#endif /* CONFIG_VIDEO_SW_CURSOR */
+
+
+#ifdef CONFIG_VIDEO_HW_CURSOR
+#ifdef CURSOR_ON
+#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+#define CURSOR_ON
+#define CURSOR_OFF
+#define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \
+ (console_row * VIDEO_FONT_HEIGHT) + VIDEO_LOGO_HEIGHT);
+#endif /* CONFIG_VIDEO_HW_CURSOR */
+
+#ifdef CONFIG_VIDEO_LOGO
+#define LINUX_LOGO_WIDTH 80
+#define LINUX_LOGO_HEIGHT 80
+#define LINUX_LOGO_COLORS 214
+#define LINUX_LOGO_LUT_OFFSET 0x20
+#define __initdata
+#include <linux_logo.h>
+#define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH
+#define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT
+
+#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
+#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
+#else
+#define VIDEO_LOGO_WIDTH 0
+#define VIDEO_LOGO_HEIGHT 0
+#endif
+
+#define VIDEO_COLS VIDEO_VISIBLE_COLS
+#define VIDEO_ROWS VIDEO_VISIBLE_ROWS
+#define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
+#define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2)
+#define VIDEO_LINE_LEN (VIDEO_COLS*VIDEO_PIXEL_SIZE)
+#define VIDEO_BURST_LEN (VIDEO_COLS/8)
+
+#ifdef CONFIG_VIDEO_LOGO
+#define CONSOLE_ROWS ((VIDEO_ROWS - VIDEO_LOGO_HEIGHT) / VIDEO_FONT_HEIGHT)
+#else
+#define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
+#endif
+
+#define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
+#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
+#define CONSOLE_ROW_FIRST (video_console_address)
+#define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
+#define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
+#define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+
+/* Macros */
+#ifdef VIDEO_FB_LITTLE_ENDIAN
+#define SWAP16(x) ((((x) & 0x00ff) << 8) | ( (x) >> 8))
+#define SWAP32(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\
+ (((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) )
+#define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | (((x) & 0x0000ff00) >> 8)|\
+ (((x) & 0x00ff0000) << 8) | (((x) & 0xff000000) >> 8) )
+#else
+#define SWAP16(x) (x)
+#define SWAP32(x) (x)
+#define SHORTSWAP32(x) (x)
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_CFB_CONSOLE)
+#define PRINTD(x) printf(x)
+#else
+#define PRINTD(x)
+#endif
+
+
+#ifdef CONFIG_CONSOLE_EXTRA_INFO
+extern void video_get_info_str ( /* setup a board string: type, speed, etc. */
+ int line_number, /* location to place info string beside logo */
+ char *info /* buffer for info string */
+ );
+
+#endif
+
+/* Locals */
+static GraphicDevice *pGD; /* Pointer to Graphic array */
+
+static void *video_fb_address; /* frame buffer address */
+static void *video_console_address; /* console buffer start address */
+
+static int console_col = 0; /* cursor col */
+static int console_row = 0; /* cursor row */
+
+static u32 eorx, fgx, bgx; /* color pats */
+
+static const int video_font_draw_table8[] = {
+ 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
+ 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
+ 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
+ 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff };
+
+static const int video_font_draw_table15[] = {
+ 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff };
+
+static const int video_font_draw_table16[] = {
+ 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff };
+
+static const int video_font_draw_table24[16][3] = {
+ { 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00ffffff },
+ { 0x00000000, 0x0000ffff, 0xff000000 },
+ { 0x00000000, 0x0000ffff, 0xffffffff },
+ { 0x000000ff, 0xffff0000, 0x00000000 },
+ { 0x000000ff, 0xffff0000, 0x00ffffff },
+ { 0x000000ff, 0xffffffff, 0xff000000 },
+ { 0x000000ff, 0xffffffff, 0xffffffff },
+ { 0xffffff00, 0x00000000, 0x00000000 },
+ { 0xffffff00, 0x00000000, 0x00ffffff },
+ { 0xffffff00, 0x0000ffff, 0xff000000 },
+ { 0xffffff00, 0x0000ffff, 0xffffffff },
+ { 0xffffffff, 0xffff0000, 0x00000000 },
+ { 0xffffffff, 0xffff0000, 0x00ffffff },
+ { 0xffffffff, 0xffffffff, 0xff000000 },
+ { 0xffffffff, 0xffffffff, 0xffffffff } };
+
+static const int video_font_draw_table32[16][4] = {
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff },
+ { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff },
+ { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff },
+ { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 },
+ { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff },
+ { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff },
+ { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 },
+ { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff },
+ { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 },
+ { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff },
+ { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 },
+ { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } };
+
+
+/******************************************************************************/
+
+
+static void video_drawchars (int xx, int yy, unsigned char *s, int count)
+{
+ u8 *cdat, *dest, *dest0;
+ int rows, offset, c;
+
+ offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
+ dest0 = video_fb_address + offset;
+
+ switch (VIDEO_DATA_FORMAT)
+ {
+ case GDF__8BIT_INDEX:
+ case GDF__8BIT_332RGB:
+ while (count--)
+ {
+ c = *s ;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+ {
+ u8 bits = *cdat++;
+ ((u32 *)dest)[0] = (video_font_draw_table8[bits >> 4] & eorx) ^ bgx;
+ ((u32 *)dest)[1] = (video_font_draw_table8[bits & 15] & eorx) ^ bgx;
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++;
+ }
+ break;
+
+ case GDF_15BIT_555RGB:
+ while (count--)
+ {
+ c = *s ;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+ {
+ u8 bits = *cdat++;
+ ((u32 *)dest)[0] = SHORTSWAP32((video_font_draw_table15[bits >> 6] & eorx) ^ bgx);
+ ((u32 *)dest)[1] = SHORTSWAP32((video_font_draw_table15[bits >> 4 & 3] & eorx) ^ bgx);
+ ((u32 *)dest)[2] = SHORTSWAP32((video_font_draw_table15[bits >> 2 & 3] & eorx) ^ bgx);
+ ((u32 *)dest)[3] = SHORTSWAP32((video_font_draw_table15[bits & 3] & eorx) ^ bgx);
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++ ;
+ }
+ break;
+
+ case GDF_16BIT_565RGB:
+ while (count--)
+ {
+ c = *s ;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+ {
+ u8 bits = *cdat++;
+ ((u32 *)dest)[0] = SHORTSWAP32((video_font_draw_table16[bits >> 6] & eorx) ^ bgx);
+ ((u32 *)dest)[1] = SHORTSWAP32((video_font_draw_table16[bits >> 4 & 3] & eorx) ^ bgx);
+ ((u32 *)dest)[2] = SHORTSWAP32((video_font_draw_table16[bits >> 2 & 3] & eorx) ^ bgx);
+ ((u32 *)dest)[3] = SHORTSWAP32((video_font_draw_table16[bits & 3] & eorx) ^ bgx);
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++ ;
+ }
+ break;
+
+ case GDF_32BIT_X888RGB:
+ while (count--)
+ {
+ c = *s ;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+ {
+ u8 bits = *cdat++;
+ ((u32 *)dest)[0] = SWAP32((video_font_draw_table32[bits >> 4][0] & eorx) ^ bgx);
+ ((u32 *)dest)[1] = SWAP32((video_font_draw_table32[bits >> 4][1] & eorx) ^ bgx);
+ ((u32 *)dest)[2] = SWAP32((video_font_draw_table32[bits >> 4][2] & eorx) ^ bgx);
+ ((u32 *)dest)[3] = SWAP32((video_font_draw_table32[bits >> 4][3] & eorx) ^ bgx);
+ ((u32 *)dest)[4] = SWAP32((video_font_draw_table32[bits & 15][0] & eorx) ^ bgx);
+ ((u32 *)dest)[5] = SWAP32((video_font_draw_table32[bits & 15][1] & eorx) ^ bgx);
+ ((u32 *)dest)[6] = SWAP32((video_font_draw_table32[bits & 15][2] & eorx) ^ bgx);
+ ((u32 *)dest)[7] = SWAP32((video_font_draw_table32[bits & 15][3] & eorx) ^ bgx);
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++ ;
+ }
+ break;
+
+ case GDF_24BIT_888RGB:
+ while (count--)
+ {
+ c = *s ;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN)
+ {
+ u8 bits = *cdat++;
+ ((u32 *)dest)[0] = (video_font_draw_table24[bits >> 4][0] & eorx) ^ bgx;
+ ((u32 *)dest)[1] = (video_font_draw_table24[bits >> 4][1] & eorx) ^ bgx;
+ ((u32 *)dest)[2] = (video_font_draw_table24[bits >> 4][2] & eorx) ^ bgx;
+ ((u32 *)dest)[3] = (video_font_draw_table24[bits & 15][0] & eorx) ^ bgx;
+ ((u32 *)dest)[4] = (video_font_draw_table24[bits & 15][1] & eorx) ^ bgx;
+ ((u32 *)dest)[5] = (video_font_draw_table24[bits & 15][2] & eorx) ^ bgx;
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++ ;
+ }
+ break;
+ }
+}
+
+/*****************************************************************************/
+
+static inline void video_drawstring(int xx, int yy, unsigned char *s)
+{
+ video_drawchars (xx, yy, s, strlen(s));
+}
+
+/*****************************************************************************/
+
+static void video_putchar(int xx, int yy, unsigned char c)
+{
+#ifdef CONFIG_VIDEO_LOGO
+ video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, &c, 1);
+#else
+ video_drawchars (xx, yy, &c, 1);
+#endif
+}
+
+/*****************************************************************************/
+#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
+static void video_set_cursor(void)
+{
+ /* swap drawing colors */
+ eorx = fgx;
+ fgx = bgx;
+ bgx = eorx;
+ eorx = fgx ^ bgx;
+ /* draw cursor */
+ video_putchar (console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT, ' ');
+ /* restore drawing colors */
+ eorx = fgx;
+ fgx = bgx;
+ bgx = eorx;
+ eorx = fgx ^ bgx;
+}
+#endif
+/*****************************************************************************/
+#ifdef CONFIG_CONSOLE_CURSOR
+void console_cursor (int state)
+{
+ static int last_state = 0;
+#ifdef CONFIG_CONSOLE_TIME
+ struct rtc_time tm;
+ char info[16];
+
+ /* time update only if cursor is on (faster scroll) */
+ if (state)
+ {
+ rtc_get (&tm);
+
+ sprintf(info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec);
+ video_drawstring(VIDEO_VISIBLE_COLS-10*VIDEO_FONT_WIDTH,
+ VIDEO_INFO_Y, info);
+
+ sprintf(info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon, tm.tm_year);
+ video_drawstring(VIDEO_VISIBLE_COLS-10*VIDEO_FONT_WIDTH,
+ VIDEO_INFO_Y+1*VIDEO_FONT_HEIGHT, info);
+ }
+#endif
+
+ if (state && (last_state != state))
+ {
+ video_set_cursor();
+ }
+
+ if (!state && (last_state != state))
+ {
+ /* clear cursor */
+ video_putchar (console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT, ' ');
+ }
+
+ last_state = state;
+}
+#endif
+
+/*****************************************************************************/
+
+#ifndef VIDEO_HW_RECTFILL
+static void memsetl (int *p, int c, int v)
+{
+ while (c--)
+ *(p++) = v;
+}
+#endif
+
+/*****************************************************************************/
+
+#ifndef VIDEO_HW_BITBLT
+static void memcpyl (int *d, int *s, int c)
+{
+ while (c--)
+ *(d++) = *(s++);
+}
+#endif
+
+/*****************************************************************************/
+
+static void console_scrollup (void)
+{
+ /* copy up rows ignoring the first one */
+
+#ifdef VIDEO_HW_BITBLT
+ video_hw_bitblt (
+ VIDEO_PIXEL_SIZE, /* bytes per pixel */
+ 0, /* source pos x */
+ VIDEO_LOGO_HEIGHT + VIDEO_FONT_HEIGHT, /* source pos y */
+ 0, /* dest pos x */
+ VIDEO_LOGO_HEIGHT, /* dest pos y */
+ VIDEO_VISIBLE_COLS, /* frame width */
+ VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT /* frame height */
+ );
+#else
+ memcpyl (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE >> 2);
+#endif
+
+ /* clear the last one */
+#ifdef VIDEO_HW_RECTFILL
+ video_hw_rectfill (
+ VIDEO_PIXEL_SIZE, /* bytes per pixel */
+ 0, /* dest pos x */
+ VIDEO_VISIBLE_ROWS - VIDEO_FONT_HEIGHT, /* dest pos y */
+ VIDEO_VISIBLE_COLS, /* frame width */
+ VIDEO_FONT_HEIGHT, /* frame height */
+ CONSOLE_BG_COL /* fill color */
+ );
+#else
+ memsetl (CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, CONSOLE_BG_COL);
+#endif
+}
+
+/*****************************************************************************/
+
+static void console_back (void)
+{
+ CURSOR_OFF
+ console_col--;
+
+ if (console_col < 0)
+ {
+ console_col = CONSOLE_COLS - 1;
+ console_row--;
+ if (console_row < 0)
+ console_row = 0;
+ }
+ video_putchar (console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT, ' ');
+}
+
+/*****************************************************************************/
+
+static void console_newline (void)
+{
+ CURSOR_OFF
+ console_row++;
+ console_col = 0;
+
+ /* Check if we need to scroll the terminal */
+ if (console_row >= CONSOLE_ROWS)
+ {
+ /* Scroll everything up */
+ console_scrollup ();
+
+ /* Decrement row number */
+ console_row--;
+ }
+}
+
+/*****************************************************************************/
+
+void video_putc (const char c)
+{
+ switch (c)
+ {
+ case 13: /* ignore */
+ break;
+
+ case '\n': /* next line */
+ console_newline();
+ break;
+
+ case 9: /* tab 8 */
+ CURSOR_OFF
+ console_col |= 0x0008;
+ console_col &= ~0x0007;
+
+ if (console_col >= CONSOLE_COLS)
+ console_newline();
+ break;
+
+ case 8: /* backspace */
+ console_back();
+ break;
+
+ default: /* draw the char */
+ video_putchar (console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT, c);
+ console_col++ ;
+
+ /* check for newline */
+ if (console_col >= CONSOLE_COLS)
+ console_newline();
+ }
+ CURSOR_SET
+}
+
+
+
+/*****************************************************************************/
+
+void video_puts (const char *s)
+{
+ int count = strlen(s);
+
+ while(count--)
+ video_putc(*s++);
+}
+
+/*****************************************************************************/
+
+#ifdef CONFIG_VIDEO_LOGO
+void logo_plot (void *screen, int width, int x, int y)
+{
+ int skip = (width - LINUX_LOGO_WIDTH) * VIDEO_PIXEL_SIZE,
+ xcount, i,
+ ycount = LINUX_LOGO_HEIGHT;
+ unsigned char
+ *source = linux_logo,
+ *dest = (unsigned char *) screen + ((y * width * VIDEO_PIXEL_SIZE) + x),
+ r, g, b;
+
+ if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX)
+ {
+ for (i = 0; i < LINUX_LOGO_COLORS; i++)
+ {
+ r = (unsigned char)linux_logo_red [i];
+ g = (unsigned char)linux_logo_green[i];
+ b = (unsigned char)linux_logo_blue [i];
+ video_set_lut (LINUX_LOGO_LUT_OFFSET + i, r, g, b);
+ }
+ }
+
+ while (ycount--)
+ {
+ xcount = LINUX_LOGO_WIDTH;
+ while (xcount--)
+ {
+ r = (unsigned char)linux_logo_red [*source - LINUX_LOGO_LUT_OFFSET];
+ g = (unsigned char)linux_logo_green[*source - LINUX_LOGO_LUT_OFFSET];
+ b = (unsigned char)linux_logo_blue [*source - LINUX_LOGO_LUT_OFFSET];
+
+ switch (VIDEO_DATA_FORMAT)
+ {
+ case GDF__8BIT_INDEX:
+ *dest = *source;
+ break;
+ case GDF__8BIT_332RGB:
+ *dest = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6);
+ break;
+ case GDF_15BIT_555RGB:
+ *(unsigned short *)dest =
+ SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3)));
+ break;
+ case GDF_16BIT_565RGB:
+ *(unsigned short *)dest =
+ SWAP16((unsigned short)(((r>>3)<<11) | ((g>>2)<<5) | (b>>3)));
+ break;
+ case GDF_32BIT_X888RGB:
+ *(unsigned long *)dest =
+ SWAP32((unsigned long)((r<<16) | (g<<8) | b));
+ break;
+ case GDF_24BIT_888RGB:
+#ifdef VIDEO_FB_LITTLE_ENDIAN
+ dest[0] = b;
+ dest[1] = g;
+ dest[2] = r;
+#else
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+#endif
+ break;
+ }
+ source++;
+ dest += VIDEO_PIXEL_SIZE;
+ }
+ dest += skip;
+ }
+}
+
+
+/*****************************************************************************/
+
+static void *video_logo (void)
+{
+ char info[128];
+
+ logo_plot (video_fb_address, VIDEO_COLS, 0, 0);
+
+ sprintf(info, " %s (%s - %s)", U_BOOT_VERSION, __DATE__, __TIME__);
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, info);
+
+#ifdef CONFIG_CONSOLE_EXTRA_INFO
+ {
+ int i, n = ((VIDEO_LOGO_HEIGHT-VIDEO_FONT_HEIGHT)/VIDEO_FONT_HEIGHT);
+
+ for (i = 1; i < n; i++)
+ {
+ video_get_info_str (i, info);
+ if (*info)
+ video_drawstring (VIDEO_INFO_X,
+ VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT, info);
+ }
+ }
+#endif
+
+ return (video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN);
+}
+#endif
+
+
+/*****************************************************************************/
+
+static int video_init(void)
+{
+ unsigned char color8;
+
+ if ((pGD=video_hw_init()) == NULL)
+ return -1;
+
+ video_fb_address = (void*)VIDEO_FB_ADRS;
+#ifdef CONFIG_VIDEO_HW_CURSOR
+ video_init_hw_cursor(VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
+#endif
+
+ /* Init drawing pats */
+ switch (VIDEO_DATA_FORMAT)
+ {
+ case GDF__8BIT_INDEX:
+ video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
+ video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL);
+ fgx = 0x01010101;
+ bgx = 0x00000000;
+ break;
+ case GDF__8BIT_332RGB:
+ color8 = ((CONSOLE_FG_COL & 0xe0) | ((CONSOLE_FG_COL>>3) & 0x1c) | CONSOLE_FG_COL>>6);
+ fgx = (color8<<24) | (color8<<16) | (color8<<8) | color8;
+ color8 = ((CONSOLE_BG_COL & 0xe0) | ((CONSOLE_BG_COL>>3) & 0x1c) | CONSOLE_BG_COL>>6);
+ bgx = (color8<<24) | (color8<<16) | (color8<<8) | color8;
+ break;
+ case GDF_15BIT_555RGB:
+ fgx = (((CONSOLE_FG_COL>>3)<<26) | ((CONSOLE_FG_COL>>3)<<21) | ((CONSOLE_FG_COL>>3)<<16) |
+ ((CONSOLE_FG_COL>>3)<<10) | ((CONSOLE_FG_COL>>3)<<5) | (CONSOLE_FG_COL>>3));
+ bgx = (((CONSOLE_BG_COL>>3)<<26) | ((CONSOLE_BG_COL>>3)<<21) | ((CONSOLE_BG_COL>>3)<<16) |
+ ((CONSOLE_BG_COL>>3)<<10) | ((CONSOLE_BG_COL>>3)<<5) | (CONSOLE_BG_COL>>3));
+ break;
+ case GDF_16BIT_565RGB:
+ fgx = (((CONSOLE_FG_COL>>3)<<27) | ((CONSOLE_FG_COL>>2)<<21) | ((CONSOLE_FG_COL>>3)<<16) |
+ ((CONSOLE_FG_COL>>3)<<11) | ((CONSOLE_FG_COL>>2)<<5) | (CONSOLE_FG_COL>>3));
+ bgx = (((CONSOLE_BG_COL>>3)<<27) | ((CONSOLE_BG_COL>>2)<<21) | ((CONSOLE_BG_COL>>3)<<16) |
+ ((CONSOLE_BG_COL>>3)<<11) | ((CONSOLE_BG_COL>>2)<<5) | (CONSOLE_BG_COL>>3));
+ break;
+ case GDF_32BIT_X888RGB:
+ fgx = (CONSOLE_FG_COL<<16) | (CONSOLE_FG_COL<<8) | CONSOLE_FG_COL;
+ bgx = (CONSOLE_BG_COL<<16) | (CONSOLE_BG_COL<<8) | CONSOLE_BG_COL;
+ break;
+ case GDF_24BIT_888RGB:
+ fgx = (CONSOLE_FG_COL<<24) | (CONSOLE_FG_COL<<16) | (CONSOLE_FG_COL<<8) | CONSOLE_FG_COL;
+ bgx = (CONSOLE_BG_COL<<24) | (CONSOLE_BG_COL<<16) | (CONSOLE_BG_COL<<8) | CONSOLE_BG_COL;
+ break;
+ }
+ eorx = fgx ^ bgx;
+
+#ifdef CONFIG_VIDEO_LOGO
+ /* Plot the logo and get start point of console */
+ PRINTD("Video: Drawing the logo ...\n");
+ video_console_address = video_logo();
+#else
+ video_console_address = video_fb_address;
+#endif
+
+ /* Initialize the console */
+ console_col = 0;
+ console_row = 0;
+
+ return 0 ;
+}
+
+
+/*****************************************************************************/
+
+int drv_video_init (void)
+{
+ int skip_dev_init;
+ device_t console_dev;
+ char *penv;
+
+ skip_dev_init = 0;
+
+ /* Force console i/o to serial ? */
+ if ((penv = getenv ("console")) != NULL)
+ if (strcmp (penv, "serial") == 0)
+ return 0;
+
+ /* Init video chip - returns with framebuffer cleared */
+ if (video_init() == -1)
+ skip_dev_init = 1;
+#ifdef CONFIG_VGA_AS_SINGLE_DEVICE
+ /* Devices VGA and Keyboard will be assigned seperately */
+ /* Init vga device */
+ if (!skip_dev_init)
+ {
+ memset (&console_dev, 0, sizeof(console_dev));
+ strcpy(console_dev.name, "vga");
+ console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */
+ console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+ console_dev.putc = video_putc; /* 'putc' function */
+ console_dev.puts = video_puts; /* 'puts' function */
+ console_dev.tstc = NULL; /* 'tstc' function */
+ console_dev.getc = NULL; /* 'getc' function */
+
+ if (device_register (&console_dev) == 0)
+ return 1;
+ }
+#else
+ PRINTD("KBD: Keyboard init ...\n");
+ if (VIDEO_KBD_INIT_FCT == -1)
+ skip_dev_init = 1;
+
+ /* Init console device */
+ if (!skip_dev_init)
+ {
+ memset (&console_dev, 0, sizeof(console_dev));
+ strcpy(console_dev.name, "console");
+ console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */
+ console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+ console_dev.putc = video_putc; /* 'putc' function */
+ console_dev.puts = video_puts; /* 'puts' function */
+ console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */
+ console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */
+
+ if (device_register (&console_dev) == 0)
+ return 1;
+ }
+#endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
+ /* No console dev available */
+ return 0;
+}
+
+#endif /* CONFIG_CFB_CONSOLE */
+
+
+
+
+
+
+
diff --git a/drivers/cs8900.c b/drivers/cs8900.c
new file mode 100644
index 0000000..ecc7c13
--- /dev/null
+++ b/drivers/cs8900.c
@@ -0,0 +1,235 @@
+/*
+ * Cirrus Logic CS8900A Ethernet
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Copyright (C) 1999 Ben Williamson <benw@pobox.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is loaded into SRAM in bootstrap mode, where it waits
+ * for commands on UART1 to read and write memory, jump to code etc.
+ * A design goal for this program is to be entirely independent of the
+ * target board. Anything with a CL-PS7111 or EP7211 should be able to run
+ * this code in bootstrap mode. All the board specifics can be handled on
+ * the host.
+ *
+ * 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 of the License, 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <common.h>
+#include <command.h>
+#include "cs8900.h"
+#include <net.h>
+
+#ifdef CONFIG_DRIVER_CS8900
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+
+
+/* packet page register access functions */
+
+#ifdef CS8900_BUS32
+/* we don't need 16 bit initialisation on 32 bit bus */
+#define get_reg_init_bus(x) get_reg((x))
+#else
+static unsigned short get_reg_init_bus(int regno)
+{
+ /* force 16 bit busmode */
+ volatile unsigned char c;
+ c = CS8900_BUS16_0;
+ c = CS8900_BUS16_1;
+ c = CS8900_BUS16_0;
+ c = CS8900_BUS16_1;
+ c = CS8900_BUS16_0;
+
+ CS8900_PPTR = regno;
+ return (unsigned short) CS8900_PDATA;
+}
+#endif
+
+static unsigned short
+get_reg(int regno)
+{
+ CS8900_PPTR = regno;
+ return (unsigned short) CS8900_PDATA;
+}
+
+
+static void put_reg(int regno, unsigned short val)
+{
+ CS8900_PPTR = regno;
+ CS8900_PDATA = val;
+}
+
+static void eth_reset(void)
+{
+ int tmo;
+ unsigned short us;
+
+ /* reset NIC */
+ put_reg(PP_SelfCTL, get_reg(PP_SelfCTL) | PP_SelfCTL_Reset );
+
+ /* wait for 200ms */
+ udelay(200000);
+ /* Wait until the chip is reset */
+
+ tmo = get_timer(0) + 1 * CFG_HZ;
+ while ((((us = get_reg_init_bus(PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0)
+ && tmo < get_timer(0))
+ /*NOP*/;
+}
+
+void cs8900_get_enetaddr (uchar *addr)
+{
+ int i;
+ /* verify chip id */
+ if (get_reg_init_bus(PP_ChipID) != 0x630e)
+ return;
+ eth_reset();
+ if ((get_reg(PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) ==
+ (PP_SelfSTAT_EEPROM|PP_SelfSTAT_EEPROM_OK)) {
+ /* Load the MAC from EEPROM */
+ for (i=0; i<6/2; i++) {
+ unsigned int Addr;
+ Addr = get_reg(PP_IA+i*2);
+ addr[i*2] = Addr & 0xFF;
+ addr[i*2+1] = Addr >> 8;
+ }
+ }
+}
+
+void eth_halt( void )
+{
+ /* disable transmitter/receiver mode */
+ put_reg(PP_LineCTL, 0);
+
+ /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */
+ get_reg_init_bus(PP_ChipID);
+}
+
+int eth_init( bd_t *bd )
+{
+
+ /* verify chip id */
+ if (get_reg_init_bus(PP_ChipID) != 0x630e)
+ {
+ printf( "CS8900 Ethernet chip not found?!\n" );
+ return 0;
+ }
+
+ eth_reset();
+ /* set the ethernet address */
+ put_reg(PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8));
+ put_reg(PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8));
+ put_reg(PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8));
+
+ /* receive only error free packets addressed to this card */
+ put_reg(PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK);
+
+ /* do not generate any interrupts on receive operations */
+ put_reg(PP_RxCFG, 0);
+
+ /* do not generate any interrupts on transmit operations */
+ put_reg(PP_TxCFG, 0);
+
+ /* do not generate any interrupts on buffer operations */
+ put_reg(PP_BufCFG, 0);
+
+ /* enable transmitter/receiver mode */
+ put_reg(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
+
+ return 0;
+}
+
+/* Get a data block via Ethernet */
+extern int eth_rx(void)
+{
+ int i;
+ unsigned short rxlen;
+ unsigned short *addr;
+ unsigned short status;
+
+ status = get_reg(PP_RER);
+
+ if ((status & PP_RER_RxOK) == 0)
+ return 0;
+
+ status = CS8900_RTDATA; /* stat */
+ rxlen = CS8900_RTDATA; /* len */
+
+ if(rxlen > PKTSIZE_ALIGN + PKTALIGN)
+ printf("packet too big!\n");
+
+ for(addr = (unsigned short *)NetRxPackets[0], i = rxlen >> 1; i > 0; i-- )
+ *addr++ = CS8900_RTDATA;
+ if(rxlen & 1)
+ *addr++ = CS8900_RTDATA;
+
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[0], rxlen);
+
+ return rxlen;
+}
+
+/* Send a data block via Ethernet. */
+extern int eth_send(volatile void *packet, int length)
+{
+ volatile unsigned short *addr;
+ int tmo;
+ unsigned short s;
+
+retry:
+ /* initiate a transmit sequence */
+ CS8900_TxCMD = PP_TxCmd_TxStart_Full;
+ CS8900_TxLEN = length;
+
+ /* Test to see if the chip has allocated memory for the packet */
+ if ((get_reg(PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {
+ /* Oops... this should not happen! */
+ printf("cs: unable to send packet; retrying...\n");
+ for (tmo = get_timer(0) + 5 * CFG_HZ; get_timer(0) < tmo; )
+ /*NOP*/;
+ eth_reset();
+ goto retry;
+ }
+
+ /* Write the contents of the packet */
+ /* assume even number of bytes */
+ for(addr = packet; length > 0; length -= 2 )
+ CS8900_RTDATA = *addr++;
+
+ /* wait for transfer to succeed */
+ tmo = get_timer(0) + 5 * CFG_HZ;
+ while((s = get_reg(PP_TER) & ~0x1F) == 0)
+ {
+ if (get_timer(0) >= tmo)
+ break;
+ }
+
+ /* nothing */ ;
+ if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) {
+ printf("\ntransmission error %#x\n", s);
+ }
+
+ return 0;
+}
+
+#endif /* COMMANDS & CFG_NET */
+
+#endif /* CONFIG_DRIVER_CS8900 */
diff --git a/drivers/ct69000.c b/drivers/ct69000.c
new file mode 100644
index 0000000..7962f74
--- /dev/null
+++ b/drivers/ct69000.c
@@ -0,0 +1,1484 @@
+/*
+ * (C) Copyright 2002
+ * Denis Peter, MPL AG Switzerland
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * ported from ctfb.c (linux kernel) for the U-Boot
+ *
+ */
+
+/************************************************************************
+ Get Parameters for the video mode:
+ Parameters can be set via the variable "videomode" in the environment.
+ 2 diferent ways are possible:
+ "videomode=301" - 301 is a hexadecimal number describing the VESA
+ mode. Following modes are implemented:
+
+ Colors 640x480 800x600 1024x768 1152x864
+ --------+-----------------------------------
+ 8 bits | 0x301 0x303 0x305 0x161
+ 15 bits | 0x310 0x313 0x316 0x162
+ 16 bits | 0x311 0x314 0x317 0x163
+ 24 bits | 0x312 0x315 0x318 ?
+ --------+-----------------------------------
+ "videomode=bootargs"
+ - the parameters are parsed from the bootargs.
+ The format is "NAME:VALUE,NAME:VALUE" etc.
+ Ex.:
+ "bootargs=video=ctfb:x:800,y:600,depth:16,pclk:25000"
+ Parameters not included in the list will be taken from
+ the default mode, which is one of the following:
+ mode:0 640x480x24
+ mode:1 800x600x16
+ mode:2 1024x768x8
+ mode:3 960x720x24
+ mode:4 1152x864x16
+ if "mode" is not provided within the parameter list,
+ mode:0 is assumed.
+ Following parameters are supported:
+ x xres = visible resolution horizontal
+ y yres = visible resolution vertical
+ pclk pixelclocks in pico sec
+ le left_marging time from sync to picture in pixelclocks
+ ri right_marging time from picture to sync in pixelclocks
+ up upper_margin time from sync to picture
+ lo lower_margin
+ hs hsync_len length of horizontal sync
+ vs vsync_len length of vertical sync
+ sync see FB_SYNC_*
+ vmode see FB_VMODE_*
+ depth Color depth in bits per pixel
+ All other parameters in the variable bootargs are ignored.
+ It is also possible to set the parameters direct in the
+ variable "videomode", or in another variable i.e.
+ "myvideo" and setting the variable "videomode=myvideo"..
+****************************************************************************/
+
+#include <common.h>
+
+#ifdef CONFIG_VIDEO
+
+#include <pci.h>
+#include <video_fb.h>
+
+#ifdef CONFIG_VIDEO_CT69000
+
+/* debug */
+#undef VGA_DEBUG
+#undef VGA_DUMP_REG
+#ifdef VGA_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Macros */
+#ifndef min
+#define min( a, b ) ( ( a ) < ( b ) ) ? ( a ) : ( b )
+#endif
+#ifndef max
+#define max( a, b ) ( ( a ) > ( b ) ) ? ( a ) : ( b )
+#endif
+#ifdef minmax
+#error "term minmax already used."
+#endif
+#define minmax( a, x, b ) max( ( a ), min( ( x ), ( b ) ) )
+#define N_ELTS( x ) ( sizeof( x ) / sizeof( x[ 0 ] ) )
+
+/* CT Register Offsets */
+#define CT_AR_O 0x3c0 /* Index and Data write port of the attribute Registers */
+#define CT_GR_O 0x3ce /* Index port of the Graphic Controller Registers */
+#define CT_SR_O 0x3c4 /* Index port of the Sequencer Controller */
+#define CT_CR_O 0x3d4 /* Index port of the CRT Controller */
+#define CT_XR_O 0x3d6 /* Extended Register index */
+#define CT_MSR_W_O 0x3c2 /* Misc. Output Register (write only) */
+#define CT_LUT_MASK_O 0x3c6 /* Color Palette Mask */
+#define CT_LUT_START_O 0x3c8 /* Color Palette Write Mode Index */
+#define CT_LUT_RGB_O 0x3c9 /* Color Palette Data Port */
+#define CT_STATUS_REG0_O 0x3c2 /* Status Register 0 (read only) */
+#define CT_STATUS_REG1_O 0x3da /* Input Status Register 1 (read only) */
+
+#define CT_FP_O 0x3d0 /* Index port of the Flat panel Registers */
+#define CT_MR_O 0x3d2 /* Index Port of the Multimedia Extension */
+
+/* defines for the memory mapped registers */
+#define BR00_o 0x400000 /* Source and Destination Span Register */
+#define BR01_o 0x400004 /* Pattern/Source Expansion Background Color & Transparency Key Register */
+#define BR02_o 0x400008 /* Pattern/Source Expansion Foreground Color Register */
+#define BR03_o 0x40000C /* Monochrome Source Control Register */
+#define BR04_o 0x400010 /* BitBLT Control Register */
+#define BR05_o 0x400014 /* Pattern Address Registe */
+#define BR06_o 0x400018 /* Source Address Register */
+#define BR07_o 0x40001C /* Destination Address Register */
+#define BR08_o 0x400020 /* Destination Width & Height Register */
+#define BR09_o 0x400024 /* Source Expansion Background Color & Transparency Key Register */
+#define BR0A_o 0x400028 /* Source Expansion Foreground Color Register */
+
+#define CURSOR_SIZE 0x1000 /* in KByte for HW Cursor */
+#define PATTERN_ADR (pGD->dprBase + CURSOR_SIZE) /* pattern Memory after Cursor Memory */
+#define PATTERN_SIZE 8*8*4 /* 4 Bytes per Pixel 8 x 8 Pixel */
+#define ACCELMEMORY (CURSOR_SIZE + PATTERN_SIZE) /* reserved Memory for BITBlt and hw cursor */
+
+/* Some Mode definitions */
+#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
+#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
+#define FB_SYNC_EXT 4 /* external sync */
+#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
+#define FB_SYNC_BROADCAST 16 /* broadcast video timings */
+ /* vtotal = 144d/288n/576i => PAL */
+ /* vtotal = 121d/242n/484i => NTSC */
+#define FB_SYNC_ON_GREEN 32 /* sync on green */
+
+#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
+#define FB_VMODE_INTERLACED 1 /* interlaced */
+#define FB_VMODE_DOUBLE 2 /* double scan */
+#define FB_VMODE_MASK 255
+
+#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */
+#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
+#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */
+
+#define text 0
+#define fntwidth 8
+
+/* table for VGA Initialization */
+typedef struct {
+ const unsigned char reg;
+ const unsigned char val;
+} CT_CFG_TABLE;
+
+/* this table provides some basic initialisations such as Memory Clock etc */
+static CT_CFG_TABLE xreg[] = {
+ {0x09, 0x01}, /* CRT Controller Extensions Enable */
+ {0x0A, 0x02}, /* Frame Buffer Mapping */
+ {0x0B, 0x01}, /* PCI Write Burst support */
+ {0x20, 0x00}, /* BitBLT Configuration */
+ {0x40, 0x03}, /* Memory Access Control */
+ {0x60, 0x00}, /* Video Pin Control */
+ {0x61, 0x00}, /* DPMS Synch control */
+ {0x62, 0x00}, /* GPIO Pin Control */
+ {0x63, 0xBD}, /* GPIO Pin Data */
+ {0x67, 0x00}, /* Pin Tri-State */
+ {0x80, 0x80}, /* Pixel Pipeline Config 0 register */
+ {0xA0, 0x00}, /* Cursor 1 Control Reg */
+ {0xA1, 0x00}, /* Cursor 1 Vertical Extension Reg */
+ {0xA2, 0x00}, /* Cursor 1 Base Address Low */
+ {0xA3, 0x00}, /* Cursor 1 Base Address High */
+ {0xA4, 0x00}, /* Cursor 1 X-Position Low */
+ {0xA5, 0x00}, /* Cursor 1 X-Position High */
+ {0xA6, 0x00}, /* Cursor 1 Y-Position Low */
+ {0xA7, 0x00}, /* Cursor 1 Y-Position High */
+ {0xA8, 0x00}, /* Cursor 2 Control Reg */
+ {0xA9, 0x00}, /* Cursor 2 Vertical Extension Reg */
+ {0xAA, 0x00}, /* Cursor 2 Base Address Low */
+ {0xAB, 0x00}, /* Cursor 2 Base Address High */
+ {0xAC, 0x00}, /* Cursor 2 X-Position Low */
+ {0xAD, 0x00}, /* Cursor 2 X-Position High */
+ {0xAE, 0x00}, /* Cursor 2 Y-Position Low */
+ {0xAF, 0x00}, /* Cursor 2 Y-Position High */
+ {0xC0, 0x7D}, /* Dot Clock 0 VCO M-Divisor */
+ {0xC1, 0x07}, /* Dot Clock 0 VCO N-Divisor */
+ {0xC3, 0x34}, /* Dot Clock 0 Divisor select */
+ {0xC4, 0x55}, /* Dot Clock 1 VCO M-Divisor */
+ {0xC5, 0x09}, /* Dot Clock 1 VCO N-Divisor */
+ {0xC7, 0x24}, /* Dot Clock 1 Divisor select */
+ {0xC8, 0x7D}, /* Dot Clock 2 VCO M-Divisor */
+ {0xC9, 0x07}, /* Dot Clock 2 VCO N-Divisor */
+ {0xCB, 0x34}, /* Dot Clock 2 Divisor select */
+ {0xCC, 0x38}, /* Memory Clock 0 VCO M-Divisor */
+ {0xCD, 0x03}, /* Memory Clock 0 VCO N-Divisor */
+ {0xCE, 0x90}, /* Memory Clock 0 Divisor select */
+ {0xCF, 0x06}, /* Clock Config */
+ {0xD0, 0x0F}, /* Power Down */
+ {0xD1, 0x01}, /* Power Down BitBLT */
+ {0xFF, 0xFF} /* end of table */
+};
+/* Clock Config:
+ * =============
+ *
+ * PD Registers:
+ * -------------
+ * Bit2 and Bit4..6 are used for the Loop Divisor and Post Divisor.
+ * They are encoded as follows:
+ *
+ * +---+--------------+
+ * | 2 | Loop Divisor |
+ * +---+--------------+
+ * | 1 | 1 |
+ * +---+--------------+
+ * | 0 | 4 |
+ * +---+--------------+
+ * Note: The Memory Clock does not have a Loop Divisor.
+ * +---+---+---+--------------+
+ * | 6 | 5 | 4 | Post Divisor |
+ * +---+---+---+--------------+
+ * | 0 | 0 | 0 | 1 |
+ * +---+---+---+--------------+
+ * | 0 | 0 | 1 | 2 |
+ * +---+---+---+--------------+
+ * | 0 | 1 | 0 | 4 |
+ * +---+---+---+--------------+
+ * | 0 | 1 | 1 | 8 |
+ * +---+---+---+--------------+
+ * | 1 | 0 | 0 | 16 |
+ * +---+---+---+--------------+
+ * | 1 | 0 | 1 | 32 |
+ * +---+---+---+--------------+
+ * | 1 | 1 | X | reserved |
+ * +---+---+---+--------------+
+ *
+ * All other bits are reserved in these registers.
+ *
+ * Clock VCO M Registers:
+ * ----------------------
+ * These Registers contain the M Value -2.
+ *
+ * Clock VCO N Registers:
+ * ----------------------
+ * These Registers contain the N Value -2.
+ *
+ * Formulas:
+ * ---------
+ * Fvco = (Fref * Loop Divisor * M/N), whereas 100MHz < Fvco < 220MHz
+ * Fout = Fvco / Post Divisor
+ *
+ * Dot Clk0 (default 25MHz):
+ * -------------------------
+ * Fvco = 14.318 * 127 / 9 = 202.045MHz
+ * Fout = 202.045MHz / 8 = 25.25MHz
+ * Post Divisor = 8
+ * Loop Divisor = 1
+ * XRC0 = (M - 2) = 125 = 0x7D
+ * XRC1 = (N - 2) = 7 = 0x07
+ * XRC3 = 0x34
+ *
+ * Dot Clk1 (default 28MHz):
+ * -------------------------
+ * Fvco = 14.318 * 87 / 11 = 113.24MHz
+ * Fout = 113.24MHz / 4 = 28.31MHz
+ * Post Divisor = 4
+ * Loop Divisor = 1
+ * XRC4 = (M - 2) = 85 = 0x55
+ * XRC5 = (N - 2) = 9 = 0x09
+ * XRC7 = 0x24
+ *
+ * Dot Clk2 (variable for extended modes set to 25MHz):
+ * ----------------------------------------------------
+ * Fvco = 14.318 * 127 / 9 = 202.045MHz
+ * Fout = 202.045MHz / 8 = 25.25MHz
+ * Post Divisor = 8
+ * Loop Divisor = 1
+ * XRC8 = (M - 2) = 125 = 0x7D
+ * XRC9 = (N - 2) = 7 = 0x07
+ * XRCB = 0x34
+ *
+ * Memory Clk for most modes >50MHz:
+ * ----------------------------------
+ * Fvco = 14.318 * 58 / 5 = 166MHz
+ * Fout = 166MHz / 2 = 83MHz
+ * Post Divisor = 2
+ * XRCC = (M - 2) = 57 = 0x38
+ * XRCD = (N - 2) = 3 = 0x03
+ * XRCE = 0x90
+ *
+ * Note Bit7 enables the clock source from the VCO
+ *
+ */
+
+/******************************************************************
+ * Resolution Struct
+ ******************************************************************/
+struct ctfb_res_modes {
+ int xres; /* visible resolution */
+ int yres;
+ /* Timing: All values in pixclocks, except pixclock (of course) */
+ int pixclock; /* pixel clock in ps (pico seconds) */
+ int left_margin; /* time from sync to picture */
+ int right_margin; /* time from picture to sync */
+ int upper_margin; /* time from sync to picture */
+ int lower_margin;
+ int hsync_len; /* length of horizontal sync */
+ int vsync_len; /* length of vertical sync */
+ int sync; /* see FB_SYNC_* */
+ int vmode; /* see FB_VMODE_* */
+};
+
+/******************************************************************
+ * Vesa Mode Struct
+ ******************************************************************/
+struct ctfb_vesa_modes {
+ int vesanr; /* Vesa number as in LILO (VESA Nr + 0x200} */
+ int resindex; /* index to resolution struct */
+ int bits_per_pixel; /* bpp */
+};
+/*******************************************************************
+ * Chips struct
+ *******************************************************************/
+struct ctfb_chips_properties {
+ int device_id; /* PCI Device ID */
+ unsigned long max_mem; /* memory for frame buffer */
+ int vld_set; /* value of VLD if bit2 in clock control is set */
+ int vld_not_set; /* value of VLD if bit2 in clock control is set */
+ int mn_diff; /* difference between M/N Value + mn_diff = M/N Register */
+ int mn_min; /* min value of M/N Value */
+ int mn_max; /* max value of M/N Value */
+ int vco_min; /* VCO Min in MHz */
+ int vco_max; /* VCO Max in MHz */
+};
+
+static const struct ctfb_chips_properties chips[] = {
+ {PCI_DEVICE_ID_CT_69000, 0x200000, 1, 4, -2, 3, 257, 100, 220},
+ {PCI_DEVICE_ID_CT_65555, 0x100000, 16, 4, 0, 1, 255, 48, 220}, /* NOT TESTED */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0} /* Terminator */
+};
+
+/*************************************************
+ Video Modes:
+Colours 640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200
+--------+--------------------------------------------------------------
+ 4 bits | ? ? 0x302 ? ? ? ?
+ 8 bits | 0x300 0x301 0x303 0x305 0x161 0x307 0x31C
+15 bits | ? 0x310 0x313 0x316 0x162 0x319 0x31D
+16 bits | ? 0x311 0x314 0x317 0x163 0x31A 0x31E
+24 bits | ? 0x312 0x315 0x318 ? 0x31B 0x31F
+32 bits | ? ? ? ? 0x164 ?
+*/
+
+#define RES_MODE_640x480 0
+#define RES_MODE_800x600 1
+#define RES_MODE_1024x768 2
+#define RES_MODE_960_720 3
+#define RES_MODE_1152x864 4
+#define RES_MODES_COUNT 5
+
+#define VESA_MODES_COUNT 15
+
+static const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
+ {0x301, RES_MODE_640x480, 8},
+ {0x310, RES_MODE_640x480, 15},
+ {0x311, RES_MODE_640x480, 16},
+ {0x312, RES_MODE_640x480, 24},
+ {0x303, RES_MODE_800x600, 8},
+ {0x313, RES_MODE_800x600, 15},
+ {0x314, RES_MODE_800x600, 16},
+ {0x315, RES_MODE_800x600, 24},
+ {0x305, RES_MODE_1024x768, 8},
+ {0x316, RES_MODE_1024x768, 15},
+ {0x317, RES_MODE_1024x768, 16},
+ {0x318, RES_MODE_1024x768, 24},
+ {0x161, RES_MODE_1152x864, 8},
+ {0x162, RES_MODE_1152x864, 15},
+ {0x163, RES_MODE_1152x864, 16}
+};
+
+static const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
+ /* x y pixclk le ri up lo hs vs s vmode */
+ {640, 480, 39721, 40, 24, 32, 11, 96, 2, 0,
+ FB_VMODE_NONINTERLACED},
+ {800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
+ {1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0,
+ FB_VMODE_NONINTERLACED},
+ {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0,
+ FB_VMODE_NONINTERLACED},
+ {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0,
+ FB_VMODE_NONINTERLACED}
+};
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+
+/*******************************************************************************
+*
+* Low Level Routines
+*/
+
+/*******************************************************************************
+*
+* Read CT ISA register
+*/
+#ifdef VGA_DEBUG
+static unsigned char
+ctRead (unsigned short index)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ if (index == CT_AR_O)
+ /* synch the Flip Flop */
+ in8 (pGD->isaBase + CT_STATUS_REG1_O);
+
+ return (in8 (pGD->isaBase + index));
+}
+#endif
+/*******************************************************************************
+*
+* Write CT ISA register
+*/
+static void
+ctWrite (unsigned short index, unsigned char val)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+ out8 ((pGD->isaBase + index), val);
+}
+
+/*******************************************************************************
+*
+* Read CT ISA register indexed
+*/
+static unsigned char
+ctRead_i (unsigned short index, char reg)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ if (index == CT_AR_O)
+ /* synch the Flip Flop */
+ in8 (pGD->isaBase + CT_STATUS_REG1_O);
+ out8 ((pGD->isaBase + index), reg);
+ return (in8 (pGD->isaBase + index + 1));
+}
+
+/*******************************************************************************
+*
+* Write CT ISA register indexed
+*/
+static void
+ctWrite_i (unsigned short index, char reg, char val)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ if (index == CT_AR_O) {
+ /* synch the Flip Flop */
+ in8 (pGD->isaBase + CT_STATUS_REG1_O);
+ out8 ((pGD->isaBase + index), reg);
+ out8 ((pGD->isaBase + index), val);
+ } else {
+ out8 ((pGD->isaBase + index), reg);
+ out8 ((pGD->isaBase + index + 1), val);
+ }
+}
+
+/*******************************************************************************
+*
+* Write a table of CT ISA register
+*/
+static void
+ctLoadRegs (unsigned short index, CT_CFG_TABLE * regTab)
+{
+ while (regTab->reg != 0xFF) {
+ ctWrite_i (index, regTab->reg, regTab->val);
+ regTab++;
+ }
+}
+
+/*****************************************************************************/
+static void
+SetArRegs (void)
+{
+ int i, tmp;
+
+ for (i = 0; i < 0x10; i++)
+ ctWrite_i (CT_AR_O, i, i);
+ if (text)
+ tmp = 0x04;
+ else
+ tmp = 0x41;
+
+ ctWrite_i (CT_AR_O, 0x10, tmp); /* Mode Control Register */
+ ctWrite_i (CT_AR_O, 0x11, 0x00); /* Overscan Color Register */
+ ctWrite_i (CT_AR_O, 0x12, 0x0f); /* Memory Plane Enable Register */
+ if (fntwidth == 9)
+ tmp = 0x08;
+ else
+ tmp = 0x00;
+ ctWrite_i (CT_AR_O, 0x13, tmp); /* Horizontal Pixel Panning */
+ ctWrite_i (CT_AR_O, 0x14, 0x00); /* Color Select Register */
+ ctWrite (CT_AR_O, 0x20); /* enable video */
+}
+
+/*****************************************************************************/
+static void
+SetGrRegs (void)
+{ /* Set Graphics Mode */
+ int i;
+
+ for (i = 0; i < 0x05; i++)
+ ctWrite_i (CT_GR_O, i, 0);
+ if (text) {
+ ctWrite_i (CT_GR_O, 0x05, 0x10);
+ ctWrite_i (CT_GR_O, 0x06, 0x02);
+ } else {
+ ctWrite_i (CT_GR_O, 0x05, 0x40);
+ ctWrite_i (CT_GR_O, 0x06, 0x05);
+ }
+ ctWrite_i (CT_GR_O, 0x07, 0x0f);
+ ctWrite_i (CT_GR_O, 0x08, 0xff);
+}
+
+/*****************************************************************************/
+static void
+SetSrRegs (void)
+{
+ int tmp = 0;
+
+ ctWrite_i (CT_SR_O, 0x00, 0x00); /* reset */
+ /*rr( sr, 0x01, tmp );
+ if( fntwidth == 8 ) tmp |= 0x01; else tmp &= ~0x01;
+ wr( sr, 0x01, tmp ); */
+ if (fntwidth == 8)
+ ctWrite_i (CT_SR_O, 0x01, 0x01); /* Clocking Mode Register */
+ else
+ ctWrite_i (CT_SR_O, 0x01, 0x00); /* Clocking Mode Register */
+ ctWrite_i (CT_SR_O, 0x02, 0x0f); /* Enable CPU wr access to given memory plane */
+ ctWrite_i (CT_SR_O, 0x03, 0x00); /* Character Map Select Register */
+ if (text)
+ tmp = 0x02;
+ else
+ tmp = 0x0e;
+ ctWrite_i (CT_SR_O, 0x04, tmp); /* Enable CPU accesses to the rest of the 256KB
+ total VGA memory beyond the first 64KB and set
+ fb mapping mode. */
+ ctWrite_i (CT_SR_O, 0x00, 0x03); /* enable */
+}
+
+/*****************************************************************************/
+static void
+SetBitsPerPixelIntoXrRegs (int bpp)
+{
+ unsigned int n = (bpp >> 3), tmp; /* only for 15, 8, 16, 24 bpp */
+ static char md[4] = { 0x04, 0x02, 0x05, 0x06 }; /* DisplayColorMode */
+ static char off[4] = { ~0x20, ~0x30, ~0x20, ~0x10 }; /* mask */
+ static char on[4] = { 0x10, 0x00, 0x10, 0x20 }; /* mask */
+ if (bpp == 15)
+ n = 0;
+ tmp = ctRead_i (CT_XR_O, 0x20);
+ tmp &= off[n];
+ tmp |= on[n];
+ ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+ ctWrite_i (CT_XR_O, 0x81, md[n]);
+}
+
+/*****************************************************************************/
+static void
+SetCrRegs (struct ctfb_res_modes *var, int bits_per_pixel)
+{ /* he -le- ht|0 hd -ri- hs -h- he */
+ unsigned char cr[0x7a];
+ int i, tmp;
+ unsigned int hd, hs, he, ht, hbe; /* Horizontal. */
+ unsigned int vd, vs, ve, vt; /* vertical */
+ unsigned int bpp, wd, dblscan, interlaced, bcast, CrtHalfLine;
+ unsigned int CompSyncCharClkDelay, CompSyncPixelClkDelay;
+ unsigned int NTSC_PAL_HorizontalPulseWidth, BlDelayCtrl;
+ unsigned int HorizontalEqualizationPulses;
+ unsigned int HorizontalSerration1Start, HorizontalSerration2Start;
+
+ const int LineCompare = 0x3ff;
+ unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
+ unsigned int RAMDAC_BlankPedestalEnable = 0; /* 1=en-, 0=disable, see XR82 */
+
+ hd = (var->xres) / 8; /* HDisp. */
+ hs = (var->xres + var->right_margin) / 8; /* HsStrt */
+ he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
+ ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
+ hbe = ht - 1; /* HBlankEnable todo docu wants ht here, but it does not work */
+ /* ve -up- vt|0 vd -lo- vs -v- ve */
+ vd = var->yres; /* VDisplay */
+ vs = var->yres + var->lower_margin; /* VSyncStart */
+ ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
+ vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
+ bpp = bits_per_pixel;
+ dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
+ interlaced = var->vmode & FB_VMODE_INTERLACED;
+ bcast = var->sync & FB_SYNC_BROADCAST;
+ CrtHalfLine = bcast ? (hd >> 1) : 0;
+ BlDelayCtrl = bcast ? 1 : 0;
+ CompSyncCharClkDelay = 0; /* 2 bit */
+ CompSyncPixelClkDelay = 0; /* 3 bit */
+ if (bcast) {
+ NTSC_PAL_HorizontalPulseWidth = 7; /*( var->hsync_len >> 1 ) + 1 */
+ HorizontalEqualizationPulses = 0; /* inverse value */
+ HorizontalSerration1Start = 31; /* ( ht >> 1 ) */
+ HorizontalSerration2Start = 89; /* ( ht >> 1 ) */
+ } else {
+ NTSC_PAL_HorizontalPulseWidth = 0;
+ /* 4 bit: hsync pulse width = ( ( CR74[4:0] - CR74[5] )
+ * / 2 ) + 1 --> CR74[4:0] = 2*(hs-1) + CR74[5] */
+ HorizontalEqualizationPulses = 1; /* inverse value */
+ HorizontalSerration1Start = 0; /* ( ht >> 1 ) */
+ HorizontalSerration2Start = 0; /* ( ht >> 1 ) */
+ }
+
+ if (bpp == 15)
+ bpp = 16;
+ wd = var->xres * bpp / 64; /* double words per line */
+ if (interlaced) { /* we divide all vertical timings, exept vd */
+ vs >>= 1;
+ ve >>= 1;
+ vt >>= 1;
+ }
+ memset (cr, 0, sizeof (cr));
+ cr[0x00] = 0xff & (ht - 5);
+ cr[0x01] = hd - 1; /* soll:4f ist 59 */
+ cr[0x02] = hd;
+ cr[0x03] = (hbe & 0x1F) | 0x80; /* hd + ht - hd */
+ cr[0x04] = hs;
+ cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
+ cr[0x06] = (vt - 2) & 0xFF;
+ cr[0x30] = (vt - 2) >> 8;
+ cr[0x07] = ((vt & 0x100) >> 8)
+ | ((vd & 0x100) >> 7)
+ | ((vs & 0x100) >> 6)
+ | ((vs & 0x100) >> 5)
+ | ((LineCompare & 0x100) >> 4)
+ | ((vt & 0x200) >> 4)
+ | ((vd & 0x200) >> 3)
+ | ((vs & 0x200) >> 2);
+ cr[0x08] = 0x00;
+ cr[0x09] = (dblscan << 7)
+ | ((LineCompare & 0x200) >> 3)
+ | ((vs & 0x200) >> 4)
+ | (TextScanLines - 1);
+ cr[0x10] = vs & 0xff; /* VSyncPulseStart */
+ cr[0x32] = (vs & 0xf00) >> 8; /* VSyncPulseStart */
+ cr[0x11] = (ve & 0x0f); /* | 0x20; */
+ cr[0x12] = (vd - 1) & 0xff; /* LineCount */
+ cr[0x31] = ((vd - 1) & 0xf00) >> 8; /* LineCount */
+ cr[0x13] = wd & 0xff;
+ cr[0x41] = (wd & 0xf00) >> 8;
+ cr[0x15] = vs & 0xff;
+ cr[0x33] = (vs & 0xf00) >> 8;
+ cr[0x38] = (0x100 & (ht - 5)) >> 8;
+ cr[0x3C] = 0xc0 & hbe;
+ cr[0x16] = (vt - 1) & 0xff; /* vbe - docu wants vt here, */
+ cr[0x17] = 0xe3; /* but it does not work */
+ cr[0x18] = 0xff & LineCompare;
+ cr[0x22] = 0xff; /* todo? */
+ cr[0x70] = interlaced ? (0x80 | CrtHalfLine) : 0x00; /* check:0xa6 */
+ cr[0x71] = 0x80 | (RAMDAC_BlankPedestalEnable << 6)
+ | (BlDelayCtrl << 5)
+ | ((0x03 & CompSyncCharClkDelay) << 3)
+ | (0x07 & CompSyncPixelClkDelay); /* todo: see XR82 */
+ cr[0x72] = HorizontalSerration1Start;
+ cr[0x73] = HorizontalSerration2Start;
+ cr[0x74] = (HorizontalEqualizationPulses << 5)
+ | NTSC_PAL_HorizontalPulseWidth;
+ /* todo: ct69000 has also 0x75-79 */
+ /* now set the registers */
+ for (i = 0; i <= 0x0d; i++) { /*CR00 .. CR0D */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ for (i = 0x10; i <= 0x18; i++) { /*CR10 .. CR18 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ i = 0x22; /*CR22 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ for (i = 0x30; i <= 0x33; i++) { /*CR30 .. CR33 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ i = 0x38; /*CR38 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ i = 0x3C; /*CR3C */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ for (i = 0x40; i <= 0x41; i++) { /*CR40 .. CR41 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ for (i = 0x70; i <= 0x74; i++) { /*CR70 .. CR74 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ tmp = ctRead_i (CT_CR_O, 0x40);
+ tmp &= 0x0f;
+ tmp |= 0x80;
+ ctWrite_i (CT_CR_O, 0x40, tmp); /* StartAddressEnable */
+}
+
+/* pixelclock control */
+
+/*****************************************************************************
+ We have a rational number p/q and need an m/n which is very close to p/q
+ but has m and n within mnmin and mnmax. We have no floating point in the
+ kernel. We can use long long without divide. And we have time to compute...
+******************************************************************************/
+static unsigned int
+FindBestPQFittingMN (unsigned int p, unsigned int q, unsigned int mnmin,
+ unsigned int mnmax, unsigned int *pm, unsigned int *pn)
+{
+ /* this code is not for general purpose usable but good for our number ranges */
+ unsigned int n = mnmin, m = 0;
+ long long int L = 0, P = p, Q = q, H = P >> 1;
+ long long int D = 0x7ffffffffffffffLL;
+ for (n = mnmin; n <= mnmax; n++) {
+ m = mnmin; /* p/q ~ m/n -> p*n ~ m*q -> p*n-x*q ~ 0 */
+ L = P * n - m * Q; /* n * vco - m * fref should be near 0 */
+ while (L > 0 && m < mnmax) {
+ L -= q; /* difference is greater as 0 subtract fref */
+ m++; /* and increment m */
+ }
+ /* difference is less or equal than 0 or m > maximum */
+ if (m > mnmax)
+ break; /* no solution: if we increase n we get the same situation */
+ /* L is <= 0 now */
+ if (-L > H && m > mnmin) { /* if difference > the half fref */
+ L += q; /* we take the situation before */
+ m--; /* because its closer to 0 */
+ }
+ L = (L < 0) ? -L : +L; /* absolute value */
+ if (D < L) /* if last difference was better take next n */
+ continue;
+ D = L;
+ *pm = m;
+ *pn = n; /* keep improved data */
+ if (D == 0)
+ break; /* best result we can get */
+ }
+ return (unsigned int) (0xffffffff & D);
+}
+
+/* that is the hardware < 69000 we have to manage
+ +---------+ +-------------------+ +----------------------+ +--+
+ | REFCLK |__|NTSC Divisor Select|__|FVCO Reference Divisor|__|÷N|__
+ | 14.3MHz | |(NTSCDS) (÷1, ÷5) | |Select (RDS) (÷1, ÷4) | | | |
+ +---------+ +-------------------+ +----------------------+ +--+ |
+ ___________________________________________________________________|
+ |
+ | fvco fout
+ | +--------+ +------------+ +-----+ +-------------------+ +----+
+ +-| Phase |__|Charge Pump |__| VCO |_____|Post Divisor (PD) |___|CLK |--->
+ +-| Detect | |& Filter VCO| | | | |÷1, 2, 4, 8, 16, 32| | |
+ | +--------+ +------------+ +-----+ | +-------------------+ +----+
+ | |
+ | +--+ +---------------+ |
+ |____|÷M|___|VCO Loop Divide|__________|
+ | | |(VLD)(÷4, ÷16) |
+ +--+ +---------------+
+****************************************************************************
+ that is the hardware >= 69000 we have to manage
+ +---------+ +--+
+ | REFCLK |__|÷N|__
+ | 14.3MHz | | | |
+ +---------+ +--+ |
+ __________________|
+ |
+ | fvco fout
+ | +--------+ +------------+ +-----+ +-------------------+ +----+
+ +-| Phase |__|Charge Pump |__| VCO |_____|Post Divisor (PD) |___|CLK |--->
+ +-| Detect | |& Filter VCO| | | | |÷1, 2, 4, 8, 16, 32| | |
+ | +--------+ +------------+ +-----+ | +-------------------+ +----+
+ | |
+ | +--+ +---------------+ |
+ |____|÷M|___|VCO Loop Divide|__________|
+ | | |(VLD)(÷1, ÷4) |
+ +--+ +---------------+
+
+
+*/
+
+#define VIDEO_FREF 14318180; /* Hz */
+/*****************************************************************************/
+static int
+ReadPixClckFromXrRegsBack (struct ctfb_chips_properties *param)
+{
+ unsigned int m, n, vld, pd, PD, fref, xr_cb, i, pixclock;
+ i = 0;
+ pixclock = -1;
+ fref = VIDEO_FREF;
+ m = ctRead_i (CT_XR_O, 0xc8);
+ n = ctRead_i (CT_XR_O, 0xc9);
+ m -= param->mn_diff;
+ n -= param->mn_diff;
+ xr_cb = ctRead_i (CT_XR_O, 0xcb);
+ PD = (0x70 & xr_cb) >> 4;
+ pd = 1;
+ for (i = 0; i < PD; i++) {
+ pd *= 2;
+ }
+ vld = (0x04 & xr_cb) ? param->vld_set : param->vld_not_set;
+ if (n * vld * m) {
+ unsigned long long p = 1000000000000LL * pd * n;
+ unsigned long long q = (long long) fref * vld * m;
+ while ((p > 0xffffffffLL) || (q > 0xffffffffLL)) {
+ p >>= 1; /* can't divide with long long so we scale down */
+ q >>= 1;
+ }
+ pixclock = (unsigned) p / (unsigned) q;
+ } else
+ printf ("Invalid data in xr regs.\n");
+ return pixclock;
+}
+
+/*****************************************************************************/
+static void
+FindAndSetPllParamIntoXrRegs (unsigned int pixelclock,
+ struct ctfb_chips_properties *param)
+{
+ unsigned int m, n, vld, pd, PD, fref, xr_cb;
+ unsigned int fvcomin, fvcomax, pclckmin, pclckmax, pclk;
+ unsigned int pfreq, fvco, new_pixclock;
+
+ fref = VIDEO_FREF;
+ pd = 1;
+ PD = 0;
+ fvcomin = param->vco_min;
+ fvcomax = param->vco_max; /* MHz */
+ pclckmin = 1000000 / fvcomax + 1; /* 4546 */
+ pclckmax = 32000000 / fvcomin - 1; /* 666665 */
+ pclk = minmax (pclckmin, pixelclock, pclckmax); /* ps pp */
+ pfreq = 250 * (4000000000U / pclk);
+ fvco = pfreq; /* Hz */
+ new_pixclock = 0;
+ while (fvco < fvcomin * 1000000) {
+ /* double VCO starting with the pixelclock frequency
+ * as long as it is lower than the minimal VCO frequency */
+ fvco *= 2;
+ pd *= 2;
+ PD++;
+ }
+ /* fvco is exactly pd * pixelclock and higher than the ninmal VCO frequency */
+ vld = (param->vld_set > param->vld_not_set) ?
+ param->vld_not_set : param->vld_set;
+ /* start with lower VLD (higher VLD is NOT yet implemented */
+ FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n); /* rds = 1 */
+ m += param->mn_diff;
+ n += param->mn_diff;
+ PRINTF ("VCO %d, pd %d, m %d n %d vld %d \n", fvco, pd, m, n, vld);
+ xr_cb = ((0x7 & PD) << 4) | (vld == param->vld_set ? 0x04 : 0);
+ /* All four of the registers used for dot clock 2 (XRC8 - XRCB) must be
+ * written, and in order from XRC8 to XRCB, before the hardware will
+ * update the synthesizer s settings.
+ */
+ ctWrite_i (CT_XR_O, 0xc8, m);
+ ctWrite_i (CT_XR_O, 0xc9, n); /* xrca does not exist in CT69000 and CT69030 */
+ ctWrite_i (CT_XR_O, 0xca, 0); /* because of a hw bug I guess, but we write */
+ ctWrite_i (CT_XR_O, 0xcb, xr_cb); /* 0 to it for savety */
+ new_pixclock = ReadPixClckFromXrRegsBack (param);
+ PRINTF ("pixelclock.set = %d, pixelclock.real = %d \n",
+ pixelclock, new_pixclock);
+}
+
+/*****************************************************************************/
+static void
+SetMsrRegs (struct ctfb_res_modes *mode)
+{
+ unsigned char h_synch_high, v_synch_high;
+
+ h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
+ v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
+ ctWrite (CT_MSR_W_O, (h_synch_high | v_synch_high | 0x29));
+ /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
+ * Selects the upper 64KB page.Bit5=1
+ * CLK2 (left reserved in standard VGA) Bit3|2=1|0
+ * Disables CPU access to frame buffer. Bit1=0
+ * Sets the I/O address decode for ST01, FCR, and all CR registers
+ * to the 3Dx I/O address range (CGA emulation). Bit0=1
+ */
+}
+
+/************************************************************************************/
+#ifdef VGA_DUMP_REG
+
+static void
+ctDispRegs (unsigned short index, int from, int to)
+{
+ unsigned char status;
+ int i;
+
+ for (i = from; i < to; i++) {
+ status = ctRead_i (index, i);
+ printf ("%02X: is %02X\n", i, status);
+ }
+}
+
+void
+video_dump_reg (void)
+{
+ int i;
+
+ printf ("Extended Regs:\n");
+ ctDispRegs (CT_XR_O, 0, 0xC);
+ ctDispRegs (CT_XR_O, 0xe, 0xf);
+ ctDispRegs (CT_XR_O, 0x20, 0x21);
+ ctDispRegs (CT_XR_O, 0x40, 0x50);
+ ctDispRegs (CT_XR_O, 0x60, 0x64);
+ ctDispRegs (CT_XR_O, 0x67, 0x68);
+ ctDispRegs (CT_XR_O, 0x70, 0x72);
+ ctDispRegs (CT_XR_O, 0x80, 0x83);
+ ctDispRegs (CT_XR_O, 0xA0, 0xB0);
+ ctDispRegs (CT_XR_O, 0xC0, 0xD3);
+ printf ("Sequencer Regs:\n");
+ ctDispRegs (CT_SR_O, 0, 0x8);
+ printf ("Graphic Regs:\n");
+ ctDispRegs (CT_GR_O, 0, 0x9);
+ printf ("CRT Regs:\n");
+ ctDispRegs (CT_CR_O, 0, 0x19);
+ ctDispRegs (CT_CR_O, 0x22, 0x23);
+ ctDispRegs (CT_CR_O, 0x30, 0x34);
+ ctDispRegs (CT_CR_O, 0x38, 0x39);
+ ctDispRegs (CT_CR_O, 0x3C, 0x3D);
+ ctDispRegs (CT_CR_O, 0x40, 0x42);
+ ctDispRegs (CT_CR_O, 0x70, 0x80);
+ /* don't display the attributes */
+}
+
+#endif
+
+#ifdef CONFIG_VIDEO_HW_CURSOR
+/***************************************************************
+ * Set Hardware Cursor in Pixel
+ */
+void
+video_set_hw_cursor (int x, int y)
+{
+ int sig_x = 0, sig_y = 0;
+ if (x < 0) {
+ x *= -1;
+ sig_x = 1;
+ }
+ if (y < 0) {
+ y *= -1;
+ sig_y = 1;
+ }
+ ctWrite_i (CT_XR_O, 0xa4, x & 0xff);
+ ctWrite_i (CT_XR_O, 0xa5, (x >> 8) & 0x7);
+ ctWrite_i (CT_XR_O, 0xa6, y & 0xff);
+ ctWrite_i (CT_XR_O, 0xa7, (y >> 8) & 0x7);
+}
+
+/***************************************************************
+ * Init Hardware Cursor. To know the size of the Cursor,
+ * we have to know the Font size.
+ */
+void
+video_init_hw_cursor (int font_width, int font_height)
+{
+ unsigned char xr_80;
+ unsigned long *curs, pattern;
+ int i;
+ int cursor_start;
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+ cursor_start = pGD->dprBase;
+ xr_80 = ctRead_i (CT_XR_O, 0x80);
+ /* set start address */
+ ctWrite_i (CT_XR_O, 0xa2, (cursor_start >> 8) & 0xf0);
+ ctWrite_i (CT_XR_O, 0xa3, (cursor_start >> 16) & 0x3f);
+ /* set cursor shape */
+ curs = (unsigned long *) cursor_start;
+ i = 0;
+ while (i < 0x400) {
+ curs[i++] = 0xffffffff; /* AND mask */
+ curs[i++] = 0xffffffff; /* AND mask */
+ curs[i++] = 0; /* XOR mask */
+ curs[i++] = 0; /* XOR mask */
+ /* Transparent */
+ }
+ pattern = 0xffffffff >> font_width;
+ i = 0;
+ while (i < (font_height * 2)) {
+ curs[i++] = pattern; /* AND mask */
+ curs[i++] = pattern; /* AND mask */
+ curs[i++] = 0; /* XOR mask */
+ curs[i++] = 0; /* XOR mask */
+ /* Cursor Color 0 */
+ }
+ /* set blink rate */
+ ctWrite_i (CT_FP_O, 0x19, 0xf);
+
+ /* set cursors colors */
+ xr_80 = ctRead_i (CT_XR_O, 0x80);
+ xr_80 |= 0x1; /* alternate palette select */
+ ctWrite_i (CT_XR_O, 0x80, xr_80);
+ video_set_lut (4, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
+ /* position 4 is color 0 cursor 0 */
+ xr_80 &= 0xfe; /* normal palette select */
+ ctWrite_i (CT_XR_O, 0x80, xr_80);
+ /* cursor enable */
+ ctWrite_i (CT_XR_O, 0xa0, 0x91);
+ xr_80 |= 0x10; /* enable hwcursor */
+ ctWrite_i (CT_XR_O, 0x80, xr_80);
+ video_set_hw_cursor (0, 0);
+}
+#endif /* CONFIG_VIDEO_HW_CURSOR */
+
+/***************************************************************
+ * Wait for BitBlt ready
+ */
+static int
+video_wait_bitblt (unsigned long addr)
+{
+ unsigned long br04;
+ int i = 0;
+ br04 = in32r (addr);
+ while (br04 & 0x80000000) {
+ udelay (1);
+ br04 = in32r (addr);
+ if (i++ > 1000000) {
+ printf ("ERROR Timeout %lx\n", br04);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/***************************************************************
+ * Set up BitBlt Registrs
+ */
+static void
+SetDrawingEngine (int bits_per_pixel)
+{
+ unsigned long br04, br00;
+ unsigned char tmp;
+
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+ tmp = ctRead_i (CT_XR_O, 0x20); /* BitBLT Configuration */
+ tmp |= 0x02; /* reset BitBLT */
+ ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+ udelay (10);
+ tmp &= 0xfd; /* release reset BitBLT */
+ ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+
+ /* set pattern Address */
+ out32r (pGD->pciBase + BR05_o, PATTERN_ADR & 0x003ffff8);
+ br04 = 0;
+ if (bits_per_pixel == 1) {
+ br04 |= 0x00040000; /* monochome Pattern */
+ br04 |= 0x00001000; /* monochome source */
+ }
+ br00 = ((pGD->winSizeX * pGD->gdfBytesPP) << 16) + (pGD->winSizeX * pGD->gdfBytesPP); /* bytes per scanline */
+ out32r (pGD->pciBase + BR00_o, br00); /* */
+ out32r (pGD->pciBase + BR08_o, (10 << 16) + 10); /* dummy */
+ out32r (pGD->pciBase + BR04_o, br04); /* write all 0 */
+ out32r (pGD->pciBase + BR07_o, 0); /* destination */
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+/************************************************************************
+ * Get Parameters for the video mode:
+ */
+/*********************************************************************
+ * returns the length to the next seperator
+ */
+static int
+video_get_param_len (char *start, char sep)
+{
+ int i = 0;
+ while ((*start != 0) && (*start != sep)) {
+ start++;
+ i++;
+ }
+ return i;
+}
+
+static int
+video_search_param (char *start, char *param)
+{
+ int len, totallen, i;
+ char *p = start;
+ len = strlen (param);
+ totallen = len + strlen (start);
+ for (i = 0; i < totallen; i++) {
+ if (strncmp (p++, param, len) == 0)
+ return (i);
+ }
+ return -1;
+}
+
+/***************************************************************
+* Get parameter via the environment as it is done for the
+* linux kernel i.e:
+* video=ctfb:x:800,xv:1280,y:600,yv:1024,depth:16,mode:0,pclk:25000,
+* le:56,ri:48,up:26,lo:5,hs:152,vs:2,sync:0,vmode:0,accel:0
+*
+* penv is a pointer to the environment, containing the string, or the name of
+* another environment variable. It could even be the term "bootargs"
+*/
+
+#define GET_OPTION(name,var) \
+ if(strncmp(p,name,strlen(name))==0) { \
+ val_s=p+strlen(name); \
+ var=simple_strtoul(val_s, NULL, 10); \
+ }
+
+static int
+video_get_params (struct ctfb_res_modes *pPar, char *penv)
+{
+ char *p, *s, *val_s;
+ int i = 0, t;
+ int bpp;
+ int mode;
+ /* first search for the environment containing the real param string */
+ s = penv;
+ if ((p = getenv (s)) != NULL) {
+ s = p;
+ }
+ /* in case of the bootargs line, we have to start
+ * after "video=ctfb:"
+ */
+ i = video_search_param (s, "video=ctfb:");
+ if (i >= 0) {
+ s += i;
+ s += strlen ("video=ctfb:");
+ }
+ /* search for mode as a default value */
+ p = s;
+ t = 0;
+ mode = 0; /* default */
+ while ((i = video_get_param_len (p, ',')) != 0) {
+ GET_OPTION ("mode:", mode)
+ p += i;
+ if (*p != 0)
+ p++; /* skip ',' */
+ }
+ if (mode >= RES_MODES_COUNT)
+ mode = 0;
+ *pPar = res_mode_init[mode]; /* copy default values */
+ bpp = 24 - ((mode % 3) * 8);
+ p = s; /* restart */
+ while ((i = video_get_param_len (p, ',')) != 0) {
+ GET_OPTION ("x:", pPar->xres)
+ GET_OPTION ("y:", pPar->yres)
+ GET_OPTION ("le:", pPar->left_margin)
+ GET_OPTION ("ri:", pPar->right_margin)
+ GET_OPTION ("up:", pPar->upper_margin)
+ GET_OPTION ("lo:", pPar->lower_margin)
+ GET_OPTION ("hs:", pPar->hsync_len)
+ GET_OPTION ("vs:", pPar->vsync_len)
+ GET_OPTION ("sync:", pPar->sync)
+ GET_OPTION ("vmode:", pPar->vmode)
+ GET_OPTION ("pclk:", pPar->pixclock)
+ GET_OPTION ("depth:", bpp)
+ p += i;
+ if (*p != 0)
+ p++; /* skip ',' */
+ }
+ return bpp;
+}
+
+/****************************************************************************
+* supported Video Chips
+*/
+static struct pci_device_id supported[] = {
+ {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000},
+ {}
+};
+
+/*******************************************************************************
+*
+* Init video chip
+*/
+void *
+video_hw_init (void)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ unsigned short device_id;
+ pci_dev_t devbusfn;
+ int videomode;
+ unsigned long t1, hsynch, vsynch;
+ unsigned int pci_mem_base, *vm;
+ int tmp, i, bits_per_pixel;
+ char *penv;
+ struct ctfb_res_modes *res_mode;
+ struct ctfb_res_modes var_mode;
+ struct ctfb_chips_properties *chips_param;
+ /* Search for video chip */
+
+ if ((devbusfn = pci_find_devices (supported, 0)) < 0) {
+#ifdef CONFIG_VIDEO_ONBOARD
+ printf ("Video: Controller not found !\n");
+#endif
+ return (NULL);
+ }
+
+ /* PCI setup */
+ pci_write_config_dword (devbusfn, PCI_COMMAND,
+ (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
+ pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
+ pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
+ pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
+
+ /* get chips params */
+ for (chips_param = (struct ctfb_chips_properties *) &chips[0];
+ chips_param->device_id != 0; chips_param++) {
+ if (chips_param->device_id == device_id)
+ break;
+ }
+ if (chips_param->device_id == 0) {
+#ifdef CONFIG_VIDEO_ONBOARD
+ printf ("Video: controller 0x%X not supported\n", device_id);
+#endif
+ return NULL;
+ }
+ /* supported Video controller found */
+ printf ("Video: ");
+
+ tmp = 0;
+ videomode = 0x301;
+ /* get video mode via environment */
+ if ((penv = getenv ("videomode")) != NULL) {
+ /* deceide if it is a string */
+ if (penv[0] <= '9') {
+ videomode = (int) simple_strtoul (penv, NULL, 16);
+ tmp = 1;
+ }
+ } else {
+ tmp = 1;
+ }
+ if (tmp) {
+ /* parameter are vesa modes */
+ /* search params */
+ for (i = 0; i < VESA_MODES_COUNT; i++) {
+ if (vesa_modes[i].vesanr == videomode)
+ break;
+ }
+ if (i == VESA_MODES_COUNT) {
+ printf ("no VESA Mode found, switching to mode 0x301 ");
+ i = 0;
+ }
+ res_mode =
+ (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
+ resindex];
+ bits_per_pixel = vesa_modes[i].bits_per_pixel;
+ } else {
+
+ res_mode = (struct ctfb_res_modes *) &var_mode;
+ bits_per_pixel = video_get_params (res_mode, penv);
+ }
+
+ /* calculate available color depth for controller memory */
+ if (bits_per_pixel == 15)
+ tmp = 2;
+ else
+ tmp = bits_per_pixel >> 3; /* /8 */
+ if (((chips_param->max_mem -
+ ACCELMEMORY) / (res_mode->xres * res_mode->yres)) < tmp) {
+ tmp =
+ ((chips_param->max_mem -
+ ACCELMEMORY) / (res_mode->xres * res_mode->yres));
+ if (tmp == 0) {
+ printf
+ ("No matching videomode found .-> reduce resolution\n");
+ return NULL;
+ } else {
+ printf ("Switching back to %d Bits per Pixel ",
+ tmp << 3);
+ bits_per_pixel = tmp << 3;
+ }
+ }
+
+ /* calculate hsynch and vsynch freq (info only) */
+ t1 = (res_mode->left_margin + res_mode->xres +
+ res_mode->right_margin + res_mode->hsync_len) / 8;
+ t1 *= 8;
+ t1 *= res_mode->pixclock;
+ t1 /= 1000;
+ hsynch = 1000000000L / t1;
+ t1 *=
+ (res_mode->upper_margin + res_mode->yres +
+ res_mode->lower_margin + res_mode->vsync_len);
+ t1 /= 1000;
+ vsynch = 1000000000L / t1;
+
+ /* fill in Graphic device struct */
+ sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
+ res_mode->yres, bits_per_pixel, (hsynch / 1000),
+ (vsynch / 1000));
+ printf ("%s\n", pGD->modeIdent);
+ pGD->winSizeX = res_mode->xres;
+ pGD->winSizeY = res_mode->yres;
+ pGD->plnSizeX = res_mode->xres;
+ pGD->plnSizeY = res_mode->yres;
+ switch (bits_per_pixel) {
+ case 8:
+ pGD->gdfBytesPP = 1;
+ pGD->gdfIndex = GDF__8BIT_INDEX;
+ break;
+ case 15:
+ pGD->gdfBytesPP = 2;
+ pGD->gdfIndex = GDF_15BIT_555RGB;
+ break;
+ case 16:
+ pGD->gdfBytesPP = 2;
+ pGD->gdfIndex = GDF_16BIT_565RGB;
+ break;
+ case 24:
+ pGD->gdfBytesPP = 3;
+ pGD->gdfIndex = GDF_24BIT_888RGB;
+ break;
+ }
+ pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
+ pGD->pciBase = pci_mem_base;
+ pGD->frameAdrs = pci_mem_base;
+ pGD->memSize = chips_param->max_mem;
+ /* Cursor Start Address */
+ pGD->dprBase =
+ (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + pci_mem_base;
+ if ((pGD->dprBase & 0x0fff) != 0) {
+ /* allign it */
+ pGD->dprBase &= 0xfffff000;
+ pGD->dprBase += 0x00001000;
+ }
+ PRINTF ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
+ PATTERN_ADR);
+ pGD->vprBase = pci_mem_base; /* Dummy */
+ pGD->cprBase = pci_mem_base; /* Dummy */
+ /* set up Hardware */
+
+ ctWrite (CT_MSR_W_O, 0x01);
+
+ /* set the extended Registers */
+ ctLoadRegs (CT_XR_O, xreg);
+ /* set atribute registers */
+ SetArRegs ();
+ /* set Graphics register */
+ SetGrRegs ();
+ /* set sequencer */
+ SetSrRegs ();
+
+ /* set msr */
+ SetMsrRegs (res_mode);
+
+ /* set CRT Registers */
+ SetCrRegs (res_mode, bits_per_pixel);
+ /* set color mode */
+ SetBitsPerPixelIntoXrRegs (bits_per_pixel);
+
+ /* set PLL */
+ FindAndSetPllParamIntoXrRegs (res_mode->pixclock, chips_param);
+
+ ctWrite_i (CT_SR_O, 0, 0x03); /* clear synchronous reset */
+ /* Clear video memory */
+ i = pGD->memSize / 4;
+ vm = (unsigned int *) pGD->pciBase;
+ while (i--)
+ *vm++ = 0;
+ SetDrawingEngine (bits_per_pixel);
+#ifdef VGA_DUMP_REG
+ video_dump_reg ();
+#endif
+
+ return ((void *) &ctfb);
+}
+
+ /*******************************************************************************
+*
+* Set a RGB color in the LUT (8 bit index)
+*/
+void
+video_set_lut (unsigned int index, /* color number */
+ unsigned char r, /* red */
+ unsigned char g, /* green */
+ unsigned char b /* blue */
+ )
+{
+
+ ctWrite (CT_LUT_MASK_O, 0xff);
+
+ ctWrite (CT_LUT_START_O, (char) index);
+
+ ctWrite (CT_LUT_RGB_O, r); /* red */
+ ctWrite (CT_LUT_RGB_O, g); /* green */
+ ctWrite (CT_LUT_RGB_O, b); /* blue */
+ udelay (1);
+ ctWrite (CT_LUT_MASK_O, 0xff);
+}
+
+/*******************************************************************************
+*
+* Drawing engine fill on screen region
+*/
+void
+video_hw_rectfill (unsigned int bpp, /* bytes per pixel */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y, /* frame height */
+ unsigned int color /* fill color */
+ )
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ unsigned long *p, br04;
+
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+
+ p = (unsigned long *) PATTERN_ADR;
+ dim_x *= bpp;
+ if (bpp == 3)
+ bpp++; /* 24Bit needs a 32bit pattern */
+ memset (p, color, (bpp * sizeof (unsigned char) * 8 * 8)); /* 8 x 8 pattern data */
+ out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP); /* destination */
+ br04 = in32r (pGD->pciBase + BR04_o) & 0xffffff00;
+ br04 |= 0xF0; /* write Pattern P -> D */
+ out32r (pGD->pciBase + BR04_o, br04); /* */
+ out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x); /* starts the BITBlt */
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+/*******************************************************************************
+*
+* Drawing engine bitblt with screen region
+*/
+void
+video_hw_bitblt (unsigned int bpp, /* bytes per pixel */
+ unsigned int src_x, /* source pos x */
+ unsigned int src_y, /* source pos y */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y /* frame height */
+ )
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ unsigned long br04;
+
+ br04 = in32r (pGD->pciBase + BR04_o);
+
+ /* to prevent data corruption due to overlap, we have to
+ * find out if, and how the frames overlaps */
+ if (src_x < dst_x) {
+ /* src is more left than dest
+ * the frame may overlap -> start from right to left */
+ br04 |= 0x00000100; /* set bit 8 */
+ src_x += dim_x;
+ dst_x += dim_x;
+ } else {
+ br04 &= 0xfffffeff; /* clear bit 8 left to right */
+ }
+ if (src_y < dst_y) {
+ /* src is higher than dst
+ * the frame may overlap => start from bottom */
+ br04 |= 0x00000200; /* set bit 9 */
+ src_y += dim_y;
+ dst_y += dim_y;
+ } else {
+ br04 &= 0xfffffdff; /* clear bit 9 top to bottom */
+ }
+ dim_x *= bpp;
+ out32r (pGD->pciBase + BR06_o, ((pGD->winSizeX * src_y) + src_x) * pGD->gdfBytesPP); /* source */
+ out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP); /* destination */
+ br04 &= 0xffffff00;
+ br04 |= 0x000000CC; /* S -> D */
+ out32r (pGD->pciBase + BR04_o, br04); /* */
+ out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x); /* start the BITBlt */
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+#endif /* CONFIG_CT69000 */
+
+#endif /* CONFIG_VIDEO */
diff --git a/drivers/dc2114x.c b/drivers/dc2114x.c
new file mode 100644
index 0000000..e1147c0
--- /dev/null
+++ b/drivers/dc2114x.c
@@ -0,0 +1,720 @@
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
+ && defined(CONFIG_TULIP)
+
+#include <malloc.h>
+#include <net.h>
+#include <pci.h>
+
+#undef DEBUG
+#undef DEBUG_SROM
+#undef DEBUG_SROM2
+
+#undef UPDATE_SROM
+
+/* PCI Registers.
+ */
+#define PCI_CFDA_PSM 0x43
+
+#define CFRV_RN 0x000000f0 /* Revision Number */
+
+#define WAKEUP 0x00 /* Power Saving Wakeup */
+#define SLEEP 0x80 /* Power Saving Sleep Mode */
+
+#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */
+
+/* Ethernet chip registers.
+ */
+#define DE4X5_BMR 0x000 /* Bus Mode Register */
+#define DE4X5_TPD 0x008 /* Transmit Poll Demand Reg */
+#define DE4X5_RRBA 0x018 /* RX Ring Base Address Reg */
+#define DE4X5_TRBA 0x020 /* TX Ring Base Address Reg */
+#define DE4X5_STS 0x028 /* Status Register */
+#define DE4X5_OMR 0x030 /* Operation Mode Register */
+#define DE4X5_SICR 0x068 /* SIA Connectivity Register */
+#define DE4X5_APROM 0x048 /* Ethernet Address PROM */
+
+/* Register bits.
+ */
+#define BMR_SWR 0x00000001 /* Software Reset */
+#define STS_TS 0x00700000 /* Transmit Process State */
+#define STS_RS 0x000e0000 /* Receive Process State */
+#define OMR_ST 0x00002000 /* Start/Stop Transmission Command */
+#define OMR_SR 0x00000002 /* Start/Stop Receive */
+#define OMR_PS 0x00040000 /* Port Select */
+#define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */
+#define OMR_PM 0x00000080 /* Pass All Multicast */
+
+/* Descriptor bits.
+ */
+#define R_OWN 0x80000000 /* Own Bit */
+#define RD_RER 0x02000000 /* Receive End Of Ring */
+#define RD_LS 0x00000100 /* Last Descriptor */
+#define RD_ES 0x00008000 /* Error Summary */
+#define TD_TER 0x02000000 /* Transmit End Of Ring */
+#define T_OWN 0x80000000 /* Own Bit */
+#define TD_LS 0x40000000 /* Last Segment */
+#define TD_FS 0x20000000 /* First Segment */
+#define TD_ES 0x00008000 /* Error Summary */
+#define TD_SET 0x08000000 /* Setup Packet */
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define SROM_WRITE_CMD 5
+#define SROM_READ_CMD 6
+#define SROM_ERASE_CMD 7
+
+#define SROM_HWADD 0x0014 /* Hardware Address offset in SROM */
+#define SROM_RD 0x00004000 /* Read from Boot ROM */
+#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x4801
+#define EE_WRITE_1 0x4805
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define SROM_SR 0x00000800 /* Select Serial ROM when set */
+
+#define DT_IN 0x00000004 /* Serial Data In */
+#define DT_CLK 0x00000002 /* Serial ROM Clock */
+#define DT_CS 0x00000001 /* Serial ROM Chip Select */
+
+#define POLL_DEMAND 1
+
+#define RESET_DE4X5(dev) {\
+ int i;\
+ i=INL(dev, DE4X5_BMR);\
+ udelay(1000);\
+ OUTL(dev, i | BMR_SWR, DE4X5_BMR);\
+ udelay(1000);\
+ OUTL(dev, i, DE4X5_BMR);\
+ udelay(1000);\
+ for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\
+ udelay(1000);\
+}
+
+#define START_DE4X5(dev) {\
+ s32 omr; \
+ omr = INL(dev, DE4X5_OMR);\
+ omr |= OMR_ST | OMR_SR;\
+ OUTL(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */\
+}
+
+#define STOP_DE4X5(dev) {\
+ s32 omr; \
+ omr = INL(dev, DE4X5_OMR);\
+ omr &= ~(OMR_ST|OMR_SR);\
+ OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ \
+}
+
+#define NUM_RX_DESC PKTBUFSRX
+#define NUM_TX_DESC 1 /* Number of TX descriptors */
+#define RX_BUFF_SZ PKTSIZE_ALIGN
+
+#define TOUT_LOOP 1000000
+
+#define SETUP_FRAME_LEN 192
+#define ETH_ALEN 6
+
+
+struct de4x5_desc {
+ volatile s32 status;
+ u32 des1;
+ u32 buf;
+ u32 next;
+};
+
+static struct de4x5_desc rx_ring[NUM_RX_DESC]; /* RX descriptor ring */
+static struct de4x5_desc tx_ring[NUM_TX_DESC]; /* TX descriptor ring */
+static int rx_new; /* RX descriptor ring pointer */
+static int tx_new; /* TX descriptor ring pointer */
+
+static char rxRingSize;
+static char txRingSize;
+
+static void sendto_srom(struct eth_device* dev, u_int command, u_long addr);
+static int getfrom_srom(struct eth_device* dev, u_long addr);
+static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len);
+static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len);
+static int read_srom(struct eth_device *dev, u_long ioaddr, int index);
+#ifdef UPDATE_SROM
+static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value);
+static void update_srom(struct eth_device *dev, bd_t *bis);
+#endif
+static void read_hw_addr(struct eth_device* dev, bd_t * bis);
+static void send_setup_frame(struct eth_device* dev, bd_t * bis);
+
+static int dc21x4x_init(struct eth_device* dev, bd_t* bis);
+static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length);
+static int dc21x4x_recv(struct eth_device* dev);
+static void dc21x4x_halt(struct eth_device* dev);
+#ifdef CONFIG_TULIP_SELECT_MEDIA
+extern void dc21x4x_select_media(struct eth_device* dev);
+#endif
+
+#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a)
+
+static int INL(struct eth_device* dev, u_long addr)
+{
+ return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase));
+}
+
+static void OUTL(struct eth_device* dev, int command, u_long addr)
+{
+ *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command);
+}
+
+static struct pci_device_id supported[] = {
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST },
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 },
+ { }
+};
+
+int dc21x4x_initialize(bd_t *bis)
+{
+ int idx=0;
+ int card_number = 0;
+ int cfrv;
+ unsigned char timer;
+ pci_dev_t devbusfn;
+ unsigned int iobase;
+ unsigned short status;
+ struct eth_device* dev;
+
+ while(1) {
+ devbusfn = pci_find_devices(supported, idx++);
+ if (devbusfn == -1) {
+ break;
+ }
+
+ /* Get the chip configuration revision register. */
+ pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv);
+
+ if ((cfrv & CFRV_RN) < DC2114x_BRK ) {
+ printf("Error: The chip is not DC21143.\n");
+ continue;
+ }
+
+ pci_read_config_word(devbusfn, PCI_COMMAND, &status);
+ status |=
+#ifdef CONFIG_TULIP_USE_IO
+ PCI_COMMAND_IO |
+#else
+ PCI_COMMAND_MEMORY |
+#endif
+ PCI_COMMAND_MASTER;
+ pci_write_config_word(devbusfn, PCI_COMMAND, status);
+
+ pci_read_config_word(devbusfn, PCI_COMMAND, &status);
+ if (!(status & PCI_COMMAND_IO)) {
+ printf("Error: Can not enable I/O access.\n");
+ continue;
+ }
+
+ if (!(status & PCI_COMMAND_IO)) {
+ printf("Error: Can not enable I/O access.\n");
+ continue;
+ }
+
+ if (!(status & PCI_COMMAND_MASTER)) {
+ printf("Error: Can not enable Bus Mastering.\n");
+ continue;
+ }
+
+ /* Check the latency timer for values >= 0x60. */
+ pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer);
+
+ if (timer < 0x60) {
+ pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x60);
+ }
+
+#ifdef CONFIG_TULIP_USE_IO
+ /* read BAR for memory space access */
+ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
+ iobase &= PCI_BASE_ADDRESS_IO_MASK;
+#else
+ /* read BAR for memory space access */
+ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase);
+ iobase &= PCI_BASE_ADDRESS_MEM_MASK;
+#endif
+
+#ifdef DEBUG
+ printf("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase);
+#endif
+
+ dev = (struct eth_device*) malloc(sizeof *dev);
+
+ sprintf(dev->name, "dc21x4x#%d", card_number);
+#ifdef CONFIG_TULIP_USE_IO
+ dev->iobase = pci_io_to_phys(devbusfn, iobase);
+#else
+ dev->iobase = pci_mem_to_phys(devbusfn, iobase);
+#endif
+ dev->priv = (void*) devbusfn;
+ dev->init = dc21x4x_init;
+ dev->halt = dc21x4x_halt;
+ dev->send = dc21x4x_send;
+ dev->recv = dc21x4x_recv;
+
+ /* Ensure we're not sleeping. */
+ pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
+
+ udelay(10 * 1000);
+
+ read_hw_addr(dev, bis);
+
+ eth_register(dev);
+
+ card_number++;
+ }
+
+ return card_number;
+}
+
+static int dc21x4x_init(struct eth_device* dev, bd_t* bis)
+{
+ int i;
+ int devbusfn = (int) dev->priv;
+
+ /* Ensure we're not sleeping. */
+ pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
+
+ RESET_DE4X5(dev);
+
+ if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) {
+ printf("Error: Cannot reset ethernet controller.\n");
+ return 0;
+ }
+
+#ifdef CONFIG_TULIP_SELECT_MEDIA
+ dc21x4x_select_media(dev);
+#else
+ OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
+#endif
+
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ rx_ring[i].status = cpu_to_le32(R_OWN);
+ rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
+ rx_ring[i].buf = cpu_to_le32(phys_to_bus((u32) NetRxPackets[i]));
+ rx_ring[i].next = 0;
+ }
+
+ for (i=0; i < NUM_TX_DESC; i++) {
+ tx_ring[i].status = 0;
+ tx_ring[i].des1 = 0;
+ tx_ring[i].buf = 0;
+ tx_ring[i].next = 0;
+ }
+
+ rxRingSize = NUM_RX_DESC;
+ txRingSize = NUM_TX_DESC;
+
+ /* Write the end of list marker to the descriptor lists. */
+ rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
+ tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
+
+ /* Tell the adapter where the TX/RX rings are located. */
+ OUTL(dev, phys_to_bus((u32) &rx_ring), DE4X5_RRBA);
+ OUTL(dev, phys_to_bus((u32) &tx_ring), DE4X5_TRBA);
+
+ START_DE4X5(dev);
+
+ tx_new = 0;
+ rx_new = 0;
+
+ send_setup_frame(dev, bis);
+
+ return 1;
+}
+
+static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length)
+{
+ int status = -1;
+ int i;
+
+ if (length <= 0) {
+ printf("%s: bad packet size: %d\n", dev->name, length);
+ goto Done;
+ }
+
+ for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+ printf("%s: tx error buffer not ready\n", dev->name);
+ goto Done;
+ }
+ }
+
+ tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) packet));
+ tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length);
+ tx_ring[tx_new].status = cpu_to_le32(T_OWN);
+
+ OUTL(dev, POLL_DEMAND, DE4X5_TPD);
+
+ for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+ printf(".%s: tx buffer not ready\n", dev->name);
+ goto Done;
+ }
+ }
+
+ if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) {
+#if 0 /* test-only */
+ printf("TX error status = 0x%08X\n",
+ le32_to_cpu(tx_ring[tx_new].status));
+#endif
+ goto Done;
+ }
+
+ status = length;
+
+ Done:
+ return status;
+}
+
+static int dc21x4x_recv(struct eth_device* dev)
+{
+ s32 status;
+ int length = 0;
+
+ for ( ; ; ) {
+ status = (s32)le32_to_cpu(rx_ring[rx_new].status);
+
+ if (status & R_OWN) {
+ break;
+ }
+
+ if (status & RD_LS) {
+ /* Valid frame status.
+ */
+ if (status & RD_ES) {
+
+ /* There was an error.
+ */
+ printf("RX error status = 0x%08X\n", status);
+ } else {
+ /* A valid frame received.
+ */
+ length = (le32_to_cpu(rx_ring[rx_new].status) >> 16);
+
+ /* Pass the packet up to the protocol
+ * layers.
+ */
+ NetReceive(NetRxPackets[rx_new], length - 4);
+ }
+
+ /* Change buffer ownership for this frame, back
+ * to the adapter.
+ */
+ rx_ring[rx_new].status = cpu_to_le32(R_OWN);
+ }
+
+ /* Update entry information.
+ */
+ rx_new = (rx_new + 1) % rxRingSize;
+ }
+
+ return length;
+}
+
+static void dc21x4x_halt(struct eth_device* dev)
+{
+ int devbusfn = (int) dev->priv;
+
+ STOP_DE4X5(dev);
+ OUTL(dev, 0, DE4X5_SICR);
+
+ pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP);
+}
+
+static void send_setup_frame(struct eth_device* dev, bd_t *bis)
+{
+ int i;
+ char setup_frame[SETUP_FRAME_LEN];
+ char *pa = &setup_frame[0];
+
+ memset(pa, 0xff, SETUP_FRAME_LEN);
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ *(pa + (i & 1)) = dev->enetaddr[i];
+ if (i & 0x01) {
+ pa += 4;
+ }
+ }
+
+ for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+ printf("%s: tx error buffer not ready\n", dev->name);
+ goto Done;
+ }
+ }
+
+ tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0]));
+ tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN);
+ tx_ring[tx_new].status = cpu_to_le32(T_OWN);
+
+ OUTL(dev, POLL_DEMAND, DE4X5_TPD);
+
+ for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+ printf("%s: tx buffer not ready\n", dev->name);
+ goto Done;
+ }
+ }
+
+ if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) {
+ printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status));
+ }
+Done:
+ return;
+}
+
+/* SROM Read and write routines.
+ */
+
+static void
+sendto_srom(struct eth_device* dev, u_int command, u_long addr)
+{
+ OUTL(dev, command, addr);
+ udelay(1);
+}
+
+static int
+getfrom_srom(struct eth_device* dev, u_long addr)
+{
+ s32 tmp;
+
+ tmp = INL(dev, addr);
+ udelay(1);
+
+ return tmp;
+}
+
+/* Note: this routine returns extra data bits for size detection. */
+static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len)
+{
+ int i;
+ unsigned retval = 0;
+ int read_cmd = location | (SROM_READ_CMD << addr_len);
+
+ sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
+ sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+
+#ifdef DEBUG_SROM
+ printf(" EEPROM read at %d ", location);
+#endif
+
+ /* Shift the read command bits out. */
+ for (i = 4 + addr_len; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, ioaddr);
+ udelay(10);
+ sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr);
+ udelay(10);
+#ifdef DEBUG_SROM2
+ printf("%X", getfrom_srom(dev, ioaddr) & 15);
+#endif
+ retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0);
+ }
+
+ sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+
+#ifdef DEBUG_SROM2
+ printf(" :%X:", getfrom_srom(dev, ioaddr) & 15);
+#endif
+
+ for (i = 16; i > 0; i--) {
+ sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
+ udelay(10);
+#ifdef DEBUG_SROM2
+ printf("%X", getfrom_srom(dev, ioaddr) & 15);
+#endif
+ retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0);
+ sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+ udelay(10);
+ }
+
+ /* Terminate the EEPROM access. */
+ sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
+
+#ifdef DEBUG_SROM2
+ printf(" EEPROM value at %d is %5.5x.\n", location, retval);
+#endif
+
+ return retval;
+}
+
+/* This executes a generic EEPROM command, typically a write or write enable.
+ It returns the data output from the EEPROM, and thus may also be used for
+ reads. */
+static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len)
+{
+ unsigned retval = 0;
+
+#ifdef DEBUG_SROM
+ printf(" EEPROM op 0x%x: ", cmd);
+#endif
+
+ sendto_srom(dev,SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
+
+ /* Shift the command bits out. */
+ do {
+ short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
+ sendto_srom(dev,dataval, ioaddr);
+ udelay(10);
+
+#ifdef DEBUG_SROM2
+ printf("%X", getfrom_srom(dev,ioaddr) & 15);
+#endif
+
+ sendto_srom(dev,dataval | DT_CLK, ioaddr);
+ udelay(10);
+ retval = (retval << 1) | ((getfrom_srom(dev,ioaddr) & EE_DATA_READ) ? 1 : 0);
+ } while (--cmd_len >= 0);
+ sendto_srom(dev,SROM_RD | SROM_SR | DT_CS, ioaddr);
+
+ /* Terminate the EEPROM access. */
+ sendto_srom(dev,SROM_RD | SROM_SR, ioaddr);
+
+#ifdef DEBUG_SROM
+ printf(" EEPROM result is 0x%5.5x.\n", retval);
+#endif
+
+ return retval;
+}
+
+static int read_srom(struct eth_device *dev, u_long ioaddr, int index)
+{
+ int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
+
+ return do_eeprom_cmd(dev, ioaddr,
+ (((SROM_READ_CMD << ee_addr_size) | index) << 16)
+ | 0xffff, 3 + ee_addr_size + 16);
+}
+
+#ifdef UPDATE_SROM
+static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value)
+{
+ int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
+ int i;
+ unsigned short newval;
+
+ udelay(10*1000); /* test-only */
+
+#ifdef DEBUG_SROM
+ printf("ee_addr_size=%d.\n", ee_addr_size);
+ printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index);
+#endif
+
+ /* Enable programming modes. */
+ do_eeprom_cmd(dev, ioaddr, (0x4f << (ee_addr_size-4)), 3+ee_addr_size);
+
+ /* Do the actual write. */
+ do_eeprom_cmd(dev, ioaddr,
+ (((SROM_WRITE_CMD<<ee_addr_size)|index) << 16) | new_value,
+ 3 + ee_addr_size + 16);
+
+ /* Poll for write finished. */
+ sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+ for (i = 0; i < 10000; i++) /* Typical 2000 ticks */
+ if (getfrom_srom(dev, ioaddr) & EE_DATA_READ)
+ break;
+
+#ifdef DEBUG_SROM
+ printf(" Write finished after %d ticks.\n", i);
+#endif
+
+ /* Disable programming. */
+ do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size-4)), 3 + ee_addr_size);
+
+ /* And read the result. */
+ newval = do_eeprom_cmd(dev, ioaddr,
+ (((SROM_READ_CMD<<ee_addr_size)|index) << 16)
+ | 0xffff, 3 + ee_addr_size + 16);
+#ifdef DEBUG_SROM
+ printf(" New value at offset %d is %4.4x.\n", index, newval);
+#endif
+ return 1;
+}
+#endif
+
+static void read_hw_addr(struct eth_device *dev, bd_t *bis)
+{
+ u_short tmp, *p = (short *)(&dev->enetaddr[0]);
+ int i, j = 0;
+
+ for (i = 0; i < (ETH_ALEN >> 1); i++) {
+ tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i));
+ *p = le16_to_cpu(tmp);
+ j += *p++;
+ }
+
+ if ((j == 0) || (j == 0x2fffd)) {
+ memset (dev->enetaddr, 0, ETH_ALEN);
+#ifdef DEBUG
+ printf("Warning: can't read HW address from SROM.\n");
+#endif
+ goto Done;
+ }
+
+ return;
+
+Done:
+#ifdef UPDATE_SROM
+ update_srom(dev, bis);
+#endif
+ return;
+}
+
+#ifdef UPDATE_SROM
+static void update_srom(struct eth_device *dev, bd_t *bis)
+{
+ int i;
+ static unsigned short eeprom[0x40] = {
+ 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */
+ 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */
+ 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */
+ 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */
+ 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */
+ 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */
+ };
+
+ /* Ethernet Addr... */
+ eeprom[0x0a] = ((bis->bi_enetaddr[1] & 0xff) << 8) | (bis->bi_enetaddr[0] & 0xff);
+ eeprom[0x0b] = ((bis->bi_enetaddr[3] & 0xff) << 8) | (bis->bi_enetaddr[2] & 0xff);
+ eeprom[0x0c] = ((bis->bi_enetaddr[5] & 0xff) << 8) | (bis->bi_enetaddr[4] & 0xff);
+
+ for (i=0; i<0x40; i++)
+ {
+ write_srom(dev, DE4X5_APROM, i, eeprom[i]);
+ }
+}
+#endif
+
+#endif
diff --git a/drivers/i8042.c b/drivers/i8042.c
new file mode 100644
index 0000000..ce24fc9
--- /dev/null
+++ b/drivers/i8042.c
@@ -0,0 +1,655 @@
+/*
+ * (C) Copyright 2002 ELTEC Elektronik AG
+ * Frank Gottschling <fgottschling@eltec.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* i8042.c - Intel 8042 keyboard driver routines */
+
+/* includes */
+
+#include <common.h>
+
+#ifdef CONFIG_I8042_KBD
+
+#include <i8042.h>
+
+/* defines */
+
+#ifdef CONFIG_CONSOLE_CURSOR
+extern void console_cursor (int state);
+static int blinkCount = CFG_CONSOLE_BLINK_COUNT;
+static int cursor_state = 0;
+#endif
+
+/* locals */
+
+static int kbd_input = -1; /* no input yet */
+static int kbd_mapping = KBD_US; /* default US keyboard */
+static int kbd_flags = NORMAL; /* after reset */
+static int kbd_state = 0; /* unshift code */
+
+static void kbd_conv_char (unsigned char scan_code);
+static void kbd_led_set (void);
+static void kbd_normal (unsigned char scan_code);
+static void kbd_shift (unsigned char scan_code);
+static void kbd_ctrl (unsigned char scan_code);
+static void kbd_num (unsigned char scan_code);
+static void kbd_caps (unsigned char scan_code);
+static void kbd_scroll (unsigned char scan_code);
+static void kbd_alt (unsigned char scan_code);
+static int kbd_input_empty (void);
+static int kbd_reset (void);
+
+static unsigned char kbd_fct_map [144] =
+ { /* kbd_fct_map table for scan code */
+ 0, AS, AS, AS, AS, AS, AS, AS, /* scan 0- 7 */
+ AS, AS, AS, AS, AS, AS, AS, AS, /* scan 8- F */
+ AS, AS, AS, AS, AS, AS, AS, AS, /* scan 10-17 */
+ AS, AS, AS, AS, AS, CN, AS, AS, /* scan 18-1F */
+ AS, AS, AS, AS, AS, AS, AS, AS, /* scan 20-27 */
+ AS, AS, SH, AS, AS, AS, AS, AS, /* scan 28-2F */
+ AS, AS, AS, AS, AS, AS, SH, AS, /* scan 30-37 */
+ AS, AS, CP, 0, 0, 0, 0, 0, /* scan 38-3F */
+ 0, 0, 0, 0, 0, NM, ST, ES, /* scan 40-47 */
+ ES, ES, ES, ES, ES, ES, ES, ES, /* scan 48-4F */
+ ES, ES, ES, ES, 0, 0, AS, 0, /* scan 50-57 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
+ AS, 0, 0, AS, 0, 0, AS, 0, /* scan 70-77 */
+ 0, AS, 0, 0, 0, AS, 0, 0, /* scan 78-7F */
+ AS, CN, AS, AS, AK, ST, EX, EX, /* enhanced */
+ AS, EX, EX, AS, EX, AS, EX, EX /* enhanced */
+ };
+
+static unsigned char kbd_key_map [2][5][144] =
+ {
+ { /* US keyboard */
+ { /* unshift code */
+ 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */
+ '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */
+ 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */
+ '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */
+ 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */
+ ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
+ 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
+ '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
+ '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
+ '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
+ 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
+ },
+ { /* shift code */
+ 0, 0x1b, '!', '@', '#', '$', '%', '^', /* scan 0- 7 */
+ '&', '*', '(', ')', '_', '+', 0x08, '\t', /* scan 8- F */
+ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* scan 10-17 */
+ 'O', 'P', '{', '}', '\r', CN, 'A', 'S', /* scan 18-1F */
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* scan 20-27 */
+ '"', '~', SH, '|', 'Z', 'X', 'C', 'V', /* scan 28-2F */
+ 'B', 'N', 'M', '<', '>', '?', SH, '*', /* scan 30-37 */
+ ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
+ 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
+ '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
+ '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
+ '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
+ 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
+ },
+ { /* control code */
+ 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */
+ 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */
+ 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */
+ 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */
+ 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */
+ 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */
+ 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */
+ 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
+ '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
+ },
+ { /* non numeric code */
+ 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */
+ '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */
+ 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */
+ '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */
+ 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */
+ ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
+ 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */
+ 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */
+ 'r', 's', 'p', 'n', 0, 0, 0, 0, /* scan 50-57 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
+ '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
+ 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
+ },
+ { /* right alt mode - not used in US keyboard */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 0 - 7 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 8 - F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10 -17 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 18 -1F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20 -27 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28 -2F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30 -37 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38 -3F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40 -47 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48 -4F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50 -57 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58 -5F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60 -67 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68 -6F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70 -77 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78 -7F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
+ }
+ },
+ { /* german keyboard */
+ { /* unshift code */
+ 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */
+ '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */
+ 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */
+ 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */
+ 0x84, '^', SH, '#', 'y', 'x', 'c', 'v', /* scan 28-2F */
+ 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */
+ ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
+ 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
+ '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
+ '2', '3', '0', ',', 0, 0, '<', 0, /* scan 50-57 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
+ '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
+ 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
+ },
+ { /* shift code */
+ 0, 0x1b, '!', '"', 0x15, '$', '%', '&', /* scan 0- 7 */
+ '/', '(', ')', '=', '?', '`', 0x08, '\t', /* scan 8- F */
+ 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* scan 10-17 */
+ 'O', 'P', 0x9a, '*', '\r', CN, 'A', 'S', /* scan 18-1F */
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0x99, /* scan 20-27 */
+ 0x8e, 0xf8, SH, '\'', 'Y', 'X', 'C', 'V', /* scan 28-2F */
+ 'B', 'N', 'M', ';', ':', '_', SH, '*', /* scan 30-37 */
+ ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
+ 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
+ '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
+ '2', '3', '0', ',', 0, 0, '>', 0, /* scan 50-57 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
+ '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
+ 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
+ },
+ { /* control code */
+ 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */
+ 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */
+ 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */
+ 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */
+ 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */
+ 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */
+ 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */
+ 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
+ '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
+ },
+ { /* non numeric code */
+ 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */
+ '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */
+ 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */
+ 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */
+ 0x84, '^', SH, 0, 'y', 'x', 'c', 'v', /* scan 28-2F */
+ 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */
+ ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
+ 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */
+ 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */
+ 'r', 's', 'p', 'n', 0, 0, '<', 0, /* scan 50-57 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
+ '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
+ 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
+ },
+ { /* Right alt mode - is used in German keyboard */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 0 - 7 */
+ '{', '[', ']', '}', '\\', 0xff, 0xff, 0xff, /* scan 8 - F */
+ '@', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10 -17 */
+ 0xff, 0xff, 0xff, '~', 0xff, 0xff, 0xff, 0xff, /* scan 18 -1F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20 -27 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28 -2F */
+ 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30 -37 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38 -3F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40 -47 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48 -4F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '|', 0xff, /* scan 50 -57 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58 -5F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60 -67 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68 -6F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70 -77 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78 -7F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
+ }
+ }
+ };
+
+static unsigned char ext_key_map [] =
+ {
+ 0x1c, /* keypad enter */
+ 0x1d, /* right control */
+ 0x35, /* keypad slash */
+ 0x37, /* print screen */
+ 0x38, /* right alt */
+ 0x46, /* break */
+ 0x47, /* editpad home */
+ 0x48, /* editpad up */
+ 0x49, /* editpad pgup */
+ 0x4b, /* editpad left */
+ 0x4d, /* editpad right */
+ 0x4f, /* editpad end */
+ 0x50, /* editpad dn */
+ 0x51, /* editpad pgdn */
+ 0x52, /* editpad ins */
+ 0x53, /* editpad del */
+ 0x00 /* map end */
+ };
+
+/*******************************************************************************
+ *
+ * i8042_kbd_init - reset keyboard and init state flags
+ */
+int i8042_kbd_init (void)
+{
+ int keymap, try;
+ char *penv;
+
+ /* Init keyboard device (default US layout) */
+ keymap = KBD_US;
+ if ((penv = getenv ("keymap")) != NULL)
+ {
+ if (strncmp (penv, "de", 3) == 0)
+ keymap = KBD_GER;
+ }
+
+ for (try = 0; try < KBD_RESET_TRIES; try++)
+ {
+ if (kbd_reset() == 0)
+ {
+ kbd_mapping = keymap;
+ kbd_flags = NORMAL;
+ kbd_state = 0;
+ kbd_led_set();
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+/*******************************************************************************
+ *
+ * i8042_tstc - test if keyboard input is available
+ * option: cursor blinking if called in a loop
+ */
+int i8042_tstc (void)
+{
+ unsigned char scan_code = 0;
+
+#ifdef CONFIG_CONSOLE_CURSOR
+ if (--blinkCount == 0)
+ {
+ cursor_state ^= 1;
+ console_cursor (cursor_state);
+ blinkCount = CFG_CONSOLE_BLINK_COUNT;
+ udelay (10);
+ }
+#endif
+
+ if ((in8 (I8042_STATUS_REG) & 0x01) == 0)
+ return 0;
+ else
+ {
+ scan_code = in8 (I8042_DATA_REG);
+ if (scan_code == 0xfa)
+ return 0;
+
+ kbd_conv_char(scan_code);
+
+ if (kbd_input != -1)
+ return 1;
+ }
+ return 0;
+}
+
+
+/*******************************************************************************
+ *
+ * i8042_getc - wait till keyboard input is available
+ * option: turn on/off cursor while waiting
+ */
+int i8042_getc (void)
+{
+ int ret_chr;
+ unsigned char scan_code;
+
+ while (kbd_input == -1)
+ {
+ while ((in8 (I8042_STATUS_REG) & 0x01) == 0)
+ {
+#ifdef CONFIG_CONSOLE_CURSOR
+ if (--blinkCount==0)
+ {
+ cursor_state ^= 1;
+ console_cursor (cursor_state);
+ blinkCount = CFG_CONSOLE_BLINK_COUNT;
+ }
+ udelay (10);
+#endif
+ }
+
+ scan_code = in8 (I8042_DATA_REG);
+
+ if (scan_code != 0xfa)
+ kbd_conv_char (scan_code);
+ }
+ ret_chr = kbd_input;
+ kbd_input = -1;
+ return ret_chr;
+}
+
+
+/******************************************************************************/
+
+static void kbd_conv_char (unsigned char scan_code)
+{
+ if (scan_code == 0xe0)
+ {
+ kbd_flags |= EXT;
+ return;
+ }
+
+ /* if high bit of scan_code, set break flag */
+ if (scan_code & 0x80)
+ kbd_flags |= BRK;
+ else
+ kbd_flags &= ~BRK;
+
+ if ((scan_code == 0xe1) || (kbd_flags & E1))
+ {
+ if (scan_code == 0xe1)
+ {
+ kbd_flags ^= BRK; /* reset the break flag */
+ kbd_flags ^= E1; /* bitwise EXOR with E1 flag */
+ }
+ return;
+ }
+
+ scan_code &= 0x7f;
+
+ if (kbd_flags & EXT)
+ {
+ int i;
+
+ kbd_flags ^= EXT;
+ for (i=0; ext_key_map[i]; i++)
+ {
+ if (ext_key_map[i] == scan_code)
+ {
+ scan_code = 0x80 + i;
+ break;
+ }
+ }
+ /* not found ? */
+ if (!ext_key_map[i])
+ return;
+ }
+
+ switch (kbd_fct_map [scan_code])
+ {
+ case AS: kbd_normal (scan_code);
+ break;
+ case SH: kbd_shift (scan_code);
+ break;
+ case CN: kbd_ctrl (scan_code);
+ break;
+ case NM: kbd_num (scan_code);
+ break;
+ case CP: kbd_caps (scan_code);
+ break;
+ case ST: kbd_scroll (scan_code);
+ break;
+ case AK: kbd_alt (scan_code);
+ break;
+ }
+ return;
+}
+
+
+/******************************************************************************/
+
+static void kbd_normal (unsigned char scan_code)
+{
+ unsigned char chr;
+
+ if ((kbd_flags & BRK) == NORMAL)
+ {
+ chr = kbd_key_map [kbd_mapping][kbd_state][scan_code];
+ if ((chr == 0xff) || (chr == 0x00))
+ {
+ return;
+ }
+
+ /* if caps lock convert upper to lower */
+ if (((kbd_flags & CAPS) == CAPS) && (chr >= 'a' && chr <= 'z'))
+ {
+ chr -= 'a' - 'A';
+ }
+ kbd_input = chr;
+ }
+}
+
+
+/******************************************************************************/
+
+static void kbd_shift (unsigned char scan_code)
+{
+ if ((kbd_flags & BRK) == BRK)
+ {
+ kbd_state = AS;
+ kbd_flags &= (~SHIFT);
+ }
+ else
+ {
+ kbd_state = SH;
+ kbd_flags |= SHIFT;
+ }
+}
+
+
+/******************************************************************************/
+
+static void kbd_ctrl (unsigned char scan_code)
+{
+ if ((kbd_flags & BRK) == BRK)
+ {
+ kbd_state = AS;
+ kbd_flags &= (~CTRL);
+ }
+ else
+ {
+ kbd_state = CN;
+ kbd_flags |= CTRL;
+ }
+}
+
+
+/******************************************************************************/
+
+static void kbd_caps (unsigned char scan_code)
+{
+ if ((kbd_flags & BRK) == NORMAL)
+ {
+ kbd_flags ^= CAPS;
+ kbd_led_set (); /* update keyboard LED */
+ }
+}
+
+
+/******************************************************************************/
+
+static void kbd_num (unsigned char scan_code)
+{
+ if ((kbd_flags & BRK) == NORMAL)
+ {
+ kbd_flags ^= NUM;
+ kbd_state = (kbd_flags & NUM) ? AS : NM;
+ kbd_led_set (); /* update keyboard LED */
+ }
+}
+
+
+/******************************************************************************/
+
+static void kbd_scroll (unsigned char scan_code)
+{
+ if ((kbd_flags & BRK) == NORMAL)
+ {
+ kbd_flags ^= STP;
+ kbd_led_set (); /* update keyboard LED */
+ if (kbd_flags & STP)
+ kbd_input = 0x13;
+ else
+ kbd_input = 0x11;
+ }
+}
+
+/******************************************************************************/
+
+static void kbd_alt (unsigned char scan_code)
+{
+ if ((kbd_flags & BRK) == BRK)
+ {
+ kbd_state = AS;
+ kbd_flags &= (~ALT);
+ }
+ else
+ {
+ kbd_state = AK;
+ kbd_flags &= ALT;
+ }
+}
+
+
+/******************************************************************************/
+
+static void kbd_led_set (void)
+{
+ kbd_input_empty();
+ out8 (I8042_DATA_REG, 0xed); /* SET LED command */
+ kbd_input_empty();
+ out8 (I8042_DATA_REG, (kbd_flags & 0x7)); /* LED bits only */
+}
+
+
+/******************************************************************************/
+
+static int kbd_input_empty (void)
+{
+ int kbdTimeout = KBD_TIMEOUT;
+
+ /* wait for input buf empty */
+ while ((in8 (I8042_STATUS_REG) & 0x02) && kbdTimeout--)
+ udelay(1000);
+
+ return kbdTimeout;
+}
+
+/******************************************************************************/
+
+static int kbd_reset (void)
+{
+ if (kbd_input_empty() == 0)
+ return -1;
+
+ out8 (I8042_DATA_REG, 0xff);
+
+ udelay(250000);
+
+ if (kbd_input_empty() == 0)
+ return -1;
+
+ out8 (I8042_DATA_REG, 0x60);
+
+ if (kbd_input_empty() == 0)
+ return -1;
+
+ out8 (I8042_DATA_REG, 0x45);
+
+
+ if (kbd_input_empty() == 0)
+ return -1;
+
+ out8 (I8042_COMMAND_REG, 0xae);
+
+ if (kbd_input_empty() == 0)
+ return -1;
+
+ return 0;
+}
+
+#endif /* CONFIG_I8042_KBD */
diff --git a/drivers/ns87308.c b/drivers/ns87308.c
new file mode 100644
index 0000000..cf4d359
--- /dev/null
+++ b/drivers/ns87308.c
@@ -0,0 +1,121 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+#ifdef CFG_NS87308
+
+#include <ns87308.h>
+
+void initialise_ns87308 (void)
+{
+#ifdef CFG_NS87308_PS2MOD
+ unsigned char data;
+
+ /*
+ * Switch floppy drive to PS/2 mode.
+ */
+ read_pnp_config(SUPOERIO_CONF1, &data);
+ data &= 0xFB;
+ write_pnp_config(SUPOERIO_CONF1, data);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_KBC1)
+ PNP_SET_DEVICE_BASE(LDEV_KBC1, CFG_NS87308_KBC1_BASE);
+ write_pnp_config(LUN_CONFIG_REG, 0);
+ write_pnp_config(CBASE_HIGH, 0x00);
+ write_pnp_config(CBASE_LOW, 0x64);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_MOUSE)
+ PNP_ACTIVATE_DEVICE(LDEV_MOUSE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_RTC_APC)
+ PNP_SET_DEVICE_BASE(LDEV_RTC_APC, CFG_NS87308_RTC_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_FDC)
+ PNP_SET_DEVICE_BASE(LDEV_FDC, CFG_NS87308_FDC_BASE);
+ write_pnp_config(LUN_CONFIG_REG, 0x40);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_RARP)
+ PNP_SET_DEVICE_BASE(LDEV_PARP, CFG_NS87308_LPT_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_UART1)
+ PNP_SET_DEVICE_BASE(LDEV_UART1, CFG_NS87308_UART1_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_UART2)
+ PNP_SET_DEVICE_BASE(LDEV_UART2, CFG_NS87308_UART2_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_GPIO)
+ PNP_SET_DEVICE_BASE(LDEV_GPIO, CFG_NS87308_GPIO_BASE);
+#endif
+
+#if (CFG_NS87308_DEVS & CFG_NS87308_POWRMAN)
+#ifndef CFG_NS87308_PWMAN_BASE
+ PNP_ACTIVATE_DEVICE(LDEV_POWRMAN);
+#else
+ PNP_SET_DEVICE_BASE(LDEV_POWRMAN, CFG_NS87308_PWMAN_BASE);
+
+ /*
+ * Enable all units
+ */
+ write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_FER1, 0x7d);
+ write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_FER2, 0x87);
+
+#ifdef CFG_NS87308_PMC1
+ write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC1, CFG_NS87308_PMC1);
+#endif
+
+#ifdef CFG_NS87308_PMC2
+ write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC2, CFG_NS87308_PMC2);
+#endif
+
+#ifdef CFG_NS87308_PMC3
+ write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC3, CFG_NS87308_PMC3);
+#endif
+#endif
+#endif
+
+#ifdef CFG_NS87308_CS0_BASE
+ PNP_PGCS_CSLINE_BASE(0, CFG_NS87308_CS0_BASE);
+ PNP_PGCS_CSLINE_CONF(0, CFG_NS87308_CS0_CONF);
+#endif
+
+#ifdef CFG_NS87308_CS1_BASE
+ PNP_PGCS_CSLINE_BASE(1, CFG_NS87308_CS1_BASE);
+ PNP_PGCS_CSLINE_CONF(1, CFG_NS87308_CS1_CONF);
+#endif
+
+#ifdef CFG_NS87308_CS2_BASE
+ PNP_PGCS_CSLINE_BASE(2, CFG_NS87308_CS2_BASE);
+ PNP_PGCS_CSLINE_CONF(2, CFG_NS87308_CS2_CONF);
+#endif
+}
+
+#endif
diff --git a/drivers/pci.c b/drivers/pci.c
new file mode 100644
index 0000000..52584ce
--- /dev/null
+++ b/drivers/pci.c
@@ -0,0 +1,503 @@
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * PCI routines
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <command.h>
+#include <cmd_boot.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#ifdef DEBUG
+#define DEBUGF(x...) printf(x)
+#else
+#define DEBUGF(x...)
+#endif /* DEBUG */
+
+/*
+ *
+ */
+
+#define PCI_HOSE_OP(rw, size, type) \
+int pci_hose_##rw##_config_##size(struct pci_controller *hose, \
+ pci_dev_t dev, \
+ int offset, type value) \
+{ \
+ return hose->rw##_##size(hose, dev, offset, value); \
+}
+
+PCI_HOSE_OP(read, byte, u8 *)
+PCI_HOSE_OP(read, word, u16 *)
+PCI_HOSE_OP(read, dword, u32 *)
+PCI_HOSE_OP(write, byte, u8)
+PCI_HOSE_OP(write, word, u16)
+PCI_HOSE_OP(write, dword, u32)
+
+#define PCI_OP(rw, size, type, error_code) \
+int pci_##rw##_config_##size(pci_dev_t dev, int offset, type value) \
+{ \
+ struct pci_controller *hose = pci_bus_to_hose(PCI_BUS(dev)); \
+ \
+ if (!hose) \
+ { \
+ error_code; \
+ return -1; \
+ } \
+ \
+ return pci_hose_##rw##_config_##size(hose, dev, offset, value); \
+}
+
+PCI_OP(read, byte, u8 *, *value = 0xff)
+PCI_OP(read, word, u16 *, *value = 0xffff)
+PCI_OP(read, dword, u32 *, *value = 0xffffffff)
+PCI_OP(write, byte, u8, )
+PCI_OP(write, word, u16, )
+PCI_OP(write, dword, u32, )
+
+#define PCI_READ_VIA_DWORD_OP(size, type, off_mask) \
+int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose, \
+ pci_dev_t dev, \
+ int offset, type val) \
+{ \
+ u32 val32; \
+ \
+ if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0) \
+ return -1; \
+ \
+ *val = (val32 >> ((offset & (int)off_mask) * 8)); \
+ \
+ return 0; \
+}
+
+#define PCI_WRITE_VIA_DWORD_OP(size, type, off_mask, val_mask) \
+int pci_hose_write_config_##size##_via_dword(struct pci_controller *hose, \
+ pci_dev_t dev, \
+ int offset, type val) \
+{ \
+ u32 val32, mask, ldata; \
+ \
+ if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0) \
+ return -1; \
+ \
+ mask = val_mask; \
+ ldata = (((unsigned long)val) & mask) << ((offset & (int)off_mask) * 8);\
+ mask <<= ((mask & (int)off_mask) * 8); \
+ val32 = (val32 & ~mask) | ldata; \
+ \
+ if (pci_hose_write_config_dword(hose, dev, offset & 0xfc, val32) < 0) \
+ return -1; \
+ \
+ return 0; \
+}
+
+PCI_READ_VIA_DWORD_OP(byte, u8 *, 0x03)
+PCI_READ_VIA_DWORD_OP(word, u16 *, 0x02)
+PCI_WRITE_VIA_DWORD_OP(byte, u8, 0x03, 0x000000ff)
+PCI_WRITE_VIA_DWORD_OP(word, u16, 0x02, 0x0000ffff)
+
+/*
+ *
+ */
+
+static struct pci_controller* hose_head = NULL;
+
+void pci_register_hose(struct pci_controller* hose)
+{
+ struct pci_controller **phose = &hose_head;
+
+ while(*phose)
+ phose = &(*phose)->next;
+
+ hose->next = NULL;
+
+ *phose = hose;
+}
+
+struct pci_controller* pci_bus_to_hose(int bus)
+{
+ struct pci_controller *hose;
+
+ for (hose = hose_head; hose; hose = hose->next)
+ if (bus >= hose->first_busno &&
+ bus <= hose->last_busno)
+ return hose;
+
+ return NULL;
+}
+
+pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
+{
+ struct pci_controller * hose;
+ u16 vendor, device;
+ u8 header_type;
+ pci_dev_t bdf;
+ int i, bus, found_multi = 0;
+
+ for (hose = hose_head; hose; hose = hose->next)
+ {
+#if CFG_SCSI_SCAN_BUS_REVERSE
+ for (bus = hose->last_busno; bus >= hose->first_busno; bus--)
+#else
+ for (bus = hose->first_busno; bus <= hose->last_busno; bus++)
+#endif
+ for (bdf = PCI_BDF(bus,0,0);
+#ifdef CONFIG_ELPPC
+ bdf < PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1);
+#else
+ bdf < PCI_BDF(bus+1,0,0);
+#endif
+ bdf += PCI_BDF(0,0,1))
+ {
+ if (!PCI_FUNC(bdf))
+ {
+ pci_read_config_byte(bdf,
+ PCI_HEADER_TYPE,
+ &header_type);
+
+ found_multi = header_type & 0x80;
+ }
+ else
+ {
+ if (!found_multi)
+ continue;
+ }
+
+ pci_read_config_word(bdf,
+ PCI_VENDOR_ID,
+ &vendor);
+ pci_read_config_word(bdf,
+ PCI_DEVICE_ID,
+ &device);
+
+ for (i=0; ids[i].vendor != 0; i++)
+ if (vendor == ids[i].vendor &&
+ device == ids[i].device)
+ {
+ if (index <= 0)
+ return bdf;
+
+ index--;
+ }
+ }
+ }
+
+ return (-1);
+}
+
+pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
+{
+ static struct pci_device_id ids[2] = {{}, {0, 0}};
+
+ ids[0].vendor = vendor;
+ ids[0].device = device;
+
+ return pci_find_devices(ids, index);
+}
+
+/*
+ *
+ */
+
+unsigned long pci_hose_phys_to_bus(struct pci_controller* hose,
+ unsigned long phys_addr,
+ unsigned long flags)
+{
+ struct pci_region *res;
+ unsigned long bus_addr;
+ int i;
+
+ if (!hose)
+ {
+ printf("pci_hose_phys_to_bus: %s\n", "invalid hose");
+ goto Done;
+ }
+
+ for (i=0; i<hose->region_count; i++)
+ {
+ res = &hose->regions[i];
+
+ if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
+ continue;
+
+ bus_addr = phys_addr - res->phys_start + res->bus_start;
+
+ if (bus_addr >= res->bus_start &&
+ bus_addr < res->bus_start + res->size)
+ {
+ return bus_addr;
+ }
+ }
+
+ printf("pci_hose_phys_to_bus: %s\n", "invalid physical address");
+
+ Done:
+ return 0;
+}
+
+unsigned long pci_hose_bus_to_phys(struct pci_controller* hose,
+ unsigned long bus_addr,
+ unsigned long flags)
+{
+ struct pci_region *res;
+ int i;
+
+ if (!hose)
+ {
+ printf("pci_hose_bus_to_phys: %s\n", "invalid hose");
+ goto Done;
+ }
+
+ for (i=0; i<hose->region_count; i++)
+ {
+ res = &hose->regions[i];
+
+ if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
+ continue;
+
+ if (bus_addr >= res->bus_start &&
+ bus_addr < res->bus_start + res->size)
+ {
+ return bus_addr - res->bus_start + res->phys_start;
+ }
+ }
+
+ printf("pci_hose_bus_to_phys: %s\n", "invalid physical address");
+
+ Done:
+ return 0;
+}
+
+/*
+ *
+ */
+
+int pci_hose_config_device(struct pci_controller *hose,
+ pci_dev_t dev,
+ unsigned long io,
+ unsigned long mem,
+ unsigned long command)
+{
+ unsigned int bar_response, bar_size, bar_value, old_command;
+ unsigned char pin;
+ int bar, found_mem64;
+
+ DEBUGF("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n", io, mem, command);
+
+ pci_hose_write_config_dword(hose, dev, PCI_COMMAND, 0);
+
+ for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_5; bar += 4)
+ {
+ pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
+ pci_hose_read_config_dword(hose, dev, bar, &bar_response);
+
+ if (!bar_response)
+ continue;
+
+ found_mem64 = 0;
+
+ /* Check the BAR type and set our address mask */
+ if (bar_response & PCI_BASE_ADDRESS_SPACE)
+ {
+ bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1;
+ bar_value = io;
+
+ io = ((io - 1) | (bar_size - 1)) + 1;
+ }
+ else
+ {
+ if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64)
+ found_mem64 = 1;
+
+ bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ bar_value = mem;
+
+ mem = ((mem - 1) | (bar_size - 1)) + 1;
+ }
+
+ /* Write it out and update our limit */
+ pci_hose_write_config_dword(hose, dev, bar, bar_value);
+
+ if (found_mem64)
+ {
+ bar += 4;
+ pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
+ }
+ }
+
+ /* Configure Cache Line Size Register */
+ pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+
+ /* Configure Latency Timer */
+ pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+
+ /* Disable interrupt line, if device says it wants to use interrupts */
+ pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin != 0)
+ {
+ pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 0xff);
+ }
+
+ pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command);
+ pci_hose_write_config_dword(hose, dev, PCI_COMMAND,
+ (old_command & 0xffff0000) | command );
+
+ return 0;
+}
+
+/*
+ *
+ */
+
+struct pci_config_table *pci_find_config(struct pci_controller *hose,
+ unsigned short class,
+ unsigned int vendor,
+ unsigned int device,
+ unsigned int bus,
+ unsigned int dev,
+ unsigned int func)
+{
+ struct pci_config_table *table;
+
+ for (table = hose->config_table; table && table->vendor; table++)
+ {
+ if ((table->vendor == PCI_ANY_ID || table->vendor == vendor) &&
+ (table->device == PCI_ANY_ID || table->device == device) &&
+ (table->class == PCI_ANY_ID || table->class == class) &&
+ (table->bus == PCI_ANY_ID || table->bus == bus) &&
+ (table->dev == PCI_ANY_ID || table->dev == dev) &&
+ (table->func == PCI_ANY_ID || table->func == func))
+ {
+ return table;
+ }
+ }
+
+ return NULL;
+}
+
+void pci_cfgfunc_config_device(struct pci_controller *hose,
+ pci_dev_t dev,
+ struct pci_config_table *entry)
+{
+ pci_hose_config_device(hose, dev, entry->priv[0], entry->priv[1], entry->priv[2]);
+}
+
+void pci_cfgfunc_do_nothing(struct pci_controller *hose,
+ pci_dev_t dev, struct pci_config_table *entry)
+{
+}
+
+/*
+ *
+ */
+
+extern void pciauto_config_init(struct pci_controller *hose);
+extern void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
+
+int pci_hose_scan_bus(struct pci_controller *hose, int bus)
+{
+ unsigned int sub_bus, found_multi=0;
+ unsigned short vendor, device, class;
+ unsigned char header_type;
+ struct pci_config_table *cfg;
+ pci_dev_t dev;
+
+ sub_bus = bus;
+
+ for (dev = PCI_BDF(bus,0,0);
+ dev < PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1);
+ dev += PCI_BDF(0,0,1))
+ {
+#ifndef CONFIG_405GP /* don't skip host bridge on ppc405gp */
+ /* Skip our host bridge */
+ if ( dev == PCI_BDF(hose->first_busno,0,0) )
+ continue;
+#endif
+
+ if (PCI_FUNC(dev) && !found_multi)
+ continue;
+
+ pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
+
+ pci_hose_read_config_word(hose, dev, PCI_VENDOR_ID, &vendor);
+
+ if (vendor != 0xffff && vendor != 0x0000)
+ {
+
+ if (!PCI_FUNC(dev))
+ found_multi = header_type & 0x80;
+
+ DEBUGF("PCI Scan: Found Bus %d, Device %d, Function %d\n",
+ PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev) );
+
+ pci_hose_read_config_word(hose, dev, PCI_DEVICE_ID, &device);
+ pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
+
+ cfg = pci_find_config(hose, class, vendor, device,
+ PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
+ if (cfg)
+ cfg->config_device(hose, dev, cfg);
+#ifdef CONFIG_PCI_PNP
+ else
+ pciauto_config_device(hose, dev);
+#endif
+ if (hose->fixup_irq)
+ hose->fixup_irq(hose, dev);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+ /* Skip our host bridge */
+ if ( dev != PCI_BDF(hose->first_busno,0,0) ) {
+ unsigned char int_line;
+
+ pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_LINE,
+ &int_line);
+ printf(" %02x %02x %04x %04x %04x %02x\n",
+ PCI_BUS(dev), PCI_DEV(dev), vendor, device, class,
+ int_line);
+ }
+#endif
+ }
+ }
+
+ return sub_bus;
+}
+
+int pci_hose_scan(struct pci_controller *hose)
+{
+#ifdef CONFIG_PCI_PNP
+ pciauto_config_init(hose);
+#endif
+ return pci_hose_scan_bus(hose, hose->first_busno);
+}
+
+#endif /* CONFIG_PCI */
diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c
new file mode 100644
index 0000000..f665ee6
--- /dev/null
+++ b/drivers/pci_auto.c
@@ -0,0 +1,319 @@
+/*
+ * arch/ppc/kernel/pci_auto.c
+ *
+ * PCI autoconfiguration library
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ *
+ * 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 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <pci.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DEBUGF(x...) printf(x)
+#else
+#define DEBUGF(x...)
+#endif /* DEBUG */
+
+#define PCIAUTO_IDE_MODE_MASK 0x05
+
+/*
+ *
+ */
+
+void pciauto_region_init(struct pci_region* res)
+{
+ res->bus_lower = res->bus_start;
+}
+
+void pciauto_region_align(struct pci_region *res, unsigned long size)
+{
+ res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1;
+}
+
+int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar)
+{
+ unsigned long addr;
+
+ if (!res)
+ {
+ DEBUGF("No resource");
+ goto error;
+ }
+
+ addr = ((res->bus_lower - 1) | (size - 1)) + 1;
+
+ if (addr - res->bus_start + size > res->size)
+ {
+ DEBUGF("No room in resource");
+ goto error;
+ }
+
+ res->bus_lower = addr + size;
+
+ DEBUGF("address=0x%lx", addr);
+
+ *bar = addr;
+ return 0;
+
+ error:
+ *bar = 0xffffffff;
+ return -1;
+}
+
+/*
+ *
+ */
+
+void pciauto_setup_device(struct pci_controller *hose,
+ pci_dev_t dev, int bars_num,
+ struct pci_region *mem,
+ struct pci_region *io)
+{
+ unsigned int bar_value, bar_response, bar_size;
+ unsigned int cmdstat = 0;
+ struct pci_region *bar_res;
+ int bar, bar_nr = 0;
+ int found_mem64 = 0;
+
+ pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
+ cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER;
+
+ for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_0 + (bars_num*4); bar += 4)
+ {
+ /* Tickle the BAR and get the response */
+ pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
+ pci_hose_read_config_dword(hose, dev, bar, &bar_response);
+
+ /* If BAR is not implemented go to the next BAR */
+ if (!bar_response)
+ continue;
+
+ found_mem64 = 0;
+
+ /* Check the BAR type and set our address mask */
+ if (bar_response & PCI_BASE_ADDRESS_SPACE)
+ {
+ bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1;
+ bar_res = io;
+
+ DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%x, ", bar_nr, bar_size);
+ }
+ else
+ {
+ if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64)
+ found_mem64 = 1;
+
+ bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ bar_res = mem;
+
+ DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size);
+ }
+
+ if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0)
+ {
+ /* Write it out and update our limit */
+ pci_hose_write_config_dword(hose, dev, bar, bar_value);
+
+ /*
+ * If we are a 64-bit decoder then increment to the
+ * upper 32 bits of the bar and force it to locate
+ * in the lower 4GB of memory.
+ */
+ if (found_mem64)
+ {
+ bar += 4;
+ pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
+ }
+
+ cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ?
+ PCI_COMMAND_IO : PCI_COMMAND_MEMORY;
+ }
+
+ DEBUGF("\n");
+
+ bar_nr++;
+ }
+
+ pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat);
+ pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+ pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+}
+
+static void pciauto_prescan_setup_bridge(struct pci_controller *hose,
+ pci_dev_t dev, int sub_bus)
+{
+ struct pci_region *pci_mem = hose->pci_mem;
+ struct pci_region *pci_io = hose->pci_io;
+ unsigned int cmdstat;
+
+ pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
+
+ /* Configure bus number registers */
+ pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev));
+ pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus + 1);
+ pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff);
+
+ if (pci_mem)
+ {
+ /* Round memory allocator to 1MB boundary */
+ pciauto_region_align(pci_mem, 0x100000);
+
+ /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+ pci_hose_write_config_word(hose, dev, PCI_MEMORY_BASE,
+ (pci_mem->bus_lower & 0xfff00000) >> 16);
+
+ cmdstat |= PCI_COMMAND_MEMORY;
+ }
+
+ if (pci_io)
+ {
+ /* Round I/O allocator to 4KB boundary */
+ pciauto_region_align(pci_io, 0x1000);
+
+ pci_hose_write_config_byte(hose, dev, PCI_IO_BASE,
+ (pci_io->bus_lower & 0x0000f000) >> 8);
+ pci_hose_write_config_word(hose, dev, PCI_IO_BASE_UPPER16,
+ (pci_io->bus_lower & 0xffff0000) >> 16);
+
+ cmdstat |= PCI_COMMAND_IO;
+ }
+
+ /* We don't support prefetchable memory for now, so disable */
+ pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000);
+ pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x1000);
+
+ /* Enable memory and I/O accesses, enable bus master */
+ pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat | PCI_COMMAND_MASTER);
+}
+
+static void pciauto_postscan_setup_bridge(struct pci_controller *hose,
+ pci_dev_t dev, int sub_bus)
+{
+ struct pci_region *pci_mem = hose->pci_mem;
+ struct pci_region *pci_io = hose->pci_io;
+
+ /* Configure bus number registers */
+ pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus);
+
+ if (pci_mem)
+ {
+ /* Round memory allocator to 1MB boundary */
+ pciauto_region_align(pci_mem, 0x100000);
+
+ pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT,
+ (pci_mem->bus_lower-1) >> 16);
+ }
+
+ if (pci_io)
+ {
+ /* Round I/O allocator to 4KB boundary */
+ pciauto_region_align(pci_io, 0x1000);
+
+ pci_hose_write_config_byte(hose, dev, PCI_IO_LIMIT,
+ ((pci_io->bus_lower-1) & 0x0000f000) >> 8);
+ pci_hose_write_config_word(hose, dev, PCI_IO_LIMIT_UPPER16,
+ ((pci_io->bus_lower-1) & 0xffff0000) >> 16);
+ }
+}
+
+/*
+ *
+ */
+
+void pciauto_config_init(struct pci_controller *hose)
+{
+ int i;
+
+ hose->pci_io = hose->pci_mem = NULL;
+
+ for (i=0; i<hose->region_count; i++)
+ {
+ switch(hose->regions[i].flags)
+ {
+ case PCI_REGION_IO:
+ if (!hose->pci_io ||
+ hose->pci_io->size < hose->regions[i].size)
+ hose->pci_io = hose->regions + i;
+ break;
+ case PCI_REGION_MEM:
+ if (!hose->pci_mem ||
+ hose->pci_mem->size < hose->regions[i].size)
+ hose->pci_mem = hose->regions + i;
+ break;
+ }
+ }
+
+
+
+ if (hose->pci_mem)
+ {
+ pciauto_region_init(hose->pci_mem);
+
+ DEBUGF("PCI Autoconfig: Memory region: [%lx-%lx]\n",
+ hose->pci_mem->bus_start,
+ hose->pci_mem->bus_start + hose->pci_mem->size - 1);
+ }
+
+ if (hose->pci_io)
+ {
+ pciauto_region_init(hose->pci_io);
+
+ DEBUGF("PCI Autoconfig: I/O region: [%lx-%lx]\n",
+ hose->pci_io->bus_start,
+ hose->pci_io->bus_start + hose->pci_io->size - 1);
+ }
+}
+
+void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
+{
+ unsigned int sub_bus;
+ unsigned short class;
+ unsigned char prg_iface;
+
+ pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
+
+ switch(class)
+ {
+ case PCI_CLASS_BRIDGE_PCI:
+ pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_io);
+
+ DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev));
+
+ pciauto_prescan_setup_bridge(hose, dev, PCI_BUS(dev));
+
+ sub_bus = pci_hose_scan_bus(hose, PCI_BUS(dev)+1);
+
+ pciauto_postscan_setup_bridge(hose, dev, sub_bus);
+ break;
+
+ case PCI_CLASS_STORAGE_IDE:
+ pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prg_iface);
+ if (!(prg_iface & PCIAUTO_IDE_MODE_MASK))
+ {
+ DEBUGF("PCI Autoconfig: Skipping legacy mode IDE controller\n");
+ return;
+ }
+
+ pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
+ break;
+
+ default:
+ pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
+ break;
+ }
+}
+
+#endif /* CONFIG_PCI */
diff --git a/drivers/pcnet.c b/drivers/pcnet.c
new file mode 100644
index 0000000..f69cd2c
--- /dev/null
+++ b/drivers/pcnet.c
@@ -0,0 +1,526 @@
+/*
+ * (C) Copyright 2002 Wolfgang Grandegger, wg@denx.de.
+ *
+ * This driver for AMD PCnet network controllers is derived from the
+ * Linux driver pcnet32.c written 1996-1999 by Thomas Bogendoerfer.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#if 0
+#define PCNET_DEBUG_LEVEL 0 /* 0=off, 1=init, 2=rx/tx */
+#endif
+
+#if PCNET_DEBUG_LEVEL > 0
+#define DEBUG1(fmt,args...) printf (fmt ,##args)
+#if PCNET_DEBUG_LEVEL > 1
+#define DEBUG2(fmt,args...) printf (fmt ,##args)
+#else
+#define DEBUG2(fmt,args...)
+#endif
+#else
+#define DEBUG1(fmt,args...)
+#define DEBUG2(fmt,args...)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
+ && defined(CONFIG_PCNET)
+
+#if !defined(CONF_PCNET_79C973) && defined(CONF_PCNET_79C975)
+#error "Macro for PCnet chip version is not defined!"
+#endif
+
+/*
+ * Set the number of Tx and Rx buffers, using Log_2(# buffers).
+ * Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
+ * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
+ */
+#define PCNET_LOG_TX_BUFFERS 0
+#define PCNET_LOG_RX_BUFFERS 2
+
+#define TX_RING_SIZE (1 << (PCNET_LOG_TX_BUFFERS))
+#define TX_RING_LEN_BITS ((PCNET_LOG_TX_BUFFERS) << 12)
+
+#define RX_RING_SIZE (1 << (PCNET_LOG_RX_BUFFERS))
+#define RX_RING_LEN_BITS ((PCNET_LOG_RX_BUFFERS) << 4)
+
+#define PKT_BUF_SZ 1544
+
+/* The PCNET Rx and Tx ring descriptors. */
+struct pcnet_rx_head {
+ u32 base;
+ s16 buf_length;
+ s16 status;
+ u32 msg_length;
+ u32 reserved;
+};
+
+struct pcnet_tx_head {
+ u32 base;
+ s16 length;
+ s16 status;
+ u32 misc;
+ u32 reserved;
+};
+
+/* The PCNET 32-Bit initialization block, described in databook. */
+struct pcnet_init_block {
+ u16 mode;
+ u16 tlen_rlen;
+ u8 phys_addr[6];
+ u16 reserved;
+ u32 filter[2];
+ /* Receive and transmit ring base, along with extra bits. */
+ u32 rx_ring;
+ u32 tx_ring;
+ u32 reserved2;
+};
+
+typedef struct pcnet_priv {
+ struct pcnet_rx_head rx_ring[RX_RING_SIZE];
+ struct pcnet_tx_head tx_ring[TX_RING_SIZE];
+ struct pcnet_init_block init_block;
+ /* Receive Buffer space */
+ unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4];
+ int cur_rx;
+ int cur_tx;
+} pcnet_priv_t;
+
+static pcnet_priv_t *lp;
+
+/* Offsets from base I/O address for WIO mode */
+#define PCNET_RDP 0x10
+#define PCNET_RAP 0x12
+#define PCNET_RESET 0x14
+#define PCNET_BDP 0x16
+
+static u16 pcnet_read_csr (struct eth_device *dev, int index)
+{
+ outw (index, dev->iobase+PCNET_RAP);
+ return inw (dev->iobase+PCNET_RDP);
+}
+
+static void pcnet_write_csr (struct eth_device *dev, int index, u16 val)
+{
+ outw (index, dev->iobase+PCNET_RAP);
+ outw (val, dev->iobase+PCNET_RDP);
+}
+
+static u16 pcnet_read_bcr (struct eth_device *dev, int index)
+{
+ outw (index, dev->iobase+PCNET_RAP);
+ return inw (dev->iobase+PCNET_BDP);
+}
+
+static void pcnet_write_bcr (struct eth_device *dev, int index, u16 val)
+{
+ outw (index, dev->iobase+PCNET_RAP);
+ outw (val, dev->iobase+PCNET_BDP);
+}
+
+static void pcnet_reset (struct eth_device *dev)
+{
+ inw (dev->iobase+PCNET_RESET);
+}
+
+static int pcnet_check (struct eth_device *dev)
+{
+ outw (88, dev->iobase+PCNET_RAP);
+ return (inw (dev->iobase+PCNET_RAP) == 88);
+}
+
+static int pcnet_init( struct eth_device* dev, bd_t *bis);
+static int pcnet_send (struct eth_device* dev, volatile void *packet,
+ int length);
+static int pcnet_recv (struct eth_device* dev);
+static void pcnet_halt (struct eth_device* dev);
+static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_num);
+
+#define PCI_TO_MEM(d,a) pci_phys_to_mem((pci_dev_t)d->priv, (u_long)(a))
+#define PCI_TO_MEM_LE(d,a) (u32)(cpu_to_le32(PCI_TO_MEM(d,a)))
+
+static struct pci_device_id supported[] = {
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE },
+ { }
+};
+
+
+int pcnet_initialize(bd_t *bis)
+{
+ pci_dev_t devbusfn;
+ struct eth_device* dev;
+ u16 command, status;
+ int dev_nr = 0;
+
+ DEBUG1("\npcnet_initialize...\n");
+
+ for (dev_nr = 0; ; dev_nr++) {
+
+ /*
+ * Find the PCnet PCI device(s).
+ */
+ if ((devbusfn = pci_find_devices(supported, dev_nr)) < 0) {
+ break;
+ }
+
+ /*
+ * Allocate and pre-fill the device structure.
+ */
+ dev = (struct eth_device*) malloc(sizeof *dev);
+ dev->priv = (void *)devbusfn;
+ sprintf(dev->name, "pcnet#%d", dev_nr);
+
+ /*
+ * Setup the PCI device.
+ */
+ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &dev->iobase);
+ dev->iobase &= ~0xf;
+
+ DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ",
+ dev->name, devbusfn, dev->iobase);
+
+ command = PCI_COMMAND_IO | PCI_COMMAND_MASTER;
+ pci_write_config_word(devbusfn, PCI_COMMAND, command);
+ pci_read_config_word(devbusfn, PCI_COMMAND, &status);
+ if ((status & command) != command) {
+ printf("%s: Couldn't enable IO access or Bus Mastering\n",
+ dev->name);
+ free(dev);
+ continue;
+ }
+
+ pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40);
+
+ /*
+ * Probe the PCnet chip.
+ */
+ if (pcnet_probe(dev, bis, dev_nr) < 0) {
+ free(dev);
+ continue;
+ }
+
+ /*
+ * Setup device structure and register the driver.
+ */
+ dev->init = pcnet_init;
+ dev->halt = pcnet_halt;
+ dev->send = pcnet_send;
+ dev->recv = pcnet_recv;
+
+ eth_register(dev);
+ }
+
+ udelay(10 * 1000);
+
+ return dev_nr;
+}
+
+static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr)
+{
+ int chip_version;
+ char *chipname;
+#ifdef PCNET_HAS_PROM
+ int i;
+#endif
+
+ /* Reset the PCnet controller */
+ pcnet_reset(dev);
+
+ /* Check if register access is working */
+ if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) {
+ printf("%s: CSR register access check failed\n", dev->name);
+ return -1;
+ }
+
+ /* Identify the chip */
+ chip_version = pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev,89) << 16);
+ if ((chip_version & 0xfff) != 0x003)
+ return -1;
+ chip_version = (chip_version >> 12) & 0xffff;
+ switch (chip_version) {
+#ifdef CONFIG_PCNET_79C973
+ case 0x2625:
+ chipname = "PCnet/FAST III 79C973"; /* PCI */
+ break;
+#endif
+#ifdef CONFIG_PCNET_79C975
+ case 0x2627:
+ chipname = "PCnet/FAST III 79C975"; /* PCI */
+ break;
+#endif
+ default:
+ printf("%s: PCnet version %#x not supported\n",
+ dev->name, chip_version);
+ return -1;
+ }
+
+ DEBUG1("AMD %s\n", chipname);
+
+#ifdef PCNET_HAS_PROM
+ /*
+ * In most chips, after a chip reset, the ethernet address is read from
+ * the station address PROM at the base address and programmed into the
+ * "Physical Address Registers" CSR12-14.
+ */
+ for (i = 0; i < 3; i++) {
+ unsigned int val;
+ val = pcnet_read_csr(dev, i+12) & 0x0ffff;
+ /* There may be endianness issues here. */
+ dev->dev_addr[2*i] = val & 0x0ff;
+ dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff;
+ }
+#endif /* PCNET_HAS_PROM */
+
+ return 0;
+}
+
+static int pcnet_init(struct eth_device* dev, bd_t *bis)
+{
+ int i, val;
+ u32 addr;
+
+ DEBUG1("%s: pcnet_init...\n", dev->name);
+
+ /* Switch pcnet to 32bit mode */
+ pcnet_write_bcr (dev, 20, 2);
+
+#ifdef CONFIG_PN62
+ /* Setup LED registers */
+ val = pcnet_read_bcr (dev, 2) | 0x1000;
+ pcnet_write_bcr (dev, 2, val); /* enable LEDPE */
+ pcnet_write_bcr (dev, 4, 0x5080); /* 100MBit */
+ pcnet_write_bcr (dev, 5, 0x40c0); /* LNKSE */
+ pcnet_write_bcr (dev, 6, 0x4090); /* TX Activity */
+ pcnet_write_bcr (dev, 7, 0x4084); /* RX Activity */
+#endif
+
+ /* Set/reset autoselect bit */
+ val = pcnet_read_bcr (dev, 2) & ~2;
+ val |= 2;
+ pcnet_write_bcr (dev, 2, val);
+
+ /* Enable auto negotiate, setup, disable fd */
+ val = pcnet_read_bcr(dev, 32) & ~0x98;
+ val |= 0x20;
+ pcnet_write_bcr(dev, 32, val);
+
+ /*
+ * We only maintain one structure because the drivers will never
+ * be used concurrently. In 32bit mode the RX and TX ring entries
+ * must be aligned on 16-byte boundaries.
+ */
+ if (lp == NULL) {
+ addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10);
+ addr = (addr + 0xf) & ~0xf;
+ lp = (pcnet_priv_t *)addr;
+ }
+
+ lp->init_block.mode = cpu_to_le16(0x0000);
+ lp->init_block.filter[0] = 0x00000000;
+ lp->init_block.filter[1] = 0x00000000;
+
+ /*
+ * Initialize the Rx ring.
+ */
+ lp->cur_rx = 0;
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]);
+ lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ);
+ lp->rx_ring[i].status = cpu_to_le16(0x8000);
+ DEBUG1("Rx%d: base=0x%x buf_length=0x%x status=0x%x\n",
+ i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length,
+ lp->rx_ring[i].status);
+ }
+
+ /*
+ * Initialize the Tx ring. The Tx buffer address is filled in as
+ * needed, but we do need to clear the upper ownership bit.
+ */
+ lp->cur_tx = 0;
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ lp->tx_ring[i].base = 0;
+ lp->tx_ring[i].status = 0;
+ }
+
+ /*
+ * Setup Init Block.
+ */
+ DEBUG1("Init block at 0x%p: MAC", &lp->init_block);
+
+ for (i = 0; i < 6; i++) {
+ lp->init_block.phys_addr[i] = dev->enetaddr[i];
+ DEBUG1(" %02x", lp->init_block.phys_addr[i]);
+ }
+
+ lp->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS |
+ RX_RING_LEN_BITS);
+ lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring);
+ lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring);
+
+ DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n",
+ lp->init_block.tlen_rlen,
+ lp->init_block.rx_ring, lp->init_block.tx_ring);
+
+ /*
+ * Tell the controller where the Init Block is located.
+ */
+ addr = PCI_TO_MEM(dev, &lp->init_block);
+ pcnet_write_csr(dev, 1, addr & 0xffff);
+ pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff);
+
+ pcnet_write_csr (dev, 4, 0x0915);
+ pcnet_write_csr (dev, 0, 0x0001); /* start */
+
+ /* Wait for Init Done bit */
+ for (i = 10000; i > 0; i--) {
+ if (pcnet_read_csr (dev, 0) & 0x0100)
+ break;
+ udelay(10);
+ }
+ if (i <= 0) {
+ printf("%s: TIMEOUT: controller init failed\n", dev->name);
+ pcnet_reset (dev);
+ return 0;
+ }
+
+ /*
+ * Finally start network controller operation.
+ */
+ pcnet_write_csr (dev, 0, 0x0002);
+
+ return 1;
+}
+
+static int pcnet_send(struct eth_device* dev, volatile void *packet, int pkt_len)
+{
+ int i, status;
+ struct pcnet_tx_head *entry = &lp->tx_ring[lp->cur_tx];
+
+ DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len, packet);
+
+ /* Wait for completion by testing the OWN bit */
+ for (i = 1000; i > 0; i--) {
+ status = le16_to_cpu(entry->status);
+ if ((status & 0x8000) == 0)
+ break;
+ udelay(100);
+ DEBUG2(".");
+ }
+ if (i <= 0) {
+ printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n",
+ dev->name, lp->cur_tx, status);
+ pkt_len = 0;
+ goto failure;
+ }
+
+ /*
+ * Setup Tx ring. Caution: the write order is important here,
+ * set the status with the "ownership" bits last.
+ */
+ status = 0x8300;
+ entry->length = le16_to_cpu(-pkt_len);
+ entry->misc = 0x00000000;
+ entry->base = PCI_TO_MEM_LE(dev, packet);
+ entry->status = le16_to_cpu(status);
+
+ /* Trigger an immediate send poll. */
+ pcnet_write_csr (dev, 0, 0x0008);
+
+ failure:
+ if (++lp->cur_tx >= TX_RING_SIZE)
+ lp->cur_tx = 0;
+
+ DEBUG2("done\n");
+ return pkt_len;
+}
+
+static int pcnet_recv(struct eth_device* dev)
+{
+ struct pcnet_rx_head *entry;
+ int pkt_len = 0;
+ u16 status;
+
+ while (1) {
+ entry = &lp->rx_ring[lp->cur_rx];
+ /*
+ * If we own the next entry, it's a new packet. Send it up.
+ */
+ if (((status = le16_to_cpu(entry->status)) & 0x8000) != 0) {
+ break;
+ }
+ status >>= 8;
+
+ if (status != 0x03) { /* There was an error. */
+
+ printf("%s: Rx%d", dev->name, lp->cur_rx);
+ DEBUG1(" (status=0x%x)", status);
+ if (status & 0x20) printf(" Frame");
+ if (status & 0x10) printf(" Overflow");
+ if (status & 0x08) printf(" CRC");
+ if (status & 0x04) printf(" Fifo");
+ printf(" Error\n");
+ entry->status &= le16_to_cpu(0x03ff);
+
+ } else {
+
+ pkt_len = (le32_to_cpu(entry->msg_length) & 0xfff) - 4;
+ if (pkt_len < 60) {
+ printf("%s: Rx%d: invalid packet length %d\n",
+ dev->name, lp->cur_rx, pkt_len);
+ } else {
+ NetReceive(lp->rx_buf[lp->cur_rx], pkt_len);
+ DEBUG2("Rx%d: %d bytes from 0x%p\n",
+ lp->cur_rx, pkt_len, lp->rx_buf[lp->cur_rx]);
+ }
+ }
+ entry->status |= cpu_to_le16(0x8000);
+
+ if (++lp->cur_rx >= RX_RING_SIZE)
+ lp->cur_rx = 0;
+ }
+ return pkt_len;
+}
+
+static void pcnet_halt(struct eth_device* dev)
+{
+ int i;
+
+ DEBUG1("%s: pcnet_halt...\n", dev->name);
+
+ /* Reset the PCnet controller */
+ pcnet_reset (dev);
+
+ /* Wait for Stop bit */
+ for (i = 1000; i > 0; i--) {
+ if (pcnet_read_csr (dev, 0) & 0x4)
+ break;
+ udelay(10);
+ }
+ if (i <= 0) {
+ printf("%s: TIMEOUT: controller reset failed\n", dev->name);
+ }
+}
+
+#endif
diff --git a/drivers/smiLynxEM.c b/drivers/smiLynxEM.c
new file mode 100644
index 0000000..75d5a31
--- /dev/null
+++ b/drivers/smiLynxEM.c
@@ -0,0 +1,1059 @@
+/*
+ * (C) Copyright 1997-2002 ELTEC Elektronik AG
+ * Frank Gottschling <fgottschling@eltec.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * smiLynxEM.c
+ *
+ * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
+ *
+ * modification history
+ * --------------------
+ * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
+ *
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_VIDEO_SMI_LYNXEM)
+
+#include <pci.h>
+#include <video_fb.h>
+
+/*
+ * Export Graphic Device
+ */
+GraphicDevice smi;
+
+/*
+ * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
+ */
+#define VIDEO_MEM_SIZE 0x400000
+
+/*
+ * Supported video modes for SMI Lynx E/EM/EM+
+ */
+#define VIDEO_MODES 7
+#define DUAL_800_600 0 /* SMI710:VGA1:75Hz (pitch=1600) */
+ /* VGA2:60/120Hz (pitch=1600) */
+ /* SMI810:VGA1:75Hz (pitch=1600) */
+ /* VGA2:75Hz (pitch=1600) */
+#define DUAL_1024_768 1 /* VGA1:75Hz VGA2:73Hz (pitch=2048) */
+#define SINGLE_800_600 2 /* VGA1:75Hz (pitch=800) */
+#define SINGLE_1024_768 3 /* VGA1:75Hz (pitch=1024) */
+#define SINGLE_1280_1024 4 /* VGA1:75Hz (pitch=1280) */
+#define TV_MODE_CCIR 5 /* VGA1:50Hz (h=720;v=576;pitch=720) */
+#define TV_MODE_EIA 6 /* VGA1:60Hz (h=720;v=484;pitch=720) */
+
+
+/*
+ * ISA mapped regs
+ */
+#define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */
+#define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */
+#define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */
+#define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */
+#define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */
+#define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */
+#define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */
+#define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */
+#define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */
+#define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */
+#define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/
+
+
+/*
+ * Video processor control
+*/
+typedef struct {
+ unsigned int control;
+ unsigned int colorKey;
+ unsigned int colorKeyMask;
+ unsigned int start;
+ unsigned short offset;
+ unsigned short width;
+ unsigned int fifoPrio;
+ unsigned int fifoERL;
+ unsigned int YUVtoRGB;
+} SmiVideoProc;
+
+/*
+ * Video window control
+ */
+typedef struct {
+ unsigned short top;
+ unsigned short left;
+ unsigned short bottom;
+ unsigned short right;
+ unsigned int srcStart;
+ unsigned short width;
+ unsigned short offset;
+ unsigned char hStretch;
+ unsigned char vStretch;
+} SmiVideoWin;
+
+/*
+ * Capture port control
+ */
+typedef struct {
+ unsigned int control;
+ unsigned short topClip;
+ unsigned short leftClip;
+ unsigned short srcHeight;
+ unsigned short srcWidth;
+ unsigned int srcBufStart1;
+ unsigned int srcBufStart2;
+ unsigned short srcOffset;
+ unsigned short fifoControl;
+} SmiCapturePort;
+
+
+
+/*
+ * Register values for common video modes
+ */
+static char SMI_SCR[22] = {
+ /* all modes */
+ 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0x00, 0x15, 0x90,
+ 0x16, 0x10, 0x17, 0x2c, 0x18, 0xb1, 0x19, 0x20, 0x1a, 0x01
+};
+
+static char SMI_EXT_CRT[VIDEO_MODES][24] = {
+ { /* DUAL_800_600_8 */
+ 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+ 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+ },
+ { /* DUAL_1024_768_8 */
+ 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+ 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+ },
+ { /* SINGLE_800_600_8 */
+ 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+ 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+ 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x30, 0x09, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+ 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+ },
+ { /* TV_MODE_CCIR */
+ 0x30, 0x80, 0x31, 0x2b, 0x32, 0x06, 0x33, 0x01, 0x34, 0x26, 0x35, 0x88,
+ 0x36, 0x02, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x20, 0x3e, 0xa3, 0x3f, 0x00
+ },
+ { /* TV_MODE_EIA */
+ 0x30, 0x80, 0x31, 0x2b, 0x32, 0x06, 0x33, 0x00, 0x34, 0xf8, 0x35, 0x88,
+ 0x36, 0x02, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x20, 0x3e, 0xa3, 0x3f, 0x00
+ },
+};
+
+static char SMI_CRTCR[VIDEO_MODES][50] = {
+ { /* DUAL_800_600_8 */
+ 0x00, 0x7f, 0x01, 0x63, 0x02, 0x63, 0x03, 0x00, 0x04, 0x68, 0x05, 0x12,
+ 0x06, 0x6f, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x59, 0x11, 0x2c,
+ 0x12, 0x57, 0x13, 0x64, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
+ 0x18, 0xff
+ },
+ { /* DUAL_1024_768_8 */
+ 0x00, 0x9f, 0x01, 0x7f, 0x02, 0x7f, 0x03, 0x00, 0x04, 0x82, 0x05, 0x0e,
+ 0x06, 0x1e, 0x07, 0xf5, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x24,
+ 0x12, 0xff, 0x13, 0x80, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
+ 0x18, 0xff
+ },
+ { /* SINGLE_800_600_8 */
+ 0x00, 0x7f, 0x01, 0x63, 0x02, 0x63, 0x03, 0x00, 0x04, 0x68, 0x05, 0x12,
+ 0x06, 0x6f, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x59, 0x11, 0x2c,
+ 0x12, 0x57, 0x13, 0x32, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
+ 0x18, 0xff
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x00, 0x9f, 0x01, 0x7f, 0x02, 0x7f, 0x03, 0x00, 0x04, 0x82, 0x05, 0x0e,
+ 0x06, 0x1e, 0x07, 0xf5, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x24,
+ 0x12, 0xff, 0x13, 0x40, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
+ 0x18, 0xff
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x00, 0xce, 0x01, 0x9f, 0x02, 0x9f, 0x03, 0x00, 0x04, 0xa2, 0x05, 0x12,
+ 0x06, 0x2a, 0x07, 0x5a, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x23,
+ 0x12, 0xff, 0x13, 0x50, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
+ 0x18, 0xff
+ },
+ { /* TV_MODE_CCIR */
+ 0x00, 0x00, 0x01, 0x59, 0x02, 0x63, 0x03, 0x00, 0x04, 0x69, 0x05, 0x10,
+ 0x06, 0x72, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x58, 0x11, 0x2c,
+ 0x12, 0x57, 0x13, 0x2d, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
+ 0x18, 0xff
+ },
+ { /* TV_MODE_EIA */
+ 0x00, 0x00, 0x01, 0x59, 0x02, 0x63, 0x03, 0x00, 0x04, 0x69, 0x05, 0x10,
+ 0x06, 0x72, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
+ 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x58, 0x11, 0x2c,
+ 0x12, 0x57, 0x13, 0x2d, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
+ 0x18, 0xff
+ },
+};
+
+static char SMI_SEQR[10] = {
+ 0x00, 0x03, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e
+};
+
+static char SMI_PCR[VIDEO_MODES][8] = {
+ { /* DUAL_800_600_8 */
+ 0x20, 0x04, 0x21, 0x20, 0x22, 0x00, 0x23, 0x00
+ },
+ { /* DUAL_1024_768_8 */
+ 0x20, 0x04, 0x21, 0x20, 0x22, 0x00, 0x23, 0x00
+ },
+ { /* SINGLE_800_600_8 */
+ 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+ },
+ { /* TV_MODE_CCIR */
+ 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+ },
+ { /* TV_MODE_EIA */
+ 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
+ },
+};
+
+static char SMI_MCR[VIDEO_MODES][6] = {
+ { /* DUAL_800_600_8 */
+ 0x60, 0x01, 0x61, 0x00, 0x62, 0x7a
+ },
+ { /* DUAL_1024_768_8 */
+ 0x60, 0x01, 0x61, 0x00, 0x62, 0x7a
+ },
+ { /* SINGLE_800_600_8 */
+ 0x60, 0x00, 0x61, 0x00, 0x62, 0x34
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x60, 0x00, 0x61, 0x00, 0x62, 0xfe
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x60, 0x00, 0x61, 0x00, 0x62, 0xfe
+ },
+ { /* TV_MODE_CCIR */
+ 0x60, 0x00, 0x61, 0x00, 0x62, 0x34
+ },
+ { /* TV_MODE_EIA */
+ 0x60, 0x00, 0x61, 0x00, 0x62, 0x34
+ },
+};
+
+static char SMI_CCR[VIDEO_MODES][18] = {
+ { /* DUAL_800_600_8 */
+ 0x65, 0x34, 0x68, 0x50, 0x69, 0x05, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
+ 0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
+ },
+ { /* DUAL_1024_768_8 */
+ 0x65, 0x00, 0x68, 0x50, 0x69, 0x06, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x0b,
+ 0x6d, 0x02, 0x6e, 0x0b, 0x6f, 0x02
+ },
+ { /* SINGLE_800_600_8 */
+ 0x65, 0x34, 0x68, 0x40, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
+ 0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x65, 0x00, 0x68, 0x50, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x0b,
+ 0x6d, 0x02, 0x6e, 0x0b, 0x6f, 0x02
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x65, 0x00, 0x68, 0x50, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0xd9,
+ 0x6d, 0x17, 0x6e, 0xd9, 0x6f, 0x17
+ },
+ { /* TV_MODE_CCIR */
+ 0x65, 0x07, 0x68, 0xc0, 0x69, 0x81, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
+ 0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
+ },
+ { /* TV_MODE_EIA */
+ 0x65, 0x07, 0x68, 0xc0, 0x69, 0x81, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
+ 0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
+ },
+};
+
+static char SMI_SHVGA[VIDEO_MODES][24] = {
+ { /* DUAL_800_600_8 */
+ 0x40, 0x7f, 0x41, 0x63, 0x42, 0x00, 0x43, 0x68, 0x44, 0x12, 0x45, 0x6f,
+ 0x46, 0x57, 0x47, 0x00, 0x48, 0x59, 0x49, 0x0c, 0x4a, 0xa0, 0x4b, 0x20,
+ },
+ { /* DUAL_1024_768_8 */
+ 0x40, 0x9f, 0x41, 0x7f, 0x42, 0x00, 0x43, 0x82, 0x44, 0x0e, 0x45, 0x1e,
+ 0x46, 0xff, 0x47, 0x00, 0x48, 0x00, 0x49, 0x03, 0x4a, 0xe5, 0x4b, 0x20,
+ },
+ { /* SINGLE_800_600_8 */
+ 0x40, 0x7f, 0x41, 0x63, 0x42, 0x00, 0x43, 0x68, 0x44, 0x12, 0x45, 0x6f,
+ 0x46, 0x57, 0x47, 0x00, 0x48, 0x59, 0x49, 0x0c, 0x4a, 0xa0, 0x4b, 0x20,
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x40, 0x9f, 0x41, 0x7f, 0x42, 0x00, 0x43, 0x82, 0x44, 0x0e, 0x45, 0x1e,
+ 0x46, 0xff, 0x47, 0x00, 0x48, 0x01, 0x49, 0x04, 0x4a, 0xa5, 0x4b, 0x20,
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x40, 0xce, 0x41, 0x9f, 0x42, 0x00, 0x43, 0xa2, 0x44, 0x12, 0x45, 0x2a,
+ 0x46, 0xff, 0x47, 0x00, 0x48, 0x01, 0x49, 0x03, 0x4a, 0x4a, 0x4b, 0x20,
+ },
+ { /* TV_MODE_CCIR */
+ 0x40, 0x6d, 0x41, 0x59, 0x42, 0x00, 0x43, 0x60, 0x44, 0x09, 0x45, 0x38,
+ 0x46, 0x25, 0x47, 0x05, 0x48, 0x2a, 0x49, 0x00, 0x4a, 0x4d, 0x4b, 0x00,
+ },
+ { /* TV_MODE_EIA */
+ 0x40, 0x6d, 0x41, 0x59, 0x42, 0x00, 0x43, 0x60, 0x44, 0x09, 0x45, 0x06,
+ 0x46, 0xf7, 0x47, 0x05, 0x48, 0xfa, 0x49, 0x00, 0x4a, 0x41, 0x4b, 0x00,
+ },
+};
+
+
+static char SMI_GPR[VIDEO_MODES][12] = {
+ { /* DUAL_800_600_8 */
+ 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+ },
+ { /* DUAL_1024_768_8 */
+ 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+ },
+ { /* SINGLE_800_600_8 */
+ 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
+ },
+ { /* TV_MODE_CCIR */
+ 0x70, 0x82, 0x71, 0x8d, 0x72, 0x0c, 0x73, 0x32, 0x74, 0x09, 0x75, 0x28
+ },
+ { /* TV_MODE_EIA */
+ 0x70, 0x82, 0x71, 0x8d, 0x72, 0x0c, 0x73, 0x32, 0x74, 0x09, 0x75, 0x28
+ },
+};
+
+static char SMI_HCR[VIDEO_MODES][22] = {
+ { /* DUAL_800_600_8 */
+ 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+ },
+ { /* DUAL_1024_768_8 */
+ 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+ },
+ { /* SINGLE_800_600_8 */
+ 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+ },
+ { /* TV_MODE_CCIR */
+ 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+ },
+ { /* TV_MODE_EIA */
+ 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+ },
+};
+
+static char SMI_FPR[VIDEO_MODES][88] = {
+ { /* DUAL_800_600_8 */
+ 0x30, 0x36, 0x31, 0x83, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x03,
+ 0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
+ 0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x41,
+ 0x4b, 0xa0, 0x4c, 0x00,
+ 0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x67, 0x55, 0x71,
+ 0x56, 0x57, 0x57, 0x59, 0x58, 0x03, 0x59, 0x00, 0x5a, 0x4a,
+ 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+ 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+ 0xa0, 0x44
+ },
+ { /* DUAL_1024_768_8 */
+ 0x30, 0x3a, 0x31, 0x83, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
+ 0x3f, 0x00, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
+ 0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x41,
+ 0x4b, 0xa0, 0x4c, 0x00,
+ 0x50, 0x06, 0x51, 0x68, 0x52, 0xa7, 0x53, 0x7f, 0x54, 0x83, 0x55, 0x25,
+ 0x56, 0xff, 0x57, 0x03, 0x58, 0x04, 0x59, 0x00, 0x5a, 0xc2,
+ 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+ 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+ 0xa0, 0x44
+ },
+ { /* SINGLE_800_600_8 */
+ 0x30, 0x36, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x03,
+ 0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
+ 0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
+ 0x4b, 0xa0, 0x4c, 0x00,
+ 0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x67, 0x55, 0x71,
+ 0x56, 0x57, 0x57, 0x59, 0x58, 0x03, 0x59, 0x00, 0x5a, 0x4a,
+ 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+ 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+ 0xa0, 0x44
+ },
+ { /* SINGLE_1024_768_8 */
+ 0x30, 0x3a, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
+ 0x3f, 0x00, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
+ 0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x11,
+ 0x4b, 0xa0, 0x4c, 0x00,
+ 0x50, 0x06, 0x51, 0x68, 0x52, 0xa7, 0x53, 0x7f, 0x54, 0x83, 0x55, 0x24,
+ 0x56, 0xff, 0x57, 0x03, 0x58, 0x04, 0x59, 0x00, 0x5a, 0xc2,
+ 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+ 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+ 0xa0, 0x44
+ },
+ { /* SINGLE_1280_1024_8 */
+ 0x30, 0x3e, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
+ 0x3f, 0x00, 0x40, 0xa0, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
+ 0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x11,
+ 0x4b, 0xa0, 0x4c, 0x00,
+ 0x50, 0x08, 0x51, 0x88, 0x52, 0xd3, 0x53, 0x9f, 0x54, 0xa3, 0x55, 0x2a,
+ 0x56, 0xff, 0x57, 0x04, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x63,
+ 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
+ 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
+ 0xa0, 0x44
+ },
+ { /* TV_MODE_CCIR */
+ 0x30, 0x24, 0x31, 0x84, 0x32, 0x20, 0x33, 0x09, 0x34, 0xf0, 0x3e, 0x03,
+ 0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
+ 0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
+ 0x4b, 0xa0, 0x4c, 0x00,
+ 0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x68, 0x55, 0x73,
+ 0x56, 0x57, 0x57, 0x58, 0x58, 0x04, 0x59, 0x57, 0x5a, 0x7b,
+ 0xa1, 0x10, 0xa2, 0xab, 0xa3, 0x98, 0xa4, 0xc1, 0xa8, 0x8c, 0xa9, 0x05,
+ 0xaa, 0x17, 0xab, 0x35, 0xac, 0x41, 0xad, 0x68, 0xae, 0x00, 0xaf, 0x00,
+ 0xa0, 0x00
+ },
+ { /* TV_MODE_EIA */
+ 0x30, 0x24, 0x31, 0x84, 0x32, 0x20, 0x33, 0x09, 0x34, 0xf0, 0x3e, 0x03,
+ 0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
+ 0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
+ 0x4b, 0xa0, 0x4c, 0x00,
+ 0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x68, 0x55, 0x73,
+ 0x56, 0x57, 0x57, 0x58, 0x58, 0x04, 0x59, 0x57, 0x5a, 0x7b,
+ 0xa1, 0x10, 0xa2, 0xab, 0xa3, 0x98, 0xa4, 0xc1, 0xa8, 0x8c, 0xa9, 0x05,
+ 0xaa, 0x17, 0xab, 0x35, 0xac, 0x41, 0xad, 0x68, 0xae, 0x00, 0xaf, 0x00,
+ 0xa0, 0x00
+ },
+};
+
+static char SMI_GCR[18] = {
+ 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
+ 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff
+};
+
+/*******************************************************************************
+*
+* Read SMI ISA register
+*/
+static char smiRead (unsigned short index, char reg)
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+ out8 ((pGD->isaBase + index), reg);
+ return (in8 (pGD->isaBase + index + 1));
+}
+
+/*******************************************************************************
+*
+* Write SMI ISA register
+*/
+static void smiWrite (unsigned short index, char reg, char val)
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+ out8 ((pGD->isaBase + index), reg);
+ out8 ((pGD->isaBase + index + 1), val);
+}
+
+/*******************************************************************************
+*
+* Write a table of SMI ISA register
+*/
+static void smiLoadRegs (
+ unsigned int iReg,
+ unsigned int dReg,
+ char *regTab,
+ unsigned int tabSize
+ )
+{
+ register int i;
+
+ for (i=0; i<tabSize; i+=2)
+ {
+ out8 (iReg, regTab[i]);
+ out8 (dReg, regTab[i+1]);
+ }
+}
+
+/*******************************************************************************
+*
+* Init capture port registers
+*/
+static void smiInitCapturePort (void)
+{
+ SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
+
+ out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip));
+ out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
+ out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
+ out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
+ out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
+ out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
+ out32r ((pGD->cprBase + 0x0000), pCP->control);
+}
+
+
+/*******************************************************************************
+*
+* Init video processor registers
+*/
+static void smiInitVideoProcessor (void)
+{
+ SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
+ SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
+ register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
+
+ pVP->width = pGD->plnSizeX * pGD->gdfBytesPP;
+ pVP->control |= pGD->gdfIndex << 16;
+ pVWin->bottom = pGD->winSizeY - 1;
+ pVWin->right = pGD->winSizeX - 1;
+ pVWin->width = pVP->width;
+
+ /* color key */
+ out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
+
+ /* color key mask */
+ out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
+
+ /* data src start adrs */
+ out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
+
+ /* data width and offset */
+ out32r ((pGD->vprBase + 0x0010),
+ ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
+ (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
+
+ /* video window 1 */
+ out32r ((pGD->vprBase + 0x0014),
+ ((pVWin->top << 16) | pVWin->left));
+
+ out32r ((pGD->vprBase + 0x0018),
+ ((pVWin->bottom << 16) | pVWin->right));
+
+ out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
+
+ out32r ((pGD->vprBase + 0x0020),
+ (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
+
+ out32r ((pGD->vprBase + 0x0024),
+ (((pVWin->hStretch) << 8) | pVWin->vStretch));
+
+ /* video window 2 */
+ out32r ((pGD->vprBase + 0x0028),
+ ((pVWin->top << 16) | pVWin->left));
+
+ out32r ((pGD->vprBase + 0x002c),
+ ((pVWin->bottom << 16) | pVWin->right));
+
+ out32r ((pGD->vprBase + 0x0030),
+ pVWin->srcStart / 8);
+
+ out32r ((pGD->vprBase + 0x0034),
+ (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
+
+ out32r ((pGD->vprBase + 0x0038),
+ (((pVWin->hStretch) << 8) | pVWin->vStretch));
+
+ /* fifo prio control */
+ out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
+
+ /* fifo empty request levell */
+ out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
+
+ /* conversion constant */
+ out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
+
+ /* vpr control word */
+ out32r ((pGD->vprBase + 0x0000), pVP->control);
+}
+
+/******************************************************************************
+ *
+ * Init drawing engine registers
+ */
+static void smiInitDrawingEngine (void)
+{
+ GraphicDevice *pGD = (GraphicDevice *)&smi;
+ unsigned int val;
+
+ /* don't start now */
+ out32r ((pGD->dprBase + 0x000c), 0x000f0000);
+
+ /* set rop2 to copypen */
+ val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
+ out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
+
+ /* set clip rect */
+ out32r ((pGD->dprBase + 0x002c), 0);
+ out32r ((pGD->dprBase + 0x0030),
+ ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
+
+ /* src row pitch */
+ val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
+ out32r ((pGD->dprBase + 0x0010),
+ (val | pGD->plnSizeX * pGD->gdfBytesPP));
+
+ /* dst row pitch */
+ val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
+ out32r ((pGD->dprBase + 0x0010),
+ (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
+
+ /* window width src/dst */
+ out32r ((pGD->dprBase + 0x003c),
+ (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
+ (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
+ out16r ((pGD->dprBase + 0x001e), 0x0000);
+
+ /* src base adrs */
+ out32r ((pGD->dprBase + 0x0040),
+ (((pGD->frameAdrs/8) & 0x000fffff)));
+
+ /* dst base adrs */
+ out32r ((pGD->dprBase + 0x0044),
+ (((pGD->frameAdrs/8) & 0x000fffff)));
+
+ /* foreground color */
+ out32r ((pGD->dprBase + 0x0014), pGD->fg);
+
+ /* background color */
+ out32r ((pGD->dprBase + 0x0018), pGD->bg);
+
+ /* xcolor */
+ out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
+
+ /* xcolor mask */
+ out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
+
+ /* bit mask */
+ out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
+
+ /* load mono pattern */
+ out32r ((pGD->dprBase + 0x0034), 0);
+ out32r ((pGD->dprBase + 0x0038), 0);
+}
+
+static struct pci_device_id supported[] = {
+ { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
+ { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
+ { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
+ { }
+};
+
+
+/*******************************************************************************
+*
+* Init video chip with common Linux graphic modes (lilo)
+*/
+void *video_hw_init (void)
+{
+ GraphicDevice *pGD = (GraphicDevice *)&smi;
+ unsigned short device_id;
+ pci_dev_t devbusfn;
+ int videomode;
+ unsigned int pci_mem_base, *vm, i;
+ unsigned int gdfTab[] = { 1, 2, 2, 4, 3, 1 };
+ char *penv;
+ char *gdfModes[] =
+ {
+ "8 Bit Index Color",
+ "15 Bit 5-5-5 RGB",
+ "16 Bit 5-6-5 RGB",
+ "32 Bit X-8-8-8 RGB",
+ "24 Bit 8-8-8 RGB",
+ "8 Bit 3-3-2 RGB"
+ };
+ int vgaModes[16][2] =
+ {
+ {769, -1}, {771, 0x00002}, {773, 0x00003}, {775, 0x00004},
+ {784, -1}, {787, 0x10002}, {790, 0x10003}, {793, 0x10004},
+ {785, -1}, {788, 0x20002}, {791, 0x20003}, {794, 0x20004},
+ {786, -1}, {789, 0x40002}, {792, 0x40003}, {795, 0x40004}
+ };
+
+ /* Search for video chip */
+ printf("Video: ");
+
+ if ((devbusfn = pci_find_devices(supported, 0)) < 0)
+ {
+ printf ("Controller not found !\n");
+ return (NULL);
+ }
+
+ /* PCI setup */
+ pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
+ pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
+ pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
+ pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
+
+ /* Initialize the video controller */
+ if ((penv = getenv ("videomode")) != NULL)
+ videomode = (int)simple_strtoul (penv, NULL, 16);
+ else
+ videomode = 0x303; /* Default 800x600 8 bit index color */
+
+ /* Compare with common vga mode numbers */
+ for (i=0; i<16; i++)
+ {
+ if (vgaModes[i][0] == videomode)
+ {
+ if (vgaModes[i][1] == -1)
+ {
+ printf("Videomode not supported !\n");
+ return (NULL); /* mode not supported */
+ }
+ pGD->mode = vgaModes[i][1]; /* use driver int. mode number */
+ break;
+ }
+ }
+
+ /* Extract graphic data format */
+ pGD->gdfIndex = (pGD->mode & 0x00070000) >> 16;
+ if (pGD->gdfIndex > 5)
+ pGD->gdfIndex = 0;
+ pGD->gdfBytesPP = gdfTab[pGD->gdfIndex];
+
+ /* Extract graphic resolution */
+ pGD->mode &= 0xf;
+
+ /* Exit for not supported resolutions */
+ if (((pGD->mode==DUAL_800_600) || (pGD->mode==DUAL_1024_768)) && (pGD->gdfBytesPP > 1))
+ {
+ printf ("Dual screen for 1BPP only !\n");
+ return (NULL);
+ }
+
+ if ((pGD->mode==SINGLE_1280_1024) && (pGD->gdfBytesPP==4))
+ {
+ printf ("Out of memory !\n");
+ return (NULL);
+ }
+
+ /* Set graphic parameters */
+ switch (pGD->mode)
+ {
+ case DUAL_800_600:
+ pGD->winSizeX = 800;
+ pGD->winSizeY = 600;
+ pGD->plnSizeX = 1600;
+ pGD->plnSizeY = 600;
+ sprintf (pGD->modeIdent, "Dual Screen 800x600 with %s", gdfModes[pGD->gdfIndex]);
+ break;
+ case DUAL_1024_768:
+ pGD->winSizeX = 1024;
+ pGD->winSizeY = 768;
+ pGD->plnSizeX = 2048;
+ pGD->plnSizeY = 768;
+ sprintf (pGD->modeIdent, "Dual Screen 1024x768 with %s", gdfModes[pGD->gdfIndex]);
+ break;
+ case SINGLE_800_600:
+ pGD->winSizeX = 800;
+ pGD->winSizeY = 600;
+ pGD->plnSizeX = 800;
+ pGD->plnSizeY = 600;
+ sprintf (pGD->modeIdent, "Single Screen 800x600 with %s", gdfModes[pGD->gdfIndex]);
+ break;
+ case SINGLE_1024_768:
+ pGD->winSizeX = 1024;
+ pGD->winSizeY = 768;
+ pGD->plnSizeX = 1024;
+ pGD->plnSizeY = 768;
+ sprintf (pGD->modeIdent,"Single Screen 1024x768 with %s", gdfModes[pGD->gdfIndex]);
+ break;
+ case TV_MODE_CCIR:
+ pGD->winSizeX = 720;
+ pGD->winSizeY = 576;
+ pGD->plnSizeX = 720;
+ pGD->plnSizeY = 576;
+ sprintf (pGD->modeIdent, "TV Mode CCIR with %s", gdfModes[pGD->gdfIndex]);
+ break;
+ case TV_MODE_EIA:
+ pGD->winSizeX = 720;
+ pGD->winSizeY = 484;
+ pGD->plnSizeX = 720;
+ pGD->plnSizeY = 484;
+ sprintf (pGD->modeIdent, "TV Mode EIA with %s", gdfModes[pGD->gdfIndex]);
+ break;
+ case SINGLE_1280_1024:
+ pGD->winSizeX = 1280;
+ pGD->winSizeY = 1024;
+ pGD->plnSizeX = 1280;
+ pGD->plnSizeY = 1024;
+ sprintf (pGD->modeIdent, "Single Screen 1280x1024 with %s", gdfModes[pGD->gdfIndex]);
+ break;
+ default:
+ printf("Videomode not supported !\n");
+ return (NULL);
+ }
+
+
+ pGD->isaBase = CFG_ISA_IO;
+ pGD->pciBase = pci_mem_base;
+ pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
+ pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
+ pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
+ pGD->frameAdrs = pci_mem_base;
+ pGD->memSize = VIDEO_MEM_SIZE;
+
+ /* Turn off display */
+ smiWrite (0x3c4, 0x01, 0x20);
+
+ /* Unlock ext. crt regs */
+ out8 (SMI_LOCK_REG, 0x40);
+
+ /* Set Register base to isa 3dx for 3?x regs (color mode) */
+ out8 (SMI_MISC_REG, 0x2b);
+
+ /* Unlock crt regs 0-7 */
+ smiWrite (0x3d4, 0x11, 0x0e);
+
+ /* Sytem Control Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+ SMI_SCR, sizeof(SMI_SCR));
+
+ /* extented CRT Register */
+ smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
+ SMI_EXT_CRT[pGD->mode], sizeof(SMI_EXT_CRT)/VIDEO_MODES);
+
+ /* Sequencer Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+ SMI_SEQR, sizeof(SMI_SEQR));
+
+ /* Power Control Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+ SMI_PCR[pGD->mode], sizeof(SMI_PCR)/VIDEO_MODES);
+
+ /* Memory Control Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+ SMI_MCR[pGD->mode], sizeof(SMI_MCR)/VIDEO_MODES);
+
+ /* Clock Control Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+ SMI_CCR[pGD->mode], sizeof(SMI_CCR)/VIDEO_MODES);
+
+ /* Shadow VGA Register */
+ smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
+ SMI_SHVGA[pGD->mode], sizeof(SMI_SHVGA)/VIDEO_MODES);
+
+ /* General Purpose Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+ SMI_GPR[pGD->mode], sizeof(SMI_GPR)/VIDEO_MODES);
+
+ /* Hardware Cusor Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+ SMI_HCR[pGD->mode], sizeof(SMI_HCR)/VIDEO_MODES);
+
+ /* Flat Panel Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
+ SMI_FPR[pGD->mode], sizeof(SMI_FPR)/VIDEO_MODES);
+
+ /* CRTC Register */
+ smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
+ SMI_CRTCR[pGD->mode], sizeof(SMI_CRTCR)/VIDEO_MODES);
+
+ /* Graphics Controller Register */
+ smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF,
+ SMI_GCR, sizeof(SMI_GCR));
+
+ /* Patch memory and refresh settings for SMI710 */
+ if (device_id == PCI_DEVICE_ID_SMI_710)
+ {
+ unsigned char reg = smiRead (0x3c4, 0x62);
+
+ /* external memory disabled */
+ smiWrite (0x3c4, 0x62, (reg & 0xfb));
+ /* memory clock */
+ smiWrite (0x3c4, 0x6a, 0x75);
+ }
+
+ /* Patch memory and refresh settings for SMI712 */
+ if (device_id == PCI_DEVICE_ID_SMI_712)
+ {
+ unsigned char reg = smiRead (0x3c4, 0x62);
+
+ /* IL runs at MCLK; 64bit bus; external memory disabled */
+ smiWrite (0x3c4, 0x62, (reg | 0xc4));
+ /* memory clock */
+ smiWrite (0x3c4, 0x6a, 0x80);
+ }
+
+ /* Patch clock settings for SMI810 */
+ if (device_id == PCI_DEVICE_ID_SMI_810)
+ {
+ /* clock control */
+ smiWrite (0x3c4, 0x69, 0x03);
+ }
+
+ /* Video processor default setup */
+ smiInitVideoProcessor ();
+
+ /* Capture port default setup */
+ smiInitCapturePort ();
+
+ /* Drawing engine default setup */
+ smiInitDrawingEngine ();
+
+ /* Turn on display */
+ smiWrite (0x3c4, 0x01, 0x01);
+
+ /* Clear video memory */
+ i = pGD->memSize/4;
+ vm = (unsigned int *)pGD->pciBase;
+ while(i--)
+ *vm++ = 0;
+
+ printf("mode=%x - %s\n", videomode, pGD->modeIdent);
+ return ((void*)&smi);
+}
+
+/*******************************************************************************
+*
+* Drawing engine fill on screen region
+*/
+void video_hw_rectfill (
+ unsigned int bpp, /* bytes per pixel */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y, /* frame height */
+ unsigned int color /* fill color */
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register unsigned int control;
+
+ dim_x *= bpp;
+
+ out32r ((pGD->dprBase + 0x0014), color);
+ out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
+ out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
+
+ control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
+
+ control |= 0x80010000;
+
+ out32r ((pGD->dprBase + 0x000c), control);
+
+ /* Wait for drawing processor */
+ do
+ {
+ out8 ((pGD->isaBase + 0x3c4), 0x16);
+ } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
+}
+
+/*******************************************************************************
+*
+* Drawing engine bitblt with screen region
+*/
+void video_hw_bitblt (
+ unsigned int bpp, /* bytes per pixel */
+ unsigned int src_x, /* source pos x */
+ unsigned int src_y, /* source pos y */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y /* frame height */
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register unsigned int control;
+
+ dim_x *= bpp;
+
+ if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
+ {
+ out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
+ out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
+ control = 0x88000000;
+ }
+ else
+ {
+ out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
+ out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
+ control = 0x80000000;
+ }
+
+ out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
+ control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
+ out32r ((pGD->dprBase + 0x000c), control);
+
+ /* Wait for drawing processor */
+ do
+ {
+ out8 ((pGD->isaBase + 0x3c4), 0x16);
+ } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
+}
+
+/*******************************************************************************
+*
+* Set a RGB color in the LUT (8 bit index)
+*/
+void video_set_lut (
+ unsigned int index, /* color number */
+ unsigned char r, /* red */
+ unsigned char g, /* green */
+ unsigned char b /* blue */
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+ out8 (SMI_LUT_MASK, 0xff);
+
+ out8 (SMI_LUT_START, (char)index);
+
+ out8 (SMI_LUT_RGB, r>>2); /* red */
+ udelay (10);
+ out8 (SMI_LUT_RGB, g>>2); /* green */
+ udelay (10);
+ out8 (SMI_LUT_RGB, b>>2); /* blue */
+ udelay (10);
+}
+
+#endif /* CONFIG_VIDEO_SMI_LYNXEM */
diff --git a/drivers/tigon3.c b/drivers/tigon3.c
new file mode 100644
index 0000000..5883744
--- /dev/null
+++ b/drivers/tigon3.c
@@ -0,0 +1,6222 @@
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/* History: */
+/******************************************************************************/
+#include <common.h>
+#include "bcm570x_mm.h"
+#include <asm/types.h>
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \
+ defined(CONFIG_TIGON3)
+#ifdef CONFIG_BMW
+#include <mpc824x.h>
+#endif
+#include <malloc.h>
+#include <linux/byteorder/big_endian.h>
+
+#define EMBEDDED 1
+/******************************************************************************/
+/* Local functions. */
+/******************************************************************************/
+
+LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+
+static LM_STATUS LM_TranslateRequestedMediaType(
+ LM_REQUESTED_MEDIA_TYPE RequestedMediaType,
+ PLM_MEDIA_TYPE pMediaType, PLM_LINE_SPEED pLineSpeed,
+ PLM_DUPLEX_MODE pDuplexMode);
+
+static LM_STATUS LM_InitBcm540xPhy(PLM_DEVICE_BLOCK pDevice);
+
+__inline static LM_VOID LM_ServiceRxInterrupt(PLM_DEVICE_BLOCK pDevice);
+__inline static LM_VOID LM_ServiceTxInterrupt(PLM_DEVICE_BLOCK pDevice);
+
+static LM_STATUS LM_ForceAutoNegBcm540xPhy(PLM_DEVICE_BLOCK pDevice,
+ LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+static LM_STATUS LM_ForceAutoNeg(PLM_DEVICE_BLOCK pDevice,
+ LM_REQUESTED_MEDIA_TYPE RequestedMediaType);
+static LM_UINT32 GetPhyAdFlowCntrlSettings(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_SetFlowControl(PLM_DEVICE_BLOCK pDevice,
+ LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd);
+#if INCLUDE_TBI_SUPPORT
+STATIC LM_STATUS LM_SetupFiberPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_InitBcm800xPhy(PLM_DEVICE_BLOCK pDevice);
+#endif
+STATIC LM_STATUS LM_SetupCopperPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid(LM_UINT16 Svid, LM_UINT16 Ssid);
+STATIC LM_STATUS LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt,
+ LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize);
+STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number);
+STATIC LM_STATUS LM_ResetChip(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
+ PT3_SND_BD pSendBd);
+
+/******************************************************************************/
+/* External functions. */
+/******************************************************************************/
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice);
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_UINT32
+LM_RegRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register) {
+ LM_UINT32 Value32;
+
+#if PCIX_TARGET_WORKAROUND
+ MM_ACQUIRE_UNDI_LOCK(pDevice);
+#endif
+ MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+ MM_ReadConfig32(pDevice, T3_PCI_REG_DATA_REG, &Value32);
+#if PCIX_TARGET_WORKAROUND
+ MM_RELEASE_UNDI_LOCK(pDevice);
+#endif
+
+ return Value32;
+} /* LM_RegRdInd */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_VOID
+LM_RegWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register,
+LM_UINT32 Value32) {
+
+#if PCIX_TARGET_WORKAROUND
+ MM_ACQUIRE_UNDI_LOCK(pDevice);
+#endif
+ MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+ MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, Value32);
+#if PCIX_TARGET_WORKAROUND
+ MM_RELEASE_UNDI_LOCK(pDevice);
+#endif
+} /* LM_RegWrInd */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_UINT32
+LM_MemRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr) {
+ LM_UINT32 Value32;
+
+ MM_ACQUIRE_UNDI_LOCK(pDevice);
+#ifdef BIG_ENDIAN_HOST
+ MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+ Value32 = REG_RD(pDevice, PciCfg.MemWindowData);
+ /* Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */
+#else
+ MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+ MM_ReadConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32);
+#endif
+ MM_RELEASE_UNDI_LOCK(pDevice);
+
+ return Value32;
+} /* LM_MemRdInd */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_VOID
+LM_MemWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr,
+LM_UINT32 Value32) {
+ MM_ACQUIRE_UNDI_LOCK(pDevice);
+#ifdef BIG_ENDIAN_HOST
+ REG_WR(pDevice,PciCfg.MemWindowBaseAddr,MemAddr);
+ REG_WR(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4],Value32);
+#else
+ MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+ MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32);
+#endif
+ MM_RELEASE_UNDI_LOCK(pDevice);
+} /* LM_MemWrInd */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_QueueRxPackets(
+PLM_DEVICE_BLOCK pDevice) {
+ LM_STATUS Lmstatus;
+ PLM_PACKET pPacket;
+ PT3_RCV_BD pRcvBd;
+ LM_UINT32 StdBdAdded = 0;
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ LM_UINT32 JumboBdAdded = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ Lmstatus = LM_STATUS_SUCCESS;
+
+ pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+ while(pPacket) {
+ switch(pPacket->u.Rx.RcvProdRing) {
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ case T3_JUMBO_RCV_PROD_RING: /* Jumbo Receive Ring. */
+ /* Initialize the buffer descriptor. */
+ pRcvBd =
+ &pDevice->pRxJumboBdVirt[pDevice->RxJumboProdIdx];
+ pRcvBd->Flags = RCV_BD_FLAG_END | RCV_BD_FLAG_JUMBO_RING;
+ pRcvBd->Len = (LM_UINT16) pDevice->RxJumboBufferSize;
+
+ /* Initialize the receive buffer pointer */
+#if 0 /* Jimmy, deleted in new */
+ pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low;
+ pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High;
+#endif
+ MM_MapRxDma(pDevice, pPacket, &pRcvBd->HostAddr);
+
+ /* The opaque field may point to an offset from a fix addr. */
+ pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR(pPacket) -
+ MM_UINT_PTR(pDevice->pPacketDescBase));
+
+ /* Update the producer index. */
+ pDevice->RxJumboProdIdx = (pDevice->RxJumboProdIdx + 1) &
+ T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
+
+ JumboBdAdded++;
+ break;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ case T3_STD_RCV_PROD_RING: /* Standard Receive Ring. */
+ /* Initialize the buffer descriptor. */
+ pRcvBd = &pDevice->pRxStdBdVirt[pDevice->RxStdProdIdx];
+ pRcvBd->Flags = RCV_BD_FLAG_END;
+ pRcvBd->Len = MAX_STD_RCV_BUFFER_SIZE;
+
+ /* Initialize the receive buffer pointer */
+#if 0 /* Jimmy, deleted in new replaced with MM_MapRxDma */
+ pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low;
+ pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High;
+#endif
+ MM_MapRxDma(pDevice, pPacket, &pRcvBd->HostAddr);
+
+ /* The opaque field may point to an offset from a fix addr. */
+ pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR(pPacket) -
+ MM_UINT_PTR(pDevice->pPacketDescBase));
+
+ /* Update the producer index. */
+ pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) &
+ T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+
+ StdBdAdded++;
+ break;
+
+ case T3_UNKNOWN_RCV_PROD_RING:
+ default:
+ Lmstatus = LM_STATUS_FAILURE;
+ break;
+ } /* switch */
+
+ /* Bail out if there is any error. */
+ if(Lmstatus != LM_STATUS_SUCCESS)
+ {
+ break;
+ }
+
+ pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+ } /* while */
+
+ wmb();
+ /* Update the procedure index. */
+ if(StdBdAdded)
+ {
+ MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, pDevice->RxStdProdIdx);
+ }
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ if(JumboBdAdded)
+ {
+ MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low,
+ pDevice->RxJumboProdIdx);
+ }
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ return Lmstatus;
+} /* LM_QueueRxPackets */
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+STATIC LM_VOID
+LM_NvramInit(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 Value32;
+ LM_UINT32 j;
+
+ /* Intialize clock period and state machine. */
+ Value32 = SEEPROM_ADDR_CLK_PERD(SEEPROM_CLOCK_PERIOD) |
+ SEEPROM_ADDR_FSM_RESET;
+ REG_WR(pDevice, Grc.EepromAddr, Value32);
+
+ for(j = 0; j < 100; j++)
+ {
+ MM_Wait(10);
+ }
+
+ /* Serial eeprom access using the Grc.EepromAddr/EepromData registers. */
+ Value32 = REG_RD(pDevice, Grc.LocalCtrl);
+ REG_WR(pDevice, Grc.LocalCtrl, Value32 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM);
+
+ /* Set the 5701 compatibility mode if we are using EEPROM. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+ T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+ {
+ Value32 = REG_RD(pDevice, Nvram.Config1);
+ if((Value32 & FLASH_INTERFACE_ENABLE) == 0)
+ {
+ /* Use the new interface to read EEPROM. */
+ Value32 &= ~FLASH_COMPAT_BYPASS;
+
+ REG_WR(pDevice, Nvram.Config1, Value32);
+ }
+ }
+} /* LM_NvRamInit */
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_EepromRead(
+ PLM_DEVICE_BLOCK pDevice,
+ LM_UINT32 Offset,
+ LM_UINT32 *pData)
+{
+ LM_UINT32 Value32;
+ LM_UINT32 Addr;
+ LM_UINT32 Dev;
+ LM_UINT32 j;
+
+ if(Offset > SEEPROM_CHIP_SIZE)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ Dev = Offset / SEEPROM_CHIP_SIZE;
+ Addr = Offset % SEEPROM_CHIP_SIZE;
+
+ Value32 = REG_RD(pDevice, Grc.EepromAddr);
+ Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK |
+ SEEPROM_ADDR_RW_MASK);
+ REG_WR(pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID(Dev) |
+ SEEPROM_ADDR_ADDRESS(Addr) | SEEPROM_ADDR_START | SEEPROM_ADDR_READ);
+
+ for(j = 0; j < 1000; j++)
+ {
+ Value32 = REG_RD(pDevice, Grc.EepromAddr);
+ if(Value32 & SEEPROM_ADDR_COMPLETE)
+ {
+ break;
+ }
+ MM_Wait(10);
+ }
+
+ if(Value32 & SEEPROM_ADDR_COMPLETE)
+ {
+ Value32 = REG_RD(pDevice, Grc.EepromData);
+ *pData = Value32;
+
+ return LM_STATUS_SUCCESS;
+ }
+
+ return LM_STATUS_FAILURE;
+} /* LM_EepromRead */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_NvramRead(
+ PLM_DEVICE_BLOCK pDevice,
+ LM_UINT32 Offset,
+ LM_UINT32 *pData)
+{
+ LM_UINT32 Value32;
+ LM_STATUS Status;
+ LM_UINT32 j;
+
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ Status = LM_EepromRead(pDevice, Offset, pData);
+ }
+ else
+ {
+ /* Determine if we have flash or EEPROM. */
+ Value32 = REG_RD(pDevice, Nvram.Config1);
+ if(Value32 & FLASH_INTERFACE_ENABLE)
+ {
+ if(Value32 & FLASH_SSRAM_BUFFERRED_MODE)
+ {
+ Offset = ((Offset/BUFFERED_FLASH_PAGE_SIZE) <<
+ BUFFERED_FLASH_PAGE_POS) +
+ (Offset % BUFFERED_FLASH_PAGE_SIZE);
+ }
+ }
+
+ REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+ for (j = 0; j < 1000; j++)
+ {
+ if (REG_RD(pDevice, Nvram.SwArb) & SW_ARB_GNT1)
+ {
+ break;
+ }
+ MM_Wait(20);
+ }
+ if (j == 1000)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ /* Read from flash or EEPROM with the new 5703/02 interface. */
+ REG_WR(pDevice, Nvram.Addr, Offset & NVRAM_ADDRESS_MASK);
+
+ REG_WR(pDevice, Nvram.Cmd, NVRAM_CMD_RD | NVRAM_CMD_DO_IT |
+ NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
+
+ /* Wait for the done bit to clear. */
+ for(j = 0; j < 500; j++)
+ {
+ MM_Wait(10);
+
+ Value32 = REG_RD(pDevice, Nvram.Cmd);
+ if(!(Value32 & NVRAM_CMD_DONE))
+ {
+ break;
+ }
+ }
+
+ /* Wait for the done bit. */
+ if(!(Value32 & NVRAM_CMD_DONE))
+ {
+ for(j = 0; j < 500; j++)
+ {
+ MM_Wait(10);
+
+ Value32 = REG_RD(pDevice, Nvram.Cmd);
+ if(Value32 & NVRAM_CMD_DONE)
+ {
+ MM_Wait(10);
+
+ *pData = REG_RD(pDevice, Nvram.ReadData);
+
+ /* Change the endianess. */
+ *pData = ((*pData & 0xff) << 24)| ((*pData & 0xff00) << 8)|
+ ((*pData & 0xff0000) >> 8) | ((*pData >> 24) & 0xff);
+
+ break;
+ }
+ }
+ }
+
+ REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1);
+ if(Value32 & NVRAM_CMD_DONE)
+ {
+ Status = LM_STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = LM_STATUS_FAILURE;
+ }
+ }
+
+ return Status;
+} /* LM_NvramRead */
+
+
+STATIC void
+LM_ReadVPD(PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 Vpd_arr[256/4];
+ LM_UINT8 *Vpd = (LM_UINT8 *) &Vpd_arr[0];
+ LM_UINT32 *Vpd_dptr = &Vpd_arr[0];
+ LM_UINT32 Value32;
+ unsigned int j;
+
+ /* Read PN from VPD */
+ for (j = 0; j < 256; j += 4, Vpd_dptr++ )
+ {
+ if (LM_NvramRead(pDevice, 0x100 + j, &Value32) != LM_STATUS_SUCCESS) {
+ printf("BCM570x: LM_ReadVPD: VPD read failed"
+ " (no EEPROM onboard)\n");
+ return;
+ }
+ *Vpd_dptr = cpu_to_le32(Value32);
+ }
+ for (j = 0; j < 256; )
+ {
+ unsigned int Vpd_r_len;
+ unsigned int Vpd_r_end;
+
+ if ((Vpd[j] == 0x82) || (Vpd[j] == 0x91))
+ {
+ j = j + 3 + Vpd[j + 1] + (Vpd[j + 2] << 8);
+ }
+ else if (Vpd[j] == 0x90)
+ {
+ Vpd_r_len = Vpd[j + 1] + (Vpd[j + 2] << 8);
+ j += 3;
+ Vpd_r_end = Vpd_r_len + j;
+ while (j < Vpd_r_end)
+ {
+ if ((Vpd[j] == 'P') && (Vpd[j + 1] == 'N'))
+ {
+ unsigned int len = Vpd[j + 2];
+
+ if (len <= 24)
+ {
+ memcpy(pDevice->PartNo, &Vpd[j + 3], len);
+ }
+ break;
+ }
+ else
+ {
+ if (Vpd[j + 2] == 0)
+ {
+ break;
+ }
+ j = j + Vpd[j + 2];
+ }
+ }
+ break;
+ }
+ else {
+ break;
+ }
+ }
+}
+
+STATIC void
+LM_ReadBootCodeVersion(PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 Value32, offset, ver_offset;
+ int i;
+
+ if (LM_NvramRead(pDevice, 0x0, &Value32) != LM_STATUS_SUCCESS)
+ return;
+ if (Value32 != 0xaa559966)
+ return;
+ if (LM_NvramRead(pDevice, 0xc, &offset) != LM_STATUS_SUCCESS)
+ return;
+
+ offset = ((offset & 0xff) << 24)| ((offset & 0xff00) << 8)|
+ ((offset & 0xff0000) >> 8) | ((offset >> 24) & 0xff);
+ if (LM_NvramRead(pDevice, offset, &Value32) != LM_STATUS_SUCCESS)
+ return;
+ if ((Value32 == 0x0300000e) &&
+ (LM_NvramRead(pDevice, offset + 4, &Value32) == LM_STATUS_SUCCESS) &&
+ (Value32 == 0)) {
+
+ if (LM_NvramRead(pDevice, offset + 8, &ver_offset) != LM_STATUS_SUCCESS)
+ return;
+ ver_offset = ((ver_offset & 0xff0000) >> 8) |
+ ((ver_offset >> 24) & 0xff);
+ for (i = 0; i < 16; i += 4) {
+ if (LM_NvramRead(pDevice, offset + ver_offset + i, &Value32) !=
+ LM_STATUS_SUCCESS)
+ {
+ return;
+ }
+ *((LM_UINT32 *) &pDevice->BootCodeVer[i]) = cpu_to_le32(Value32);
+ }
+ }
+ else {
+ char c;
+
+ if (LM_NvramRead(pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS)
+ return;
+
+ i = 0;
+ c = ((Value32 & 0xff0000) >> 16);
+
+ if (c < 10) {
+ pDevice->BootCodeVer[i++] = c + '0';
+ }
+ else {
+ pDevice->BootCodeVer[i++] = (c / 10) + '0';
+ pDevice->BootCodeVer[i++] = (c % 10) + '0';
+ }
+ pDevice->BootCodeVer[i++] = '.';
+ c = (Value32 & 0xff000000) >> 24;
+ if (c < 10) {
+ pDevice->BootCodeVer[i++] = c + '0';
+ }
+ else {
+ pDevice->BootCodeVer[i++] = (c / 10) + '0';
+ pDevice->BootCodeVer[i++] = (c % 10) + '0';
+ }
+ pDevice->BootCodeVer[i] = 0;
+ }
+}
+
+STATIC void
+LM_GetBusSpeed(PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 PciState = pDevice->PciState;
+ LM_UINT32 ClockCtrl;
+ char *SpeedStr = "";
+
+ if (PciState & T3_PCI_STATE_32BIT_PCI_BUS)
+ {
+ strcpy(pDevice->BusSpeedStr, "32-bit ");
+ }
+ else
+ {
+ strcpy(pDevice->BusSpeedStr, "64-bit ");
+ }
+ if (PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)
+ {
+ strcat(pDevice->BusSpeedStr, "PCI ");
+ if (PciState & T3_PCI_STATE_HIGH_BUS_SPEED)
+ {
+ SpeedStr = "66MHz";
+ }
+ else
+ {
+ SpeedStr = "33MHz";
+ }
+ }
+ else
+ {
+ strcat(pDevice->BusSpeedStr, "PCIX ");
+ if (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)
+ {
+ SpeedStr = "133MHz";
+ }
+ else
+ {
+ ClockCtrl = REG_RD(pDevice, PciCfg.ClockCtrl) & 0x1f;
+ switch (ClockCtrl)
+ {
+ case 0:
+ SpeedStr = "33MHz";
+ break;
+
+ case 2:
+ SpeedStr = "50MHz";
+ break;
+
+ case 4:
+ SpeedStr = "66MHz";
+ break;
+
+ case 6:
+ SpeedStr = "100MHz";
+ break;
+
+ case 7:
+ SpeedStr = "133MHz";
+ break;
+ }
+ }
+ }
+ strcat(pDevice->BusSpeedStr, SpeedStr);
+}
+
+/******************************************************************************/
+/* Description: */
+/* This routine initializes default parameters and reads the PCI */
+/* configurations. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_GetAdapterInfo(
+PLM_DEVICE_BLOCK pDevice)
+{
+ PLM_ADAPTER_INFO pAdapterInfo;
+ LM_UINT32 Value32;
+ LM_STATUS Status;
+ LM_UINT32 j;
+ LM_UINT32 EeSigFound;
+ LM_UINT32 EePhyTypeSerdes = 0;
+ LM_UINT32 EePhyLedMode = 0;
+ LM_UINT32 EePhyId = 0;
+
+ /* Get Device Id and Vendor Id */
+ Status = MM_ReadConfig32(pDevice, PCI_VENDOR_ID_REG, &Value32);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+ pDevice->PciVendorId = (LM_UINT16) Value32;
+ pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16);
+
+ /* If we are not getting the write adapter, exit. */
+ if((Value32 != T3_PCI_ID_BCM5700) &&
+ (Value32 != T3_PCI_ID_BCM5701) &&
+ (Value32 != T3_PCI_ID_BCM5702) &&
+ (Value32 != T3_PCI_ID_BCM5702x) &&
+ (Value32 != T3_PCI_ID_BCM5702FE) &&
+ (Value32 != T3_PCI_ID_BCM5703) &&
+ (Value32 != T3_PCI_ID_BCM5703x) &&
+ (Value32 != T3_PCI_ID_BCM5704))
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ Status = MM_ReadConfig32(pDevice, PCI_REV_ID_REG, &Value32);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+ pDevice->PciRevId = (LM_UINT8) Value32;
+
+ /* Get IRQ. */
+ Status = MM_ReadConfig32(pDevice, PCI_INT_LINE_REG, &Value32);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+ pDevice->Irq = (LM_UINT8) Value32;
+
+ /* Get interrupt pin. */
+ pDevice->IntPin = (LM_UINT8) (Value32 >> 8);
+
+ /* Get chip revision id. */
+ Status = MM_ReadConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32);
+ pDevice->ChipRevId = Value32 >> 16;
+
+ /* Get subsystem vendor. */
+ Status = MM_ReadConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+ pDevice->SubsystemVendorId = (LM_UINT16) Value32;
+
+ /* Get PCI subsystem id. */
+ pDevice->SubsystemId = (LM_UINT16) (Value32 >> 16);
+
+ /* Get the cache line size. */
+ MM_ReadConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG, &Value32);
+ pDevice->CacheLineSize = (LM_UINT8) Value32;
+ pDevice->SavedCacheLineReg = Value32;
+
+ if(pDevice->ChipRevId != T3_CHIP_ID_5703_A1 &&
+ pDevice->ChipRevId != T3_CHIP_ID_5703_A2 &&
+ pDevice->ChipRevId != T3_CHIP_ID_5704_A0)
+ {
+ pDevice->UndiFix = FALSE;
+ }
+#if !PCIX_TARGET_WORKAROUND
+ pDevice->UndiFix = FALSE;
+#endif
+ /* Map the memory base to system address space. */
+ if (!pDevice->UndiFix)
+ {
+ Status = MM_MapMemBase(pDevice);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+ /* Initialize the memory view pointer. */
+ pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase;
+ }
+
+#if PCIX_TARGET_WORKAROUND
+ /* store whether we are in PCI are PCI-X mode */
+ pDevice->EnablePciXFix = FALSE;
+
+ MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+ if((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0)
+ {
+ /* Enable PCI-X workaround only if we are running on 5700 BX. */
+ if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+ {
+ pDevice->EnablePciXFix = TRUE;
+ }
+ }
+ if (pDevice->UndiFix)
+ {
+ pDevice->EnablePciXFix = TRUE;
+ }
+#endif
+ /* Bx bug: due to the "byte_enable bug" in PCI-X mode, the power */
+ /* management register may be clobbered which may cause the */
+ /* BCM5700 to go into D3 state. While in this state, we will */
+ /* not have memory mapped register access. As a workaround, we */
+ /* need to restore the device to D0 state. */
+ MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &Value32);
+ Value32 |= T3_PM_PME_ASSERTED;
+ Value32 &= ~T3_PM_POWER_STATE_MASK;
+ Value32 |= T3_PM_POWER_STATE_D0;
+ MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, Value32);
+
+ /* read the current PCI command word */
+ MM_ReadConfig32(pDevice, PCI_COMMAND_REG, &Value32);
+
+ /* Make sure bus-mastering is enabled. */
+ Value32 |= PCI_BUSMASTER_ENABLE;
+
+#if PCIX_TARGET_WORKAROUND
+ /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR#
+ are enabled */
+ if (pDevice->EnablePciXFix == TRUE) {
+ Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE |
+ PCI_PARITY_ERROR_ENABLE);
+ }
+ if (pDevice->UndiFix)
+ {
+ Value32 &= ~PCI_MEM_SPACE_ENABLE;
+ }
+
+#endif
+
+ if(pDevice->EnableMWI)
+ {
+ Value32 |= PCI_MEMORY_WRITE_INVALIDATE;
+ }
+ else {
+ Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE);
+ }
+
+ /* Error out if mem-mapping is NOT enabled for PCI systems */
+ if (!(Value32 | PCI_MEM_SPACE_ENABLE))
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ /* save the value we are going to write into the PCI command word */
+ pDevice->PciCommandStatusWords = Value32;
+
+ Status = MM_WriteConfig32(pDevice, PCI_COMMAND_REG, Value32);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+
+ /* Set power state to D0. */
+ LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+#ifdef BIG_ENDIAN_PCI
+ pDevice->MiscHostCtrl =
+ MISC_HOST_CTRL_MASK_PCI_INT |
+ MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS |
+ MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP |
+ MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW;
+#else /* No CPU Swap modes for PCI IO */
+
+ /* Setup the mode registers. */
+ pDevice->MiscHostCtrl =
+ MISC_HOST_CTRL_MASK_PCI_INT |
+ MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP |
+#ifdef BIG_ENDIAN_HOST
+ MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP |
+#endif /* BIG_ENDIAN_HOST */
+ MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS |
+ MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW;
+#endif /* !BIG_ENDIAN_PCI */
+
+ /* write to PCI misc host ctr first in order to enable indirect accesses */
+ MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl);
+
+ REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl);
+
+#ifdef BIG_ENDIAN_PCI
+ Value32 = GRC_MODE_WORD_SWAP_DATA|
+ GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+/* No CPU Swap modes for PCI IO */
+#ifdef BIG_ENDIAN_HOST
+ Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA |
+ GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+ Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA;
+#endif
+#endif /* !BIG_ENDIAN_PCI */
+
+ REG_WR(pDevice, Grc.Mode, Value32);
+
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ REG_WR(pDevice, Grc.LocalCtrl, GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+ }
+ MM_Wait(40);
+
+ /* Enable indirect memory access */
+ REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+
+ if (REG_RD(pDevice, PciCfg.ClockCtrl) & T3_PCI_44MHZ_CORE_CLOCK)
+ {
+ REG_WR(pDevice, PciCfg.ClockCtrl, T3_PCI_44MHZ_CORE_CLOCK |
+ T3_PCI_SELECT_ALTERNATE_CLOCK);
+ REG_WR(pDevice, PciCfg.ClockCtrl, T3_PCI_SELECT_ALTERNATE_CLOCK);
+ MM_Wait(40); /* required delay is 27usec */
+ }
+ REG_WR(pDevice, PciCfg.ClockCtrl, 0);
+ REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+
+#if PCIX_TARGET_WORKAROUND
+ MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+ if ((pDevice->EnablePciXFix == FALSE) &&
+ ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0))
+ {
+ if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B0 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B2 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B5)
+ {
+ __raw_writel(0, &(pDevice->pMemView->uIntMem.MemBlock32K[0x300]));
+ __raw_writel(0, &(pDevice->pMemView->uIntMem.MemBlock32K[0x301]));
+ __raw_writel(0xffffffff, &(pDevice->pMemView->uIntMem.MemBlock32K[0x301]));
+ if (__raw_readl(&(pDevice->pMemView->uIntMem.MemBlock32K[0x300])))
+ {
+ pDevice->EnablePciXFix = TRUE;
+ }
+ }
+ }
+#endif
+#if 1
+ /*
+ * This code was at the beginning of else block below, but that's
+ * a bug if node address in shared memory.
+ */
+ MM_Wait(50);
+ LM_NvramInit(pDevice);
+#endif
+ /* Get the node address. First try to get in from the shared memory. */
+ /* If the signature is not present, then get it from the NVRAM. */
+ Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_HIGH_MAILBOX);
+ if((Value32 >> 16) == 0x484b)
+ {
+
+ pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 8);
+ pDevice->NodeAddress[1] = (LM_UINT8) Value32;
+
+ Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_LOW_MAILBOX);
+
+ pDevice->NodeAddress[2] = (LM_UINT8) (Value32 >> 24);
+ pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 16);
+ pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 8);
+ pDevice->NodeAddress[5] = (LM_UINT8) Value32;
+
+ Status = LM_STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = LM_NvramRead(pDevice, 0x7c, &Value32);
+ if(Status == LM_STATUS_SUCCESS)
+ {
+ pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 16);
+ pDevice->NodeAddress[1] = (LM_UINT8) (Value32 >> 24);
+
+ Status = LM_NvramRead(pDevice, 0x80, &Value32);
+
+ pDevice->NodeAddress[2] = (LM_UINT8) Value32;
+ pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 8);
+ pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 16);
+ pDevice->NodeAddress[5] = (LM_UINT8) (Value32 >> 24);
+ }
+ }
+
+ /* Assign a default address. */
+ if(Status != LM_STATUS_SUCCESS)
+ {
+#ifndef EMBEDDED
+ printk(KERN_ERR "Cannot get MAC addr from NVRAM. Using default.\n");
+#endif
+ pDevice->NodeAddress[0] = 0x00; pDevice->NodeAddress[1] = 0x10;
+ pDevice->NodeAddress[2] = 0x18; pDevice->NodeAddress[3] = 0x68;
+ pDevice->NodeAddress[4] = 0x61; pDevice->NodeAddress[5] = 0x76;
+ }
+
+ pDevice->PermanentNodeAddress[0] = pDevice->NodeAddress[0];
+ pDevice->PermanentNodeAddress[1] = pDevice->NodeAddress[1];
+ pDevice->PermanentNodeAddress[2] = pDevice->NodeAddress[2];
+ pDevice->PermanentNodeAddress[3] = pDevice->NodeAddress[3];
+ pDevice->PermanentNodeAddress[4] = pDevice->NodeAddress[4];
+ pDevice->PermanentNodeAddress[5] = pDevice->NodeAddress[5];
+
+ /* Initialize the default values. */
+ pDevice->NoTxPseudoHdrChksum = FALSE;
+ pDevice->NoRxPseudoHdrChksum = FALSE;
+ pDevice->NicSendBd = FALSE;
+ pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT;
+ pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT;
+ pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS;
+ pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS;
+ pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES;
+ pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES;
+ pDevice->RxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE;
+ pDevice->TxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE;
+ pDevice->RxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE;
+ pDevice->TxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE;
+ pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS;
+ pDevice->EnableMWI = FALSE;
+ pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+ pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+ pDevice->DisableAutoNeg = FALSE;
+ pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO;
+ pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO;
+ pDevice->LedMode = LED_MODE_AUTO;
+ pDevice->ResetPhyOnInit = TRUE;
+ pDevice->DelayPciGrant = TRUE;
+ pDevice->UseTaggedStatus = FALSE;
+ pDevice->OneDmaAtOnce = BAD_DEFAULT_VALUE;
+
+ pDevice->DmaMbufLowMark = T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO;
+ pDevice->RxMacMbufLowMark = T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO;
+ pDevice->MbufHighMark = T3_DEF_MBUF_HIGH_WMARK_JUMBO;
+
+ pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO;
+ pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_NONE;
+ pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE;
+ pDevice->EnableTbi = FALSE;
+#if INCLUDE_TBI_SUPPORT
+ pDevice->PollTbiLink = BAD_DEFAULT_VALUE;
+#endif
+
+ switch (T3_ASIC_REV(pDevice->ChipRevId))
+ {
+ case T3_ASIC_REV_5704:
+ pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+ pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE64;
+ break;
+ default:
+ pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+ pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96;
+ break;
+ }
+
+ pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+ pDevice->QueueRxPackets = TRUE;
+
+ pDevice->EnableWireSpeed = TRUE;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ /* Make this is a known adapter. */
+ pAdapterInfo = LM_GetAdapterInfoBySsid(pDevice->SubsystemVendorId,
+ pDevice->SubsystemId);
+
+ pDevice->BondId = REG_RD(pDevice, Grc.MiscCfg) & GRC_MISC_BD_ID_MASK;
+ if (pDevice->BondId != GRC_MISC_BD_ID_5700 &&
+ pDevice->BondId != GRC_MISC_BD_ID_5701 &&
+ pDevice->BondId != GRC_MISC_BD_ID_5702FE &&
+ pDevice->BondId != GRC_MISC_BD_ID_5703 &&
+ pDevice->BondId != GRC_MISC_BD_ID_5703S &&
+ pDevice->BondId != GRC_MISC_BD_ID_5704 &&
+ pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE)
+ {
+ return LM_STATUS_UNKNOWN_ADAPTER;
+ }
+
+ pDevice->SplitModeEnable = SPLIT_MODE_DISABLE;
+ if ((pDevice->ChipRevId == T3_CHIP_ID_5704_A0) &&
+ (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE))
+ {
+ pDevice->SplitModeEnable = SPLIT_MODE_ENABLE;
+ pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ;
+ }
+
+ /* Get Eeprom info. */
+ Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_SIG_ADDR);
+ if (Value32 == T3_NIC_DATA_SIG)
+ {
+ EeSigFound = TRUE;
+ Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_NIC_CFG_ADDR);
+
+ /* Determine PHY type. */
+ switch (Value32 & T3_NIC_CFG_PHY_TYPE_MASK)
+ {
+ case T3_NIC_CFG_PHY_TYPE_COPPER:
+ EePhyTypeSerdes = FALSE;
+ break;
+
+ case T3_NIC_CFG_PHY_TYPE_FIBER:
+ EePhyTypeSerdes = TRUE;
+ break;
+
+ default:
+ EePhyTypeSerdes = FALSE;
+ break;
+ }
+
+ /* Determine PHY led mode. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ switch(Value32 & T3_NIC_CFG_LED_MODE_MASK)
+ {
+ case T3_NIC_CFG_LED_MODE_TRIPLE_SPEED:
+ EePhyLedMode = LED_MODE_THREE_LINK;
+ break;
+
+ case T3_NIC_CFG_LED_MODE_LINK_SPEED:
+ EePhyLedMode = LED_MODE_LINK10;
+ break;
+
+ default:
+ EePhyLedMode = LED_MODE_AUTO;
+ break;
+ }
+ }
+ else
+ {
+ switch(Value32 & T3_NIC_CFG_LED_MODE_MASK)
+ {
+ case T3_NIC_CFG_LED_MODE_OPEN_DRAIN:
+ EePhyLedMode = LED_MODE_OPEN_DRAIN;
+ break;
+
+ case T3_NIC_CFG_LED_MODE_OUTPUT:
+ EePhyLedMode = LED_MODE_OUTPUT;
+ break;
+
+ default:
+ EePhyLedMode = LED_MODE_AUTO;
+ break;
+ }
+ }
+ if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5703_A2)
+ {
+ /* Enable EEPROM write protection. */
+ if(Value32 & T3_NIC_EEPROM_WP)
+ {
+ pDevice->EepromWp = TRUE;
+ }
+ }
+
+ /* Get the PHY Id. */
+ Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_PHY_ID_ADDR);
+ if (Value32)
+ {
+ EePhyId = (((Value32 & T3_NIC_PHY_ID1_MASK) >> 16) &
+ PHY_ID1_OUI_MASK) << 10;
+
+ Value32 = Value32 & T3_NIC_PHY_ID2_MASK;
+
+ EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
+ (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
+ }
+ else
+ {
+ EePhyId = 0;
+ }
+ }
+ else
+ {
+ EeSigFound = FALSE;
+ }
+
+ /* Set the PHY address. */
+ pDevice->PhyAddr = PHY_DEVICE_ID;
+
+ /* Disable auto polling. */
+ pDevice->MiMode = 0xc0000;
+ REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+ MM_Wait(40);
+
+ /* Get the PHY id. */
+ LM_ReadPhy(pDevice, PHY_ID1_REG, &Value32);
+ pDevice->PhyId = (Value32 & PHY_ID1_OUI_MASK) << 10;
+
+ LM_ReadPhy(pDevice, PHY_ID2_REG, &Value32);
+ pDevice->PhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
+ (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
+
+ /* Set the EnableTbi flag to false if we have a copper PHY. */
+ switch(pDevice->PhyId & PHY_ID_MASK)
+ {
+ case PHY_BCM5400_PHY_ID:
+ pDevice->EnableTbi = FALSE;
+ break;
+
+ case PHY_BCM5401_PHY_ID:
+ pDevice->EnableTbi = FALSE;
+ break;
+
+ case PHY_BCM5411_PHY_ID:
+ pDevice->EnableTbi = FALSE;
+ break;
+
+ case PHY_BCM5701_PHY_ID:
+ pDevice->EnableTbi = FALSE;
+ break;
+
+ case PHY_BCM5703_PHY_ID:
+ pDevice->EnableTbi = FALSE;
+ break;
+
+ case PHY_BCM5704_PHY_ID:
+ pDevice->EnableTbi = FALSE;
+ break;
+
+ case PHY_BCM8002_PHY_ID:
+ pDevice->EnableTbi = TRUE;
+ break;
+
+ default:
+
+ if (pAdapterInfo)
+ {
+ pDevice->PhyId = pAdapterInfo->PhyId;
+ pDevice->EnableTbi = pAdapterInfo->Serdes;
+ }
+ else if (EeSigFound)
+ {
+ pDevice->PhyId = EePhyId;
+ pDevice->EnableTbi = EePhyTypeSerdes;
+ }
+ break;
+ }
+
+ /* Bail out if we don't know the copper PHY id. */
+ if(UNKNOWN_PHY_ID(pDevice->PhyId) && !pDevice->EnableTbi)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+ {
+ if((pDevice->SavedCacheLineReg & 0xff00) < 0x4000)
+ {
+ pDevice->SavedCacheLineReg &= 0xffff00ff;
+ pDevice->SavedCacheLineReg |= 0x4000;
+ }
+ }
+ /* Change driver parameters. */
+ Status = MM_GetConfig(pDevice);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+
+#if INCLUDE_5701_AX_FIX
+ if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+ {
+ pDevice->ResetPhyOnInit = TRUE;
+ }
+#endif
+
+ /* Save the current phy link status. */
+ if(!pDevice->EnableTbi)
+ {
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+ /* If we don't have link reset the PHY. */
+ if(!(Value32 & PHY_STATUS_LINK_PASS) || pDevice->ResetPhyOnInit)
+ {
+
+ LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+
+ for(j = 0; j < 100; j++)
+ {
+ MM_Wait(10);
+
+ LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+ if(Value32 && !(Value32 & PHY_CTRL_PHY_RESET))
+ {
+ MM_Wait(40);
+ break;
+ }
+ }
+
+
+#if INCLUDE_5701_AX_FIX
+ /* 5701_AX_BX bug: only advertises 10mb speed. */
+ if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+ {
+
+ Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
+ PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL |
+ PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+ Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+ LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+ pDevice->advertising = Value32;
+
+ Value32 = BCM540X_AN_AD_1000BASET_HALF |
+ BCM540X_AN_AD_1000BASET_FULL | BCM540X_CONFIG_AS_MASTER |
+ BCM540X_ENABLE_CONFIG_AS_MASTER;
+ LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+ pDevice->advertising1000 = Value32;
+
+ LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+ PHY_CTRL_RESTART_AUTO_NEG);
+ }
+#endif
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+ {
+ LM_WritePhy(pDevice, 0x18, 0x0c00);
+ LM_WritePhy(pDevice, 0x17, 0x201f);
+ LM_WritePhy(pDevice, 0x15, 0x2aaa);
+ }
+ if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+ {
+ LM_WritePhy(pDevice, 0x1c, 0x8d68);
+ LM_WritePhy(pDevice, 0x1c, 0x8d68);
+ }
+ /* Enable Ethernet@WireSpeed. */
+ if(pDevice->EnableWireSpeed)
+ {
+ LM_WritePhy(pDevice, 0x18, 0x7007);
+ LM_ReadPhy(pDevice, 0x18, &Value32);
+ LM_WritePhy(pDevice, 0x18, Value32 | BIT_15 | BIT_4);
+ }
+ }
+ }
+
+ /* Turn off tap power management. */
+ if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+ {
+ LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20);
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+
+ MM_Wait(40);
+ }
+
+#if INCLUDE_TBI_SUPPORT
+ pDevice->IgnoreTbiLinkChange = FALSE;
+
+ if(pDevice->EnableTbi)
+ {
+ pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
+ pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+ if ((pDevice->PollTbiLink == BAD_DEFAULT_VALUE) ||
+ pDevice->DisableAutoNeg)
+ {
+ pDevice->PollTbiLink = FALSE;
+ }
+ }
+ else
+ {
+ pDevice->PollTbiLink = FALSE;
+ }
+#endif /* INCLUDE_TBI_SUPPORT */
+
+ /* UseTaggedStatus is only valid for 5701 and later. */
+ if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ pDevice->UseTaggedStatus = FALSE;
+
+ pDevice->CoalesceMode = 0;
+ }
+ else
+ {
+ pDevice->CoalesceMode = HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT |
+ HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT;
+ }
+
+ /* Set the status block size. */
+ if(T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_AX &&
+ T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_BX)
+ {
+ pDevice->CoalesceMode |= HOST_COALESCE_32_BYTE_STATUS_MODE;
+ }
+
+ /* Check the DURING_INT coalescing ticks parameters. */
+ if(pDevice->UseTaggedStatus)
+ {
+ if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+ {
+ pDevice->RxCoalescingTicksDuringInt =
+ DEFAULT_RX_COALESCING_TICKS_DURING_INT;
+ }
+
+ if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+ {
+ pDevice->TxCoalescingTicksDuringInt =
+ DEFAULT_TX_COALESCING_TICKS_DURING_INT;
+ }
+
+ if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+ {
+ pDevice->RxMaxCoalescedFramesDuringInt =
+ DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT;
+ }
+
+ if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+ {
+ pDevice->TxMaxCoalescedFramesDuringInt =
+ DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT;
+ }
+ }
+ else
+ {
+ if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+ {
+ pDevice->RxCoalescingTicksDuringInt = 0;
+ }
+
+ if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+ {
+ pDevice->TxCoalescingTicksDuringInt = 0;
+ }
+
+ if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+ {
+ pDevice->RxMaxCoalescedFramesDuringInt = 0;
+ }
+
+ if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+ {
+ pDevice->TxMaxCoalescedFramesDuringInt = 0;
+ }
+ }
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ if(pDevice->RxMtu <= (MAX_STD_RCV_BUFFER_SIZE - 8 /* CRC */))
+ {
+ pDevice->RxJumboDescCnt = 0;
+ if(pDevice->RxMtu <= MAX_ETHERNET_PACKET_SIZE_NO_CRC)
+ {
+ pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+ }
+ }
+ else
+ {
+ pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ +
+ COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK;
+
+ if(pDevice->RxJumboBufferSize > MAX_JUMBO_RCV_BUFFER_SIZE)
+ {
+ pDevice->RxJumboBufferSize = DEFAULT_JUMBO_RCV_BUFFER_SIZE;
+ pDevice->RxMtu = pDevice->RxJumboBufferSize - 8 /* CRC + VLAN */;
+ }
+ pDevice->TxMtu = pDevice->RxMtu;
+
+ }
+#else
+ pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ pDevice->RxPacketDescCnt =
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ pDevice->RxJumboDescCnt +
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+ pDevice->RxStdDescCnt;
+
+ if(pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC)
+ {
+ pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+ }
+
+ if(pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE)
+ {
+ pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE;
+ }
+
+ /* Configure the proper ways to get link change interrupt. */
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO)
+ {
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+ }
+ else
+ {
+ pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+ }
+ }
+ else if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+ {
+ /* Auto-polling does not work on 5700_AX and 5700_BX. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+ }
+ }
+
+ /* Determine the method to get link change status. */
+ if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_AUTO)
+ {
+ /* The link status bit in the status block does not work on 5700_AX */
+ /* and 5700_BX chips. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+ }
+ else
+ {
+ pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_BLOCK;
+ }
+ }
+
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+ }
+
+ /* Configure PHY led mode. */
+ if(pDevice->LedMode == LED_MODE_AUTO)
+ {
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ if(pDevice->SubsystemVendorId == T3_SVID_DELL)
+ {
+ pDevice->LedMode = LED_MODE_LINK10;
+ }
+ else
+ {
+ pDevice->LedMode = LED_MODE_THREE_LINK;
+
+ if(EeSigFound && EePhyLedMode != LED_MODE_AUTO)
+ {
+ pDevice->LedMode = EePhyLedMode;
+ }
+ }
+
+ /* bug? 5701 in LINK10 mode does not seem to work when */
+ /* PhyIntMode is LINK_READY. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+#if INCLUDE_TBI_SUPPORT
+ pDevice->EnableTbi == FALSE &&
+#endif
+ pDevice->LedMode == LED_MODE_LINK10)
+ {
+ pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+ pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+ }
+
+ if(pDevice->EnableTbi)
+ {
+ pDevice->LedMode = LED_MODE_THREE_LINK;
+ }
+ }
+ else
+ {
+ if(EeSigFound && EePhyLedMode != LED_MODE_AUTO)
+ {
+ pDevice->LedMode = EePhyLedMode;
+ }
+ else
+ {
+ pDevice->LedMode = LED_MODE_OPEN_DRAIN;
+ }
+ }
+ }
+
+ /* Enable OneDmaAtOnce. */
+ if(pDevice->OneDmaAtOnce == BAD_DEFAULT_VALUE)
+ {
+ pDevice->OneDmaAtOnce = FALSE;
+ }
+
+ if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B0 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B2)
+ {
+ pDevice->WolSpeed = WOL_SPEED_10MB;
+ }
+ else
+ {
+ pDevice->WolSpeed = WOL_SPEED_100MB;
+ }
+
+ /* Offloadings. */
+ pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+
+ /* Turn off task offloading on Ax. */
+ if(pDevice->ChipRevId == T3_CHIP_ID_5700_B0)
+ {
+ pDevice->TaskOffloadCap &= ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+ LM_TASK_OFFLOAD_TX_UDP_CHECKSUM);
+ }
+ pDevice->PciState = REG_RD(pDevice, PciCfg.PciState);
+ LM_ReadVPD(pDevice);
+ LM_ReadBootCodeVersion(pDevice);
+ LM_GetBusSpeed(pDevice);
+
+ return LM_STATUS_SUCCESS;
+} /* LM_GetAdapterInfo */
+
+STATIC PLM_ADAPTER_INFO
+LM_GetAdapterInfoBySsid(
+ LM_UINT16 Svid,
+ LM_UINT16 Ssid)
+{
+ static LM_ADAPTER_INFO AdapterArr[] =
+ {
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A6, PHY_BCM5401_PHY_ID, 0},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A5, PHY_BCM5701_PHY_ID, 0},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700T6, PHY_BCM8002_PHY_ID, 1},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A9, 0, 1 },
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T1, PHY_BCM5701_PHY_ID, 0},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T8, PHY_BCM5701_PHY_ID, 0},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A7, 0, 1},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A10, PHY_BCM5701_PHY_ID, 0},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A12, PHY_BCM5701_PHY_ID, 0},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax1, PHY_BCM5701_PHY_ID, 0},
+ { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax2, PHY_BCM5701_PHY_ID, 0},
+
+ { T3_SVID_3COM, T3_SSID_3COM_3C996T, PHY_BCM5401_PHY_ID, 0 },
+ { T3_SVID_3COM, T3_SSID_3COM_3C996BT, PHY_BCM5701_PHY_ID, 0 },
+ { T3_SVID_3COM, T3_SSID_3COM_3C996SX, 0, 1 },
+ { T3_SVID_3COM, T3_SSID_3COM_3C1000T, PHY_BCM5701_PHY_ID, 0 },
+ { T3_SVID_3COM, T3_SSID_3COM_3C940BR01, PHY_BCM5701_PHY_ID, 0 },
+
+ { T3_SVID_DELL, T3_SSID_DELL_VIPER, PHY_BCM5401_PHY_ID, 0 },
+ { T3_SVID_DELL, T3_SSID_DELL_JAGUAR, PHY_BCM5401_PHY_ID, 0 },
+ { T3_SVID_DELL, T3_SSID_DELL_MERLOT, PHY_BCM5411_PHY_ID, 0 },
+ { T3_SVID_DELL, T3_SSID_DELL_SLIM_MERLOT, PHY_BCM5411_PHY_ID, 0 },
+
+ { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE, PHY_BCM5701_PHY_ID, 0 },
+ { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE_2, PHY_BCM5701_PHY_ID, 0 },
+ { T3_SVID_COMPAQ, T3_SSID_COMPAQ_CHANGELING, 0, 1 },
+ { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780, PHY_BCM5701_PHY_ID, 0 },
+ { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780_2, PHY_BCM5701_PHY_ID, 0 },
+
+ };
+ LM_UINT32 j;
+
+ for(j = 0; j < sizeof(AdapterArr)/sizeof(LM_ADAPTER_INFO); j++)
+ {
+ if(AdapterArr[j].Svid == Svid && AdapterArr[j].Ssid == Ssid)
+ {
+ return &AdapterArr[j];
+ }
+ }
+
+ return NULL;
+}
+
+
+/******************************************************************************/
+/* Description: */
+/* This routine sets up receive/transmit buffer descriptions queues. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_InitializeAdapter(
+PLM_DEVICE_BLOCK pDevice)
+{
+ LM_PHYSICAL_ADDRESS MemPhy;
+ PLM_UINT8 pMemVirt;
+ PLM_PACKET pPacket;
+ LM_STATUS Status;
+ LM_UINT32 Size;
+ LM_UINT32 j;
+
+ /* Set power state to D0. */
+ LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+ /* Intialize the queues. */
+ QQ_InitQueue(&pDevice->RxPacketReceivedQ.Container,
+ MAX_RX_PACKET_DESC_COUNT);
+ QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
+ MAX_RX_PACKET_DESC_COUNT);
+
+ QQ_InitQueue(&pDevice->TxPacketFreeQ.Container,MAX_TX_PACKET_DESC_COUNT);
+ QQ_InitQueue(&pDevice->TxPacketActiveQ.Container,MAX_TX_PACKET_DESC_COUNT);
+ QQ_InitQueue(&pDevice->TxPacketXmittedQ.Container,MAX_TX_PACKET_DESC_COUNT);
+
+ /* Allocate shared memory for: status block, the buffers for receive */
+ /* rings -- standard, mini, jumbo, and return rings. */
+ Size = T3_STATUS_BLOCK_SIZE + sizeof(T3_STATS_BLOCK) +
+ T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD) +
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD) +
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+ T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+
+ /* Memory for host based Send BD. */
+ if(pDevice->NicSendBd == FALSE)
+ {
+ Size += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT;
+ }
+
+ /* Allocate the memory block. */
+ Status = MM_AllocateSharedMemory(pDevice, Size, (PLM_VOID) &pMemVirt, &MemPhy, FALSE);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+
+ /* Program DMA Read/Write */
+ if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS)
+ {
+ pDevice->DmaReadWriteCtrl = 0x763f000f;
+ }
+ else
+ {
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+ {
+ pDevice->DmaReadWriteCtrl = 0x761f0000;
+ }
+ else
+ {
+ pDevice->DmaReadWriteCtrl = 0x761b000f;
+ }
+ if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5703_A2)
+ {
+ pDevice->OneDmaAtOnce = TRUE;
+ }
+ }
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+ {
+ pDevice->DmaReadWriteCtrl &= 0xfffffff0;
+ }
+
+ if(pDevice->OneDmaAtOnce)
+ {
+ pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_ONE_DMA_AT_ONCE;
+ }
+ REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl);
+
+ if (LM_DmaTest(pDevice, pMemVirt, MemPhy, 0x400) != LM_STATUS_SUCCESS)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ /* Status block. */
+ pDevice->pStatusBlkVirt = (PT3_STATUS_BLOCK) pMemVirt;
+ pDevice->StatusBlkPhy = MemPhy;
+ pMemVirt += T3_STATUS_BLOCK_SIZE;
+ LM_INC_PHYSICAL_ADDRESS(&MemPhy, T3_STATUS_BLOCK_SIZE);
+
+ /* Statistics block. */
+ pDevice->pStatsBlkVirt = (PT3_STATS_BLOCK) pMemVirt;
+ pDevice->StatsBlkPhy = MemPhy;
+ pMemVirt += sizeof(T3_STATS_BLOCK);
+ LM_INC_PHYSICAL_ADDRESS(&MemPhy, sizeof(T3_STATS_BLOCK));
+
+ /* Receive standard BD buffer. */
+ pDevice->pRxStdBdVirt = (PT3_RCV_BD) pMemVirt;
+ pDevice->RxStdBdPhy = MemPhy;
+
+ pMemVirt += T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+ LM_INC_PHYSICAL_ADDRESS(&MemPhy,
+ T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ /* Receive jumbo BD buffer. */
+ pDevice->pRxJumboBdVirt = (PT3_RCV_BD) pMemVirt;
+ pDevice->RxJumboBdPhy = MemPhy;
+
+ pMemVirt += T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+ LM_INC_PHYSICAL_ADDRESS(&MemPhy,
+ T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ /* Receive return BD buffer. */
+ pDevice->pRcvRetBdVirt = (PT3_RCV_BD) pMemVirt;
+ pDevice->RcvRetBdPhy = MemPhy;
+
+ pMemVirt += T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+ LM_INC_PHYSICAL_ADDRESS(&MemPhy,
+ T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+
+ /* Set up Send BD. */
+ if(pDevice->NicSendBd == FALSE)
+ {
+ pDevice->pSendBdVirt = (PT3_SND_BD) pMemVirt;
+ pDevice->SendBdPhy = MemPhy;
+
+ pMemVirt += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT;
+ LM_INC_PHYSICAL_ADDRESS(&MemPhy,
+ sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT);
+ }
+ else
+ {
+ pDevice->pSendBdVirt = (PT3_SND_BD)
+ pDevice->pMemView->uIntMem.First32k.BufferDesc;
+ pDevice->SendBdPhy.High = 0;
+ pDevice->SendBdPhy.Low = T3_NIC_SND_BUFFER_DESC_ADDR;
+ }
+
+ /* Allocate memory for packet descriptors. */
+ Size = (pDevice->RxPacketDescCnt +
+ pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE;
+ Status = MM_AllocateMemory(pDevice, Size, (PLM_VOID *) &pPacket);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+ pDevice->pPacketDescBase = (PLM_VOID) pPacket;
+
+ /* Create transmit packet descriptors from the memory block and add them */
+ /* to the TxPacketFreeQ for each send ring. */
+ for(j = 0; j < pDevice->TxPacketDescCnt; j++)
+ {
+ /* Ring index. */
+ pPacket->Flags = 0;
+
+ /* Queue the descriptor in the TxPacketFreeQ of the 'k' ring. */
+ QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+
+ /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */
+ /* is the total size of the packet descriptor including the */
+ /* os-specific extensions in the UM_PACKET structure. */
+ pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+ } /* for(j.. */
+
+ /* Create receive packet descriptors from the memory block and add them */
+ /* to the RxPacketFreeQ. Create the Standard packet descriptors. */
+ for(j = 0; j < pDevice->RxStdDescCnt; j++)
+ {
+ /* Receive producer ring. */
+ pPacket->u.Rx.RcvProdRing = T3_STD_RCV_PROD_RING;
+
+ /* Receive buffer size. */
+ pPacket->u.Rx.RxBufferSize = MAX_STD_RCV_BUFFER_SIZE;
+
+ /* Add the descriptor to RxPacketFreeQ. */
+ QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+ /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */
+ /* is the total size of the packet descriptor including the */
+ /* os-specific extensions in the UM_PACKET structure. */
+ pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+ } /* for */
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ /* Create the Jumbo packet descriptors. */
+ for(j = 0; j < pDevice->RxJumboDescCnt; j++)
+ {
+ /* Receive producer ring. */
+ pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING;
+
+ /* Receive buffer size. */
+ pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize;
+
+ /* Add the descriptor to RxPacketFreeQ. */
+ QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+ /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */
+ /* is the total size of the packet descriptor including the */
+ /* os-specific extensions in the UM_PACKET structure. */
+ pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+ } /* for */
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ /* Initialize the rest of the packet descriptors. */
+ Status = MM_InitializeUmPackets(pDevice);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ } /* if */
+
+ /* Default receive mask. */
+ pDevice->ReceiveMask = LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST |
+ LM_ACCEPT_UNICAST;
+
+ /* Make sure we are in the first 32k memory window or NicSendBd. */
+ REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+
+ /* Initialize the hardware. */
+ Status = LM_ResetAdapter(pDevice);
+ if(Status != LM_STATUS_SUCCESS)
+ {
+ return Status;
+ }
+
+ /* We are done with initialization. */
+ pDevice->InitDone = TRUE;
+
+ return LM_STATUS_SUCCESS;
+} /* LM_InitializeAdapter */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* This function Enables/Disables a given block. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_CntrlBlock(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 mask,LM_UINT32 cntrl)
+{
+ LM_UINT32 j,i,data;
+ LM_UINT32 MaxWaitCnt;
+
+ MaxWaitCnt = 2;
+ j = 0;
+
+ for(i = 0 ; i < 32; i++)
+ {
+ if(!(mask & (1 << i)))
+ continue;
+
+ switch (1 << i)
+ {
+ case T3_BLOCK_DMA_RD:
+ data = REG_RD(pDevice, DmaRead.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~DMA_READ_MODE_ENABLE;
+ REG_WR(pDevice, DmaRead.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, DmaRead.Mode) & DMA_READ_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, DmaRead.Mode, data | DMA_READ_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_DMA_COMP:
+ data = REG_RD(pDevice,DmaComp.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~DMA_COMP_MODE_ENABLE;
+ REG_WR(pDevice, DmaComp.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, DmaComp.Mode) & DMA_COMP_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, DmaComp.Mode, data | DMA_COMP_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_RX_BD_INITIATOR:
+ data = REG_RD(pDevice, RcvBdIn.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~RCV_BD_IN_MODE_ENABLE;
+ REG_WR(pDevice, RcvBdIn.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, RcvBdIn.Mode) & RCV_BD_IN_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, RcvBdIn.Mode,data | RCV_BD_IN_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_RX_BD_COMP:
+ data = REG_RD(pDevice, RcvBdComp.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~RCV_BD_COMP_MODE_ENABLE;
+ REG_WR(pDevice, RcvBdComp.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, RcvBdComp.Mode) & RCV_BD_COMP_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, RcvBdComp.Mode,data | RCV_BD_COMP_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_DMA_WR:
+ data = REG_RD(pDevice, DmaWrite.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~DMA_WRITE_MODE_ENABLE;
+ REG_WR(pDevice, DmaWrite.Mode,data);
+
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, DmaWrite.Mode) & DMA_WRITE_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, DmaWrite.Mode,data | DMA_WRITE_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_MSI_HANDLER:
+ data = REG_RD(pDevice, Msi.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~MSI_MODE_ENABLE;
+ REG_WR(pDevice, Msi.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, Msi.Mode) & MSI_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, Msi.Mode, data |MSI_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_RX_LIST_PLMT:
+ data = REG_RD(pDevice, RcvListPlmt.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~RCV_LIST_PLMT_MODE_ENABLE;
+ REG_WR(pDevice, RcvListPlmt.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, RcvListPlmt.Mode) & RCV_LIST_PLMT_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, RcvListPlmt.Mode,data | RCV_LIST_PLMT_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_RX_LIST_SELECTOR:
+ data = REG_RD(pDevice, RcvListSel.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~RCV_LIST_SEL_MODE_ENABLE;
+ REG_WR(pDevice, RcvListSel.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, RcvListSel.Mode) & RCV_LIST_SEL_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, RcvListSel.Mode,data |RCV_LIST_SEL_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_RX_DATA_INITIATOR:
+ data = REG_RD(pDevice, RcvDataBdIn.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~RCV_DATA_BD_IN_MODE_ENABLE;
+ REG_WR(pDevice, RcvDataBdIn.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_BD_IN_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, RcvDataBdIn.Mode, data | RCV_DATA_BD_IN_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_RX_DATA_COMP:
+ data = REG_RD(pDevice, RcvDataComp.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~RCV_DATA_COMP_MODE_ENABLE;
+ REG_WR(pDevice, RcvDataComp.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_COMP_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, RcvDataComp.Mode,data | RCV_DATA_COMP_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_HOST_COALESING:
+ data = REG_RD(pDevice, HostCoalesce.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~HOST_COALESCE_ENABLE;
+ REG_WR(pDevice, HostCoalesce.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, SndBdIn.Mode) & HOST_COALESCE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, HostCoalesce.Mode, data | HOST_COALESCE_ENABLE);
+ break;
+
+ case T3_BLOCK_MAC_RX_ENGINE:
+ if(cntrl == LM_DISABLE)
+ {
+ pDevice->RxMode &= ~RX_MODE_ENABLE;
+ REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, MacCtrl.RxMode) & RX_MODE_ENABLE))
+ {
+ break;
+ }
+ MM_Wait(10);
+ }
+ }
+ else
+ {
+ pDevice->RxMode |= RX_MODE_ENABLE;
+ REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+ }
+ break;
+
+ case T3_BLOCK_MBUF_CLUSTER_FREE:
+ data = REG_RD(pDevice, MbufClusterFree.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~MBUF_CLUSTER_FREE_MODE_ENABLE;
+ REG_WR(pDevice, MbufClusterFree.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, MbufClusterFree.Mode) & MBUF_CLUSTER_FREE_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, MbufClusterFree.Mode, data | MBUF_CLUSTER_FREE_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_SEND_BD_INITIATOR:
+ data = REG_RD(pDevice, SndBdIn.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~SND_BD_IN_MODE_ENABLE;
+ REG_WR(pDevice, SndBdIn.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, SndBdIn.Mode) & SND_BD_IN_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, SndBdIn.Mode, data | SND_BD_IN_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_SEND_BD_COMP:
+ data = REG_RD(pDevice, SndBdComp.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~SND_BD_COMP_MODE_ENABLE;
+ REG_WR(pDevice, SndBdComp.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, SndBdComp.Mode) & SND_BD_COMP_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, SndBdComp.Mode, data | SND_BD_COMP_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_SEND_BD_SELECTOR:
+ data = REG_RD(pDevice, SndBdSel.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~SND_BD_SEL_MODE_ENABLE;
+ REG_WR(pDevice, SndBdSel.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, SndBdSel.Mode) & SND_BD_SEL_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, SndBdSel.Mode, data | SND_BD_SEL_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_SEND_DATA_INITIATOR:
+ data = REG_RD(pDevice, SndDataIn.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~T3_SND_DATA_IN_MODE_ENABLE;
+ REG_WR(pDevice, SndDataIn.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, SndDataIn.Mode) & T3_SND_DATA_IN_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, SndDataIn.Mode,data | T3_SND_DATA_IN_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_SEND_DATA_COMP:
+ data = REG_RD(pDevice, SndDataComp.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~SND_DATA_COMP_MODE_ENABLE;
+ REG_WR(pDevice, SndDataComp.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, SndDataComp.Mode) & SND_DATA_COMP_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, SndDataComp.Mode,data | SND_DATA_COMP_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_MAC_TX_ENGINE:
+ if(cntrl == LM_DISABLE)
+ {
+ pDevice->TxMode &= ~TX_MODE_ENABLE;
+ REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, MacCtrl.TxMode) & TX_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ {
+ pDevice->TxMode |= TX_MODE_ENABLE;
+ REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+ }
+ break;
+
+ case T3_BLOCK_MEM_ARBITOR:
+ data = REG_RD(pDevice, MemArbiter.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~T3_MEM_ARBITER_MODE_ENABLE;
+ REG_WR(pDevice, MemArbiter.Mode, data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, MemArbiter.Mode) & T3_MEM_ARBITER_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, MemArbiter.Mode,data|T3_MEM_ARBITER_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_MBUF_MANAGER:
+ data = REG_RD(pDevice, BufMgr.Mode);
+ if (cntrl == LM_DISABLE)
+ {
+ data &= ~BUFMGR_MODE_ENABLE;
+ REG_WR(pDevice, BufMgr.Mode,data);
+ for(j = 0; j < MaxWaitCnt; j++)
+ {
+ if(!(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE))
+ break;
+ MM_Wait(10);
+ }
+ }
+ else
+ REG_WR(pDevice, BufMgr.Mode,data | BUFMGR_MODE_ENABLE);
+ break;
+
+ case T3_BLOCK_MAC_GLOBAL:
+ if(cntrl == LM_DISABLE)
+ {
+ pDevice->MacMode &= ~(MAC_MODE_ENABLE_TDE |
+ MAC_MODE_ENABLE_RDE |
+ MAC_MODE_ENABLE_FHDE);
+ }
+ else
+ {
+ pDevice->MacMode |= (MAC_MODE_ENABLE_TDE |
+ MAC_MODE_ENABLE_RDE |
+ MAC_MODE_ENABLE_FHDE);
+ }
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+ break;
+
+ default:
+ return LM_STATUS_FAILURE;
+ } /* switch */
+
+ if(j >= MaxWaitCnt)
+ {
+ return LM_STATUS_FAILURE;
+ }
+ }
+
+ return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description: */
+/* This function reinitializes the adapter. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_ResetAdapter(
+PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 Value32;
+ LM_UINT16 Value16;
+ LM_UINT32 j, k;
+
+ /* Disable interrupt. */
+ LM_DisableInterrupt(pDevice);
+
+ /* May get a spurious interrupt */
+ pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED;
+
+ /* Disable transmit and receive DMA engines. Abort all pending requests. */
+ if(pDevice->InitDone)
+ {
+ LM_Abort(pDevice);
+ }
+
+ pDevice->ShuttingDown = FALSE;
+
+ LM_ResetChip(pDevice);
+
+ /* Bug: Athlon fix for B3 silicon only. This bit does not do anything */
+ /* in other chip revisions. */
+ if(pDevice->DelayPciGrant)
+ {
+ Value32 = REG_RD(pDevice, PciCfg.ClockCtrl);
+ REG_WR(pDevice, PciCfg.ClockCtrl, Value32 | BIT_31);
+ }
+
+ if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+ {
+ if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+ {
+ Value32 = REG_RD(pDevice, PciCfg.PciState);
+ Value32 |= T3_PCI_STATE_RETRY_SAME_DMA;
+ REG_WR(pDevice, PciCfg.PciState, Value32);
+ }
+ }
+
+ /* Enable TaggedStatus mode. */
+ if(pDevice->UseTaggedStatus)
+ {
+ pDevice->MiscHostCtrl |= MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE;
+ }
+
+ /* Restore PCI configuration registers. */
+ MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+ pDevice->SavedCacheLineReg);
+ MM_WriteConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG,
+ (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+ /* Clear the statistics block. */
+ for(j = 0x0300; j < 0x0b00; j++)
+ {
+ MEM_WR_OFFSET(pDevice, j, 0);
+ }
+
+ /* Initialize the statistis Block */
+ pDevice->pStatusBlkVirt->Status = 0;
+ pDevice->pStatusBlkVirt->RcvStdConIdx = 0;
+ pDevice->pStatusBlkVirt->RcvJumboConIdx = 0;
+ pDevice->pStatusBlkVirt->RcvMiniConIdx = 0;
+
+ for(j = 0; j < 16; j++)
+ {
+ pDevice->pStatusBlkVirt->Idx[j].RcvProdIdx = 0;
+ pDevice->pStatusBlkVirt->Idx[j].SendConIdx = 0;
+ }
+
+ for(k = 0; k < T3_STD_RCV_RCB_ENTRY_COUNT ;k++)
+ {
+ pDevice->pRxStdBdVirt[k].HostAddr.High = 0;
+ pDevice->pRxStdBdVirt[k].HostAddr.Low = 0;
+ }
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ /* Receive jumbo BD buffer. */
+ for(k = 0; k < T3_JUMBO_RCV_RCB_ENTRY_COUNT; k++)
+ {
+ pDevice->pRxJumboBdVirt[k].HostAddr.High = 0;
+ pDevice->pRxJumboBdVirt[k].HostAddr.Low = 0;
+ }
+#endif
+
+ REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl);
+
+ /* GRC mode control register. */
+#ifdef BIG_ENDIAN_PCI /* Jimmy, this ifdef block deleted in new code! */
+ Value32 =
+ GRC_MODE_WORD_SWAP_DATA |
+ GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+ GRC_MODE_INT_ON_MAC_ATTN |
+ GRC_MODE_HOST_STACK_UP;
+#else
+ /* No CPU Swap modes for PCI IO */
+ Value32 =
+#ifdef BIG_ENDIAN_HOST
+ GRC_MODE_BYTE_SWAP_NON_FRAME_DATA |
+ GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+ GRC_MODE_BYTE_SWAP_DATA |
+ GRC_MODE_WORD_SWAP_DATA |
+#else
+ GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+ GRC_MODE_BYTE_SWAP_DATA |
+ GRC_MODE_WORD_SWAP_DATA |
+#endif
+ GRC_MODE_INT_ON_MAC_ATTN |
+ GRC_MODE_HOST_STACK_UP;
+#endif /* !BIG_ENDIAN_PCI */
+
+ /* Configure send BD mode. */
+ if(pDevice->NicSendBd == FALSE)
+ {
+ Value32 |= GRC_MODE_HOST_SEND_BDS;
+ }
+ else
+ {
+ Value32 |= GRC_MODE_4X_NIC_BASED_SEND_RINGS;
+ }
+
+ /* Configure pseudo checksum mode. */
+ if(pDevice->NoTxPseudoHdrChksum)
+ {
+ Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM;
+ }
+
+ if(pDevice->NoRxPseudoHdrChksum)
+ {
+ Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM;
+ }
+
+ REG_WR(pDevice, Grc.Mode, Value32);
+
+ /* Setup the timer prescalar register. */
+ REG_WR(pDevice, Grc.MiscCfg, 65 << 1); /* Clock is alwasy 66Mhz. */
+
+ /* Set up the MBUF pool base address and size. */
+ REG_WR(pDevice, BufMgr.MbufPoolAddr, pDevice->MbufBase);
+ REG_WR(pDevice, BufMgr.MbufPoolSize, pDevice->MbufSize);
+
+ /* Set up the DMA descriptor pool base address and size. */
+ REG_WR(pDevice, BufMgr.DmaDescPoolAddr, T3_NIC_DMA_DESC_POOL_ADDR);
+ REG_WR(pDevice, BufMgr.DmaDescPoolSize, T3_NIC_DMA_DESC_POOL_SIZE);
+
+ /* Configure MBUF and Threshold watermarks */
+ /* Configure the DMA read MBUF low water mark. */
+ if(pDevice->DmaMbufLowMark)
+ {
+ REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+ pDevice->DmaMbufLowMark);
+ }
+ else
+ {
+ if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+ {
+ REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+ T3_DEF_DMA_MBUF_LOW_WMARK);
+ }
+ else
+ {
+ REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+ T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO);
+ }
+ }
+
+ /* Configure the MAC Rx MBUF low water mark. */
+ if(pDevice->RxMacMbufLowMark)
+ {
+ REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+ pDevice->RxMacMbufLowMark);
+ }
+ else
+ {
+ if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+ {
+ REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+ T3_DEF_RX_MAC_MBUF_LOW_WMARK);
+ }
+ else
+ {
+ REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+ T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO);
+ }
+ }
+
+ /* Configure the MBUF high water mark. */
+ if(pDevice->MbufHighMark)
+ {
+ REG_WR(pDevice, BufMgr.MbufHighWaterMark, pDevice->MbufHighMark);
+ }
+ else
+ {
+ if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+ {
+ REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+ T3_DEF_MBUF_HIGH_WMARK);
+ }
+ else
+ {
+ REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+ T3_DEF_MBUF_HIGH_WMARK_JUMBO);
+ }
+ }
+
+ REG_WR(pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK);
+ REG_WR(pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK);
+
+ /* Enable buffer manager. */
+ REG_WR(pDevice, BufMgr.Mode, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
+
+ for(j = 0 ;j < 2000; j++)
+ {
+ if(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE)
+ break;
+ MM_Wait(10);
+ }
+
+ if(j >= 2000)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ /* Enable the FTQs. */
+ REG_WR(pDevice, Ftq.Reset, 0xffffffff);
+ REG_WR(pDevice, Ftq.Reset, 0);
+
+ /* Wait until FTQ is ready */
+ for(j = 0; j < 2000; j++)
+ {
+ if(REG_RD(pDevice, Ftq.Reset) == 0)
+ break;
+ MM_Wait(10);
+ }
+
+ if(j >= 2000)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ /* Initialize the Standard Receive RCB. */
+ REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.High,
+ pDevice->RxStdBdPhy.High);
+ REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.Low,
+ pDevice->RxStdBdPhy.Low);
+ REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags,
+ MAX_STD_RCV_BUFFER_SIZE << 16);
+
+ /* Initialize the Jumbo Receive RCB. */
+ REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags,
+ T3_RCB_FLAG_RING_DISABLED);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.High,
+ pDevice->RxJumboBdPhy.High);
+ REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.Low,
+ pDevice->RxJumboBdPhy.Low);
+
+ REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, 0);
+
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ /* Initialize the Mini Receive RCB. */
+ REG_WR(pDevice, RcvDataBdIn.MiniRcvRcb.u.MaxLen_Flags,
+ T3_RCB_FLAG_RING_DISABLED);
+
+ {
+ REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.NicRingAddr,
+ (LM_UINT32) T3_NIC_STD_RCV_BUFFER_DESC_ADDR);
+ REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.NicRingAddr,
+ (LM_UINT32) T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR);
+ }
+
+ /* Receive BD Ring replenish threshold. */
+ REG_WR(pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt/8);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ REG_WR(pDevice, RcvBdIn.JumboRcvThreshold, pDevice->RxJumboDescCnt/8);
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ /* Disable all the unused rings. */
+ for(j = 0; j < T3_MAX_SEND_RCB_COUNT; j++) {
+ MEM_WR(pDevice, SendRcb[j].u.MaxLen_Flags, T3_RCB_FLAG_RING_DISABLED);
+ } /* for */
+
+ /* Initialize the indices. */
+ pDevice->SendProdIdx = 0;
+ pDevice->SendConIdx = 0;
+
+ MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, 0);
+ MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, 0);
+
+ /* Set up host or NIC based send RCB. */
+ if(pDevice->NicSendBd == FALSE)
+ {
+ MEM_WR(pDevice, SendRcb[0].HostRingAddr.High,
+ pDevice->SendBdPhy.High);
+ MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low,
+ pDevice->SendBdPhy.Low);
+
+ /* Set up the NIC ring address in the RCB. */
+ MEM_WR(pDevice, SendRcb[0].NicRingAddr,T3_NIC_SND_BUFFER_DESC_ADDR);
+
+ /* Setup the RCB. */
+ MEM_WR(pDevice, SendRcb[0].u.MaxLen_Flags,
+ T3_SEND_RCB_ENTRY_COUNT << 16);
+
+ for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++)
+ {
+ pDevice->pSendBdVirt[k].HostAddr.High = 0;
+ pDevice->pSendBdVirt[k].HostAddr.Low = 0;
+ }
+ }
+ else
+ {
+ MEM_WR(pDevice, SendRcb[0].HostRingAddr.High, 0);
+ MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low, 0);
+ MEM_WR(pDevice, SendRcb[0].NicRingAddr,
+ pDevice->SendBdPhy.Low);
+
+ for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++)
+ {
+ __raw_writel(0, &(pDevice->pSendBdVirt[k].HostAddr.High));
+ __raw_writel(0, &(pDevice->pSendBdVirt[k].HostAddr.Low));
+ __raw_writel(0, &(pDevice->pSendBdVirt[k].u1.Len_Flags));
+ pDevice->ShadowSendBd[k].HostAddr.High = 0;
+ pDevice->ShadowSendBd[k].u1.Len_Flags = 0;
+ }
+ }
+ atomic_set(&pDevice->SendBdLeft, T3_SEND_RCB_ENTRY_COUNT-1);
+
+ /* Configure the receive return rings. */
+ for(j = 0; j < T3_MAX_RCV_RETURN_RCB_COUNT; j++)
+ {
+ MEM_WR(pDevice, RcvRetRcb[j].u.MaxLen_Flags, T3_RCB_FLAG_RING_DISABLED);
+ }
+
+ pDevice->RcvRetConIdx = 0;
+
+ MEM_WR(pDevice, RcvRetRcb[0].HostRingAddr.High,
+ pDevice->RcvRetBdPhy.High);
+ MEM_WR(pDevice, RcvRetRcb[0].HostRingAddr.Low,
+ pDevice->RcvRetBdPhy.Low);
+
+ /* Set up the NIC ring address in the RCB. */
+ /* Not very clear from the spec. I am guessing that for Receive */
+ /* Return Ring, NicRingAddr is not used. */
+ MEM_WR(pDevice, RcvRetRcb[0].NicRingAddr, 0);
+
+ /* Setup the RCB. */
+ MEM_WR(pDevice, RcvRetRcb[0].u.MaxLen_Flags,
+ T3_RCV_RETURN_RCB_ENTRY_COUNT << 16);
+
+ /* Reinitialize RX ring producer index */
+ MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, 0);
+ MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low, 0);
+ MB_REG_WR(pDevice, Mailbox.RcvMiniProdIdx.Low, 0);
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ pDevice->RxJumboProdIdx = 0;
+ pDevice->RxJumboQueuedCnt = 0;
+#endif
+
+ /* Reinitialize our copy of the indices. */
+ pDevice->RxStdProdIdx = 0;
+ pDevice->RxStdQueuedCnt = 0;
+
+#if T3_JUMBO_RCV_ENTRY_COUNT
+ pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_ENTRY_COUNT */
+
+ /* Configure the MAC address. */
+ LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+ /* Initialize the transmit random backoff seed. */
+ Value32 = (pDevice->NodeAddress[0] + pDevice->NodeAddress[1] +
+ pDevice->NodeAddress[2] + pDevice->NodeAddress[3] +
+ pDevice->NodeAddress[4] + pDevice->NodeAddress[5]) &
+ MAC_TX_BACKOFF_SEED_MASK;
+ REG_WR(pDevice, MacCtrl.TxBackoffSeed, Value32);
+
+ /* Receive MTU. Frames larger than the MTU is marked as oversized. */
+ REG_WR(pDevice, MacCtrl.MtuSize, pDevice->RxMtu + 8); /* CRC + VLAN. */
+
+ /* Configure Time slot/IPG per 802.3 */
+ REG_WR(pDevice, MacCtrl.TxLengths, 0x2620);
+
+ /*
+ * Configure Receive Rules so that packets don't match
+ * Programmble rule will be queued to Return Ring 1
+ */
+ REG_WR(pDevice, MacCtrl.RcvRuleCfg, RX_RULE_DEFAULT_CLASS);
+
+ /*
+ * Configure to have 16 Classes of Services (COS) and one
+ * queue per class. Bad frames are queued to RRR#1.
+ * And frames don't match rules are also queued to COS#1.
+ */
+ REG_WR(pDevice, RcvListPlmt.Config, 0x181);
+
+ /* Enable Receive Placement Statistics */
+ REG_WR(pDevice, RcvListPlmt.StatsEnableMask,0xffffff);
+ REG_WR(pDevice, RcvListPlmt.StatsCtrl, RCV_LIST_STATS_ENABLE);
+
+ /* Enable Send Data Initator Statistics */
+ REG_WR(pDevice, SndDataIn.StatsEnableMask,0xffffff);
+ REG_WR(pDevice, SndDataIn.StatsCtrl,
+ T3_SND_DATA_IN_STATS_CTRL_ENABLE | \
+ T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE);
+
+ /* Disable the host coalescing state machine before configuring it's */
+ /* parameters. */
+ REG_WR(pDevice, HostCoalesce.Mode, 0);
+ for(j = 0; j < 2000; j++)
+ {
+ Value32 = REG_RD(pDevice, HostCoalesce.Mode);
+ if(!(Value32 & HOST_COALESCE_ENABLE))
+ {
+ break;
+ }
+ MM_Wait(10);
+ }
+
+ /* Host coalescing configurations. */
+ REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, pDevice->RxCoalescingTicks);
+ REG_WR(pDevice, HostCoalesce.TxCoalescingTicks, pDevice->TxCoalescingTicks);
+ REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames,
+ pDevice->RxMaxCoalescedFrames);
+ REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames,
+ pDevice->TxMaxCoalescedFrames);
+ REG_WR(pDevice, HostCoalesce.RxCoalescedTickDuringInt,
+ pDevice->RxCoalescingTicksDuringInt);
+ REG_WR(pDevice, HostCoalesce.TxCoalescedTickDuringInt,
+ pDevice->TxCoalescingTicksDuringInt);
+ REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt,
+ pDevice->RxMaxCoalescedFramesDuringInt);
+ REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFramesDuringInt,
+ pDevice->TxMaxCoalescedFramesDuringInt);
+
+ /* Initialize the address of the status block. The NIC will DMA */
+ /* the status block to this memory which resides on the host. */
+ REG_WR(pDevice, HostCoalesce.StatusBlkHostAddr.High,
+ pDevice->StatusBlkPhy.High);
+ REG_WR(pDevice, HostCoalesce.StatusBlkHostAddr.Low,
+ pDevice->StatusBlkPhy.Low);
+
+ /* Initialize the address of the statistics block. The NIC will DMA */
+ /* the statistics to this block of memory. */
+ REG_WR(pDevice, HostCoalesce.StatsBlkHostAddr.High,
+ pDevice->StatsBlkPhy.High);
+ REG_WR(pDevice, HostCoalesce.StatsBlkHostAddr.Low,
+ pDevice->StatsBlkPhy.Low);
+
+ REG_WR(pDevice, HostCoalesce.StatsCoalescingTicks,
+ pDevice->StatsCoalescingTicks);
+
+ REG_WR(pDevice, HostCoalesce.StatsBlkNicAddr, 0x300);
+ REG_WR(pDevice, HostCoalesce.StatusBlkNicAddr,0xb00);
+
+ /* Enable Host Coalesing state machine */
+ REG_WR(pDevice, HostCoalesce.Mode, HOST_COALESCE_ENABLE |
+ pDevice->CoalesceMode);
+
+ /* Enable the Receive BD Completion state machine. */
+ REG_WR(pDevice, RcvBdComp.Mode, RCV_BD_COMP_MODE_ENABLE |
+ RCV_BD_COMP_MODE_ATTN_ENABLE);
+
+ /* Enable the Receive List Placement state machine. */
+ REG_WR(pDevice, RcvListPlmt.Mode, RCV_LIST_PLMT_MODE_ENABLE);
+
+ /* Enable the Receive List Selector state machine. */
+ REG_WR(pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE |
+ RCV_LIST_SEL_MODE_ATTN_ENABLE);
+
+ /* Enable transmit DMA, clear statistics. */
+ pDevice->MacMode = MAC_MODE_ENABLE_TX_STATISTICS |
+ MAC_MODE_ENABLE_RX_STATISTICS | MAC_MODE_ENABLE_TDE |
+ MAC_MODE_ENABLE_RDE | MAC_MODE_ENABLE_FHDE;
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+ MAC_MODE_CLEAR_RX_STATISTICS | MAC_MODE_CLEAR_TX_STATISTICS);
+
+ /* GRC miscellaneous local control register. */
+ pDevice->GrcLocalCtrl = GRC_MISC_LOCAL_CTRL_INT_ON_ATTN |
+ GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM;
+
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1;
+ }
+
+ REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+ MM_Wait(40);
+
+ /* Reset RX counters. */
+ for(j = 0; j < sizeof(LM_RX_COUNTERS); j++)
+ {
+ ((PLM_UINT8) &pDevice->RxCounters)[j] = 0;
+ }
+
+ /* Reset TX counters. */
+ for(j = 0; j < sizeof(LM_TX_COUNTERS); j++)
+ {
+ ((PLM_UINT8) &pDevice->TxCounters)[j] = 0;
+ }
+
+ MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
+
+ /* Enable the DMA Completion state machine. */
+ REG_WR(pDevice, DmaComp.Mode, DMA_COMP_MODE_ENABLE);
+
+ /* Enable the DMA Write state machine. */
+ Value32 = DMA_WRITE_MODE_ENABLE |
+ DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE |
+ DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE |
+ DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE |
+ DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE |
+ DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE |
+ DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE |
+ DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE |
+ DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE;
+ REG_WR(pDevice, DmaWrite.Mode, Value32);
+
+ if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+ {
+ if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+ {
+ Value16 = REG_RD(pDevice, PciCfg.PciXCommand);
+ Value16 &= ~(PCIX_CMD_MAX_SPLIT_MASK | PCIX_CMD_MAX_BURST_MASK);
+ Value16 |= ((PCIX_CMD_MAX_BURST_CPIOB << PCIX_CMD_MAX_BURST_SHL) &
+ PCIX_CMD_MAX_BURST_MASK);
+ if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE)
+ {
+ Value16 |= (pDevice->SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL)
+ & PCIX_CMD_MAX_SPLIT_MASK;
+ }
+ REG_WR(pDevice, PciCfg.PciXCommand, Value16);
+ }
+ }
+
+ /* Enable the Read DMA state machine. */
+ Value32 = DMA_READ_MODE_ENABLE |
+ DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE |
+ DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE |
+ DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE |
+ DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE |
+ DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE |
+ DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE |
+ DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE |
+ DMA_READ_MODE_LONG_READ_ATTN_ENABLE;
+
+ if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE)
+ {
+ Value32 |= DMA_READ_MODE_SPLIT_ENABLE;
+ }
+ REG_WR(pDevice, DmaRead.Mode, Value32);
+
+ /* Enable the Receive Data Completion state machine. */
+ REG_WR(pDevice, RcvDataComp.Mode, RCV_DATA_COMP_MODE_ENABLE |
+ RCV_DATA_COMP_MODE_ATTN_ENABLE);
+
+ /* Enable the Mbuf Cluster Free state machine. */
+ REG_WR(pDevice, MbufClusterFree.Mode, MBUF_CLUSTER_FREE_MODE_ENABLE);
+
+ /* Enable the Send Data Completion state machine. */
+ REG_WR(pDevice, SndDataComp.Mode, SND_DATA_COMP_MODE_ENABLE);
+
+ /* Enable the Send BD Completion state machine. */
+ REG_WR(pDevice, SndBdComp.Mode, SND_BD_COMP_MODE_ENABLE |
+ SND_BD_COMP_MODE_ATTN_ENABLE);
+
+ /* Enable the Receive BD Initiator state machine. */
+ REG_WR(pDevice, RcvBdIn.Mode, RCV_BD_IN_MODE_ENABLE |
+ RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE);
+
+ /* Enable the Receive Data and Receive BD Initiator state machine. */
+ REG_WR(pDevice, RcvDataBdIn.Mode, RCV_DATA_BD_IN_MODE_ENABLE |
+ RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE);
+
+ /* Enable the Send Data Initiator state machine. */
+ REG_WR(pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE);
+
+ /* Enable the Send BD Initiator state machine. */
+ REG_WR(pDevice, SndBdIn.Mode, SND_BD_IN_MODE_ENABLE |
+ SND_BD_IN_MODE_ATTN_ENABLE);
+
+ /* Enable the Send BD Selector state machine. */
+ REG_WR(pDevice, SndBdSel.Mode, SND_BD_SEL_MODE_ENABLE |
+ SND_BD_SEL_MODE_ATTN_ENABLE);
+
+#if INCLUDE_5701_AX_FIX
+ /* Load the firmware for the 5701_A0 workaround. */
+ if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0)
+ {
+ LM_LoadRlsFirmware(pDevice);
+ }
+#endif
+
+ /* Enable the transmitter. */
+ pDevice->TxMode = TX_MODE_ENABLE;
+ REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+
+ /* Enable the receiver. */
+ pDevice->RxMode = RX_MODE_ENABLE;
+ REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+
+ if (pDevice->RestoreOnWakeUp)
+ {
+ pDevice->RestoreOnWakeUp = FALSE;
+ pDevice->DisableAutoNeg = pDevice->WakeUpDisableAutoNeg;
+ pDevice->RequestedMediaType = pDevice->WakeUpRequestedMediaType;
+ }
+
+ /* Disable auto polling. */
+ pDevice->MiMode = 0xc0000;
+ REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ Value32 = LED_CTRL_PHY_MODE_1;
+ }
+ else
+ {
+ if(pDevice->LedMode == LED_MODE_OUTPUT)
+ {
+ Value32 = LED_CTRL_PHY_MODE_2;
+ }
+ else
+ {
+ Value32 = LED_CTRL_PHY_MODE_1;
+ }
+ }
+ REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
+
+ /* Activate Link to enable MAC state machine */
+ REG_WR(pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN);
+
+ if (pDevice->EnableTbi)
+ {
+ REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_RESET);
+ MM_Wait(10);
+ REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+ if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1)
+ {
+ REG_WR(pDevice, MacCtrl.SerdesCfg, 0x616000);
+ }
+ }
+ /* Setup the phy chip. */
+ LM_SetupPhy(pDevice);
+
+ if (!pDevice->EnableTbi) {
+ /* Clear CRC stats */
+ LM_ReadPhy(pDevice, 0x1e, &Value32);
+ LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000);
+ LM_ReadPhy(pDevice, 0x14, &Value32);
+ }
+
+ /* Set up the receive mask. */
+ LM_SetReceiveMask(pDevice, pDevice->ReceiveMask);
+
+ /* Queue Rx packet buffers. */
+ if(pDevice->QueueRxPackets)
+ {
+ LM_QueueRxPackets(pDevice);
+ }
+
+ /* Enable interrupt to the host. */
+ if(pDevice->InitDone)
+ {
+ LM_EnableInterrupt(pDevice);
+ }
+
+ return LM_STATUS_SUCCESS;
+} /* LM_ResetAdapter */
+
+
+/******************************************************************************/
+/* Description: */
+/* This routine disables the adapter from generating interrupts. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_DisableInterrupt(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl |
+ MISC_HOST_CTRL_MASK_PCI_INT);
+ MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+
+ return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description: */
+/* This routine enables the adapter to generate interrupts. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_EnableInterrupt(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl &
+ ~MISC_HOST_CTRL_MASK_PCI_INT);
+ MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
+
+ if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED)
+ {
+ REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+ GRC_MISC_LOCAL_CTRL_SET_INT);
+ }
+
+ return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description: */
+/* This routine puts a packet on the wire if there is a transmit DMA */
+/* descriptor available; otherwise the packet is queued for later */
+/* transmission. If the second argue is NULL, this routine will put */
+/* the queued packet on the wire if possible. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+#if 0
+LM_STATUS
+LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+ LM_UINT32 FragCount;
+ PT3_SND_BD pSendBd;
+ PT3_SND_BD pShadowSendBd;
+ LM_UINT32 Value32, Len;
+ LM_UINT32 Idx;
+
+ if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) {
+ return LM_5700SendPacket(pDevice, pPacket);
+ }
+
+ /* Update the SendBdLeft count. */
+ atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+ /* Initalize the send buffer descriptors. */
+ Idx = pDevice->SendProdIdx;
+
+ pSendBd = &pDevice->pSendBdVirt[Idx];
+
+ /* Next producer index. */
+ if (pDevice->NicSendBd == TRUE)
+ {
+ T3_64BIT_HOST_ADDR paddr;
+
+ pShadowSendBd = &pDevice->ShadowSendBd[Idx];
+ for(FragCount = 0; ; )
+ {
+ MM_MapTxDma(pDevice, pPacket, &paddr, &Len, FragCount);
+ /* Initialize the pointer to the send buffer fragment. */
+ if (paddr.High != pShadowSendBd->HostAddr.High)
+ {
+ __raw_writel(paddr.High, &(pSendBd->HostAddr.High));
+ pShadowSendBd->HostAddr.High = paddr.High;
+ }
+ __raw_writel(paddr.Low, &(pSendBd->HostAddr.Low));
+
+ /* Setup the control flags and send buffer size. */
+ Value32 = (Len << 16) | pPacket->Flags;
+
+ Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+ FragCount++;
+ if (FragCount >= pPacket->u.Tx.FragCount)
+ {
+ Value32 |= SND_BD_FLAG_END;
+ if (Value32 != pShadowSendBd->u1.Len_Flags)
+ {
+ __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+ pShadowSendBd->u1.Len_Flags = Value32;
+ }
+ if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
+ __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag));
+ }
+ break;
+ }
+ else
+ {
+ if (Value32 != pShadowSendBd->u1.Len_Flags)
+ {
+ __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+ pShadowSendBd->u1.Len_Flags = Value32;
+ }
+ if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
+ __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag));
+ }
+ }
+
+ pSendBd++;
+ pShadowSendBd++;
+ if (Idx == 0)
+ {
+ pSendBd = &pDevice->pSendBdVirt[0];
+ pShadowSendBd = &pDevice->ShadowSendBd[0];
+ }
+ } /* for */
+
+ /* Put the packet descriptor in the ActiveQ. */
+ QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+ wmb();
+ MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+
+ }
+ else
+ {
+ for(FragCount = 0; ; )
+ {
+ /* Initialize the pointer to the send buffer fragment. */
+ MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount);
+
+ pSendBd->u2.VlanTag = pPacket->VlanTag;
+
+ /* Setup the control flags and send buffer size. */
+ Value32 = (Len << 16) | pPacket->Flags;
+
+ Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+ FragCount++;
+ if (FragCount >= pPacket->u.Tx.FragCount)
+ {
+ pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END;
+ break;
+ }
+ else
+ {
+ pSendBd->u1.Len_Flags = Value32;
+ }
+ pSendBd++;
+ if (Idx == 0)
+ {
+ pSendBd = &pDevice->pSendBdVirt[0];
+ }
+ } /* for */
+
+ /* Put the packet descriptor in the ActiveQ. */
+ QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+ wmb();
+ MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+
+ }
+
+ /* Update the producer index. */
+ pDevice->SendProdIdx = Idx;
+
+ return LM_STATUS_SUCCESS;
+}
+#endif
+
+LM_STATUS
+LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+ LM_UINT32 FragCount;
+ PT3_SND_BD pSendBd, pTmpSendBd, pShadowSendBd;
+ T3_SND_BD NicSendBdArr[MAX_FRAGMENT_COUNT];
+ LM_UINT32 StartIdx, Idx;
+
+ while (1)
+ {
+ /* Initalize the send buffer descriptors. */
+ StartIdx = Idx = pDevice->SendProdIdx;
+
+ if (pDevice->NicSendBd)
+ {
+ pTmpSendBd = pSendBd = &NicSendBdArr[0];
+ }
+ else
+ {
+ pTmpSendBd = pSendBd = &pDevice->pSendBdVirt[Idx];
+ }
+
+ /* Next producer index. */
+ for(FragCount = 0; ; )
+ {
+ LM_UINT32 Value32, Len;
+
+ /* Initialize the pointer to the send buffer fragment. */
+ MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount);
+
+ pSendBd->u2.VlanTag = pPacket->VlanTag;
+
+ /* Setup the control flags and send buffer size. */
+ Value32 = (Len << 16) | pPacket->Flags;
+
+ Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+ FragCount++;
+ if (FragCount >= pPacket->u.Tx.FragCount)
+ {
+ pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END;
+ break;
+ }
+ else
+ {
+ pSendBd->u1.Len_Flags = Value32;
+ }
+ pSendBd++;
+ if ((Idx == 0) && !pDevice->NicSendBd)
+ {
+ pSendBd = &pDevice->pSendBdVirt[0];
+ }
+ } /* for */
+ if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ if (LM_Test4GBoundary(pDevice, pPacket, pTmpSendBd) ==
+ LM_STATUS_SUCCESS)
+ {
+ if (MM_CoalesceTxBuffer(pDevice, pPacket) != LM_STATUS_SUCCESS)
+ {
+ QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+ return LM_STATUS_FAILURE;
+ }
+ continue;
+ }
+ }
+ break;
+ }
+ /* Put the packet descriptor in the ActiveQ. */
+ QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+ if (pDevice->NicSendBd)
+ {
+ pSendBd = &pDevice->pSendBdVirt[StartIdx];
+ pShadowSendBd = &pDevice->ShadowSendBd[StartIdx];
+
+ while (StartIdx != Idx)
+ {
+ LM_UINT32 Value32;
+
+ if ((Value32 = pTmpSendBd->HostAddr.High) !=
+ pShadowSendBd->HostAddr.High)
+ {
+ __raw_writel(Value32, &(pSendBd->HostAddr.High));
+ pShadowSendBd->HostAddr.High = Value32;
+ }
+
+ __raw_writel(pTmpSendBd->HostAddr.Low, &(pSendBd->HostAddr.Low));
+
+ if ((Value32 = pTmpSendBd->u1.Len_Flags) !=
+ pShadowSendBd->u1.Len_Flags)
+ {
+ __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
+ pShadowSendBd->u1.Len_Flags = Value32;
+ }
+
+ if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG)
+ {
+ __raw_writel(pTmpSendBd->u2.VlanTag, &(pSendBd->u2.VlanTag));
+ }
+
+ StartIdx = (StartIdx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+ if (StartIdx == 0)
+ pSendBd = &pDevice->pSendBdVirt[0];
+ else
+ pSendBd++;
+ pTmpSendBd++;
+ }
+ wmb();
+ MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+
+ if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+ {
+ MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+ }
+ }
+ else
+ {
+ wmb();
+ MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+
+ if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+ {
+ MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+ }
+ }
+
+ /* Update the SendBdLeft count. */
+ atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+ /* Update the producer index. */
+ pDevice->SendProdIdx = Idx;
+
+ return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS
+LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
+ PT3_SND_BD pSendBd)
+{
+ int FragCount;
+ LM_UINT32 Idx, Base, Len;
+
+ Idx = pDevice->SendProdIdx;
+ for(FragCount = 0; ; )
+ {
+ Len = pSendBd->u1.Len_Flags >> 16;
+ if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) &&
+ (pSendBd->HostAddr.High == 0) &&
+ ((Base + 8 + Len) < Base))
+ {
+ return LM_STATUS_SUCCESS;
+ }
+ FragCount++;
+ if (FragCount >= pPacket->u.Tx.FragCount)
+ {
+ break;
+ }
+ pSendBd++;
+ if (!pDevice->NicSendBd)
+ {
+ Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+ if (Idx == 0)
+ {
+ pSendBd = &pDevice->pSendBdVirt[0];
+ }
+ }
+ }
+ return LM_STATUS_FAILURE;
+}
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+__inline static unsigned long
+ComputeCrc32(
+unsigned char *pBuffer,
+unsigned long BufferSize) {
+ unsigned long Reg;
+ unsigned long Tmp;
+ unsigned long j, k;
+
+ Reg = 0xffffffff;
+
+ for(j = 0; j < BufferSize; j++)
+ {
+ Reg ^= pBuffer[j];
+
+ for(k = 0; k < 8; k++)
+ {
+ Tmp = Reg & 0x01;
+
+ Reg >>= 1;
+
+ if(Tmp)
+ {
+ Reg ^= 0xedb88320;
+ }
+ }
+ }
+
+ return ~Reg;
+} /* ComputeCrc32 */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* This routine sets the receive control register according to ReceiveMask */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_SetReceiveMask(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Mask) {
+ LM_UINT32 ReceiveMask;
+ LM_UINT32 RxMode;
+ LM_UINT32 j, k;
+
+ ReceiveMask = Mask;
+
+ RxMode = pDevice->RxMode;
+
+ if(Mask & LM_ACCEPT_UNICAST)
+ {
+ Mask &= ~LM_ACCEPT_UNICAST;
+ }
+
+ if(Mask & LM_ACCEPT_MULTICAST)
+ {
+ Mask &= ~LM_ACCEPT_MULTICAST;
+ }
+
+ if(Mask & LM_ACCEPT_ALL_MULTICAST)
+ {
+ Mask &= ~LM_ACCEPT_ALL_MULTICAST;
+ }
+
+ if(Mask & LM_ACCEPT_BROADCAST)
+ {
+ Mask &= ~LM_ACCEPT_BROADCAST;
+ }
+
+ RxMode &= ~RX_MODE_PROMISCUOUS_MODE;
+ if(Mask & LM_PROMISCUOUS_MODE)
+ {
+ RxMode |= RX_MODE_PROMISCUOUS_MODE;
+ Mask &= ~LM_PROMISCUOUS_MODE;
+ }
+
+ RxMode &= ~(RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED);
+ if(Mask & LM_ACCEPT_ERROR_PACKET)
+ {
+ RxMode |= RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED;
+ Mask &= ~LM_ACCEPT_ERROR_PACKET;
+ }
+
+ /* Make sure all the bits are valid before committing changes. */
+ if(Mask)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ /* Commit the new filter. */
+ pDevice->RxMode = RxMode;
+ REG_WR(pDevice, MacCtrl.RxMode, RxMode);
+
+ pDevice->ReceiveMask = ReceiveMask;
+
+ /* Set up the MC hash table. */
+ if(ReceiveMask & LM_ACCEPT_ALL_MULTICAST)
+ {
+ for(k = 0; k < 4; k++)
+ {
+ REG_WR(pDevice, MacCtrl.HashReg[k], 0xffffffff);
+ }
+ }
+ else if(ReceiveMask & LM_ACCEPT_MULTICAST)
+ {
+ LM_UINT32 HashReg[4];
+
+ HashReg[0] = 0; HashReg[1] = 0; HashReg[2] = 0; HashReg[3] = 0;
+ for(j = 0; j < pDevice->McEntryCount; j++)
+ {
+ LM_UINT32 RegIndex;
+ LM_UINT32 Bitpos;
+ LM_UINT32 Crc32;
+
+ Crc32 = ComputeCrc32(pDevice->McTable[j], ETHERNET_ADDRESS_SIZE);
+
+ /* The most significant 7 bits of the CRC32 (no inversion), */
+ /* are used to index into one of the possible 128 bit positions. */
+ Bitpos = ~Crc32 & 0x7f;
+
+ /* Hash register index. */
+ RegIndex = (Bitpos & 0x60) >> 5;
+
+ /* Bit to turn on within a hash register. */
+ Bitpos &= 0x1f;
+
+ /* Enable the multicast bit. */
+ HashReg[RegIndex] |= (1 << Bitpos);
+ }
+
+ /* REV_AX has problem with multicast filtering where it uses both */
+ /* DA and SA to perform hashing. */
+ for(k = 0; k < 4; k++)
+ {
+ REG_WR(pDevice, MacCtrl.HashReg[k], HashReg[k]);
+ }
+ }
+ else
+ {
+ /* Reject all multicast frames. */
+ for(j = 0; j < 4; j++)
+ {
+ REG_WR(pDevice, MacCtrl.HashReg[j], 0);
+ }
+ }
+
+ /* By default, Tigon3 will accept broadcast frames. We need to setup */
+ if(ReceiveMask & LM_ACCEPT_BROADCAST)
+ {
+ REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule,
+ REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK);
+ REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value,
+ REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK);
+ REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule,
+ REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK);
+ REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value,
+ REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK);
+ }
+ else
+ {
+ REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule,
+ REJECT_BROADCAST_RULE1_RULE);
+ REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value,
+ REJECT_BROADCAST_RULE1_VALUE);
+ REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule,
+ REJECT_BROADCAST_RULE2_RULE);
+ REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value,
+ REJECT_BROADCAST_RULE2_VALUE);
+ }
+
+ /* disable the rest of the rules. */
+ for(j = RCV_LAST_RULE_IDX; j < 16; j++)
+ {
+ REG_WR(pDevice, MacCtrl.RcvRules[j].Rule, 0);
+ REG_WR(pDevice, MacCtrl.RcvRules[j].Value, 0);
+ }
+
+ return LM_STATUS_SUCCESS;
+} /* LM_SetReceiveMask */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* Disable the interrupt and put the transmitter and receiver engines in */
+/* an idle state. Also aborts all pending send requests and receive */
+/* buffers. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_Abort(
+PLM_DEVICE_BLOCK pDevice)
+{
+ PLM_PACKET pPacket;
+ LM_UINT Idx;
+
+ LM_DisableInterrupt(pDevice);
+
+ /* Disable all the state machines. */
+ LM_CntrlBlock(pDevice,T3_BLOCK_MAC_RX_ENGINE,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_RX_BD_INITIATOR,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_RX_LIST_PLMT,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_RX_LIST_SELECTOR,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_RX_DATA_INITIATOR,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_RX_DATA_COMP,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_RX_BD_COMP,LM_DISABLE);
+
+ LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_SELECTOR,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_INITIATOR,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_SEND_DATA_INITIATOR,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_DMA_RD,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_SEND_DATA_COMP,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_DMA_COMP,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_COMP,LM_DISABLE);
+
+ /* Clear TDE bit */
+ pDevice->MacMode &= ~MAC_MODE_ENABLE_TDE;
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+ LM_CntrlBlock(pDevice,T3_BLOCK_MAC_TX_ENGINE,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_HOST_COALESING,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_DMA_WR,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_MBUF_CLUSTER_FREE,LM_DISABLE);
+
+ /* Reset all FTQs */
+ REG_WR(pDevice, Ftq.Reset, 0xffffffff);
+ REG_WR(pDevice, Ftq.Reset, 0x0);
+
+ LM_CntrlBlock(pDevice,T3_BLOCK_MBUF_MANAGER,LM_DISABLE);
+ LM_CntrlBlock(pDevice,T3_BLOCK_MEM_ARBITOR,LM_DISABLE);
+
+ MM_ACQUIRE_INT_LOCK(pDevice);
+
+ /* Abort packets that have already queued to go out. */
+ pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+ while(pPacket)
+ {
+
+ pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED;
+ pDevice->TxCounters.TxPacketAbortedCnt++;
+
+ atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+ QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+ pPacket = (PLM_PACKET)
+ QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+ }
+
+ /* Cleanup the receive return rings. */
+ LM_ServiceRxInterrupt(pDevice);
+
+ /* Don't want to indicate rx packets in Ndis miniport shutdown context. */
+ /* Doing so may cause system crash. */
+ if(!pDevice->ShuttingDown)
+ {
+ /* Indicate packets to the protocol. */
+ MM_IndicateTxPackets(pDevice);
+
+ /* Indicate received packets to the protocols. */
+ MM_IndicateRxPackets(pDevice);
+ }
+ else
+ {
+ /* Move the receive packet descriptors in the ReceivedQ to the */
+ /* free queue. */
+ for(; ;)
+ {
+ pPacket = (PLM_PACKET) QQ_PopHead(
+ &pDevice->RxPacketReceivedQ.Container);
+ if(pPacket == NULL)
+ {
+ break;
+ }
+ QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+ }
+ }
+
+ /* Clean up the Std Receive Producer ring. */
+ Idx = pDevice->pStatusBlkVirt->RcvStdConIdx;
+
+ while(Idx != pDevice->RxStdProdIdx) {
+ pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+ MM_UINT_PTR(pDevice->pRxStdBdVirt[Idx].Opaque));
+
+ QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+ Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+ } /* while */
+
+ /* Reinitialize our copy of the indices. */
+ pDevice->RxStdProdIdx = 0;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ /* Clean up the Jumbo Receive Producer ring. */
+ Idx = pDevice->pStatusBlkVirt->RcvJumboConIdx;
+
+ while(Idx != pDevice->RxJumboProdIdx) {
+ pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+ MM_UINT_PTR(pDevice->pRxJumboBdVirt[Idx].Opaque));
+
+ QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+ Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
+ } /* while */
+
+ /* Reinitialize our copy of the indices. */
+ pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ MM_RELEASE_INT_LOCK(pDevice);
+
+ /* Initialize the statistis Block */
+ pDevice->pStatusBlkVirt->Status = 0;
+ pDevice->pStatusBlkVirt->RcvStdConIdx = 0;
+ pDevice->pStatusBlkVirt->RcvJumboConIdx = 0;
+ pDevice->pStatusBlkVirt->RcvMiniConIdx = 0;
+
+ return LM_STATUS_SUCCESS;
+} /* LM_Abort */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* Disable the interrupt and put the transmitter and receiver engines in */
+/* an idle state. Aborts all pending send requests and receive buffers. */
+/* Also free all the receive buffers. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_Halt(
+PLM_DEVICE_BLOCK pDevice) {
+ PLM_PACKET pPacket;
+ LM_UINT32 EntryCnt;
+
+ LM_Abort(pDevice);
+
+ /* Get the number of entries in the queue. */
+ EntryCnt = QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container);
+
+ /* Make sure all the packets have been accounted for. */
+ for(EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++)
+ {
+ pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+ if (pPacket == 0)
+ break;
+
+ MM_FreeRxBuffer(pDevice, pPacket);
+
+ QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+ }
+
+ LM_ResetChip(pDevice);
+
+ /* Restore PCI configuration registers. */
+ MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+ pDevice->SavedCacheLineReg);
+ LM_RegWrInd(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG,
+ (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+ /* Reprogram the MAC address. */
+ LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+ return LM_STATUS_SUCCESS;
+} /* LM_Halt */
+
+
+STATIC LM_STATUS
+LM_ResetChip(PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 Value32;
+ LM_UINT32 j;
+
+ /* Wait for access to the nvram interface before resetting. This is */
+ /* a workaround to prevent EEPROM corruption. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+ T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+ {
+ /* Request access to the flash interface. */
+ REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+
+ for(j = 0; j < 100000; j++)
+ {
+ Value32 = REG_RD(pDevice, Nvram.SwArb);
+ if(Value32 & SW_ARB_GNT1)
+ {
+ break;
+ }
+ MM_Wait(10);
+ }
+ }
+
+ /* Global reset. */
+ REG_WR(pDevice, Grc.MiscCfg, GRC_MISC_CFG_CORE_CLOCK_RESET);
+ MM_Wait(40); MM_Wait(40); MM_Wait(40);
+
+ /* make sure we re-enable indirect accesses */
+ MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG,
+ pDevice->MiscHostCtrl);
+
+ /* Set MAX PCI retry to zero. */
+ Value32 = T3_PCI_STATE_PCI_ROM_ENABLE | T3_PCI_STATE_PCI_ROM_RETRY_ENABLE;
+ if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+ {
+ if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+ {
+ Value32 |= T3_PCI_STATE_RETRY_SAME_DMA;
+ }
+ }
+ MM_WriteConfig32(pDevice, T3_PCI_STATE_REG, Value32);
+
+ /* Restore PCI command register. */
+ MM_WriteConfig32(pDevice, PCI_COMMAND_REG,
+ pDevice->PciCommandStatusWords);
+
+ /* Disable PCI-X relaxed ordering bit. */
+ MM_ReadConfig32(pDevice, PCIX_CAP_REG, &Value32);
+ Value32 &= ~PCIX_ENABLE_RELAXED_ORDERING;
+ MM_WriteConfig32(pDevice, PCIX_CAP_REG, Value32);
+
+ /* Enable memory arbiter. */
+ REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+
+#ifdef BIG_ENDIAN_PCI /* This from jfd */
+ Value32 = GRC_MODE_WORD_SWAP_DATA|
+ GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+#ifdef BIG_ENDIAN_HOST
+ /* Reconfigure the mode register. */
+ Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA |
+ GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+ GRC_MODE_BYTE_SWAP_DATA |
+ GRC_MODE_WORD_SWAP_DATA;
+#else
+ /* Reconfigure the mode register. */
+ Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA;
+#endif
+#endif
+ REG_WR(pDevice, Grc.Mode, Value32);
+
+ /* Prevent PXE from restarting. */
+ MEM_WR_OFFSET(pDevice, 0x0b50, T3_MAGIC_NUM);
+
+ if(pDevice->EnableTbi) {
+ pDevice->MacMode = MAC_MODE_PORT_MODE_TBI;
+ REG_WR(pDevice, MacCtrl.Mode, MAC_MODE_PORT_MODE_TBI);
+ }
+ else {
+ REG_WR(pDevice, MacCtrl.Mode, 0);
+ }
+
+ /* Wait for the firmware to finish initialization. */
+ for(j = 0; j < 100000; j++)
+ {
+ MM_Wait(10);
+
+ Value32 = MEM_RD_OFFSET(pDevice, 0x0b50);
+ if(Value32 == ~T3_MAGIC_NUM)
+ {
+ break;
+ }
+ }
+ return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+__inline static void
+LM_ServiceTxInterrupt(
+PLM_DEVICE_BLOCK pDevice) {
+ PLM_PACKET pPacket;
+ LM_UINT32 HwConIdx;
+ LM_UINT32 SwConIdx;
+
+ HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
+
+ /* Get our copy of the consumer index. The buffer descriptors */
+ /* that are in between the consumer indices are freed. */
+ SwConIdx = pDevice->SendConIdx;
+
+ /* Move the packets from the TxPacketActiveQ that are sent out to */
+ /* the TxPacketXmittedQ. Packets that are sent use the */
+ /* descriptors that are between SwConIdx and HwConIdx. */
+ while(SwConIdx != HwConIdx)
+ {
+ /* Get the packet that was sent from the TxPacketActiveQ. */
+ pPacket = (PLM_PACKET) QQ_PopHead(
+ &pDevice->TxPacketActiveQ.Container);
+
+ /* Set the return status. */
+ pPacket->PacketStatus = LM_STATUS_SUCCESS;
+
+ /* Put the packet in the TxPacketXmittedQ for indication later. */
+ QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+ /* Move to the next packet's BD. */
+ SwConIdx = (SwConIdx + pPacket->u.Tx.FragCount) &
+ T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+ /* Update the number of unused BDs. */
+ atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
+
+ /* Get the new updated HwConIdx. */
+ HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
+ } /* while */
+
+ /* Save the new SwConIdx. */
+ pDevice->SendConIdx = SwConIdx;
+
+} /* LM_ServiceTxInterrupt */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+__inline static void
+LM_ServiceRxInterrupt(
+PLM_DEVICE_BLOCK pDevice) {
+ PLM_PACKET pPacket;
+ PT3_RCV_BD pRcvBd;
+ LM_UINT32 HwRcvRetProdIdx;
+ LM_UINT32 SwRcvRetConIdx;
+
+ /* Loop thru the receive return rings for received packets. */
+ HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+
+ SwRcvRetConIdx = pDevice->RcvRetConIdx;
+ while(SwRcvRetConIdx != HwRcvRetProdIdx)
+ {
+ pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx];
+
+ /* Get the received packet descriptor. */
+ pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+ MM_UINT_PTR(pRcvBd->Opaque));
+
+ /* Check the error flag. */
+ if(pRcvBd->ErrorFlag &&
+ pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII)
+ {
+ pPacket->PacketStatus = LM_STATUS_FAILURE;
+
+ pDevice->RxCounters.RxPacketErrCnt++;
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_BAD_CRC)
+ {
+ pDevice->RxCounters.RxErrCrcCnt++;
+ }
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_COLL_DETECT)
+ {
+ pDevice->RxCounters.RxErrCollCnt++;
+ }
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_LINK_LOST_DURING_PKT)
+ {
+ pDevice->RxCounters.RxErrLinkLostCnt++;
+ }
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_PHY_DECODE_ERR)
+ {
+ pDevice->RxCounters.RxErrPhyDecodeCnt++;
+ }
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_ODD_NIBBLED_RCVD_MII)
+ {
+ pDevice->RxCounters.RxErrOddNibbleCnt++;
+ }
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_MAC_ABORT)
+ {
+ pDevice->RxCounters.RxErrMacAbortCnt++;
+ }
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_LEN_LT_64)
+ {
+ pDevice->RxCounters.RxErrShortPacketCnt++;
+ }
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_TRUNC_NO_RESOURCES)
+ {
+ pDevice->RxCounters.RxErrNoResourceCnt++;
+ }
+
+ if(pRcvBd->ErrorFlag & RCV_BD_ERR_GIANT_FRAME_RCVD)
+ {
+ pDevice->RxCounters.RxErrLargePacketCnt++;
+ }
+ }
+ else
+ {
+ pPacket->PacketStatus = LM_STATUS_SUCCESS;
+ pPacket->PacketSize = pRcvBd->Len - 4;
+
+ pPacket->Flags = pRcvBd->Flags;
+ if(pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG)
+ {
+ pPacket->VlanTag = pRcvBd->VlanTag;
+ }
+
+ pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum;
+ }
+
+ /* Put the packet descriptor containing the received packet */
+ /* buffer in the RxPacketReceivedQ for indication later. */
+ QQ_PushTail(&pDevice->RxPacketReceivedQ.Container, pPacket);
+
+ /* Go to the next buffer descriptor. */
+ SwRcvRetConIdx = (SwRcvRetConIdx + 1) &
+ T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK;
+
+ /* Get the updated HwRcvRetProdIdx. */
+ HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+ } /* while */
+
+ pDevice->RcvRetConIdx = SwRcvRetConIdx;
+
+ /* Update the receive return ring consumer index. */
+ MB_REG_WR(pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx);
+} /* LM_ServiceRxInterrupt */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* This is the interrupt event handler routine. It acknowledges all */
+/* pending interrupts and process all pending events. */
+/* */
+/* Return: */
+/* LM_STATUS_SUCCESS */
+/******************************************************************************/
+LM_STATUS
+LM_ServiceInterrupts(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 Value32;
+ int ServicePhyInt = FALSE;
+
+ /* Setup the phy chip whenever the link status changes. */
+ if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_USE_STATUS_REG)
+ {
+ Value32 = REG_RD(pDevice, MacCtrl.Status);
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+ {
+ if (Value32 & MAC_STATUS_MI_INTERRUPT)
+ {
+ ServicePhyInt = TRUE;
+ }
+ }
+ else if(Value32 & MAC_STATUS_LINK_STATE_CHANGED)
+ {
+ ServicePhyInt = TRUE;
+ }
+ }
+ else
+ {
+ if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_LINK_CHANGED_STATUS)
+ {
+ pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+ (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+ ServicePhyInt = TRUE;
+ }
+ }
+#if INCLUDE_TBI_SUPPORT
+ if (pDevice->IgnoreTbiLinkChange == TRUE)
+ {
+ ServicePhyInt = FALSE;
+ }
+#endif
+ if (ServicePhyInt == TRUE)
+ {
+ LM_SetupPhy(pDevice);
+ }
+
+ /* Service receive and transmit interrupts. */
+ LM_ServiceRxInterrupt(pDevice);
+ LM_ServiceTxInterrupt(pDevice);
+
+ /* No spinlock for this queue since this routine is serialized. */
+ if(!QQ_Empty(&pDevice->RxPacketReceivedQ.Container))
+ {
+ /* Indicate receive packets. */
+ MM_IndicateRxPackets(pDevice);
+ /* LM_QueueRxPackets(pDevice); */
+ }
+
+ /* No spinlock for this queue since this routine is serialized. */
+ if(!QQ_Empty(&pDevice->TxPacketXmittedQ.Container))
+ {
+ MM_IndicateTxPackets(pDevice);
+ }
+
+ return LM_STATUS_SUCCESS;
+} /* LM_ServiceInterrupts */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastAdd(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+ PLM_UINT8 pEntry;
+ LM_UINT32 j;
+
+ pEntry = pDevice->McTable[0];
+ for(j = 0; j < pDevice->McEntryCount; j++)
+ {
+ if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+ {
+ /* Found a match, increment the instance count. */
+ pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1;
+
+ return LM_STATUS_SUCCESS;
+ }
+
+ pEntry += LM_MC_ENTRY_SIZE;
+ }
+
+ if(pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ pEntry = pDevice->McTable[pDevice->McEntryCount];
+
+ COPY_ETH_ADDRESS(pMcAddress, pEntry);
+ pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1;
+
+ pDevice->McEntryCount++;
+
+ LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST);
+
+ return LM_STATUS_SUCCESS;
+} /* LM_MulticastAdd */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastDel(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+ PLM_UINT8 pEntry;
+ LM_UINT32 j;
+
+ pEntry = pDevice->McTable[0];
+ for(j = 0; j < pDevice->McEntryCount; j++)
+ {
+ if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+ {
+ /* Found a match, decrement the instance count. */
+ pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1;
+
+ /* No more instance left, remove the address from the table. */
+ /* Move the last entry in the table to the delete slot. */
+ if(pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 &&
+ pDevice->McEntryCount > 1)
+ {
+
+ COPY_ETH_ADDRESS(
+ pDevice->McTable[pDevice->McEntryCount-1], pEntry);
+ pEntry[LM_MC_INSTANCE_COUNT_INDEX] =
+ pDevice->McTable[pDevice->McEntryCount-1]
+ [LM_MC_INSTANCE_COUNT_INDEX];
+ }
+ pDevice->McEntryCount--;
+
+ /* Update the receive mask if the table is empty. */
+ if(pDevice->McEntryCount == 0)
+ {
+ LM_SetReceiveMask(pDevice,
+ pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+ }
+
+ return LM_STATUS_SUCCESS;
+ }
+
+ pEntry += LM_MC_ENTRY_SIZE;
+ }
+
+ return LM_STATUS_FAILURE;
+} /* LM_MulticastDel */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastClear(
+PLM_DEVICE_BLOCK pDevice) {
+ pDevice->McEntryCount = 0;
+
+ LM_SetReceiveMask(pDevice, pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+
+ return LM_STATUS_SUCCESS;
+} /* LM_MulticastClear */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_SetMacAddress(
+ PLM_DEVICE_BLOCK pDevice,
+ PLM_UINT8 pMacAddress)
+{
+ LM_UINT32 j;
+
+ for(j = 0; j < 4; j++)
+ {
+ REG_WR(pDevice, MacCtrl.MacAddr[j].High,
+ (pMacAddress[0] << 8) | pMacAddress[1]);
+ REG_WR(pDevice, MacCtrl.MacAddr[j].Low,
+ (pMacAddress[2] << 24) | (pMacAddress[3] << 16) |
+ (pMacAddress[4] << 8) | pMacAddress[5]);
+ }
+
+ return LM_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************/
+/* Description: */
+/* Sets up the default line speed, and duplex modes based on the requested */
+/* media type. */
+/* */
+/* Return: */
+/* None. */
+/******************************************************************************/
+static LM_STATUS
+LM_TranslateRequestedMediaType(
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType,
+PLM_MEDIA_TYPE pMediaType,
+PLM_LINE_SPEED pLineSpeed,
+PLM_DUPLEX_MODE pDuplexMode) {
+ *pMediaType = LM_MEDIA_TYPE_AUTO;
+ *pLineSpeed = LM_LINE_SPEED_UNKNOWN;
+ *pDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+
+ /* determine media type */
+ switch(RequestedMediaType) {
+ case LM_REQUESTED_MEDIA_TYPE_BNC:
+ *pMediaType = LM_MEDIA_TYPE_BNC;
+ *pLineSpeed = LM_LINE_SPEED_10MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_UTP_AUTO:
+ *pMediaType = LM_MEDIA_TYPE_UTP;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS:
+ *pMediaType = LM_MEDIA_TYPE_UTP;
+ *pLineSpeed = LM_LINE_SPEED_10MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX:
+ *pMediaType = LM_MEDIA_TYPE_UTP;
+ *pLineSpeed = LM_LINE_SPEED_10MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS:
+ *pMediaType = LM_MEDIA_TYPE_UTP;
+ *pLineSpeed = LM_LINE_SPEED_100MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX:
+ *pMediaType = LM_MEDIA_TYPE_UTP;
+ *pLineSpeed = LM_LINE_SPEED_100MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS:
+ *pMediaType = LM_MEDIA_TYPE_UTP;
+ *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX:
+ *pMediaType = LM_MEDIA_TYPE_UTP;
+ *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS:
+ *pMediaType = LM_MEDIA_TYPE_FIBER;
+ *pLineSpeed = LM_LINE_SPEED_100MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX:
+ *pMediaType = LM_MEDIA_TYPE_FIBER;
+ *pLineSpeed = LM_LINE_SPEED_100MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS:
+ *pMediaType = LM_MEDIA_TYPE_FIBER;
+ *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX:
+ *pMediaType = LM_MEDIA_TYPE_FIBER;
+ *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
+
+ default:
+ break;
+ } /* switch */
+
+ return LM_STATUS_SUCCESS;
+} /* LM_TranslateRequestedMediaType */
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/* LM_STATUS_LINK_ACTIVE */
+/* LM_STATUS_LINK_DOWN */
+/******************************************************************************/
+static LM_STATUS
+LM_InitBcm540xPhy(
+PLM_DEVICE_BLOCK pDevice)
+{
+ LM_LINE_SPEED CurrentLineSpeed;
+ LM_DUPLEX_MODE CurrentDuplexMode;
+ LM_STATUS CurrentLinkStatus;
+ LM_UINT32 Value32;
+ LM_UINT32 j;
+
+#if 1 /* jmb: bugfix -- moved here, out of code that sets initial pwr state */
+ LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x2);
+#endif
+ if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+ {
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+ if(!pDevice->InitDone)
+ {
+ Value32 = 0;
+ }
+
+ if(!(Value32 & PHY_STATUS_LINK_PASS))
+ {
+ LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ for(j = 0; j < 1000; j++)
+ {
+ MM_Wait(10);
+
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ if(Value32 & PHY_STATUS_LINK_PASS)
+ {
+ MM_Wait(40);
+ break;
+ }
+ }
+
+ if((pDevice->PhyId & PHY_ID_REV_MASK) == PHY_BCM5401_B0_REV)
+ {
+ if(!(Value32 & PHY_STATUS_LINK_PASS) &&
+ (pDevice->OldLineSpeed == LM_LINE_SPEED_1000MBPS))
+ {
+ LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+ for(j = 0; j < 100; j++)
+ {
+ MM_Wait(10);
+
+ LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+ if(!(Value32 & PHY_CTRL_PHY_RESET))
+ {
+ MM_Wait(40);
+ break;
+ }
+ }
+
+ LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+
+ LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+ LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+ }
+ }
+ }
+ }
+ else if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+ {
+ /* Bug: 5701 A0, B0 TX CRC workaround. */
+ LM_WritePhy(pDevice, 0x15, 0x0a75);
+ LM_WritePhy(pDevice, 0x1c, 0x8c68);
+ LM_WritePhy(pDevice, 0x1c, 0x8d68);
+ LM_WritePhy(pDevice, 0x1c, 0x8c68);
+ }
+
+ /* Acknowledge interrupts. */
+ LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32);
+ LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32);
+
+ /* Configure the interrupt mask. */
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+ {
+ LM_WritePhy(pDevice, BCM540X_INT_MASK_REG, ~BCM540X_INT_LINK_CHANGE);
+ }
+
+ /* Configure PHY led mode. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 ||
+ (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700))
+ {
+ if(pDevice->LedMode == LED_MODE_THREE_LINK)
+ {
+ LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG,
+ BCM540X_EXT_CTRL_LINK3_LED_MODE);
+ }
+ else
+ {
+ LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 0);
+ }
+ }
+
+ CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+ /* Get current link and duplex mode. */
+ for(j = 0; j < 100; j++)
+ {
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+ if(Value32 & PHY_STATUS_LINK_PASS)
+ {
+ break;
+ }
+ MM_Wait(40);
+ }
+
+ if(Value32 & PHY_STATUS_LINK_PASS)
+ {
+
+ /* Determine the current line and duplex settings. */
+ LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+ for(j = 0; j < 2000; j++)
+ {
+ MM_Wait(10);
+
+ LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+ if(Value32)
+ {
+ break;
+ }
+ }
+
+ switch(Value32 & BCM540X_AUX_SPEED_MASK)
+ {
+ case BCM540X_AUX_10BASET_HD:
+ CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case BCM540X_AUX_10BASET_FD:
+ CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
+
+ case BCM540X_AUX_100BASETX_HD:
+ CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case BCM540X_AUX_100BASETX_FD:
+ CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
+
+ case BCM540X_AUX_100BASET_HD:
+ CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
+
+ case BCM540X_AUX_100BASET_FD:
+ CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
+
+ default:
+
+ CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN;
+ CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+ break;
+ }
+
+ /* Make sure we are in auto-neg mode. */
+ for (j = 0; j < 200; j++)
+ {
+ LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+ if(Value32 && Value32 != 0x7fff)
+ {
+ break;
+ }
+
+ if(Value32 == 0 && pDevice->RequestedMediaType ==
+ LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS)
+ {
+ break;
+ }
+
+ MM_Wait(10);
+ }
+
+ /* Use the current line settings for "auto" mode. */
+ if(pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+ pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO)
+ {
+ if(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+
+ /* We may be exiting low power mode and the link is in */
+ /* 10mb. In this case, we need to restart autoneg. */
+ LM_ReadPhy(pDevice, BCM540X_1000BASET_CTRL_REG, &Value32);
+ pDevice->advertising1000 = Value32;
+ /* 5702FE supports 10/100Mb only. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5703 ||
+ pDevice->BondId != GRC_MISC_BD_ID_5702FE)
+ {
+ if(!(Value32 & (BCM540X_AN_AD_1000BASET_HALF |
+ BCM540X_AN_AD_1000BASET_FULL)))
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+ }
+ }
+ }
+ else
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+ }
+ }
+ else
+ {
+ /* Force line settings. */
+ /* Use the current setting if it matches the user's requested */
+ /* setting. */
+ LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+ if((pDevice->LineSpeed == CurrentLineSpeed) &&
+ (pDevice->DuplexMode == CurrentDuplexMode))
+ {
+ if ((pDevice->DisableAutoNeg &&
+ !(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)) ||
+ (!pDevice->DisableAutoNeg &&
+ (Value32 & PHY_CTRL_AUTO_NEG_ENABLE)))
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+ }
+ else
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+ }
+ }
+ else
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+ }
+ }
+
+ /* Save line settings. */
+ pDevice->LineSpeed = CurrentLineSpeed;
+ pDevice->DuplexMode = CurrentDuplexMode;
+ pDevice->MediaType = LM_MEDIA_TYPE_UTP;
+ }
+
+ return CurrentLinkStatus;
+} /* LM_InitBcm540xPhy */
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_SetFlowControl(
+ PLM_DEVICE_BLOCK pDevice,
+ LM_UINT32 LocalPhyAd,
+ LM_UINT32 RemotePhyAd)
+{
+ LM_FLOW_CONTROL FlowCap;
+
+ /* Resolve flow control. */
+ FlowCap = LM_FLOW_CONTROL_NONE;
+
+ /* See Table 28B-3 of 802.3ab-1999 spec. */
+ if(pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE)
+ {
+ if(LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE)
+ {
+ if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+ {
+ if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+ {
+ FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+ LM_FLOW_CONTROL_RECEIVE_PAUSE;
+ }
+ else if(RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)
+ {
+ FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE;
+ }
+ }
+ else
+ {
+ if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+ {
+ FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+ LM_FLOW_CONTROL_RECEIVE_PAUSE;
+ }
+ }
+ }
+ else if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+ {
+ if((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) &&
+ (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE))
+ {
+ FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+ }
+ }
+ }
+ else
+ {
+ FlowCap = pDevice->FlowControlCap;
+ }
+
+ /* Enable/disable rx PAUSE. */
+ pDevice->RxMode &= ~RX_MODE_ENABLE_FLOW_CONTROL;
+ if(FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE &&
+ (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+ pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE))
+ {
+ pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+ pDevice->RxMode |= RX_MODE_ENABLE_FLOW_CONTROL;
+
+ }
+ REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+
+ /* Enable/disable tx PAUSE. */
+ pDevice->TxMode &= ~TX_MODE_ENABLE_FLOW_CONTROL;
+ if(FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE &&
+ (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+ pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))
+ {
+ pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+ pDevice->TxMode |= TX_MODE_ENABLE_FLOW_CONTROL;
+
+ }
+ REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+
+ return LM_STATUS_SUCCESS;
+}
+
+
+#if INCLUDE_TBI_SUPPORT
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_InitBcm800xPhy(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 Value32;
+ LM_UINT32 j;
+
+ Value32 = REG_RD(pDevice, MacCtrl.Status);
+
+ /* Reset the SERDES during init and when we have link. */
+ if(!pDevice->InitDone || Value32 & MAC_STATUS_PCS_SYNCED)
+ {
+ /* Set PLL lock range. */
+ LM_WritePhy(pDevice, 0x16, 0x8007);
+
+ /* Software reset. */
+ LM_WritePhy(pDevice, 0x00, 0x8000);
+
+ /* Wait for reset to complete. */
+ for(j = 0; j < 500; j++)
+ {
+ MM_Wait(10);
+ }
+
+ /* Config mode; seletct PMA/Ch 1 regs. */
+ LM_WritePhy(pDevice, 0x10, 0x8411);
+
+ /* Enable auto-lock and comdet, select txclk for tx. */
+ LM_WritePhy(pDevice, 0x11, 0x0a10);
+
+ LM_WritePhy(pDevice, 0x18, 0x00a0);
+ LM_WritePhy(pDevice, 0x16, 0x41ff);
+
+ /* Assert and deassert POR. */
+ LM_WritePhy(pDevice, 0x13, 0x0400);
+ MM_Wait(40);
+ LM_WritePhy(pDevice, 0x13, 0x0000);
+
+ LM_WritePhy(pDevice, 0x11, 0x0a50);
+ MM_Wait(40);
+ LM_WritePhy(pDevice, 0x11, 0x0a10);
+
+ /* Delay for signal to stabilize. */
+ for(j = 0; j < 15000; j++)
+ {
+ MM_Wait(10);
+ }
+
+ /* Deselect the channel register so we can read the PHY id later. */
+ LM_WritePhy(pDevice, 0x10, 0x8011);
+ }
+
+ return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_SetupFiberPhy(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ LM_STATUS CurrentLinkStatus;
+ AUTONEG_STATUS AnStatus = 0;
+ LM_UINT32 Value32;
+ LM_UINT32 Cnt;
+ LM_UINT32 j, k;
+
+ pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK);
+
+ /* Initialize the send_config register. */
+ REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+
+ /* Enable TBI and full duplex mode. */
+ pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI;
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+ /* Initialize the BCM8002 SERDES PHY. */
+ switch(pDevice->PhyId & PHY_ID_MASK)
+ {
+ case PHY_BCM8002_PHY_ID:
+ LM_InitBcm800xPhy(pDevice);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Enable link change interrupt. */
+ REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+
+ /* Default to link down. */
+ CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+ /* Get the link status. */
+ Value32 = REG_RD(pDevice, MacCtrl.Status);
+ if(Value32 & MAC_STATUS_PCS_SYNCED)
+ {
+ if((pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO) ||
+ (pDevice->DisableAutoNeg == FALSE))
+ {
+ /* auto-negotiation mode. */
+ /* Initialize the autoneg default capaiblities. */
+ AutonegInit(&pDevice->AnInfo);
+
+ /* Set the context pointer to point to the main device structure. */
+ pDevice->AnInfo.pContext = pDevice;
+
+ /* Setup flow control advertisement register. */
+ Value32 = GetPhyAdFlowCntrlSettings(pDevice);
+ if(Value32 & PHY_AN_AD_PAUSE_CAPABLE)
+ {
+ pDevice->AnInfo.mr_adv_sym_pause = 1;
+ }
+ else
+ {
+ pDevice->AnInfo.mr_adv_sym_pause = 0;
+ }
+
+ if(Value32 & PHY_AN_AD_ASYM_PAUSE)
+ {
+ pDevice->AnInfo.mr_adv_asym_pause = 1;
+ }
+ else
+ {
+ pDevice->AnInfo.mr_adv_asym_pause = 0;
+ }
+
+ /* Try to autoneg up to six times. */
+ if (pDevice->IgnoreTbiLinkChange)
+ {
+ Cnt = 1;
+ }
+ else
+ {
+ Cnt = 6;
+ }
+ for (j = 0; j < Cnt; j++)
+ {
+ REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+
+ Value32 = pDevice->MacMode & ~MAC_MODE_PORT_MODE_MASK;
+ REG_WR(pDevice, MacCtrl.Mode, Value32);
+ MM_Wait(20);
+
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+ MAC_MODE_SEND_CONFIGS);
+
+ MM_Wait(20);
+
+ pDevice->AnInfo.State = AN_STATE_UNKNOWN;
+ pDevice->AnInfo.CurrentTime_us = 0;
+
+ REG_WR(pDevice, Grc.Timer, 0);
+ for(k = 0; (pDevice->AnInfo.CurrentTime_us < 75000) &&
+ (k < 75000); k++)
+ {
+ AnStatus = Autoneg8023z(&pDevice->AnInfo);
+
+ if((AnStatus == AUTONEG_STATUS_DONE) ||
+ (AnStatus == AUTONEG_STATUS_FAILED))
+ {
+ break;
+ }
+
+ pDevice->AnInfo.CurrentTime_us = REG_RD(pDevice, Grc.Timer);
+
+ }
+ if((AnStatus == AUTONEG_STATUS_DONE) ||
+ (AnStatus == AUTONEG_STATUS_FAILED))
+ {
+ break;
+ }
+ if (j >= 1)
+ {
+ if (!(REG_RD(pDevice, MacCtrl.Status) &
+ MAC_STATUS_PCS_SYNCED)) {
+ break;
+ }
+ }
+ }
+
+ /* Stop sending configs. */
+ MM_AnTxIdle(&pDevice->AnInfo);
+
+ /* Resolve flow control settings. */
+ if((AnStatus == AUTONEG_STATUS_DONE) &&
+ pDevice->AnInfo.mr_an_complete && pDevice->AnInfo.mr_link_ok &&
+ pDevice->AnInfo.mr_lp_adv_full_duplex)
+ {
+ LM_UINT32 RemotePhyAd;
+ LM_UINT32 LocalPhyAd;
+
+ LocalPhyAd = 0;
+ if(pDevice->AnInfo.mr_adv_sym_pause)
+ {
+ LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE;
+ }
+
+ if(pDevice->AnInfo.mr_adv_asym_pause)
+ {
+ LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE;
+ }
+
+ RemotePhyAd = 0;
+ if(pDevice->AnInfo.mr_lp_adv_sym_pause)
+ {
+ RemotePhyAd |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
+ }
+
+ if(pDevice->AnInfo.mr_lp_adv_asym_pause)
+ {
+ RemotePhyAd |= PHY_LINK_PARTNER_ASYM_PAUSE;
+ }
+
+ LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+
+ CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+ }
+ for (j = 0; j < 30; j++)
+ {
+ MM_Wait(20);
+ REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+ MAC_STATUS_CFG_CHANGED);
+ MM_Wait(20);
+ if ((REG_RD(pDevice, MacCtrl.Status) &
+ (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+ break;
+ }
+ if (pDevice->PollTbiLink)
+ {
+ Value32 = REG_RD(pDevice, MacCtrl.Status);
+ if (Value32 & MAC_STATUS_RECEIVING_CFG)
+ {
+ pDevice->IgnoreTbiLinkChange = TRUE;
+ }
+ else
+ {
+ pDevice->IgnoreTbiLinkChange = FALSE;
+ }
+ }
+ Value32 = REG_RD(pDevice, MacCtrl.Status);
+ if (CurrentLinkStatus == LM_STATUS_LINK_DOWN &&
+ (Value32 & MAC_STATUS_PCS_SYNCED) &&
+ ((Value32 & MAC_STATUS_RECEIVING_CFG) == 0))
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+ }
+ }
+ else
+ {
+ /* We are forcing line speed. */
+ pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
+ LM_SetFlowControl(pDevice, 0, 0);
+
+ CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+ MAC_MODE_SEND_CONFIGS);
+ }
+ }
+ /* Set the link polarity bit. */
+ pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+ pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+ (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+
+ for (j = 0; j < 100; j++)
+ {
+ REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+ MAC_STATUS_CFG_CHANGED);
+ MM_Wait(5);
+ if ((REG_RD(pDevice, MacCtrl.Status) &
+ (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+ break;
+ }
+
+ Value32 = REG_RD(pDevice, MacCtrl.Status);
+ if((Value32 & MAC_STATUS_PCS_SYNCED) == 0)
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+ if (pDevice->DisableAutoNeg == FALSE)
+ {
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+ MAC_MODE_SEND_CONFIGS);
+ MM_Wait(1);
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+ }
+ }
+
+ /* Initialize the current link status. */
+ if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+ {
+ pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS;
+ pDevice->DuplexMode = LM_DUPLEX_MODE_FULL;
+ REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+ LED_CTRL_1000MBPS_LED_ON);
+ }
+ else
+ {
+ pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN;
+ pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+ REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+ LED_CTRL_OVERRIDE_TRAFFIC_LED);
+ }
+
+ /* Indicate link status. */
+ if (pDevice->LinkStatus != CurrentLinkStatus) {
+ pDevice->LinkStatus = CurrentLinkStatus;
+ MM_IndicateStatus(pDevice, CurrentLinkStatus);
+ }
+
+ return LM_STATUS_SUCCESS;
+}
+#endif /* INCLUDE_TBI_SUPPORT */
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_SetupCopperPhy(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ LM_STATUS CurrentLinkStatus;
+ LM_UINT32 Value32;
+
+ /* Assume there is not link first. */
+ CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+ /* Disable phy link change attention. */
+ REG_WR(pDevice, MacCtrl.MacEvent, 0);
+
+ /* Clear link change attention. */
+ REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+ MAC_STATUS_CFG_CHANGED);
+
+ /* Disable auto-polling for the moment. */
+ pDevice->MiMode = 0xc0000;
+ REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+ MM_Wait(40);
+
+ /* Determine the requested line speed and duplex. */
+ pDevice->OldLineSpeed = pDevice->LineSpeed;
+ LM_TranslateRequestedMediaType(pDevice->RequestedMediaType,
+ &pDevice->MediaType, &pDevice->LineSpeed, &pDevice->DuplexMode);
+
+ /* Initialize the phy chip. */
+ switch(pDevice->PhyId & PHY_ID_MASK)
+ {
+ case PHY_BCM5400_PHY_ID:
+ case PHY_BCM5401_PHY_ID:
+ case PHY_BCM5411_PHY_ID:
+ case PHY_BCM5701_PHY_ID:
+ case PHY_BCM5703_PHY_ID:
+ case PHY_BCM5704_PHY_ID:
+ CurrentLinkStatus = LM_InitBcm540xPhy(pDevice);
+ break;
+
+ default:
+ break;
+ }
+
+ if(CurrentLinkStatus == LM_STATUS_LINK_SETTING_MISMATCH)
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+ }
+
+ /* Setup flow control. */
+ pDevice->FlowControl = LM_FLOW_CONTROL_NONE;
+ if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+ {
+ LM_FLOW_CONTROL FlowCap; /* Flow control capability. */
+
+ FlowCap = LM_FLOW_CONTROL_NONE;
+
+ if(pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
+ {
+ if(pDevice->DisableAutoNeg == FALSE ||
+ pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+ pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO)
+ {
+ LM_UINT32 ExpectedPhyAd;
+ LM_UINT32 LocalPhyAd;
+ LM_UINT32 RemotePhyAd;
+
+ LM_ReadPhy(pDevice, PHY_AN_AD_REG, &LocalPhyAd);
+ pDevice->advertising = LocalPhyAd;
+ LocalPhyAd &= (PHY_AN_AD_ASYM_PAUSE | PHY_AN_AD_PAUSE_CAPABLE);
+
+ ExpectedPhyAd = GetPhyAdFlowCntrlSettings(pDevice);
+
+ if(LocalPhyAd != ExpectedPhyAd)
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+ }
+ else
+ {
+ LM_ReadPhy(pDevice, PHY_LINK_PARTNER_ABILITY_REG,
+ &RemotePhyAd);
+
+ LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+ }
+ }
+ else
+ {
+ pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
+ LM_SetFlowControl(pDevice, 0, 0);
+ }
+ }
+ }
+
+ if(CurrentLinkStatus == LM_STATUS_LINK_DOWN)
+ {
+ LM_ForceAutoNeg(pDevice, pDevice->RequestedMediaType);
+
+ /* If we force line speed, we make get link right away. */
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ if(Value32 & PHY_STATUS_LINK_PASS)
+ {
+ CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+ }
+ }
+
+ /* GMII interface. */
+ pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK;
+ if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+ {
+ if(pDevice->LineSpeed == LM_LINE_SPEED_100MBPS ||
+ pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+ {
+ pDevice->MacMode |= MAC_MODE_PORT_MODE_MII;
+ }
+ else
+ {
+ pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+ }
+ }
+ else {
+ pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+ }
+
+ /* Set the MAC to operate in the appropriate duplex mode. */
+ pDevice->MacMode &= ~MAC_MODE_HALF_DUPLEX;
+ if(pDevice->DuplexMode == LM_DUPLEX_MODE_HALF)
+ {
+ pDevice->MacMode |= MAC_MODE_HALF_DUPLEX;
+ }
+
+ /* Set the link polarity bit. */
+ pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ if((pDevice->LedMode == LED_MODE_LINK10) ||
+ (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE &&
+ pDevice->LineSpeed == LM_LINE_SPEED_10MBPS))
+ {
+ pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+ }
+ }
+ else
+ {
+ if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+ {
+ pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+ }
+
+ /* Set LED mode. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ Value32 = LED_CTRL_PHY_MODE_1;
+ }
+ else
+ {
+ if(pDevice->LedMode == LED_MODE_OUTPUT)
+ {
+ Value32 = LED_CTRL_PHY_MODE_2;
+ }
+ else
+ {
+ Value32 = LED_CTRL_PHY_MODE_1;
+ }
+ }
+ REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
+ }
+
+ REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+ /* Enable auto polling. */
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+ {
+ pDevice->MiMode |= MI_MODE_AUTO_POLLING_ENABLE;
+ REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+ }
+
+ /* Enable phy link change attention. */
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+ {
+ REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_MI_INTERRUPT);
+ }
+ else
+ {
+ REG_WR(pDevice, MacCtrl.MacEvent,
+ MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+ }
+ if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) &&
+ (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) &&
+ (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) &&
+ (((pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) &&
+ (pDevice->PciState & T3_PCI_STATE_BUS_SPEED_HIGH)) ||
+ !(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)))
+ {
+ MM_Wait(120);
+ REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+ MAC_STATUS_CFG_CHANGED);
+ MEM_WR_OFFSET(pDevice, T3_FIRMWARE_MAILBOX,
+ T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE);
+ }
+
+ /* Indicate link status. */
+ if (pDevice->LinkStatus != CurrentLinkStatus) {
+ pDevice->LinkStatus = CurrentLinkStatus;
+ MM_IndicateStatus(pDevice, CurrentLinkStatus);
+ }
+
+ return LM_STATUS_SUCCESS;
+} /* LM_SetupCopperPhy */
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_SetupPhy(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ LM_STATUS LmStatus;
+ LM_UINT32 Value32;
+
+#if INCLUDE_TBI_SUPPORT
+ if(pDevice->EnableTbi)
+ {
+ LmStatus = LM_SetupFiberPhy(pDevice);
+ }
+ else
+#endif /* INCLUDE_TBI_SUPPORT */
+ {
+ LmStatus = LM_SetupCopperPhy(pDevice);
+ }
+ if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+ {
+ if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+ {
+ Value32 = REG_RD(pDevice, PciCfg.PciState);
+ REG_WR(pDevice, PciCfg.PciState,
+ Value32 | T3_PCI_STATE_RETRY_SAME_DMA);
+ }
+ }
+ if ((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) &&
+ (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF))
+ {
+ REG_WR(pDevice, MacCtrl.TxLengths, 0x26ff);
+ }
+ else
+ {
+ REG_WR(pDevice, MacCtrl.TxLengths, 0x2620);
+ }
+
+ return LmStatus;
+}
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_VOID
+LM_ReadPhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 PhyReg,
+PLM_UINT32 pData32) {
+ LM_UINT32 Value32;
+ LM_UINT32 j;
+
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+ {
+ REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode &
+ ~MI_MODE_AUTO_POLLING_ENABLE);
+ MM_Wait(40);
+ }
+
+ Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) |
+ ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) |
+ MI_COM_CMD_READ | MI_COM_START;
+
+ REG_WR(pDevice, MacCtrl.MiCom, Value32);
+
+ for(j = 0; j < 20; j++)
+ {
+ MM_Wait(25);
+
+ Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+
+ if(!(Value32 & MI_COM_BUSY))
+ {
+ MM_Wait(5);
+ Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+ Value32 &= MI_COM_PHY_DATA_MASK;
+ break;
+ }
+ }
+
+ if(Value32 & MI_COM_BUSY)
+ {
+ Value32 = 0;
+ }
+
+ *pData32 = Value32;
+
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+ {
+ REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+ MM_Wait(40);
+ }
+} /* LM_ReadPhy */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_VOID
+LM_WritePhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 PhyReg,
+LM_UINT32 Data32) {
+ LM_UINT32 Value32;
+ LM_UINT32 j;
+
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+ {
+ REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode &
+ ~MI_MODE_AUTO_POLLING_ENABLE);
+ MM_Wait(40);
+ }
+
+ Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) |
+ ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) |
+ (Data32 & MI_COM_PHY_DATA_MASK) | MI_COM_CMD_WRITE | MI_COM_START;
+
+ REG_WR(pDevice, MacCtrl.MiCom, Value32);
+
+ for(j = 0; j < 20; j++)
+ {
+ MM_Wait(25);
+
+ Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+
+ if(!(Value32 & MI_COM_BUSY))
+ {
+ MM_Wait(5);
+ break;
+ }
+ }
+
+ if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+ {
+ REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+ MM_Wait(40);
+ }
+} /* LM_WritePhy */
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS
+LM_SetPowerState(
+PLM_DEVICE_BLOCK pDevice,
+LM_POWER_STATE PowerLevel) {
+ LM_UINT32 PmeSupport;
+ LM_UINT32 Value32;
+ LM_UINT32 PmCtrl;
+
+ /* make sureindirect accesses are enabled*/
+ MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl);
+
+ /* Clear the PME_ASSERT bit and the power state bits. Also enable */
+ /* the PME bit. */
+ MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &PmCtrl);
+
+ PmCtrl |= T3_PM_PME_ASSERTED;
+ PmCtrl &= ~T3_PM_POWER_STATE_MASK;
+
+ /* Set the appropriate power state. */
+ if(PowerLevel == LM_POWER_STATE_D0)
+ {
+
+ /* Bring the card out of low power mode. */
+ PmCtrl |= T3_PM_POWER_STATE_D0;
+ MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl);
+
+ REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+ MM_Wait (40);
+#if 0 /* Bugfix by jmb...can't call WritePhy here because pDevice not fully initialized */
+ LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x02);
+#endif
+
+ return LM_STATUS_SUCCESS;
+ }
+ else if(PowerLevel == LM_POWER_STATE_D1)
+ {
+ PmCtrl |= T3_PM_POWER_STATE_D1;
+ }
+ else if(PowerLevel == LM_POWER_STATE_D2)
+ {
+ PmCtrl |= T3_PM_POWER_STATE_D2;
+ }
+ else if(PowerLevel == LM_POWER_STATE_D3)
+ {
+ PmCtrl |= T3_PM_POWER_STATE_D3;
+ }
+ else
+ {
+ return LM_STATUS_FAILURE;
+ }
+ PmCtrl |= T3_PM_PME_ENABLE;
+
+ /* Mask out all interrupts so LM_SetupPhy won't be called while we are */
+ /* setting new line speed. */
+ Value32 = REG_RD(pDevice, PciCfg.MiscHostCtrl);
+ REG_WR(pDevice, PciCfg.MiscHostCtrl, Value32 | MISC_HOST_CTRL_MASK_PCI_INT);
+
+ if(!pDevice->RestoreOnWakeUp)
+ {
+ pDevice->RestoreOnWakeUp = TRUE;
+ pDevice->WakeUpDisableAutoNeg = pDevice->DisableAutoNeg;
+ pDevice->WakeUpRequestedMediaType = pDevice->RequestedMediaType;
+ }
+
+ /* Force auto-negotiation to 10 line speed. */
+ pDevice->DisableAutoNeg = FALSE;
+ pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
+ LM_SetupPhy(pDevice);
+
+ /* Put the driver in the initial state, and go through the power down */
+ /* sequence. */
+ LM_Halt(pDevice);
+
+ MM_ReadConfig32(pDevice, T3_PCI_PM_CAP_REG, &PmeSupport);
+
+ if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)
+ {
+
+ /* Enable WOL. */
+ LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x5a);
+ MM_Wait(40);
+
+ /* Set LED mode. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ Value32 = LED_CTRL_PHY_MODE_1;
+ }
+ else
+ {
+ if(pDevice->LedMode == LED_MODE_OUTPUT)
+ {
+ Value32 = LED_CTRL_PHY_MODE_2;
+ }
+ else
+ {
+ Value32 = LED_CTRL_PHY_MODE_1;
+ }
+ }
+
+ Value32 = MAC_MODE_PORT_MODE_MII;
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+ {
+ if(pDevice->LedMode == LED_MODE_LINK10 ||
+ pDevice->WolSpeed == WOL_SPEED_10MB)
+ {
+ Value32 |= MAC_MODE_LINK_POLARITY;
+ }
+ }
+ else
+ {
+ Value32 |= MAC_MODE_LINK_POLARITY;
+ }
+ REG_WR(pDevice, MacCtrl.Mode, Value32);
+ MM_Wait(40); MM_Wait(40); MM_Wait(40);
+
+ /* Always enable magic packet wake-up if we have vaux. */
+ if((PmeSupport & T3_PCI_PM_CAP_PME_D3COLD) &&
+ (pDevice->WakeUpModeCap & LM_WAKE_UP_MODE_MAGIC_PACKET))
+ {
+ Value32 |= MAC_MODE_DETECT_MAGIC_PACKET_ENABLE;
+ }
+
+ REG_WR(pDevice, MacCtrl.Mode, Value32);
+
+ /* Enable the receiver. */
+ REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_ENABLE);
+ }
+
+ /* Disable tx/rx clocks, and seletect an alternate clock. */
+ if(pDevice->WolSpeed == WOL_SPEED_100MB)
+ {
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+ T3_PCI_SELECT_ALTERNATE_CLOCK;
+ }
+ else
+ {
+ Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK;
+ }
+ REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+
+ MM_Wait(40);
+
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+ T3_PCI_SELECT_ALTERNATE_CLOCK | T3_PCI_44MHZ_CORE_CLOCK;
+ }
+ else
+ {
+ Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK |
+ T3_PCI_44MHZ_CORE_CLOCK;
+ }
+
+ REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+
+ MM_Wait(40);
+
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+ T3_PCI_44MHZ_CORE_CLOCK;
+ }
+ else
+ {
+ Value32 = T3_PCI_44MHZ_CORE_CLOCK;
+ }
+
+ REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+ }
+ else
+ {
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+ T3_PCI_SELECT_ALTERNATE_CLOCK |
+ T3_PCI_POWER_DOWN_PCI_PLL133;
+ }
+ else
+ {
+ Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK |
+ T3_PCI_POWER_DOWN_PCI_PLL133;
+ }
+
+ REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+ }
+
+ MM_Wait(40);
+
+ if(!pDevice->EepromWp && (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE))
+ {
+ /* Switch adapter to auxilliary power. */
+ if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+ T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+ {
+ /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */
+ REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+ MM_Wait(40);
+ }
+ else
+ {
+ /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */
+ REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2);
+ MM_Wait(40);
+
+ /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 1. */
+ REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2);
+ MM_Wait(40);
+
+ /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */
+ REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+ GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+ MM_Wait(40);
+ }
+ }
+
+ /* Set the phy to low power mode. */
+ /* Put the the hardware in low power mode. */
+ MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl);
+
+ return LM_STATUS_SUCCESS;
+} /* LM_SetPowerState */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+static LM_UINT32
+GetPhyAdFlowCntrlSettings(
+ PLM_DEVICE_BLOCK pDevice)
+{
+ LM_UINT32 Value32;
+
+ Value32 = 0;
+
+ /* Auto negotiation flow control only when autonegotiation is enabled. */
+ if(pDevice->DisableAutoNeg == FALSE ||
+ pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO ||
+ pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO)
+ {
+ /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */
+ if((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) ||
+ ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
+ (pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
+ {
+ Value32 |= PHY_AN_AD_PAUSE_CAPABLE;
+ }
+ else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+ {
+ Value32 |= PHY_AN_AD_ASYM_PAUSE;
+ }
+ else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)
+ {
+ Value32 |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
+ }
+ }
+
+ return Value32;
+}
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/* LM_STATUS_FAILURE */
+/* LM_STATUS_SUCCESS */
+/* */
+/******************************************************************************/
+static LM_STATUS
+LM_ForceAutoNegBcm540xPhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
+{
+ LM_MEDIA_TYPE MediaType;
+ LM_LINE_SPEED LineSpeed;
+ LM_DUPLEX_MODE DuplexMode;
+ LM_UINT32 NewPhyCtrl;
+ LM_UINT32 Value32;
+ LM_UINT32 Cnt;
+
+ /* Get the interface type, line speed, and duplex mode. */
+ LM_TranslateRequestedMediaType(RequestedMediaType, &MediaType, &LineSpeed,
+ &DuplexMode);
+
+ if (pDevice->RestoreOnWakeUp)
+ {
+ LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+ pDevice->advertising1000 = 0;
+ Value32 = PHY_AN_AD_10BASET_FULL | PHY_AN_AD_10BASET_HALF;
+ if (pDevice->WolSpeed == WOL_SPEED_100MB)
+ {
+ Value32 |= PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+ }
+ Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+ Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+ LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+ pDevice->advertising = Value32;
+ }
+ /* Setup the auto-negotiation advertisement register. */
+ else if(LineSpeed == LM_LINE_SPEED_UNKNOWN)
+ {
+ /* Setup the 10/100 Mbps auto-negotiation advertisement register. */
+ Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
+ PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL |
+ PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+ Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+ LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+ pDevice->advertising = Value32;
+
+ /* Advertise 1000Mbps */
+ Value32 = BCM540X_AN_AD_1000BASET_HALF | BCM540X_AN_AD_1000BASET_FULL;
+
+#if INCLUDE_5701_AX_FIX
+ /* Bug: workaround for CRC error in gigabit mode when we are in */
+ /* slave mode. This will force the PHY to operate in */
+ /* master mode. */
+ if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+ pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+ {
+ Value32 |= BCM540X_CONFIG_AS_MASTER |
+ BCM540X_ENABLE_CONFIG_AS_MASTER;
+ }
+#endif
+
+ LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+ pDevice->advertising1000 = Value32;
+ }
+ else
+ {
+ if(LineSpeed == LM_LINE_SPEED_1000MBPS)
+ {
+ Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+ Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+ LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+ pDevice->advertising = Value32;
+
+ if(DuplexMode != LM_DUPLEX_MODE_FULL)
+ {
+ Value32 = BCM540X_AN_AD_1000BASET_HALF;
+ }
+ else
+ {
+ Value32 = BCM540X_AN_AD_1000BASET_FULL;
+ }
+
+ LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+ pDevice->advertising1000 = Value32;
+ }
+ else if(LineSpeed == LM_LINE_SPEED_100MBPS)
+ {
+ LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+ pDevice->advertising1000 = 0;
+
+ if(DuplexMode != LM_DUPLEX_MODE_FULL)
+ {
+ Value32 = PHY_AN_AD_100BASETX_HALF;
+ }
+ else
+ {
+ Value32 = PHY_AN_AD_100BASETX_FULL;
+ }
+
+ Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+ Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+ LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+ pDevice->advertising = Value32;
+ }
+ else if(LineSpeed == LM_LINE_SPEED_10MBPS)
+ {
+ LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+ pDevice->advertising1000 = 0;
+
+ if(DuplexMode != LM_DUPLEX_MODE_FULL)
+ {
+ Value32 = PHY_AN_AD_10BASET_HALF;
+ }
+ else
+ {
+ Value32 = PHY_AN_AD_10BASET_FULL;
+ }
+
+ Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+ Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+ LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+ pDevice->advertising = Value32;
+ }
+ }
+
+ /* Force line speed if auto-negotiation is disabled. */
+ if(pDevice->DisableAutoNeg && LineSpeed != LM_LINE_SPEED_UNKNOWN)
+ {
+ /* This code path is executed only when there is link. */
+ pDevice->MediaType = MediaType;
+ pDevice->LineSpeed = LineSpeed;
+ pDevice->DuplexMode = DuplexMode;
+
+ /* Force line seepd. */
+ NewPhyCtrl = 0;
+ switch(LineSpeed)
+ {
+ case LM_LINE_SPEED_10MBPS:
+ NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_10MBPS;
+ break;
+ case LM_LINE_SPEED_100MBPS:
+ NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_100MBPS;
+ break;
+ case LM_LINE_SPEED_1000MBPS:
+ NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS;
+ break;
+ default:
+ NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS;
+ break;
+ }
+
+ if(DuplexMode == LM_DUPLEX_MODE_FULL)
+ {
+ NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE;
+ }
+
+ /* Don't do anything if the PHY_CTRL is already what we wanted. */
+ LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+ if(Value32 != NewPhyCtrl)
+ {
+ /* Temporary bring the link down before forcing line speed. */
+ LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_LOOPBACK_MODE);
+
+ /* Wait for link to go down. */
+ for(Cnt = 0; Cnt < 15000; Cnt++)
+ {
+ MM_Wait(10);
+
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+ if(!(Value32 & PHY_STATUS_LINK_PASS))
+ {
+ MM_Wait(40);
+ break;
+ }
+ }
+
+ LM_WritePhy(pDevice, PHY_CTRL_REG, NewPhyCtrl);
+ MM_Wait(40);
+ }
+ }
+ else
+ {
+ LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+ PHY_CTRL_RESTART_AUTO_NEG);
+ }
+
+ return LM_STATUS_SUCCESS;
+} /* LM_ForceAutoNegBcm540xPhy */
+
+
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+static LM_STATUS
+LM_ForceAutoNeg(
+PLM_DEVICE_BLOCK pDevice,
+LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
+{
+ LM_STATUS LmStatus;
+
+ /* Initialize the phy chip. */
+ switch(pDevice->PhyId & PHY_ID_MASK)
+ {
+ case PHY_BCM5400_PHY_ID:
+ case PHY_BCM5401_PHY_ID:
+ case PHY_BCM5411_PHY_ID:
+ case PHY_BCM5701_PHY_ID:
+ case PHY_BCM5703_PHY_ID:
+ case PHY_BCM5704_PHY_ID:
+ LmStatus = LM_ForceAutoNegBcm540xPhy(pDevice, RequestedMediaType);
+ break;
+
+ default:
+ LmStatus = LM_STATUS_FAILURE;
+ break;
+ }
+
+ return LmStatus;
+} /* LM_ForceAutoNeg */
+
+/******************************************************************************/
+/* Description: */
+/* */
+/* Return: */
+/******************************************************************************/
+LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice,
+ PT3_FWIMG_INFO pFwImg,
+ LM_UINT32 LoadCpu,
+ LM_UINT32 StartCpu)
+{
+ LM_UINT32 i;
+ LM_UINT32 address;
+
+ if (LoadCpu & T3_RX_CPU_ID)
+ {
+ if (LM_HaltCpu(pDevice,T3_RX_CPU_ID) != LM_STATUS_SUCCESS)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ /* First of all clear scrach pad memory */
+ for (i = 0; i < T3_RX_CPU_SPAD_SIZE; i+=4)
+ {
+ LM_RegWrInd(pDevice,T3_RX_CPU_SPAD_ADDR+i,0);
+ }
+
+ /* Copy code first */
+ address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff);
+ for (i = 0; i <= pFwImg->Text.Length; i+=4)
+ {
+ LM_RegWrInd(pDevice,address+i,
+ ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]);
+ }
+
+ address = T3_RX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff);
+ for (i = 0; i <= pFwImg->ROnlyData.Length; i+=4)
+ {
+ LM_RegWrInd(pDevice,address+i,
+ ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]);
+ }
+
+ address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff);
+ for (i= 0; i <= pFwImg->Data.Length; i+=4)
+ {
+ LM_RegWrInd(pDevice,address+i,
+ ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]);
+ }
+ }
+
+ if (LoadCpu & T3_TX_CPU_ID)
+ {
+ if (LM_HaltCpu(pDevice,T3_TX_CPU_ID) != LM_STATUS_SUCCESS)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ /* First of all clear scrach pad memory */
+ for (i = 0; i < T3_TX_CPU_SPAD_SIZE; i+=4)
+ {
+ LM_RegWrInd(pDevice,T3_TX_CPU_SPAD_ADDR+i,0);
+ }
+
+ /* Copy code first */
+ address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff);
+ for (i= 0; i <= pFwImg->Text.Length; i+=4)
+ {
+ LM_RegWrInd(pDevice,address+i,
+ ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]);
+ }
+
+ address = T3_TX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff);
+ for (i= 0; i <= pFwImg->ROnlyData.Length; i+=4)
+ {
+ LM_RegWrInd(pDevice,address+i,
+ ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]);
+ }
+
+ address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff);
+ for (i= 0; i <= pFwImg->Data.Length; i+=4)
+ {
+ LM_RegWrInd(pDevice,address+i,
+ ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]);
+ }
+ }
+
+ if (StartCpu & T3_RX_CPU_ID)
+ {
+ /* Start Rx CPU */
+ REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress);
+ for (i = 0 ; i < 5; i++)
+ {
+ if (pFwImg->StartAddress == REG_RD(pDevice,rxCpu.reg.PC))
+ break;
+
+ REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+ REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress);
+ MM_Wait(1000);
+ }
+
+ REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,rxCpu.reg.mode, 0);
+ }
+
+ if (StartCpu & T3_TX_CPU_ID)
+ {
+ /* Start Tx CPU */
+ REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress);
+ for (i = 0 ; i < 5; i++)
+ {
+ if (pFwImg->StartAddress == REG_RD(pDevice,txCpu.reg.PC))
+ break;
+
+ REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT);
+ REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress);
+ MM_Wait(1000);
+ }
+
+ REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,txCpu.reg.mode, 0);
+ }
+
+ return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number)
+{
+ LM_UINT32 i;
+
+ if (cpu_number == T3_RX_CPU_ID)
+ {
+ for (i = 0 ; i < 10000; i++)
+ {
+ REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+
+ if (REG_RD(pDevice,rxCpu.reg.mode) & CPU_MODE_HALT)
+ break;
+ }
+
+ REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+ MM_Wait(10);
+ }
+ else
+ {
+ for (i = 0 ; i < 10000; i++)
+ {
+ REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+ REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT);
+
+ if (REG_RD(pDevice,txCpu.reg.mode) & CPU_MODE_HALT)
+ break;
+ }
+ }
+
+ return (( i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS);
+}
+
+
+int
+LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec)
+{
+ LM_UINT32 Oldcfg;
+ int j;
+ int ret = 0;
+
+ if(BlinkDurationSec == 0)
+ {
+ return 0;
+ }
+ if(BlinkDurationSec > 120)
+ {
+ BlinkDurationSec = 120;
+ }
+
+ Oldcfg = REG_RD(pDevice, MacCtrl.LedCtrl);
+ for(j = 0; j < BlinkDurationSec * 2; j++)
+ {
+ if(j % 2)
+ {
+ /* Turn on the LEDs. */
+ REG_WR(pDevice, MacCtrl.LedCtrl,
+ LED_CTRL_OVERRIDE_LINK_LED |
+ LED_CTRL_1000MBPS_LED_ON |
+ LED_CTRL_100MBPS_LED_ON |
+ LED_CTRL_10MBPS_LED_ON |
+ LED_CTRL_OVERRIDE_TRAFFIC_LED |
+ LED_CTRL_BLINK_TRAFFIC_LED |
+ LED_CTRL_TRAFFIC_LED);
+ }
+ else
+ {
+ /* Turn off the LEDs. */
+ REG_WR(pDevice, MacCtrl.LedCtrl,
+ LED_CTRL_OVERRIDE_LINK_LED |
+ LED_CTRL_OVERRIDE_TRAFFIC_LED);
+ }
+
+#ifndef EMBEDDED
+ current->state = TASK_INTERRUPTIBLE;
+ if (schedule_timeout(HZ/2) != 0) {
+ ret = -EINTR;
+ break;
+ }
+#else
+ udelay(100000); /* 1s sleep */
+#endif
+ }
+ REG_WR(pDevice, MacCtrl.LedCtrl, Oldcfg);
+ return ret;
+}
+
+int t3_do_dma(PLM_DEVICE_BLOCK pDevice,
+ LM_PHYSICAL_ADDRESS host_addr_phy, int length,
+ int dma_read)
+{
+ T3_DMA_DESC dma_desc;
+ int i;
+ LM_UINT32 dma_desc_addr;
+ LM_UINT32 value32;
+
+ REG_WR(pDevice, BufMgr.Mode, 0);
+ REG_WR(pDevice, Ftq.Reset, 0);
+
+ dma_desc.host_addr.High = host_addr_phy.High;
+ dma_desc.host_addr.Low = host_addr_phy.Low;
+ dma_desc.nic_mbuf = 0x2100;
+ dma_desc.len = length;
+ dma_desc.flags = 0x00000004; /* Generate Rx-CPU event */
+
+ if (dma_read)
+ {
+ dma_desc.cqid_sqid = (T3_QID_RX_BD_COMP << 8) |
+ T3_QID_DMA_HIGH_PRI_READ;
+ REG_WR(pDevice, DmaRead.Mode, DMA_READ_MODE_ENABLE);
+ }
+ else
+ {
+ dma_desc.cqid_sqid = (T3_QID_RX_DATA_COMP << 8) |
+ T3_QID_DMA_HIGH_PRI_WRITE;
+ REG_WR(pDevice, DmaWrite.Mode, DMA_WRITE_MODE_ENABLE);
+ }
+
+ dma_desc_addr = T3_NIC_DMA_DESC_POOL_ADDR;
+
+ /* Writing this DMA descriptor to DMA memory */
+ for (i = 0; i < sizeof(T3_DMA_DESC); i += 4)
+ {
+ value32 = *((PLM_UINT32) (((PLM_UINT8) &dma_desc) + i));
+ MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, dma_desc_addr+i);
+ MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, cpu_to_le32(value32));
+ }
+ MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, 0);
+
+ if (dma_read)
+ REG_WR(pDevice, Ftq.DmaHighReadFtqFifoEnqueueDequeue, dma_desc_addr);
+ else
+ REG_WR(pDevice, Ftq.DmaHighWriteFtqFifoEnqueueDequeue, dma_desc_addr);
+
+ for (i = 0; i < 40; i++)
+ {
+ if (dma_read)
+ value32 = REG_RD(pDevice, Ftq.RcvBdCompFtqFifoEnqueueDequeue);
+ else
+ value32 = REG_RD(pDevice, Ftq.RcvDataCompFtqFifoEnqueueDequeue);
+
+ if ((value32 & 0xffff) == dma_desc_addr)
+ break;
+
+ MM_Wait(10);
+ }
+
+ return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS
+LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt,
+ LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize)
+{
+ int j;
+ LM_UINT32 *ptr;
+ int dma_success = 0;
+
+ if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+ T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+ {
+ return LM_STATUS_SUCCESS;
+ }
+ while (!dma_success)
+ {
+ /* Fill data with incremental patterns */
+ ptr = (LM_UINT32 *)pBufferVirt;
+ for (j = 0; j < BufferSize/4; j++)
+ *ptr++ = j;
+
+ if (t3_do_dma(pDevice,BufferPhy,BufferSize, 1) == LM_STATUS_FAILURE)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ MM_Wait(40);
+ ptr = (LM_UINT32 *)pBufferVirt;
+ /* Fill data with zero */
+ for (j = 0; j < BufferSize/4; j++)
+ *ptr++ = 0;
+
+ if (t3_do_dma(pDevice,BufferPhy,BufferSize, 0) == LM_STATUS_FAILURE)
+ {
+ return LM_STATUS_FAILURE;
+ }
+
+ MM_Wait(40);
+ /* Check for data */
+ ptr = (LM_UINT32 *)pBufferVirt;
+ for (j = 0; j < BufferSize/4; j++)
+ {
+ if (*ptr++ != j)
+ {
+ if ((pDevice->DmaReadWriteCtrl & DMA_CTRL_WRITE_BOUNDARY_MASK)
+ == DMA_CTRL_WRITE_BOUNDARY_DISABLE)
+ {
+ pDevice->DmaReadWriteCtrl = (pDevice->DmaReadWriteCtrl &
+ ~DMA_CTRL_WRITE_BOUNDARY_MASK) |
+ DMA_CTRL_WRITE_BOUNDARY_16;
+ REG_WR(pDevice, PciCfg.DmaReadWriteCtrl,
+ pDevice->DmaReadWriteCtrl);
+ break;
+ }
+ else
+ {
+ return LM_STATUS_FAILURE;
+ }
+ }
+ }
+ if (j == (BufferSize/4))
+ dma_success = 1;
+ }
+ return LM_STATUS_SUCCESS;
+}
+#endif /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_TIGON3 */
diff --git a/drivers/tigon3.h b/drivers/tigon3.h
new file mode 100644
index 0000000..8d30ac9
--- /dev/null
+++ b/drivers/tigon3.h
@@ -0,0 +1,3469 @@
+
+/******************************************************************************/
+/* */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
+/* Corporation. */
+/* All rights reserved. */
+/* */
+/* 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, located in the file LICENSE. */
+/* */
+/* History: */
+/* */
+/******************************************************************************/
+
+#ifndef TIGON3_H
+#define TIGON3_H
+
+#include "bcm570x_lm.h"
+#if INCLUDE_TBI_SUPPORT
+#include "bcm570x_autoneg.h"
+#endif
+
+
+/* io defines */
+#if !defined(BIG_ENDIAN_HOST)
+#define readl(addr) \
+ (LONGSWAP((*(volatile unsigned int *)(addr))))
+#define writel(b,addr) \
+ ((*(volatile unsigned int *)(addr)) = (LONGSWAP(b)))
+#else
+#if 0 /* !defined(PPC603) */
+#define readl(addr) (*(volatile unsigned int*)(0xa0000000 + (unsigned long)(addr)))
+#define writel(b,addr) ((*(volatile unsigned int *) ((unsigned long)(addr) + 0xa0000000)) = (b))
+#else
+#if 1
+#define readl(addr) (*(volatile unsigned int*)(addr))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+#else
+extern int sprintf(char* buf, const char* f, ...);
+static __inline unsigned int readl(void* addr){
+ char buf[128];
+ unsigned int tmp = (*(volatile unsigned int*)(addr));
+ sprintf(buf,"%s:%s: read 0x%x from 0x%x\n",__FILE__,__LINE__,tmp,addr,0,0);
+ sysSerialPrintString(buf);
+ return tmp;
+}
+static __inline void writel(unsigned int b, unsigned int addr){
+ char buf[128];
+ ((*(volatile unsigned int *) (addr)) = (b));
+ sprintf(buf,"%s:%s: write 0x%x to 0x%x\n",__FILE__,__LINE__,b,addr,0,0);
+ sysSerialPrintString(buf);
+}
+#endif
+#endif /* PPC603 */
+#endif
+
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+/* Maxim number of packet descriptors used for sending packets. */
+#define MAX_TX_PACKET_DESC_COUNT 600
+#define DEFAULT_TX_PACKET_DESC_COUNT 2
+
+/* Maximum number of packet descriptors used for receiving packets. */
+#if T3_JUMBO_RCB_ENTRY_COUNT
+#define MAX_RX_PACKET_DESC_COUNT \
+ (T3_STD_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT)
+#else
+#define MAX_RX_PACKET_DESC_COUNT 800
+#endif
+#define DEFAULT_RX_PACKET_DESC_COUNT 2
+
+/* Threshhold for double copying small tx packets. 0 will disable double */
+/* copying of small Tx packets. */
+#define DEFAULT_TX_COPY_BUFFER_SIZE 0
+#define MIN_TX_COPY_BUFFER_SIZE 64
+#define MAX_TX_COPY_BUFFER_SIZE 512
+
+/* Cache line. */
+#define COMMON_CACHE_LINE_SIZE 0x20
+#define COMMON_CACHE_LINE_MASK (COMMON_CACHE_LINE_SIZE-1)
+
+/* Maximum number of fragment we can handle. */
+#ifndef MAX_FRAGMENT_COUNT
+#define MAX_FRAGMENT_COUNT 32
+#endif
+
+/* B0 bug. */
+#define BCM5700_BX_MIN_FRAG_SIZE 10
+#define BCM5700_BX_MIN_FRAG_BUF_SIZE 16 /* nice aligned size. */
+#define BCM5700_BX_MIN_FRAG_BUF_SIZE_MASK (BCM5700_BX_MIN_FRAG_BUF_SIZE-1)
+#define BCM5700_BX_TX_COPY_BUF_SIZE (BCM5700_BX_MIN_FRAG_BUF_SIZE * \
+ MAX_FRAGMENT_COUNT)
+
+/* MAGIC number. */
+/* #define T3_MAGIC_NUM 'KevT' */
+#define T3_FIRMWARE_MAILBOX 0x0b50
+#define T3_MAGIC_NUM 0x4B657654
+#define T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE 0x4861764b
+
+#define T3_NIC_DATA_SIG_ADDR 0x0b54
+#define T3_NIC_DATA_SIG 0x4b657654
+
+#define T3_NIC_DATA_NIC_CFG_ADDR 0x0b58
+#define T3_NIC_CFG_LED_MODE_UNKNOWN BIT_NONE
+#define T3_NIC_CFG_LED_MODE_TRIPLE_SPEED BIT_2
+#define T3_NIC_CFG_LED_MODE_LINK_SPEED BIT_3
+#define T3_NIC_CFG_LED_MODE_OPEN_DRAIN BIT_2
+#define T3_NIC_CFG_LED_MODE_OUTPUT BIT_3
+#define T3_NIC_CFG_LED_MODE_MASK (BIT_2 | BIT_3)
+#define T3_NIC_CFG_PHY_TYPE_UNKNOWN BIT_NONE
+#define T3_NIC_CFG_PHY_TYPE_COPPER BIT_4
+#define T3_NIC_CFG_PHY_TYPE_FIBER BIT_5
+#define T3_NIC_CFG_PHY_TYPE_MASK (BIT_4 | BIT_5)
+#define T3_NIC_CFG_ENABLE_WOL BIT_6
+#define T3_NIC_CFG_ENABLE_ASF BIT_7
+#define T3_NIC_EEPROM_WP BIT_8
+
+#define T3_NIC_DATA_PHY_ID_ADDR 0x0b74
+#define T3_NIC_PHY_ID1_MASK 0xffff0000
+#define T3_NIC_PHY_ID2_MASK 0x0000ffff
+
+#define T3_CMD_MAILBOX 0x0b78
+#define T3_CMD_NICDRV_ALIVE 0x01
+#define T3_CMD_NICDRV_PAUSE_FW 0x02
+#define T3_CMD_NICDRV_IPV4ADDR_CHANGE 0x03
+#define T3_CMD_NICDRV_IPV6ADDR_CHANGE 0x04
+#define T3_CMD_5703A0_FIX_DMAFW_DMAR 0x05
+#define T3_CMD_5703A0_FIX_DMAFW_DMAW 0x06
+
+#define T3_CMD_LENGTH_MAILBOX 0x0b7c
+#define T3_CMD_DATA_MAILBOX 0x0b80
+
+#define T3_ASF_FW_STATUS_MAILBOX 0x0c00
+
+#define T3_DRV_STATE_MAILBOX 0x0c04
+#define T3_DRV_STATE_START 0x01
+#define T3_DRV_STATE_UNLOAD 0x02
+#define T3_DRV_STATE_WOL 0x03
+#define T3_DRV_STATE_SUSPEND 0x04
+
+#define T3_FW_RESET_TYPE_MAILBOX 0x0c08
+
+#define T3_MAC_ADDR_HIGH_MAILBOX 0x0c14
+#define T3_MAC_ADDR_LOW_MAILBOX 0x0c18
+
+/******************************************************************************/
+/* Hardware constants. */
+/******************************************************************************/
+
+/* Number of entries in the send ring: must be 512. */
+#define T3_SEND_RCB_ENTRY_COUNT 512
+#define T3_SEND_RCB_ENTRY_COUNT_MASK (T3_SEND_RCB_ENTRY_COUNT-1)
+
+/* Number of send RCBs. May be 1-16 but for now, only support one. */
+#define T3_MAX_SEND_RCB_COUNT 16
+
+/* Number of entries in the Standard Receive RCB. Must be 512 entries. */
+#define T3_STD_RCV_RCB_ENTRY_COUNT 512
+#define T3_STD_RCV_RCB_ENTRY_COUNT_MASK (T3_STD_RCV_RCB_ENTRY_COUNT-1)
+#define DEFAULT_STD_RCV_DESC_COUNT 200 /* Must be < 512. */
+#define MAX_STD_RCV_BUFFER_SIZE 0x600
+
+/* Number of entries in the Mini Receive RCB. This value can either be */
+/* 0, 1024. Currently Mini Receive RCB is disabled. */
+#ifndef T3_MINI_RCV_RCB_ENTRY_COUNT
+#define T3_MINI_RCV_RCB_ENTRY_COUNT 0
+#endif /* T3_MINI_RCV_RCB_ENTRY_COUNT */
+#define T3_MINI_RCV_RCB_ENTRY_COUNT_MASK (T3_MINI_RCV_RCB_ENTRY_COUNT-1)
+#define MAX_MINI_RCV_BUFFER_SIZE 512
+#define DEFAULT_MINI_RCV_BUFFER_SIZE 64
+#define DEFAULT_MINI_RCV_DESC_COUNT 100 /* Must be < 1024. */
+
+/* Number of entries in the Jumbo Receive RCB. This value must 256 or 0. */
+/* Currently, Jumbo Receive RCB is disabled. */
+#ifndef T3_JUMBO_RCV_RCB_ENTRY_COUNT
+#define T3_JUMBO_RCV_RCB_ENTRY_COUNT 0
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+#define T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK (T3_JUMBO_RCV_RCB_ENTRY_COUNT-1)
+
+#define MAX_JUMBO_RCV_BUFFER_SIZE (10 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_RCV_BUFFER_SIZE (4 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_RCV_DESC_COUNT 128 /* Must be < 256. */
+
+#define MAX_JUMBO_TX_BUFFER_SIZE (8 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_TX_BUFFER_SIZE (4 * 1024) /* > 1514 */
+
+/* Number of receive return RCBs. Maybe 1-16 but for now, only support one. */
+#define T3_MAX_RCV_RETURN_RCB_COUNT 16
+
+/* Number of entries in a Receive Return ring. This value is either 1024 */
+/* or 2048. */
+#ifndef T3_RCV_RETURN_RCB_ENTRY_COUNT
+#define T3_RCV_RETURN_RCB_ENTRY_COUNT 1024
+#endif /* T3_RCV_RETURN_RCB_ENTRY_COUNT */
+#define T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK (T3_RCV_RETURN_RCB_ENTRY_COUNT-1)
+
+
+/* Default coalescing parameters. */
+#define DEFAULT_RX_COALESCING_TICKS 100
+#define MAX_RX_COALESCING_TICKS 500
+#define DEFAULT_TX_COALESCING_TICKS 400
+#define MAX_TX_COALESCING_TICKS 500
+#define DEFAULT_RX_MAX_COALESCED_FRAMES 10
+#define MAX_RX_MAX_COALESCED_FRAMES 100
+#define ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES 5
+#define ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES 42
+#define ADAPTIVE_LO_RX_COALESCING_TICKS 50
+#define ADAPTIVE_HI_RX_COALESCING_TICKS 300
+#define ADAPTIVE_LO_PKT_THRESH 30000
+#define ADAPTIVE_HI_PKT_THRESH 74000
+#define DEFAULT_TX_MAX_COALESCED_FRAMES 40
+#define ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES 25
+#define ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES 75
+#define MAX_TX_MAX_COALESCED_FRAMES 100
+
+#define DEFAULT_RX_COALESCING_TICKS_DURING_INT 25
+#define DEFAULT_TX_COALESCING_TICKS_DURING_INT 25
+#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT 5
+#define DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT 5
+
+#define BAD_DEFAULT_VALUE 0xffffffff
+
+#define DEFAULT_STATS_COALESCING_TICKS 1000000
+#define MAX_STATS_COALESCING_TICKS 3600000000U
+
+
+/* Receive BD Replenish thresholds. */
+#define DEFAULT_RCV_STD_BD_REPLENISH_THRESHOLD 4
+#define DEFAULT_RCV_JUMBO_BD_REPLENISH_THRESHOLD 4
+
+#define SPLIT_MODE_DISABLE 0
+#define SPLIT_MODE_ENABLE 1
+
+#define SPLIT_MODE_5704_MAX_REQ 3
+
+/* Maximum physical fragment size. */
+#define MAX_FRAGMENT_SIZE (64 * 1024)
+
+
+/* Standard view. */
+#define T3_STD_VIEW_SIZE (64 * 1024)
+#define T3_FLAT_VIEW_SIZE (32 * 1024 * 1024)
+
+
+/* Buffer descriptor base address on the NIC's memory. */
+
+#define T3_NIC_SND_BUFFER_DESC_ADDR 0x4000
+#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR 0x6000
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR 0x7000
+
+#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xc000
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xd000
+#define T3_NIC_MINI_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xe000
+
+#define T3_NIC_SND_BUFFER_DESC_SIZE (T3_SEND_RCB_ENTRY_COUNT * \
+ sizeof(T3_SND_BD) / 4)
+
+#define T3_NIC_STD_RCV_BUFFER_DESC_SIZE (T3_STD_RCV_RCB_ENTRY_COUNT * \
+ sizeof(T3_RCV_BD) / 4)
+
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_SIZE (T3_JUMBO_RCV_RCB_ENTRY_COUNT * \
+ sizeof(T3_EXT_RCV_BD) / 4)
+
+
+/* MBUF pool. */
+#define T3_NIC_MBUF_POOL_ADDR 0x8000
+/* #define T3_NIC_MBUF_POOL_SIZE 0x18000 */
+#define T3_NIC_MBUF_POOL_SIZE96 0x18000
+#define T3_NIC_MBUF_POOL_SIZE64 0x10000
+
+
+#define T3_NIC_MBUF_POOL_ADDR_EXT_MEM 0x20000
+
+/* DMA descriptor pool */
+#define T3_NIC_DMA_DESC_POOL_ADDR 0x2000
+#define T3_NIC_DMA_DESC_POOL_SIZE 0x2000 /* 8KB. */
+
+#define T3_DEF_DMA_MBUF_LOW_WMARK 0x40
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK 0x20
+#define T3_DEF_MBUF_HIGH_WMARK 0x60
+
+#define T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO 304
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO 152
+#define T3_DEF_MBUF_HIGH_WMARK_JUMBO 380
+
+#define T3_DEF_DMA_DESC_LOW_WMARK 5
+#define T3_DEF_DMA_DESC_HIGH_WMARK 10
+
+/* Maximum size of giant TCP packet can be sent */
+#define T3_TCP_SEG_MAX_OFFLOAD_SIZE 64*1000
+#define T3_TCP_SEG_MIN_NUM_SEG 20
+
+#define T3_RX_CPU_ID 0x1
+#define T3_TX_CPU_ID 0x2
+#define T3_RX_CPU_SPAD_ADDR 0x30000
+#define T3_RX_CPU_SPAD_SIZE 0x4000
+#define T3_TX_CPU_SPAD_ADDR 0x34000
+#define T3_TX_CPU_SPAD_SIZE 0x4000
+
+typedef struct T3_DIR_ENTRY
+{
+ PLM_UINT8 Buffer;
+ LM_UINT32 Offset;
+ LM_UINT32 Length;
+} T3_DIR_ENTRY,*PT3_DIR_ENTRY;
+
+typedef struct T3_FWIMG_INFO
+{
+ LM_UINT32 StartAddress;
+ T3_DIR_ENTRY Text;
+ T3_DIR_ENTRY ROnlyData;
+ T3_DIR_ENTRY Data;
+ T3_DIR_ENTRY Sbss;
+ T3_DIR_ENTRY Bss;
+} T3_FWIMG_INFO, *PT3_FWIMG_INFO;
+
+
+
+/******************************************************************************/
+/* Tigon3 PCI Registers. */
+/******************************************************************************/
+#define T3_PCI_ID_BCM5700 0x164414e4
+#define T3_PCI_ID_BCM5701 0x164514e4
+#define T3_PCI_ID_BCM5702 0x164614e4
+#define T3_PCI_ID_BCM5702x 0x16A614e4
+#define T3_PCI_ID_BCM5703 0x164714e4
+#define T3_PCI_ID_BCM5703x 0x16A714e4
+#define T3_PCI_ID_BCM5702FE 0x164D14e4
+#define T3_PCI_ID_BCM5704 0x164814e4
+
+#define T3_PCI_VENDOR_ID (T3_PCI_ID & 0xffff)
+#define T3_PCI_DEVICE_ID (T3_PCI_ID >> 16)
+
+#define T3_PCI_MISC_HOST_CTRL_REG 0x68
+
+/* The most significant 16bit of register 0x68. */
+/* ChipId:4, ChipRev:4, MetalRev:8 */
+#define T3_CHIP_ID_5700_A0 0x7000
+#define T3_CHIP_ID_5700_A1 0x7001
+#define T3_CHIP_ID_5700_B0 0x7100
+#define T3_CHIP_ID_5700_B1 0x7101
+#define T3_CHIP_ID_5700_C0 0x7200
+
+#define T3_CHIP_ID_5701_A0 0x0000
+#define T3_CHIP_ID_5701_B0 0x0100
+#define T3_CHIP_ID_5701_B2 0x0102
+#define T3_CHIP_ID_5701_B5 0x0105
+
+#define T3_CHIP_ID_5703_A0 0x1000
+#define T3_CHIP_ID_5703_A1 0x1001
+#define T3_CHIP_ID_5703_A2 0x1002
+
+#define T3_CHIP_ID_5704_A0 0x2000
+
+/* Chip Id. */
+#define T3_ASIC_REV(_ChipRevId) ((_ChipRevId) >> 12)
+#define T3_ASIC_REV_5700 0x07
+#define T3_ASIC_REV_5701 0x00
+#define T3_ASIC_REV_5703 0x01
+#define T3_ASIC_REV_5704 0x02
+
+
+/* Chip id and revision. */
+#define T3_CHIP_REV(_ChipRevId) ((_ChipRevId) >> 8)
+#define T3_CHIP_REV_5700_AX 0x70
+#define T3_CHIP_REV_5700_BX 0x71
+#define T3_CHIP_REV_5700_CX 0x72
+#define T3_CHIP_REV_5701_AX 0x00
+
+/* Metal revision. */
+#define T3_METAL_REV(_ChipRevId) ((_ChipRevId) & 0xff)
+#define T3_METAL_REV_A0 0x00
+#define T3_METAL_REV_A1 0x01
+#define T3_METAL_REV_B0 0x00
+#define T3_METAL_REV_B1 0x01
+#define T3_METAL_REV_B2 0x02
+
+#define T3_PCI_REG_CLOCK_CTRL 0x74
+
+#define T3_PCI_DISABLE_RX_CLOCK BIT_10
+#define T3_PCI_DISABLE_TX_CLOCK BIT_11
+#define T3_PCI_SELECT_ALTERNATE_CLOCK BIT_12
+#define T3_PCI_POWER_DOWN_PCI_PLL133 BIT_15
+#define T3_PCI_44MHZ_CORE_CLOCK BIT_18
+
+
+#define T3_PCI_REG_ADDR_REG 0x78
+#define T3_PCI_REG_DATA_REG 0x80
+
+#define T3_PCI_MEM_WIN_ADDR_REG 0x7c
+#define T3_PCI_MEM_WIN_DATA_REG 0x84
+
+#define T3_PCI_PM_CAP_REG 0x48
+
+#define T3_PCI_PM_CAP_PME_D3COLD BIT_31
+#define T3_PCI_PM_CAP_PME_D3HOT BIT_30
+
+#define T3_PCI_PM_STATUS_CTRL_REG 0x4c
+
+#define T3_PM_POWER_STATE_MASK (BIT_0 | BIT_1)
+#define T3_PM_POWER_STATE_D0 BIT_NONE
+#define T3_PM_POWER_STATE_D1 BIT_0
+#define T3_PM_POWER_STATE_D2 BIT_1
+#define T3_PM_POWER_STATE_D3 (BIT_0 | BIT_1)
+
+#define T3_PM_PME_ENABLE BIT_8
+#define T3_PM_PME_ASSERTED BIT_15
+
+
+/* PCI state register. */
+#define T3_PCI_STATE_REG 0x70
+
+#define T3_PCI_STATE_FORCE_RESET BIT_0
+#define T3_PCI_STATE_INT_NOT_ACTIVE BIT_1
+#define T3_PCI_STATE_CONVENTIONAL_PCI_MODE BIT_2
+#define T3_PCI_STATE_BUS_SPEED_HIGH BIT_3
+#define T3_PCI_STATE_32BIT_PCI_BUS BIT_4
+
+
+/* Broadcom subsystem/subvendor IDs. */
+#define T3_SVID_BROADCOM 0x14e4
+
+#define T3_SSID_BROADCOM_BCM95700A6 0x1644
+#define T3_SSID_BROADCOM_BCM95701A5 0x0001
+#define T3_SSID_BROADCOM_BCM95700T6 0x0002 /* BCM8002 */
+#define T3_SSID_BROADCOM_BCM95700A9 0x0003 /* Agilent */
+#define T3_SSID_BROADCOM_BCM95701T1 0x0005
+#define T3_SSID_BROADCOM_BCM95701T8 0x0006
+#define T3_SSID_BROADCOM_BCM95701A7 0x0007 /* Agilent */
+#define T3_SSID_BROADCOM_BCM95701A10 0x0008
+#define T3_SSID_BROADCOM_BCM95701A12 0x8008
+#define T3_SSID_BROADCOM_BCM95703Ax1 0x0009
+#define T3_SSID_BROADCOM_BCM95703Ax2 0x8009
+
+/* 3COM subsystem/subvendor IDs. */
+#define T3_SVID_3COM 0x10b7
+
+#define T3_SSID_3COM_3C996T 0x1000
+#define T3_SSID_3COM_3C996BT 0x1006
+#define T3_SSID_3COM_3C996CT 0x1002
+#define T3_SSID_3COM_3C997T 0x1003
+#define T3_SSID_3COM_3C1000T 0x1007
+#define T3_SSID_3COM_3C940BR01 0x1008
+
+/* Fiber boards. */
+#define T3_SSID_3COM_3C996SX 0x1004
+#define T3_SSID_3COM_3C997SX 0x1005
+
+
+/* Dell subsystem/subvendor IDs. */
+
+#define T3_SVID_DELL 0x1028
+
+#define T3_SSID_DELL_VIPER 0x00d1
+#define T3_SSID_DELL_JAGUAR 0x0106
+#define T3_SSID_DELL_MERLOT 0x0109
+#define T3_SSID_DELL_SLIM_MERLOT 0x010a
+
+/* Compaq subsystem/subvendor IDs */
+
+#define T3_SVID_COMPAQ 0x0e11
+
+#define T3_SSID_COMPAQ_BANSHEE 0x007c
+#define T3_SSID_COMPAQ_BANSHEE_2 0x009a
+#define T3_SSID_COMPAQ_CHANGELING 0x007d
+#define T3_SSID_COMPAQ_NC7780 0x0085
+#define T3_SSID_COMPAQ_NC7780_2 0x0099
+
+
+/******************************************************************************/
+/* MII registers. */
+/******************************************************************************/
+
+/* Control register. */
+#define PHY_CTRL_REG 0x00
+
+#define PHY_CTRL_SPEED_MASK (BIT_6 | BIT_13)
+#define PHY_CTRL_SPEED_SELECT_10MBPS BIT_NONE
+#define PHY_CTRL_SPEED_SELECT_100MBPS BIT_13
+#define PHY_CTRL_SPEED_SELECT_1000MBPS BIT_6
+#define PHY_CTRL_COLLISION_TEST_ENABLE BIT_7
+#define PHY_CTRL_FULL_DUPLEX_MODE BIT_8
+#define PHY_CTRL_RESTART_AUTO_NEG BIT_9
+#define PHY_CTRL_ISOLATE_PHY BIT_10
+#define PHY_CTRL_LOWER_POWER_MODE BIT_11
+#define PHY_CTRL_AUTO_NEG_ENABLE BIT_12
+#define PHY_CTRL_LOOPBACK_MODE BIT_14
+#define PHY_CTRL_PHY_RESET BIT_15
+
+
+/* Status register. */
+#define PHY_STATUS_REG 0x01
+
+#define PHY_STATUS_LINK_PASS BIT_2
+#define PHY_STATUS_AUTO_NEG_COMPLETE BIT_5
+
+
+/* Phy Id registers. */
+#define PHY_ID1_REG 0x02
+#define PHY_ID1_OUI_MASK 0xffff
+
+#define PHY_ID2_REG 0x03
+#define PHY_ID2_REV_MASK 0x000f
+#define PHY_ID2_MODEL_MASK 0x03f0
+#define PHY_ID2_OUI_MASK 0xfc00
+
+
+/* Auto-negotiation advertisement register. */
+#define PHY_AN_AD_REG 0x04
+
+#define PHY_AN_AD_ASYM_PAUSE BIT_11
+#define PHY_AN_AD_PAUSE_CAPABLE BIT_10
+#define PHY_AN_AD_10BASET_HALF BIT_5
+#define PHY_AN_AD_10BASET_FULL BIT_6
+#define PHY_AN_AD_100BASETX_HALF BIT_7
+#define PHY_AN_AD_100BASETX_FULL BIT_8
+#define PHY_AN_AD_PROTOCOL_802_3_CSMA_CD 0x01
+
+
+/* Auto-negotiation Link Partner Ability register. */
+#define PHY_LINK_PARTNER_ABILITY_REG 0x05
+
+#define PHY_LINK_PARTNER_ASYM_PAUSE BIT_11
+#define PHY_LINK_PARTNER_PAUSE_CAPABLE BIT_10
+
+
+/* Auto-negotiation expansion register. */
+#define PHY_AN_EXPANSION_REG 0x06
+
+
+
+/******************************************************************************/
+/* BCM5400 and BCM5401 phy info. */
+/******************************************************************************/
+
+#define PHY_DEVICE_ID 1
+
+/* OUI: bit 31-10; Model#: bit 9-4; Rev# bit 3-0. */
+#define PHY_UNKNOWN_PHY 0x00000000
+#define PHY_BCM5400_PHY_ID 0x60008040
+#define PHY_BCM5401_PHY_ID 0x60008050
+#define PHY_BCM5411_PHY_ID 0x60008070
+#define PHY_BCM5701_PHY_ID 0x60008110
+#define PHY_BCM5703_PHY_ID 0x60008160
+#define PHY_BCM5704_PHY_ID 0x60008190
+#define PHY_BCM8002_PHY_ID 0x60010140
+
+#define PHY_BCM5401_B0_REV 0x1
+#define PHY_BCM5401_B2_REV 0x3
+#define PHY_BCM5401_C0_REV 0x6
+
+#define PHY_ID_OUI_MASK 0xfffffc00
+#define PHY_ID_MODEL_MASK 0x000003f0
+#define PHY_ID_REV_MASK 0x0000000f
+#define PHY_ID_MASK (PHY_ID_OUI_MASK | \
+ PHY_ID_MODEL_MASK)
+
+
+#define UNKNOWN_PHY_ID(x) ((((x) & PHY_ID_MASK) != PHY_BCM5400_PHY_ID) && \
+ (((x) & PHY_ID_MASK) != PHY_BCM5401_PHY_ID) && \
+ (((x) & PHY_ID_MASK) != PHY_BCM5411_PHY_ID) && \
+ (((x) & PHY_ID_MASK) != PHY_BCM5701_PHY_ID) && \
+ (((x) & PHY_ID_MASK) != PHY_BCM5703_PHY_ID) && \
+ (((x) & PHY_ID_MASK) != PHY_BCM5704_PHY_ID) && \
+ (((x) & PHY_ID_MASK) != PHY_BCM8002_PHY_ID))
+
+
+
+/* 1000Base-T control register. */
+#define BCM540X_1000BASET_CTRL_REG 0x09
+
+#define BCM540X_AN_AD_1000BASET_HALF BIT_8
+#define BCM540X_AN_AD_1000BASET_FULL BIT_9
+#define BCM540X_CONFIG_AS_MASTER BIT_11
+#define BCM540X_ENABLE_CONFIG_AS_MASTER BIT_12
+
+
+/* Extended control register. */
+#define BCM540X_EXT_CTRL_REG 0x10
+
+#define BCM540X_EXT_CTRL_LINK3_LED_MODE BIT_1
+#define BCM540X_EXT_CTRL_TBI BIT_15
+
+/* PHY extended status register. */
+#define BCM540X_EXT_STATUS_REG 0x11
+
+#define BCM540X_EXT_STATUS_LINK_PASS BIT_8
+
+
+/* DSP Coefficient Read/Write Port. */
+#define BCM540X_DSP_RW_PORT 0x15
+
+
+/* DSP Coeficient Address Register. */
+#define BCM540X_DSP_ADDRESS_REG 0x17
+
+#define BCM540X_DSP_TAP_NUMBER_MASK 0x00
+#define BCM540X_DSP_AGC_A 0x00
+#define BCM540X_DSP_AGC_B 0x01
+#define BCM540X_DSP_MSE_PAIR_STATUS 0x02
+#define BCM540X_DSP_SOFT_DECISION 0x03
+#define BCM540X_DSP_PHASE_REG 0x04
+#define BCM540X_DSP_SKEW 0x05
+#define BCM540X_DSP_POWER_SAVER_UPPER_BOUND 0x06
+#define BCM540X_DSP_POWER_SAVER_LOWER_BOUND 0x07
+#define BCM540X_DSP_LAST_ECHO 0x08
+#define BCM540X_DSP_FREQUENCY 0x09
+#define BCM540X_DSP_PLL_BANDWIDTH 0x0a
+#define BCM540X_DSP_PLL_PHASE_OFFSET 0x0b
+
+#define BCM540X_DSP_FILTER_DCOFFSET (BIT_10 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT3 (BIT_8 | BIT_9 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT2 (BIT_9 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT1 (BIT_8 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT0 BIT_11
+#define BCM540X_DSP_FILTER_NEXT3 (BIT_8 | BIT_9 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT2 (BIT_9 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT1 (BIT_8 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT0 BIT_10
+#define BCM540X_DSP_FILTER_ECHO (BIT_8 | BIT_9)
+#define BCM540X_DSP_FILTER_DFE BIT_9
+#define BCM540X_DSP_FILTER_FFE BIT_8
+
+#define BCM540X_DSP_CONTROL_ALL_FILTERS BIT_12
+
+#define BCM540X_DSP_SEL_CH_0 BIT_NONE
+#define BCM540X_DSP_SEL_CH_1 BIT_13
+#define BCM540X_DSP_SEL_CH_2 BIT_14
+#define BCM540X_DSP_SEL_CH_3 (BIT_13 | BIT_14)
+
+#define BCM540X_CONTROL_ALL_CHANNELS BIT_15
+
+
+/* Auxilliary Control Register (Shadow Register) */
+#define BCM5401_AUX_CTRL 0x18
+
+#define BCM5401_SHADOW_SEL_MASK 0x7
+#define BCM5401_SHADOW_SEL_NORMAL 0x00
+#define BCM5401_SHADOW_SEL_10BASET 0x01
+#define BCM5401_SHADOW_SEL_POWER_CONTROL 0x02
+#define BCM5401_SHADOW_SEL_IP_PHONE 0x03
+#define BCM5401_SHADOW_SEL_MISC_TEST1 0x04
+#define BCM5401_SHADOW_SEL_MISC_TEST2 0x05
+#define BCM5401_SHADOW_SEL_IP_PHONE_SEED 0x06
+
+
+/* Shadow register selector == '000' */
+#define BCM5401_SHDW_NORMAL_DIAG_MODE BIT_3
+#define BCM5401_SHDW_NORMAL_DISABLE_MBP BIT_4
+#define BCM5401_SHDW_NORMAL_DISABLE_LOW_PWR BIT_5
+#define BCM5401_SHDW_NORMAL_DISABLE_INV_PRF BIT_6
+#define BCM5401_SHDW_NORMAL_DISABLE_PRF BIT_7
+#define BCM5401_SHDW_NORMAL_RX_SLICING_NORMAL BIT_NONE
+#define BCM5401_SHDW_NORMAL_RX_SLICING_4D BIT_8
+#define BCM5401_SHDW_NORMAL_RX_SLICING_3LVL_1D BIT_9
+#define BCM5401_SHDW_NORMAL_RX_SLICING_5LVL_1D (BIT_8 | BIT_9)
+#define BCM5401_SHDW_NORMAL_TX_6DB_CODING BIT_10
+#define BCM5401_SHDW_NORMAL_ENABLE_SM_DSP_CLOCK BIT_11
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_4NS BIT_NONE
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_5NS BIT_12
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_3NS BIT_13
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_0NS (BIT_12 | BIT_13)
+#define BCM5401_SHDW_NORMAL_EXT_PACKET_LENGTH BIT_14
+#define BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK BIT_15
+
+
+/* Auxilliary status summary. */
+#define BCM540X_AUX_STATUS_REG 0x19
+
+#define BCM540X_AUX_LINK_PASS BIT_2
+#define BCM540X_AUX_SPEED_MASK (BIT_8 | BIT_9 | BIT_10)
+#define BCM540X_AUX_10BASET_HD BIT_8
+#define BCM540X_AUX_10BASET_FD BIT_9
+#define BCM540X_AUX_100BASETX_HD (BIT_8 | BIT_9)
+#define BCM540X_AUX_100BASET4 BIT_10
+#define BCM540X_AUX_100BASETX_FD (BIT_8 | BIT_10)
+#define BCM540X_AUX_100BASET_HD (BIT_9 | BIT_10)
+#define BCM540X_AUX_100BASET_FD (BIT_8 | BIT_9 | BIT_10)
+
+
+/* Interrupt status. */
+#define BCM540X_INT_STATUS_REG 0x1a
+
+#define BCM540X_INT_LINK_CHANGE BIT_1
+#define BCM540X_INT_SPEED_CHANGE BIT_2
+#define BCM540X_INT_DUPLEX_CHANGE BIT_3
+#define BCM540X_INT_AUTO_NEG_PAGE_RX BIT_10
+
+
+/* Interrupt mask register. */
+#define BCM540X_INT_MASK_REG 0x1b
+
+
+
+/******************************************************************************/
+/* Register definitions. */
+/******************************************************************************/
+
+typedef volatile LM_UINT8 T3_8BIT_REGISTER, *PT3_8BIT_REGISTER;
+typedef volatile LM_UINT16 T3_16BIT_REGISTER, *PT3_16BIT_REGISTER;
+typedef volatile LM_UINT32 T3_32BIT_REGISTER, *PT3_32BIT_REGISTER;
+
+typedef struct {
+ /* Big endian format. */
+ T3_32BIT_REGISTER High;
+ T3_32BIT_REGISTER Low;
+} T3_64BIT_REGISTER, *PT3_64BIT_REGISTER;
+
+typedef T3_64BIT_REGISTER T3_64BIT_HOST_ADDR, *PT3_64BIT_HOST_ADDR;
+
+#define T3_NUM_OF_DMA_DESC 256
+#define T3_NUM_OF_MBUF 768
+
+typedef struct
+{
+ T3_64BIT_REGISTER host_addr;
+ T3_32BIT_REGISTER nic_mbuf;
+ T3_16BIT_REGISTER len;
+ T3_16BIT_REGISTER cqid_sqid;
+ T3_32BIT_REGISTER flags;
+ T3_32BIT_REGISTER opaque1;
+ T3_32BIT_REGISTER opaque2;
+ T3_32BIT_REGISTER opaque3;
+}T3_DMA_DESC, *PT3_DMA_DESC;
+
+
+
+/******************************************************************************/
+/* Ring control block. */
+/******************************************************************************/
+
+typedef struct {
+ T3_64BIT_REGISTER HostRingAddr;
+
+ union {
+ struct {
+#ifdef BIG_ENDIAN_HOST
+ T3_16BIT_REGISTER MaxLen;
+ T3_16BIT_REGISTER Flags;
+#else /* BIG_ENDIAN_HOST */
+ T3_16BIT_REGISTER Flags;
+ T3_16BIT_REGISTER MaxLen;
+#endif
+ } s;
+
+ T3_32BIT_REGISTER MaxLen_Flags;
+ } u;
+
+ T3_32BIT_REGISTER NicRingAddr;
+} T3_RCB, *PT3_RCB;
+
+#define T3_RCB_FLAG_USE_EXT_RECV_BD BIT_0
+#define T3_RCB_FLAG_RING_DISABLED BIT_1
+
+
+
+/******************************************************************************/
+/* Status block. */
+/******************************************************************************/
+
+/*
+ * Size of status block is actually 0x50 bytes. Use 0x80 bytes for
+ * cache line alignment.
+ */
+#define T3_STATUS_BLOCK_SIZE 0x80
+
+typedef struct {
+ volatile LM_UINT32 Status;
+ #define STATUS_BLOCK_UPDATED BIT_0
+ #define STATUS_BLOCK_LINK_CHANGED_STATUS BIT_1
+ #define STATUS_BLOCK_ERROR BIT_2
+
+ volatile LM_UINT32 StatusTag;
+
+#ifdef BIG_ENDIAN_HOST
+ volatile LM_UINT16 RcvStdConIdx;
+ volatile LM_UINT16 RcvJumboConIdx;
+
+ volatile LM_UINT16 Reserved2;
+ volatile LM_UINT16 RcvMiniConIdx;
+
+ struct {
+ volatile LM_UINT16 SendConIdx; /* Send consumer index. */
+ volatile LM_UINT16 RcvProdIdx; /* Receive producer index. */
+ } Idx[16];
+#else /* BIG_ENDIAN_HOST */
+ volatile LM_UINT16 RcvJumboConIdx;
+ volatile LM_UINT16 RcvStdConIdx;
+
+ volatile LM_UINT16 RcvMiniConIdx;
+ volatile LM_UINT16 Reserved2;
+
+ struct {
+ volatile LM_UINT16 RcvProdIdx; /* Receive producer index. */
+ volatile LM_UINT16 SendConIdx; /* Send consumer index. */
+ } Idx[16];
+#endif
+} T3_STATUS_BLOCK, *PT3_STATUS_BLOCK;
+
+
+
+/******************************************************************************/
+/* Receive buffer descriptors. */
+/******************************************************************************/
+
+typedef struct {
+ T3_64BIT_HOST_ADDR HostAddr;
+
+#ifdef BIG_ENDIAN_HOST
+ volatile LM_UINT16 Index;
+ volatile LM_UINT16 Len;
+
+ volatile LM_UINT16 Type;
+ volatile LM_UINT16 Flags;
+
+ volatile LM_UINT16 IpCksum;
+ volatile LM_UINT16 TcpUdpCksum;
+
+ volatile LM_UINT16 ErrorFlag;
+ volatile LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+ volatile LM_UINT16 Len;
+ volatile LM_UINT16 Index;
+
+ volatile LM_UINT16 Flags;
+ volatile LM_UINT16 Type;
+
+ volatile LM_UINT16 TcpUdpCksum;
+ volatile LM_UINT16 IpCksum;
+
+ volatile LM_UINT16 VlanTag;
+ volatile LM_UINT16 ErrorFlag;
+#endif
+
+ volatile LM_UINT32 Reserved;
+ volatile LM_UINT32 Opaque;
+} T3_RCV_BD, *PT3_RCV_BD;
+
+
+typedef struct {
+ T3_64BIT_HOST_ADDR HostAddr[3];
+
+#ifdef BIG_ENDIAN_HOST
+ LM_UINT16 Len1;
+ LM_UINT16 Len2;
+
+ LM_UINT16 Len3;
+ LM_UINT16 Reserved1;
+#else /* BIG_ENDIAN_HOST */
+ LM_UINT16 Len2;
+ LM_UINT16 Len1;
+
+ LM_UINT16 Reserved1;
+ LM_UINT16 Len3;
+#endif
+
+ T3_RCV_BD StdRcvBd;
+} T3_EXT_RCV_BD, *PT3_EXT_RCV_BD;
+
+
+/* Error flags. */
+#define RCV_BD_ERR_BAD_CRC 0x0001
+#define RCV_BD_ERR_COLL_DETECT 0x0002
+#define RCV_BD_ERR_LINK_LOST_DURING_PKT 0x0004
+#define RCV_BD_ERR_PHY_DECODE_ERR 0x0008
+#define RCV_BD_ERR_ODD_NIBBLED_RCVD_MII 0x0010
+#define RCV_BD_ERR_MAC_ABORT 0x0020
+#define RCV_BD_ERR_LEN_LT_64 0x0040
+#define RCV_BD_ERR_TRUNC_NO_RESOURCES 0x0080
+#define RCV_BD_ERR_GIANT_FRAME_RCVD 0x0100
+
+
+/* Buffer descriptor flags. */
+#define RCV_BD_FLAG_END 0x0004
+#define RCV_BD_FLAG_JUMBO_RING 0x0020
+#define RCV_BD_FLAG_VLAN_TAG 0x0040
+#define RCV_BD_FLAG_FRAME_HAS_ERROR 0x0400
+#define RCV_BD_FLAG_MINI_RING 0x0800
+#define RCV_BD_FLAG_IP_CHKSUM_FIELD 0x1000
+#define RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD 0x2000
+#define RCV_BD_FLAG_TCP_PACKET 0x4000
+
+
+
+/******************************************************************************/
+/* Send buffer descriptor. */
+/******************************************************************************/
+
+typedef struct {
+ T3_64BIT_HOST_ADDR HostAddr;
+
+ union {
+ struct {
+#ifdef BIG_ENDIAN_HOST
+ LM_UINT16 Len;
+ LM_UINT16 Flags;
+#else /* BIG_ENDIAN_HOST */
+ LM_UINT16 Flags;
+ LM_UINT16 Len;
+#endif
+ } s1;
+
+ LM_UINT32 Len_Flags;
+ } u1;
+
+ union {
+ struct {
+#ifdef BIG_ENDIAN_HOST
+ LM_UINT16 Reserved;
+ LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+ LM_UINT16 VlanTag;
+ LM_UINT16 Reserved;
+#endif
+ } s2;
+
+ LM_UINT32 VlanTag;
+ } u2;
+} T3_SND_BD, *PT3_SND_BD;
+
+
+/* Send buffer descriptor flags. */
+#define SND_BD_FLAG_TCP_UDP_CKSUM 0x0001
+#define SND_BD_FLAG_IP_CKSUM 0x0002
+#define SND_BD_FLAG_END 0x0004
+#define SND_BD_FLAG_IP_FRAG 0x0008
+#define SND_BD_FLAG_IP_FRAG_END 0x0010
+#define SND_BD_FLAG_VLAN_TAG 0x0040
+#define SND_BD_FLAG_COAL_NOW 0x0080
+#define SND_BD_FLAG_CPU_PRE_DMA 0x0100
+#define SND_BD_FLAG_CPU_POST_DMA 0x0200
+#define SND_BD_FLAG_INSERT_SRC_ADDR 0x1000
+#define SND_BD_FLAG_CHOOSE_SRC_ADDR 0x6000
+#define SND_BD_FLAG_DONT_GEN_CRC 0x8000
+
+/* MBUFs */
+typedef struct T3_MBUF_FRAME_DESC {
+#ifdef BIG_ENDIAN_HOST
+ LM_UINT32 status_control;
+ union {
+ struct {
+ LM_UINT8 cqid;
+ LM_UINT8 reserved1;
+ LM_UINT16 length;
+ }s1;
+ LM_UINT32 word;
+ }u1;
+ union {
+ struct
+ {
+ LM_UINT16 ip_hdr_start;
+ LM_UINT16 tcp_udp_hdr_start;
+ }s2;
+
+ LM_UINT32 word;
+ }u2;
+
+ union {
+ struct {
+ LM_UINT16 data_start;
+ LM_UINT16 vlan_id;
+ }s3;
+
+ LM_UINT32 word;
+ }u3;
+
+ union {
+ struct {
+ LM_UINT16 ip_checksum;
+ LM_UINT16 tcp_udp_checksum;
+ }s4;
+
+ LM_UINT32 word;
+ }u4;
+
+ union {
+ struct {
+ LM_UINT16 pseudo_checksum;
+ LM_UINT16 checksum_status;
+ }s5;
+
+ LM_UINT32 word;
+ }u5;
+
+ union {
+ struct {
+ LM_UINT16 rule_match;
+ LM_UINT8 class;
+ LM_UINT8 rupt;
+ }s6;
+
+ LM_UINT32 word;
+ }u6;
+
+ union {
+ struct {
+ LM_UINT16 reserved2;
+ LM_UINT16 mbuf_num;
+ }s7;
+
+ LM_UINT32 word;
+ }u7;
+
+ LM_UINT32 reserved3;
+ LM_UINT32 reserved4;
+#else
+ LM_UINT32 status_control;
+ union {
+ struct {
+ LM_UINT16 length;
+ LM_UINT8 reserved1;
+ LM_UINT8 cqid;
+ }s1;
+ LM_UINT32 word;
+ }u1;
+ union {
+ struct
+ {
+ LM_UINT16 tcp_udp_hdr_start;
+ LM_UINT16 ip_hdr_start;
+ }s2;
+
+ LM_UINT32 word;
+ }u2;
+
+ union {
+ struct {
+ LM_UINT16 vlan_id;
+ LM_UINT16 data_start;
+ }s3;
+
+ LM_UINT32 word;
+ }u3;
+
+ union {
+ struct {
+ LM_UINT16 tcp_udp_checksum;
+ LM_UINT16 ip_checksum;
+ }s4;
+
+ LM_UINT32 word;
+ }u4;
+
+ union {
+ struct {
+ LM_UINT16 checksum_status;
+ LM_UINT16 pseudo_checksum;
+ }s5;
+
+ LM_UINT32 word;
+ }u5;
+
+ union {
+ struct {
+ LM_UINT8 rupt;
+ LM_UINT8 class;
+ LM_UINT16 rule_match;
+ }s6;
+
+ LM_UINT32 word;
+ }u6;
+
+ union {
+ struct {
+ LM_UINT16 mbuf_num;
+ LM_UINT16 reserved2;
+ }s7;
+
+ LM_UINT32 word;
+ }u7;
+
+ LM_UINT32 reserved3;
+ LM_UINT32 reserved4;
+#endif
+}T3_MBUF_FRAME_DESC,*PT3_MBUF_FRAME_DESC;
+
+typedef struct T3_MBUF_HDR {
+ union {
+ struct {
+ unsigned int C:1;
+ unsigned int F:1;
+ unsigned int reserved1:7;
+ unsigned int next_mbuf:16;
+ unsigned int length:7;
+ }s1;
+
+ LM_UINT32 word;
+ }u1;
+
+ LM_UINT32 next_frame_ptr;
+}T3_MBUF_HDR, *PT3_MBUF_HDR;
+
+typedef struct T3_MBUF
+{
+ T3_MBUF_HDR hdr;
+ union
+ {
+ struct {
+ T3_MBUF_FRAME_DESC frame_hdr;
+ LM_UINT32 data[20];
+ }s1;
+
+ struct {
+ LM_UINT32 data[30];
+ }s2;
+ }body;
+}T3_MBUF, *PT3_MBUF;
+
+#define T3_MBUF_BASE (T3_NIC_MBUF_POOL_ADDR >> 7)
+#define T3_MBUF_END ((T3_NIC_MBUF_POOL_ADDR + T3_NIC_MBUF_POOL_SIZE) >> 7)
+
+
+
+/******************************************************************************/
+/* Statistics block. */
+/******************************************************************************/
+
+typedef struct {
+ LM_UINT8 Reserved0[0x400-0x300];
+
+ /* Statistics maintained by Receive MAC. */
+ T3_64BIT_REGISTER ifHCInOctets;
+ T3_64BIT_REGISTER Reserved1;
+ T3_64BIT_REGISTER etherStatsFragments;
+ T3_64BIT_REGISTER ifHCInUcastPkts;
+ T3_64BIT_REGISTER ifHCInMulticastPkts;
+ T3_64BIT_REGISTER ifHCInBroadcastPkts;
+ T3_64BIT_REGISTER dot3StatsFCSErrors;
+ T3_64BIT_REGISTER dot3StatsAlignmentErrors;
+ T3_64BIT_REGISTER xonPauseFramesReceived;
+ T3_64BIT_REGISTER xoffPauseFramesReceived;
+ T3_64BIT_REGISTER macControlFramesReceived;
+ T3_64BIT_REGISTER xoffStateEntered;
+ T3_64BIT_REGISTER dot3StatsFramesTooLong;
+ T3_64BIT_REGISTER etherStatsJabbers;
+ T3_64BIT_REGISTER etherStatsUndersizePkts;
+ T3_64BIT_REGISTER inRangeLengthError;
+ T3_64BIT_REGISTER outRangeLengthError;
+ T3_64BIT_REGISTER etherStatsPkts64Octets;
+ T3_64BIT_REGISTER etherStatsPkts65Octetsto127Octets;
+ T3_64BIT_REGISTER etherStatsPkts128Octetsto255Octets;
+ T3_64BIT_REGISTER etherStatsPkts256Octetsto511Octets;
+ T3_64BIT_REGISTER etherStatsPkts512Octetsto1023Octets;
+ T3_64BIT_REGISTER etherStatsPkts1024Octetsto1522Octets;
+ T3_64BIT_REGISTER etherStatsPkts1523Octetsto2047Octets;
+ T3_64BIT_REGISTER etherStatsPkts2048Octetsto4095Octets;
+ T3_64BIT_REGISTER etherStatsPkts4096Octetsto8191Octets;
+ T3_64BIT_REGISTER etherStatsPkts8192Octetsto9022Octets;
+
+ T3_64BIT_REGISTER Unused1[37];
+
+ /* Statistics maintained by Transmit MAC. */
+ T3_64BIT_REGISTER ifHCOutOctets;
+ T3_64BIT_REGISTER Reserved2;
+ T3_64BIT_REGISTER etherStatsCollisions;
+ T3_64BIT_REGISTER outXonSent;
+ T3_64BIT_REGISTER outXoffSent;
+ T3_64BIT_REGISTER flowControlDone;
+ T3_64BIT_REGISTER dot3StatsInternalMacTransmitErrors;
+ T3_64BIT_REGISTER dot3StatsSingleCollisionFrames;
+ T3_64BIT_REGISTER dot3StatsMultipleCollisionFrames;
+ T3_64BIT_REGISTER dot3StatsDeferredTransmissions;
+ T3_64BIT_REGISTER Reserved3;
+ T3_64BIT_REGISTER dot3StatsExcessiveCollisions;
+ T3_64BIT_REGISTER dot3StatsLateCollisions;
+ T3_64BIT_REGISTER dot3Collided2Times;
+ T3_64BIT_REGISTER dot3Collided3Times;
+ T3_64BIT_REGISTER dot3Collided4Times;
+ T3_64BIT_REGISTER dot3Collided5Times;
+ T3_64BIT_REGISTER dot3Collided6Times;
+ T3_64BIT_REGISTER dot3Collided7Times;
+ T3_64BIT_REGISTER dot3Collided8Times;
+ T3_64BIT_REGISTER dot3Collided9Times;
+ T3_64BIT_REGISTER dot3Collided10Times;
+ T3_64BIT_REGISTER dot3Collided11Times;
+ T3_64BIT_REGISTER dot3Collided12Times;
+ T3_64BIT_REGISTER dot3Collided13Times;
+ T3_64BIT_REGISTER dot3Collided14Times;
+ T3_64BIT_REGISTER dot3Collided15Times;
+ T3_64BIT_REGISTER ifHCOutUcastPkts;
+ T3_64BIT_REGISTER ifHCOutMulticastPkts;
+ T3_64BIT_REGISTER ifHCOutBroadcastPkts;
+ T3_64BIT_REGISTER dot3StatsCarrierSenseErrors;
+ T3_64BIT_REGISTER ifOutDiscards;
+ T3_64BIT_REGISTER ifOutErrors;
+
+ T3_64BIT_REGISTER Unused2[31];
+
+ /* Statistics maintained by Receive List Placement. */
+ T3_64BIT_REGISTER COSIfHCInPkts[16];
+ T3_64BIT_REGISTER COSFramesDroppedDueToFilters;
+ T3_64BIT_REGISTER nicDmaWriteQueueFull;
+ T3_64BIT_REGISTER nicDmaWriteHighPriQueueFull;
+ T3_64BIT_REGISTER nicNoMoreRxBDs;
+ T3_64BIT_REGISTER ifInDiscards;
+ T3_64BIT_REGISTER ifInErrors;
+ T3_64BIT_REGISTER nicRecvThresholdHit;
+
+ T3_64BIT_REGISTER Unused3[9];
+
+ /* Statistics maintained by Send Data Initiator. */
+ T3_64BIT_REGISTER COSIfHCOutPkts[16];
+ T3_64BIT_REGISTER nicDmaReadQueueFull;
+ T3_64BIT_REGISTER nicDmaReadHighPriQueueFull;
+ T3_64BIT_REGISTER nicSendDataCompQueueFull;
+
+ /* Statistics maintained by Host Coalescing. */
+ T3_64BIT_REGISTER nicRingSetSendProdIndex;
+ T3_64BIT_REGISTER nicRingStatusUpdate;
+ T3_64BIT_REGISTER nicInterrupts;
+ T3_64BIT_REGISTER nicAvoidedInterrupts;
+ T3_64BIT_REGISTER nicSendThresholdHit;
+
+ LM_UINT8 Reserved4[0xb00-0x9c0];
+} T3_STATS_BLOCK, *PT3_STATS_BLOCK;
+
+
+
+/******************************************************************************/
+/* PCI configuration registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_16BIT_REGISTER VendorId;
+ T3_16BIT_REGISTER DeviceId;
+
+ T3_16BIT_REGISTER Command;
+ T3_16BIT_REGISTER Status;
+
+ T3_32BIT_REGISTER ClassCodeRevId;
+
+ T3_8BIT_REGISTER CacheLineSize;
+ T3_8BIT_REGISTER LatencyTimer;
+ T3_8BIT_REGISTER HeaderType;
+ T3_8BIT_REGISTER Bist;
+
+ T3_32BIT_REGISTER MemBaseAddrLow;
+ T3_32BIT_REGISTER MemBaseAddrHigh;
+
+ LM_UINT8 Unused1[20];
+
+ T3_16BIT_REGISTER SubsystemVendorId;
+ T3_16BIT_REGISTER SubsystemId;
+
+ T3_32BIT_REGISTER RomBaseAddr;
+
+ T3_8BIT_REGISTER PciXCapiblityPtr;
+ LM_UINT8 Unused2[7];
+
+ T3_8BIT_REGISTER IntLine;
+ T3_8BIT_REGISTER IntPin;
+ T3_8BIT_REGISTER MinGnt;
+ T3_8BIT_REGISTER MaxLat;
+
+ T3_8BIT_REGISTER PciXCapabilities;
+ T3_8BIT_REGISTER PmCapabilityPtr;
+ T3_16BIT_REGISTER PciXCommand;
+
+ T3_32BIT_REGISTER PciXStatus;
+
+ T3_8BIT_REGISTER PmCapabilityId;
+ T3_8BIT_REGISTER VpdCapabilityPtr;
+ T3_16BIT_REGISTER PmCapabilities;
+
+ T3_16BIT_REGISTER PmCtrlStatus;
+ #define PM_CTRL_PME_STATUS BIT_15
+ #define PM_CTRL_PME_ENABLE BIT_8
+ #define PM_CTRL_PME_POWER_STATE_D0 0
+ #define PM_CTRL_PME_POWER_STATE_D1 1
+ #define PM_CTRL_PME_POWER_STATE_D2 2
+ #define PM_CTRL_PME_POWER_STATE_D3H 3
+
+ T3_8BIT_REGISTER BridgeSupportExt;
+ T3_8BIT_REGISTER PmData;
+
+ T3_8BIT_REGISTER VpdCapabilityId;
+ T3_8BIT_REGISTER MsiCapabilityPtr;
+ T3_16BIT_REGISTER VpdAddrFlag;
+ #define VPD_FLAG_WRITE (1 << 15)
+ #define VPD_FLAG_RW_MASK (1 << 15)
+ #define VPD_FLAG_READ 0
+
+
+ T3_32BIT_REGISTER VpdData;
+
+ T3_8BIT_REGISTER MsiCapabilityId;
+ T3_8BIT_REGISTER NextCapabilityPtr;
+ T3_16BIT_REGISTER MsiCtrl;
+ #define MSI_CTRL_64BIT_CAP (1 << 7)
+ #define MSI_CTRL_MSG_ENABLE(x) (x << 4)
+ #define MSI_CTRL_MSG_CAP(x) (x << 1)
+ #define MSI_CTRL_ENABLE (1 << 0)
+
+
+ T3_32BIT_REGISTER MsiAddrLow;
+ T3_32BIT_REGISTER MsiAddrHigh;
+
+ T3_16BIT_REGISTER MsiData;
+ T3_16BIT_REGISTER Unused3;
+
+ T3_32BIT_REGISTER MiscHostCtrl;
+ #define MISC_HOST_CTRL_CLEAR_INT BIT_0
+ #define MISC_HOST_CTRL_MASK_PCI_INT BIT_1
+ #define MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP BIT_2
+ #define MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP BIT_3
+ #define MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW BIT_4
+ #define MISC_HOST_CTRL_ENABLE_CLK_REG_RW BIT_5
+ #define MISC_HOST_CTRL_ENABLE_REG_WORD_SWAP BIT_6
+ #define MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS BIT_7
+ #define MISC_HOST_CTRL_ENABLE_INT_MASK_MODE BIT_8
+ #define MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE BIT_9
+
+ T3_32BIT_REGISTER DmaReadWriteCtrl;
+ #define DMA_CTRL_WRITE_BOUNDARY_MASK (BIT_11 | BIT_12 | BIT_13)
+ #define DMA_CTRL_WRITE_BOUNDARY_DISABLE 0
+ #define DMA_CTRL_WRITE_BOUNDARY_16 BIT_11
+ #define DMA_CTRL_WRITE_BOUNDARY_32 BIT_12
+ #define DMA_CTRL_WRITE_BOUNDARY_64 (BIT_12 | BIT_11)
+ #define DMA_CTRL_WRITE_BOUNDARY_128 BIT_13
+ #define DMA_CTRL_WRITE_BOUNDARY_256 (BIT_13 | BIT_11)
+ #define DMA_CTRL_WRITE_BOUNDARY_512 (BIT_13 | BIT_12)
+ #define DMA_CTRL_WRITE_BOUNDARY_1024 (BIT_13 | BIT_12 | BIT_11)
+ #define DMA_CTRL_WRITE_ONE_DMA_AT_ONCE BIT_14
+
+
+ T3_32BIT_REGISTER PciState;
+ #define T3_PCI_STATE_FORCE_PCI_RESET BIT_0
+ #define T3_PCI_STATE_INTERRUPT_NOT_ACTIVE BIT_1
+ #define T3_PCI_STATE_NOT_PCI_X_BUS BIT_2
+ #define T3_PCI_STATE_HIGH_BUS_SPEED BIT_3
+ #define T3_PCI_STATE_32BIT_PCI_BUS BIT_4
+ #define T3_PCI_STATE_PCI_ROM_ENABLE BIT_5
+ #define T3_PCI_STATE_PCI_ROM_RETRY_ENABLE BIT_6
+ #define T3_PCI_STATE_FLAT_VIEW BIT_8
+ #define T3_PCI_STATE_RETRY_SAME_DMA BIT_13
+
+ T3_32BIT_REGISTER ClockCtrl;
+ #define T3_PCI_CLKCTRL_TXCPU_CLK_DISABLE BIT_11
+ #define T3_PCI_CLKCTRL_RXCPU_CLK_DISABLE BIT_10
+ #define T3_PCI_CLKCTRL_CORE_CLK_DISABLE BIT_9
+
+ T3_32BIT_REGISTER RegBaseAddr;
+
+ T3_32BIT_REGISTER MemWindowBaseAddr;
+
+#ifdef NIC_CPU_VIEW
+ /* These registers are ONLY visible to NIC CPU */
+ T3_32BIT_REGISTER PowerConsumed;
+ T3_32BIT_REGISTER PowerDissipated;
+#else /* NIC_CPU_VIEW */
+ T3_32BIT_REGISTER RegData;
+ T3_32BIT_REGISTER MemWindowData;
+#endif /* !NIC_CPU_VIEW */
+
+ T3_32BIT_REGISTER ModeCtrl;
+
+ T3_32BIT_REGISTER MiscCfg;
+
+ T3_32BIT_REGISTER MiscLocalCtrl;
+
+ T3_32BIT_REGISTER Unused4;
+
+ /* NOTE: Big/Little-endian clarification needed. Are these register */
+ /* in big or little endian formate. */
+ T3_64BIT_REGISTER StdRingProdIdx;
+ T3_64BIT_REGISTER RcvRetRingConIdx;
+ T3_64BIT_REGISTER SndProdIdx;
+
+ LM_UINT8 Unused5[80];
+} T3_PCI_CONFIGURATION, *PT3_PCI_CONFIGURATION;
+
+#define PCIX_CMD_MAX_SPLIT_MASK 0x0070
+#define PCIX_CMD_MAX_SPLIT_SHL 4
+#define PCIX_CMD_MAX_BURST_MASK 0x000c
+#define PCIX_CMD_MAX_BURST_SHL 2
+#define PCIX_CMD_MAX_BURST_CPIOB 2
+
+/******************************************************************************/
+/* Mac control registers. */
+/******************************************************************************/
+
+typedef struct {
+ /* MAC mode control. */
+ T3_32BIT_REGISTER Mode;
+ #define MAC_MODE_GLOBAL_RESET BIT_0
+ #define MAC_MODE_HALF_DUPLEX BIT_1
+ #define MAC_MODE_PORT_MODE_MASK (BIT_2 | BIT_3)
+ #define MAC_MODE_PORT_MODE_TBI (BIT_2 | BIT_3)
+ #define MAC_MODE_PORT_MODE_GMII BIT_3
+ #define MAC_MODE_PORT_MODE_MII BIT_2
+ #define MAC_MODE_PORT_MODE_NONE BIT_NONE
+ #define MAC_MODE_PORT_INTERNAL_LOOPBACK BIT_4
+ #define MAC_MODE_TAGGED_MAC_CONTROL BIT_7
+ #define MAC_MODE_TX_BURSTING BIT_8
+ #define MAC_MODE_MAX_DEFER BIT_9
+ #define MAC_MODE_LINK_POLARITY BIT_10
+ #define MAC_MODE_ENABLE_RX_STATISTICS BIT_11
+ #define MAC_MODE_CLEAR_RX_STATISTICS BIT_12
+ #define MAC_MODE_FLUSH_RX_STATISTICS BIT_13
+ #define MAC_MODE_ENABLE_TX_STATISTICS BIT_14
+ #define MAC_MODE_CLEAR_TX_STATISTICS BIT_15
+ #define MAC_MODE_FLUSH_TX_STATISTICS BIT_16
+ #define MAC_MODE_SEND_CONFIGS BIT_17
+ #define MAC_MODE_DETECT_MAGIC_PACKET_ENABLE BIT_18
+ #define MAC_MODE_ACPI_POWER_ON_ENABLE BIT_19
+ #define MAC_MODE_ENABLE_MIP BIT_20
+ #define MAC_MODE_ENABLE_TDE BIT_21
+ #define MAC_MODE_ENABLE_RDE BIT_22
+ #define MAC_MODE_ENABLE_FHDE BIT_23
+
+ /* MAC status */
+ T3_32BIT_REGISTER Status;
+ #define MAC_STATUS_PCS_SYNCED BIT_0
+ #define MAC_STATUS_SIGNAL_DETECTED BIT_1
+ #define MAC_STATUS_RECEIVING_CFG BIT_2
+ #define MAC_STATUS_CFG_CHANGED BIT_3
+ #define MAC_STATUS_SYNC_CHANGED BIT_4
+ #define MAC_STATUS_PORT_DECODE_ERROR BIT_10
+ #define MAC_STATUS_LINK_STATE_CHANGED BIT_12
+ #define MAC_STATUS_MI_COMPLETION BIT_22
+ #define MAC_STATUS_MI_INTERRUPT BIT_23
+ #define MAC_STATUS_AP_ERROR BIT_24
+ #define MAC_STATUS_ODI_ERROR BIT_25
+ #define MAC_STATUS_RX_STATS_OVERRUN BIT_26
+ #define MAC_STATUS_TX_STATS_OVERRUN BIT_27
+
+ /* Event Enable */
+ T3_32BIT_REGISTER MacEvent;
+ #define MAC_EVENT_ENABLE_PORT_DECODE_ERR BIT_10
+ #define MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN BIT_12
+ #define MAC_EVENT_ENABLE_MI_COMPLETION BIT_22
+ #define MAC_EVENT_ENABLE_MI_INTERRUPT BIT_23
+ #define MAC_EVENT_ENABLE_AP_ERROR BIT_24
+ #define MAC_EVENT_ENABLE_ODI_ERROR BIT_25
+ #define MAC_EVENT_ENABLE_RX_STATS_OVERRUN BIT_26
+ #define MAC_EVENT_ENABLE_TX_STATS_OVERRUN BIT_27
+
+ /* Led control. */
+ T3_32BIT_REGISTER LedCtrl;
+ #define LED_CTRL_OVERRIDE_LINK_LED BIT_0
+ #define LED_CTRL_1000MBPS_LED_ON BIT_1
+ #define LED_CTRL_100MBPS_LED_ON BIT_2
+ #define LED_CTRL_10MBPS_LED_ON BIT_3
+ #define LED_CTRL_OVERRIDE_TRAFFIC_LED BIT_4
+ #define LED_CTRL_BLINK_TRAFFIC_LED BIT_5
+ #define LED_CTRL_TRAFFIC_LED BIT_6
+ #define LED_CTRL_1000MBPS_LED_STATUS BIT_7
+ #define LED_CTRL_100MBPS_LED_STATUS BIT_8
+ #define LED_CTRL_10MBPS_LED_STATUS BIT_9
+ #define LED_CTRL_TRAFFIC_LED_STATUS BIT_10
+ #define LED_CTRL_MAC_MODE BIT_NONE
+ #define LED_CTRL_PHY_MODE_1 BIT_11
+ #define LED_CTRL_PHY_MODE_2 BIT_12
+ #define LED_CTRL_BLINK_RATE_MASK 0x7ff80000
+ #define LED_CTRL_OVERRIDE_BLINK_PERIOD BIT_19
+ #define LED_CTRL_OVERRIDE_BLINK_RATE BIT_31
+
+ /* MAC addresses. */
+ struct {
+ T3_32BIT_REGISTER High; /* Upper 2 bytes. */
+ T3_32BIT_REGISTER Low; /* Lower 4 bytes. */
+ } MacAddr[4];
+
+ /* ACPI Mbuf pointer. */
+ T3_32BIT_REGISTER AcpiMbufPtr;
+
+ /* ACPI Length and Offset. */
+ T3_32BIT_REGISTER AcpiLengthOffset;
+ #define ACPI_LENGTH_MASK 0xffff
+ #define ACPI_OFFSET_MASK 0x0fff0000
+ #define ACPI_LENGTH(x) x
+ #define ACPI_OFFSET(x) ((x) << 16)
+
+ /* Transmit random backoff. */
+ T3_32BIT_REGISTER TxBackoffSeed;
+ #define MAC_TX_BACKOFF_SEED_MASK 0x3ff
+
+ /* Receive MTU */
+ T3_32BIT_REGISTER MtuSize;
+ #define MAC_RX_MTU_MASK 0xffff
+
+ /* Gigabit PCS Test. */
+ T3_32BIT_REGISTER PcsTest;
+ #define MAC_PCS_TEST_DATA_PATTERN_MASK 0x0fffff
+ #define MAC_PCS_TEST_ENABLE BIT_20
+
+ /* Transmit Gigabit Auto-Negotiation. */
+ T3_32BIT_REGISTER TxAutoNeg;
+ #define MAC_AN_TX_AN_DATA_MASK 0xffff
+
+ /* Receive Gigabit Auto-Negotiation. */
+ T3_32BIT_REGISTER RxAutoNeg;
+ #define MAC_AN_RX_AN_DATA_MASK 0xffff
+
+ /* MI Communication. */
+ T3_32BIT_REGISTER MiCom;
+ #define MI_COM_CMD_MASK (BIT_26 | BIT_27)
+ #define MI_COM_CMD_WRITE BIT_26
+ #define MI_COM_CMD_READ BIT_27
+ #define MI_COM_READ_FAILED BIT_28
+ #define MI_COM_START BIT_29
+ #define MI_COM_BUSY BIT_29
+
+ #define MI_COM_PHY_ADDR_MASK 0x1f
+ #define MI_COM_FIRST_PHY_ADDR_BIT 21
+
+ #define MI_COM_PHY_REG_ADDR_MASK 0x1f
+ #define MI_COM_FIRST_PHY_REG_ADDR_BIT 16
+
+ #define MI_COM_PHY_DATA_MASK 0xffff
+
+ /* MI Status. */
+ T3_32BIT_REGISTER MiStatus;
+ #define MI_STATUS_ENABLE_LINK_STATUS_ATTN BIT_0
+
+ /* MI Mode. */
+ T3_32BIT_REGISTER MiMode;
+ #define MI_MODE_CLOCK_SPEED_10MHZ BIT_0
+ #define MI_MODE_USE_SHORT_PREAMBLE BIT_1
+ #define MI_MODE_AUTO_POLLING_ENABLE BIT_4
+ #define MI_MODE_CORE_CLOCK_SPEED_62MHZ BIT_15
+
+ /* Auto-polling status. */
+ T3_32BIT_REGISTER AutoPollStatus;
+ #define AUTO_POLL_ERROR BIT_0
+
+ /* Transmit MAC mode. */
+ T3_32BIT_REGISTER TxMode;
+ #define TX_MODE_RESET BIT_0
+ #define TX_MODE_ENABLE BIT_1
+ #define TX_MODE_ENABLE_FLOW_CONTROL BIT_4
+ #define TX_MODE_ENABLE_BIG_BACKOFF BIT_5
+ #define TX_MODE_ENABLE_LONG_PAUSE BIT_6
+
+ /* Transmit MAC status. */
+ T3_32BIT_REGISTER TxStatus;
+ #define TX_STATUS_RX_CURRENTLY_XOFFED BIT_0
+ #define TX_STATUS_SENT_XOFF BIT_1
+ #define TX_STATUS_SENT_XON BIT_2
+ #define TX_STATUS_LINK_UP BIT_3
+ #define TX_STATUS_ODI_UNDERRUN BIT_4
+ #define TX_STATUS_ODI_OVERRUN BIT_5
+
+ /* Transmit MAC length. */
+ T3_32BIT_REGISTER TxLengths;
+ #define TX_LEN_SLOT_TIME_MASK 0xff
+ #define TX_LEN_IPG_MASK 0x0f00
+ #define TX_LEN_IPG_CRS_MASK (BIT_12 | BIT_13)
+
+ /* Receive MAC mode. */
+ T3_32BIT_REGISTER RxMode;
+ #define RX_MODE_RESET BIT_0
+ #define RX_MODE_ENABLE BIT_1
+ #define RX_MODE_ENABLE_FLOW_CONTROL BIT_2
+ #define RX_MODE_KEEP_MAC_CONTROL BIT_3
+ #define RX_MODE_KEEP_PAUSE BIT_4
+ #define RX_MODE_ACCEPT_OVERSIZED BIT_5
+ #define RX_MODE_ACCEPT_RUNTS BIT_6
+ #define RX_MODE_LENGTH_CHECK BIT_7
+ #define RX_MODE_PROMISCUOUS_MODE BIT_8
+ #define RX_MODE_NO_CRC_CHECK BIT_9
+ #define RX_MODE_KEEP_VLAN_TAG BIT_10
+
+ /* Receive MAC status. */
+ T3_32BIT_REGISTER RxStatus;
+ #define RX_STATUS_REMOTE_TRANSMITTER_XOFFED BIT_0
+ #define RX_STATUS_XOFF_RECEIVED BIT_1
+ #define RX_STATUS_XON_RECEIVED BIT_2
+
+ /* Hash registers. */
+ T3_32BIT_REGISTER HashReg[4];
+
+ /* Receive placement rules registers. */
+ struct {
+ T3_32BIT_REGISTER Rule;
+ T3_32BIT_REGISTER Value;
+ } RcvRules[16];
+
+ #define RCV_DISABLE_RULE_MASK 0x7fffffff
+
+ #define RCV_RULE1_REJECT_BROADCAST_IDX 0x00
+ #define REJECT_BROADCAST_RULE1_RULE 0xc2000000
+ #define REJECT_BROADCAST_RULE1_VALUE 0xffffffff
+
+ #define RCV_RULE2_REJECT_BROADCAST_IDX 0x01
+ #define REJECT_BROADCAST_RULE2_RULE 0x86000004
+ #define REJECT_BROADCAST_RULE2_VALUE 0xffffffff
+
+#if INCLUDE_5701_AX_FIX
+ #define RCV_LAST_RULE_IDX 0x04
+#else
+ #define RCV_LAST_RULE_IDX 0x02
+#endif
+
+ T3_32BIT_REGISTER RcvRuleCfg;
+ #define RX_RULE_DEFAULT_CLASS (1 << 3)
+
+ LM_UINT8 Reserved1[140];
+
+ T3_32BIT_REGISTER SerdesCfg;
+ T3_32BIT_REGISTER SerdesStatus;
+
+ LM_UINT8 Reserved2[104];
+
+ volatile LM_UINT8 TxMacState[16];
+ volatile LM_UINT8 RxMacState[20];
+
+ LM_UINT8 Reserved3[476];
+
+ T3_32BIT_REGISTER RxStats[26];
+
+ LM_UINT8 Reserved4[24];
+
+ T3_32BIT_REGISTER TxStats[28];
+
+ LM_UINT8 Reserved5[784];
+} T3_MAC_CONTROL, *PT3_MAC_CONTROL;
+
+
+
+/******************************************************************************/
+/* Send data initiator control registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define T3_SND_DATA_IN_MODE_RESET BIT_0
+ #define T3_SND_DATA_IN_MODE_ENABLE BIT_1
+ #define T3_SND_DATA_IN_MODE_STATS_OFLW_ATTN_ENABLE BIT_2
+
+ T3_32BIT_REGISTER Status;
+ #define T3_SND_DATA_IN_STATUS_STATS_OFLW_ATTN BIT_2
+
+ T3_32BIT_REGISTER StatsCtrl;
+ #define T3_SND_DATA_IN_STATS_CTRL_ENABLE BIT_0
+ #define T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE BIT_1
+ #define T3_SND_DATA_IN_STATS_CTRL_CLEAR BIT_2
+ #define T3_SND_DATA_IN_STATS_CTRL_FLUSH BIT_3
+ #define T3_SND_DATA_IN_STATS_CTRL_FORCE_ZERO BIT_4
+
+ T3_32BIT_REGISTER StatsEnableMask;
+ T3_32BIT_REGISTER StatsIncMask;
+
+ LM_UINT8 Reserved[108];
+
+ T3_32BIT_REGISTER ClassOfServCnt[16];
+ T3_32BIT_REGISTER DmaReadQFullCnt;
+ T3_32BIT_REGISTER DmaPriorityReadQFullCnt;
+ T3_32BIT_REGISTER SdcQFullCnt;
+
+ T3_32BIT_REGISTER NicRingSetSendProdIdxCnt;
+ T3_32BIT_REGISTER StatusUpdatedCnt;
+ T3_32BIT_REGISTER InterruptsCnt;
+ T3_32BIT_REGISTER AvoidInterruptsCnt;
+ T3_32BIT_REGISTER SendThresholdHitCnt;
+
+ /* Unused space. */
+ LM_UINT8 Unused[800];
+} T3_SEND_DATA_INITIATOR, *PT3_SEND_DATA_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Send data completion control registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define SND_DATA_COMP_MODE_RESET BIT_0
+ #define SND_DATA_COMP_MODE_ENABLE BIT_1
+
+ /* Unused space. */
+ LM_UINT8 Unused[1020];
+} T3_SEND_DATA_COMPLETION, *PT3_SEND_DATA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Send BD Ring Selector Control Registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define SND_BD_SEL_MODE_RESET BIT_0
+ #define SND_BD_SEL_MODE_ENABLE BIT_1
+ #define SND_BD_SEL_MODE_ATTN_ENABLE BIT_2
+
+ T3_32BIT_REGISTER Status;
+ #define SND_BD_SEL_STATUS_ERROR_ATTN BIT_2
+
+ T3_32BIT_REGISTER HwDiag;
+
+ /* Unused space. */
+ LM_UINT8 Unused1[52];
+
+ /* Send BD Ring Selector Local NIC Send BD Consumer Index. */
+ T3_32BIT_REGISTER NicSendBdSelConIdx[16];
+
+ /* Unused space. */
+ LM_UINT8 Unused2[896];
+} T3_SEND_BD_SELECTOR, *PT3_SEND_BD_SELECTOR;
+
+
+
+/******************************************************************************/
+/* Send BD initiator control registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define SND_BD_IN_MODE_RESET BIT_0
+ #define SND_BD_IN_MODE_ENABLE BIT_1
+ #define SND_BD_IN_MODE_ATTN_ENABLE BIT_2
+
+ T3_32BIT_REGISTER Status;
+ #define SND_BD_IN_STATUS_ERROR_ATTN BIT_2
+
+ /* Send BD initiator local NIC send BD producer index. */
+ T3_32BIT_REGISTER NicSendBdInProdIdx[16];
+
+ /* Unused space. */
+ LM_UINT8 Unused2[952];
+} T3_SEND_BD_INITIATOR, *PT3_SEND_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Send BD Completion Control. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define SND_BD_COMP_MODE_RESET BIT_0
+ #define SND_BD_COMP_MODE_ENABLE BIT_1
+ #define SND_BD_COMP_MODE_ATTN_ENABLE BIT_2
+
+ /* Unused space. */
+ LM_UINT8 Unused2[1020];
+} T3_SEND_BD_COMPLETION, *PT3_SEND_BD_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive list placement control registers. */
+/******************************************************************************/
+
+typedef struct {
+ /* Mode. */
+ T3_32BIT_REGISTER Mode;
+ #define RCV_LIST_PLMT_MODE_RESET BIT_0
+ #define RCV_LIST_PLMT_MODE_ENABLE BIT_1
+ #define RCV_LIST_PLMT_MODE_CLASS0_ATTN_ENABLE BIT_2
+ #define RCV_LIST_PLMT_MODE_MAPPING_OOR_ATTN_ENABLE BIT_3
+ #define RCV_LIST_PLMT_MODE_STATS_OFLOW_ATTN_ENABLE BIT_4
+
+ /* Status. */
+ T3_32BIT_REGISTER Status;
+ #define RCV_LIST_PLMT_STATUS_CLASS0_ATTN BIT_2
+ #define RCV_LIST_PLMT_STATUS_MAPPING_ATTN BIT_3
+ #define RCV_LIST_PLMT_STATUS_STATS_OFLOW_ATTN BIT_4
+
+ /* Receive selector list lock register. */
+ T3_32BIT_REGISTER Lock;
+ #define RCV_LIST_SEL_LOCK_REQUEST_MASK 0xffff
+ #define RCV_LIST_SEL_LOCK_GRANT_MASK 0xffff0000
+
+ /* Selector non-empty bits. */
+ T3_32BIT_REGISTER NonEmptyBits;
+ #define RCV_LIST_SEL_NON_EMPTY_MASK 0xffff
+
+ /* Receive list placement configuration register. */
+ T3_32BIT_REGISTER Config;
+
+ /* Receive List Placement statistics Control. */
+ T3_32BIT_REGISTER StatsCtrl;
+#define RCV_LIST_STATS_ENABLE BIT_0
+#define RCV_LIST_STATS_FAST_UPDATE BIT_1
+
+ /* Receive List Placement statistics Enable Mask. */
+ T3_32BIT_REGISTER StatsEnableMask;
+
+ /* Receive List Placement statistics Increment Mask. */
+ T3_32BIT_REGISTER StatsIncMask;
+
+ /* Unused space. */
+ LM_UINT8 Unused1[224];
+
+ struct {
+ T3_32BIT_REGISTER Head;
+ T3_32BIT_REGISTER Tail;
+ T3_32BIT_REGISTER Count;
+
+ /* Unused space. */
+ LM_UINT8 Unused[4];
+ } RcvSelectorList[16];
+
+ /* Local statistics counter. */
+ T3_32BIT_REGISTER ClassOfServCnt[16];
+
+ T3_32BIT_REGISTER DropDueToFilterCnt;
+ T3_32BIT_REGISTER DmaWriteQFullCnt;
+ T3_32BIT_REGISTER DmaHighPriorityWriteQFullCnt;
+ T3_32BIT_REGISTER NoMoreReceiveBdCnt;
+ T3_32BIT_REGISTER IfInDiscardsCnt;
+ T3_32BIT_REGISTER IfInErrorsCnt;
+ T3_32BIT_REGISTER RcvThresholdHitCnt;
+
+ /* Another unused space. */
+ LM_UINT8 Unused2[420];
+} T3_RCV_LIST_PLACEMENT, *PT3_RCV_LIST_PLACEMENT;
+
+
+
+/******************************************************************************/
+/* Receive Data and Receive BD Initiator Control. */
+/******************************************************************************/
+
+typedef struct {
+ /* Mode. */
+ T3_32BIT_REGISTER Mode;
+ #define RCV_DATA_BD_IN_MODE_RESET BIT_0
+ #define RCV_DATA_BD_IN_MODE_ENABLE BIT_1
+ #define RCV_DATA_BD_IN_MODE_JUMBO_BD_NEEDED BIT_2
+ #define RCV_DATA_BD_IN_MODE_FRAME_TOO_BIG BIT_3
+ #define RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE BIT_4
+
+ /* Status. */
+ T3_32BIT_REGISTER Status;
+ #define RCV_DATA_BD_IN_STATUS_JUMBO_BD_NEEDED BIT_2
+ #define RCV_DATA_BD_IN_STATUS_FRAME_TOO_BIG BIT_3
+ #define RCV_DATA_BD_IN_STATUS_INVALID_RING_SIZE BIT_4
+
+ /* Split frame minium size. */
+ T3_32BIT_REGISTER SplitFrameMinSize;
+
+ /* Unused space. */
+ LM_UINT8 Unused1[0x2440-0x240c];
+
+ /* Receive RCBs. */
+ T3_RCB JumboRcvRcb;
+ T3_RCB StdRcvRcb;
+ T3_RCB MiniRcvRcb;
+
+ /* Receive Data and Receive BD Ring Initiator Local NIC Receive */
+ /* BD Consumber Index. */
+ T3_32BIT_REGISTER NicJumboConIdx;
+ T3_32BIT_REGISTER NicStdConIdx;
+ T3_32BIT_REGISTER NicMiniConIdx;
+
+ /* Unused space. */
+ LM_UINT8 Unused2[4];
+
+ /* Receive Data and Receive BD Initiator Local Receive Return ProdIdx. */
+ T3_32BIT_REGISTER RcvDataBdProdIdx[16];
+
+ /* Receive Data and Receive BD Initiator Hardware Diagnostic. */
+ T3_32BIT_REGISTER HwDiag;
+
+ /* Unused space. */
+ LM_UINT8 Unused3[828];
+} T3_RCV_DATA_BD_INITIATOR, *PT3_RCV_DATA_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Receive Data Completion Control Registes. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define RCV_DATA_COMP_MODE_RESET BIT_0
+ #define RCV_DATA_COMP_MODE_ENABLE BIT_1
+ #define RCV_DATA_COMP_MODE_ATTN_ENABLE BIT_2
+
+ /* Unused spaced. */
+ LM_UINT8 Unused[1020];
+} T3_RCV_DATA_COMPLETION, *PT3_RCV_DATA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive BD Initiator Control. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define RCV_BD_IN_MODE_RESET BIT_0
+ #define RCV_BD_IN_MODE_ENABLE BIT_1
+ #define RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE BIT_2
+
+ T3_32BIT_REGISTER Status;
+ #define RCV_BD_IN_STATUS_BD_IN_DIABLED_RCB_ATTN BIT_2
+
+ T3_32BIT_REGISTER NicJumboRcvProdIdx;
+ T3_32BIT_REGISTER NicStdRcvProdIdx;
+ T3_32BIT_REGISTER NicMiniRcvProdIdx;
+
+ T3_32BIT_REGISTER MiniRcvThreshold;
+ T3_32BIT_REGISTER StdRcvThreshold;
+ T3_32BIT_REGISTER JumboRcvThreshold;
+
+ /* Unused space. */
+ LM_UINT8 Unused[992];
+} T3_RCV_BD_INITIATOR, *PT3_RCV_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Receive BD Completion Control Registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define RCV_BD_COMP_MODE_RESET BIT_0
+ #define RCV_BD_COMP_MODE_ENABLE BIT_1
+ #define RCV_BD_COMP_MODE_ATTN_ENABLE BIT_2
+
+ T3_32BIT_REGISTER Status;
+ #define RCV_BD_COMP_STATUS_ERROR_ATTN BIT_2
+
+ T3_32BIT_REGISTER NicJumboRcvBdProdIdx;
+ T3_32BIT_REGISTER NicStdRcvBdProdIdx;
+ T3_32BIT_REGISTER NicMiniRcvBdProdIdx;
+
+ /* Unused space. */
+ LM_UINT8 Unused[1004];
+} T3_RCV_BD_COMPLETION, *PT3_RCV_BD_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive list selector control register. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define RCV_LIST_SEL_MODE_RESET BIT_0
+ #define RCV_LIST_SEL_MODE_ENABLE BIT_1
+ #define RCV_LIST_SEL_MODE_ATTN_ENABLE BIT_2
+
+ T3_32BIT_REGISTER Status;
+ #define RCV_LIST_SEL_STATUS_ERROR_ATTN BIT_2
+
+ /* Unused space. */
+ LM_UINT8 Unused[1016];
+} T3_RCV_LIST_SELECTOR, *PT3_RCV_LIST_SELECTOR;
+
+
+
+/******************************************************************************/
+/* Mbuf cluster free registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+#define MBUF_CLUSTER_FREE_MODE_RESET BIT_0
+#define MBUF_CLUSTER_FREE_MODE_ENABLE BIT_1
+
+ T3_32BIT_REGISTER Status;
+
+ /* Unused space. */
+ LM_UINT8 Unused[1016];
+} T3_MBUF_CLUSTER_FREE, *PT3_MBUF_CLUSTER_FREE;
+
+
+
+/******************************************************************************/
+/* Host coalescing control registers. */
+/******************************************************************************/
+
+typedef struct {
+ /* Mode. */
+ T3_32BIT_REGISTER Mode;
+ #define HOST_COALESCE_RESET BIT_0
+ #define HOST_COALESCE_ENABLE BIT_1
+ #define HOST_COALESCE_ATTN BIT_2
+ #define HOST_COALESCE_NOW BIT_3
+ #define HOST_COALESCE_FULL_STATUS_MODE BIT_NONE
+ #define HOST_COALESCE_64_BYTE_STATUS_MODE BIT_7
+ #define HOST_COALESCE_32_BYTE_STATUS_MODE BIT_8
+ #define HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT BIT_9
+ #define HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT BIT_10
+ #define HOST_COALESCE_NO_INT_ON_COALESCE_NOW_MODE BIT_11
+ #define HOST_COALESCE_NO_INT_ON_FORCE_DMAD_MODE BIT_12
+
+ /* Status. */
+ T3_32BIT_REGISTER Status;
+ #define HOST_COALESCE_ERROR_ATTN BIT_2
+
+ /* Receive coalescing ticks. */
+ T3_32BIT_REGISTER RxCoalescingTicks;
+
+ /* Send coalescing ticks. */
+ T3_32BIT_REGISTER TxCoalescingTicks;
+
+ /* Receive max coalesced frames. */
+ T3_32BIT_REGISTER RxMaxCoalescedFrames;
+
+ /* Send max coalesced frames. */
+ T3_32BIT_REGISTER TxMaxCoalescedFrames;
+
+ /* Receive coalescing ticks during interrupt. */
+ T3_32BIT_REGISTER RxCoalescedTickDuringInt;
+
+ /* Send coalescing ticks during interrupt. */
+ T3_32BIT_REGISTER TxCoalescedTickDuringInt;
+
+ /* Receive max coalesced frames during interrupt. */
+ T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt;
+
+ /* Send max coalesced frames during interrupt. */
+ T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt;
+
+ /* Statistics tick. */
+ T3_32BIT_REGISTER StatsCoalescingTicks;
+
+ /* Unused space. */
+ LM_UINT8 Unused2[4];
+
+ /* Statistics host address. */
+ T3_64BIT_REGISTER StatsBlkHostAddr;
+
+ /* Status block host address.*/
+ T3_64BIT_REGISTER StatusBlkHostAddr;
+
+ /* Statistics NIC address. */
+ T3_32BIT_REGISTER StatsBlkNicAddr;
+
+ /* Statust block NIC address. */
+ T3_32BIT_REGISTER StatusBlkNicAddr;
+
+ /* Flow attention registers. */
+ T3_32BIT_REGISTER FlowAttn;
+
+ /* Unused space. */
+ LM_UINT8 Unused3[4];
+
+ T3_32BIT_REGISTER NicJumboRcvBdConIdx;
+ T3_32BIT_REGISTER NicStdRcvBdConIdx;
+ T3_32BIT_REGISTER NicMiniRcvBdConIdx;
+
+ /* Unused space. */
+ LM_UINT8 Unused4[36];
+
+ T3_32BIT_REGISTER NicRetProdIdx[16];
+ T3_32BIT_REGISTER NicSndBdConIdx[16];
+
+ /* Unused space. */
+ LM_UINT8 Unused5[768];
+} T3_HOST_COALESCING, *PT3_HOST_COALESCING;
+
+
+
+/******************************************************************************/
+/* Memory arbiter registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+#define T3_MEM_ARBITER_MODE_RESET BIT_0
+#define T3_MEM_ARBITER_MODE_ENABLE BIT_1
+
+ T3_32BIT_REGISTER Status;
+
+ T3_32BIT_REGISTER ArbTrapAddrLow;
+ T3_32BIT_REGISTER ArbTrapAddrHigh;
+
+ /* Unused space. */
+ LM_UINT8 Unused[1008];
+} T3_MEM_ARBITER, *PT3_MEM_ARBITER;
+
+
+
+/******************************************************************************/
+/* Buffer manager control register. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define BUFMGR_MODE_RESET BIT_0
+ #define BUFMGR_MODE_ENABLE BIT_1
+ #define BUFMGR_MODE_ATTN_ENABLE BIT_2
+ #define BUFMGR_MODE_BM_TEST BIT_3
+ #define BUFMGR_MODE_MBUF_LOW_ATTN_ENABLE BIT_4
+
+ T3_32BIT_REGISTER Status;
+ #define BUFMGR_STATUS_ERROR BIT_2
+ #define BUFMGR_STATUS_MBUF_LOW BIT_4
+
+ T3_32BIT_REGISTER MbufPoolAddr;
+ T3_32BIT_REGISTER MbufPoolSize;
+ T3_32BIT_REGISTER MbufReadDmaLowWaterMark;
+ T3_32BIT_REGISTER MbufMacRxLowWaterMark;
+ T3_32BIT_REGISTER MbufHighWaterMark;
+
+ T3_32BIT_REGISTER RxCpuMbufAllocReq;
+ #define BUFMGR_MBUF_ALLOC_BIT BIT_31
+ T3_32BIT_REGISTER RxCpuMbufAllocResp;
+ T3_32BIT_REGISTER TxCpuMbufAllocReq;
+ T3_32BIT_REGISTER TxCpuMbufAllocResp;
+
+ T3_32BIT_REGISTER DmaDescPoolAddr;
+ T3_32BIT_REGISTER DmaDescPoolSize;
+ T3_32BIT_REGISTER DmaLowWaterMark;
+ T3_32BIT_REGISTER DmaHighWaterMark;
+
+ T3_32BIT_REGISTER RxCpuDmaAllocReq;
+ T3_32BIT_REGISTER RxCpuDmaAllocResp;
+ T3_32BIT_REGISTER TxCpuDmaAllocReq;
+ T3_32BIT_REGISTER TxCpuDmaAllocResp;
+
+ T3_32BIT_REGISTER Hwdiag[3];
+
+ /* Unused space. */
+ LM_UINT8 Unused[936];
+} T3_BUFFER_MANAGER, *PT3_BUFFER_MANAGER;
+
+
+
+/******************************************************************************/
+/* Read DMA control registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define DMA_READ_MODE_RESET BIT_0
+ #define DMA_READ_MODE_ENABLE BIT_1
+ #define DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE BIT_2
+ #define DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE BIT_3
+ #define DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE BIT_4
+ #define DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE BIT_5
+ #define DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE BIT_6
+ #define DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE BIT_7
+ #define DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE BIT_8
+ #define DMA_READ_MODE_LONG_READ_ATTN_ENABLE BIT_9
+ #define DMA_READ_MODE_SPLIT_ENABLE BIT_11
+ #define DMA_READ_MODE_SPLIT_RESET BIT_12
+
+ T3_32BIT_REGISTER Status;
+ #define DMA_READ_STATUS_TARGET_ABORT_ATTN BIT_2
+ #define DMA_READ_STATUS_MASTER_ABORT_ATTN BIT_3
+ #define DMA_READ_STATUS_PARITY_ERROR_ATTN BIT_4
+ #define DMA_READ_STATUS_ADDR_OVERFLOW_ATTN BIT_5
+ #define DMA_READ_STATUS_FIFO_OVERRUN_ATTN BIT_6
+ #define DMA_READ_STATUS_FIFO_UNDERRUN_ATTN BIT_7
+ #define DMA_READ_STATUS_FIFO_OVERREAD_ATTN BIT_8
+ #define DMA_READ_STATUS_LONG_READ_ATTN BIT_9
+
+ /* Unused space. */
+ LM_UINT8 Unused[1016];
+} T3_DMA_READ, *PT3_DMA_READ;
+
+typedef union T3_CPU
+{
+ struct
+ {
+ T3_32BIT_REGISTER mode;
+ #define CPU_MODE_HALT BIT_10
+ #define CPU_MODE_RESET BIT_0
+ T3_32BIT_REGISTER state;
+ T3_32BIT_REGISTER EventMask;
+ T3_32BIT_REGISTER reserved1[4];
+ T3_32BIT_REGISTER PC;
+ T3_32BIT_REGISTER Instruction;
+ T3_32BIT_REGISTER SpadUnderflow;
+ T3_32BIT_REGISTER WatchdogClear;
+ T3_32BIT_REGISTER WatchdogVector;
+ T3_32BIT_REGISTER WatchdogSavedPC;
+ T3_32BIT_REGISTER HardwareBp;
+ T3_32BIT_REGISTER reserved2[3];
+ T3_32BIT_REGISTER WatchdogSavedState;
+ T3_32BIT_REGISTER LastBrchAddr;
+ T3_32BIT_REGISTER SpadUnderflowSet;
+ T3_32BIT_REGISTER reserved3[(0x200-0x50)/4];
+ T3_32BIT_REGISTER Regs[32];
+ T3_32BIT_REGISTER reserved4[(0x400-0x280)/4];
+ }reg;
+}T3_CPU, *PT3_CPU;
+
+/******************************************************************************/
+/* Write DMA control registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define DMA_WRITE_MODE_RESET BIT_0
+ #define DMA_WRITE_MODE_ENABLE BIT_1
+ #define DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE BIT_2
+ #define DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE BIT_3
+ #define DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE BIT_4
+ #define DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE BIT_5
+ #define DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE BIT_6
+ #define DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE BIT_7
+ #define DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE BIT_8
+ #define DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE BIT_9
+
+ T3_32BIT_REGISTER Status;
+ #define DMA_WRITE_STATUS_TARGET_ABORT_ATTN BIT_2
+ #define DMA_WRITE_STATUS_MASTER_ABORT_ATTN BIT_3
+ #define DMA_WRITE_STATUS_PARITY_ERROR_ATTN BIT_4
+ #define DMA_WRITE_STATUS_ADDR_OVERFLOW_ATTN BIT_5
+ #define DMA_WRITE_STATUS_FIFO_OVERRUN_ATTN BIT_6
+ #define DMA_WRITE_STATUS_FIFO_UNDERRUN_ATTN BIT_7
+ #define DMA_WRITE_STATUS_FIFO_OVERREAD_ATTN BIT_8
+ #define DMA_WRITE_STATUS_LONG_READ_ATTN BIT_9
+
+ /* Unused space. */
+ LM_UINT8 Unused[1016];
+} T3_DMA_WRITE, *PT3_DMA_WRITE;
+
+
+
+/******************************************************************************/
+/* Mailbox registers. */
+/******************************************************************************/
+
+typedef struct {
+ /* Interrupt mailbox registers. */
+ T3_64BIT_REGISTER Interrupt[4];
+
+ /* General mailbox registers. */
+ T3_64BIT_REGISTER General[8];
+
+ /* Reload statistics mailbox. */
+ T3_64BIT_REGISTER ReloadStat;
+
+ /* Receive BD ring producer index registers. */
+ T3_64BIT_REGISTER RcvStdProdIdx;
+ T3_64BIT_REGISTER RcvJumboProdIdx;
+ T3_64BIT_REGISTER RcvMiniProdIdx;
+
+ /* Receive return ring consumer index registers. */
+ T3_64BIT_REGISTER RcvRetConIdx[16];
+
+ /* Send BD ring host producer index registers. */
+ T3_64BIT_REGISTER SendHostProdIdx[16];
+
+ /* Send BD ring nic producer index registers. */
+ T3_64BIT_REGISTER SendNicProdIdx[16];
+}T3_MAILBOX, *PT3_MAILBOX;
+
+typedef struct {
+ T3_MAILBOX Mailbox;
+
+ /* Priority mailbox registers. */
+ T3_32BIT_REGISTER HighPriorityEventVector;
+ T3_32BIT_REGISTER HighPriorityEventMask;
+ T3_32BIT_REGISTER LowPriorityEventVector;
+ T3_32BIT_REGISTER LowPriorityEventMask;
+
+ /* Unused space. */
+ LM_UINT8 Unused[496];
+} T3_GRC_MAILBOX, *PT3_GRC_MAILBOX;
+
+
+/******************************************************************************/
+/* Flow through queues. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Reset;
+
+ LM_UINT8 Unused[12];
+
+ T3_32BIT_REGISTER DmaNormalReadFtqCtrl;
+ T3_32BIT_REGISTER DmaNormalReadFtqFullCnt;
+ T3_32BIT_REGISTER DmaNormalReadFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER DmaNormalReadFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER DmaHighReadFtqCtrl;
+ T3_32BIT_REGISTER DmaHighReadFtqFullCnt;
+ T3_32BIT_REGISTER DmaHighReadFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER DmaHighReadFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER DmaCompDiscardFtqCtrl;
+ T3_32BIT_REGISTER DmaCompDiscardFtqFullCnt;
+ T3_32BIT_REGISTER DmaCompDiscardFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER DmaCompDiscardFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER SendBdCompFtqCtrl;
+ T3_32BIT_REGISTER SendBdCompFtqFullCnt;
+ T3_32BIT_REGISTER SendBdCompFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER SendBdCompFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER SendDataInitiatorFtqCtrl;
+ T3_32BIT_REGISTER SendDataInitiatorFtqFullCnt;
+ T3_32BIT_REGISTER SendDataInitiatorFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER SendDataInitiatorFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER DmaNormalWriteFtqCtrl;
+ T3_32BIT_REGISTER DmaNormalWriteFtqFullCnt;
+ T3_32BIT_REGISTER DmaNormalWriteFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER DmaNormalWriteFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER DmaHighWriteFtqCtrl;
+ T3_32BIT_REGISTER DmaHighWriteFtqFullCnt;
+ T3_32BIT_REGISTER DmaHighWriteFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER DmaHighWriteFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER SwType1FtqCtrl;
+ T3_32BIT_REGISTER SwType1FtqFullCnt;
+ T3_32BIT_REGISTER SwType1FtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER SwType1FtqFifoWritePeek;
+
+ T3_32BIT_REGISTER SendDataCompFtqCtrl;
+ T3_32BIT_REGISTER SendDataCompFtqFullCnt;
+ T3_32BIT_REGISTER SendDataCompFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER SendDataCompFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER HostCoalesceFtqCtrl;
+ T3_32BIT_REGISTER HostCoalesceFtqFullCnt;
+ T3_32BIT_REGISTER HostCoalesceFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER HostCoalesceFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER MacTxFtqCtrl;
+ T3_32BIT_REGISTER MacTxFtqFullCnt;
+ T3_32BIT_REGISTER MacTxFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER MacTxFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER MbufClustFreeFtqCtrl;
+ T3_32BIT_REGISTER MbufClustFreeFtqFullCnt;
+ T3_32BIT_REGISTER MbufClustFreeFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER MbufClustFreeFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER RcvBdCompFtqCtrl;
+ T3_32BIT_REGISTER RcvBdCompFtqFullCnt;
+ T3_32BIT_REGISTER RcvBdCompFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER RcvBdCompFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER RcvListPlmtFtqCtrl;
+ T3_32BIT_REGISTER RcvListPlmtFtqFullCnt;
+ T3_32BIT_REGISTER RcvListPlmtFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER RcvListPlmtFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER RcvDataBdInitiatorFtqCtrl;
+ T3_32BIT_REGISTER RcvDataBdInitiatorFtqFullCnt;
+ T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER RcvDataCompFtqCtrl;
+ T3_32BIT_REGISTER RcvDataCompFtqFullCnt;
+ T3_32BIT_REGISTER RcvDataCompFtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER RcvDataCompFtqFifoWritePeek;
+
+ T3_32BIT_REGISTER SwType2FtqCtrl;
+ T3_32BIT_REGISTER SwType2FtqFullCnt;
+ T3_32BIT_REGISTER SwType2FtqFifoEnqueueDequeue;
+ T3_32BIT_REGISTER SwType2FtqFifoWritePeek;
+
+ /* Unused space. */
+ LM_UINT8 Unused2[736];
+} T3_FTQ, *PT3_FTQ;
+
+
+
+/******************************************************************************/
+/* Message signaled interrupt registers. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+#define MSI_MODE_RESET BIT_0
+#define MSI_MODE_ENABLE BIT_1
+ T3_32BIT_REGISTER Status;
+
+ T3_32BIT_REGISTER MsiFifoAccess;
+
+ /* Unused space. */
+ LM_UINT8 Unused[1012];
+} T3_MSG_SIGNALED_INT, *PT3_MSG_SIGNALED_INT;
+
+
+
+/******************************************************************************/
+/* DMA Completion registes. */
+/******************************************************************************/
+
+typedef struct {
+ T3_32BIT_REGISTER Mode;
+ #define DMA_COMP_MODE_RESET BIT_0
+ #define DMA_COMP_MODE_ENABLE BIT_1
+
+ /* Unused space. */
+ LM_UINT8 Unused[1020];
+} T3_DMA_COMPLETION, *PT3_DMA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* GRC registers. */
+/******************************************************************************/
+
+typedef struct {
+ /* Mode control register. */
+ T3_32BIT_REGISTER Mode;
+ #define GRC_MODE_UPDATE_ON_COALESCING BIT_0
+ #define GRC_MODE_BYTE_SWAP_NON_FRAME_DATA BIT_1
+ #define GRC_MODE_WORD_SWAP_NON_FRAME_DATA BIT_2
+ #define GRC_MODE_BYTE_SWAP_DATA BIT_4
+ #define GRC_MODE_WORD_SWAP_DATA BIT_5
+ #define GRC_MODE_SPLIT_HEADER_MODE BIT_8
+ #define GRC_MODE_NO_FRAME_CRACKING BIT_9
+ #define GRC_MODE_INCLUDE_CRC BIT_10
+ #define GRC_MODE_ALLOW_BAD_FRAMES BIT_11
+ #define GRC_MODE_NO_INTERRUPT_ON_SENDS BIT_13
+ #define GRC_MODE_NO_INTERRUPT_ON_RECEIVE BIT_14
+ #define GRC_MODE_FORCE_32BIT_PCI_BUS_MODE BIT_15
+ #define GRC_MODE_HOST_STACK_UP BIT_16
+ #define GRC_MODE_HOST_SEND_BDS BIT_17
+ #define GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM BIT_20
+ #define GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM BIT_23
+ #define GRC_MODE_INT_ON_TX_CPU_ATTN BIT_24
+ #define GRC_MODE_INT_ON_RX_CPU_ATTN BIT_25
+ #define GRC_MODE_INT_ON_MAC_ATTN BIT_26
+ #define GRC_MODE_INT_ON_DMA_ATTN BIT_27
+ #define GRC_MODE_INT_ON_FLOW_ATTN BIT_28
+ #define GRC_MODE_4X_NIC_BASED_SEND_RINGS BIT_29
+ #define GRC_MODE_MULTICAST_FRAME_ENABLE BIT_30
+
+ /* Misc configuration register. */
+ T3_32BIT_REGISTER MiscCfg;
+ #define GRC_MISC_CFG_CORE_CLOCK_RESET BIT_0
+ #define GRC_MISC_PRESCALAR_TIMER_MASK 0xfe
+ #define GRC_MISC_BD_ID_MASK 0x0001e000
+ #define GRC_MISC_BD_ID_5700 0x0001e000
+ #define GRC_MISC_BD_ID_5701 0x00000000
+ #define GRC_MISC_BD_ID_5703 0x00000000
+ #define GRC_MISC_BD_ID_5703S 0x00002000
+ #define GRC_MISC_BD_ID_5702FE 0x00004000
+ #define GRC_MISC_BD_ID_5704 0x00000000
+ #define GRC_MISC_BD_ID_5704CIOBE 0x00004000
+
+ /* Miscellaneous local control register. */
+ T3_32BIT_REGISTER LocalCtrl;
+ #define GRC_MISC_LOCAL_CTRL_INT_ACTIVE BIT_0
+ #define GRC_MISC_LOCAL_CTRL_CLEAR_INT BIT_1
+ #define GRC_MISC_LOCAL_CTRL_SET_INT BIT_2
+ #define GRC_MISC_LOCAL_CTRL_INT_ON_ATTN BIT_3
+ #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT0 BIT_8
+ #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT1 BIT_9
+ #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT2 BIT_10
+ #define GRC_MISC_LOCAL_CTRL_GPIO_OE0 BIT_11
+ #define GRC_MISC_LOCAL_CTRL_GPIO_OE1 BIT_12
+ #define GRC_MISC_LOCAL_CTRL_GPIO_OE2 BIT_13
+ #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 BIT_14
+ #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 BIT_15
+ #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2 BIT_16
+ #define GRC_MISC_LOCAL_CTRL_ENABLE_EXT_MEMORY BIT_17
+ #define GRC_MISC_LOCAL_CTRL_BANK_SELECT BIT_21
+ #define GRC_MISC_LOCAL_CTRL_SSRAM_TYPE BIT_22
+
+ #define GRC_MISC_MEMSIZE_256K 0
+ #define GRC_MISC_MEMSIZE_512K (1 << 18)
+ #define GRC_MISC_MEMSIZE_1024K (2 << 18)
+ #define GRC_MISC_MEMSIZE_2048K (3 << 18)
+ #define GRC_MISC_MEMSIZE_4096K (4 << 18)
+ #define GRC_MISC_MEMSIZE_8192K (5 << 18)
+ #define GRC_MISC_MEMSIZE_16M (6 << 18)
+ #define GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM BIT_24
+
+
+ T3_32BIT_REGISTER Timer;
+
+ T3_32BIT_REGISTER RxCpuEvent;
+ T3_32BIT_REGISTER RxTimerRef;
+ T3_32BIT_REGISTER RxCpuSemaphore;
+ T3_32BIT_REGISTER RemoteRxCpuAttn;
+
+ T3_32BIT_REGISTER TxCpuEvent;
+ T3_32BIT_REGISTER TxTimerRef;
+ T3_32BIT_REGISTER TxCpuSemaphore;
+ T3_32BIT_REGISTER RemoteTxCpuAttn;
+
+ T3_64BIT_REGISTER MemoryPowerUp;
+
+ T3_32BIT_REGISTER EepromAddr;
+ #define SEEPROM_ADDR_WRITE 0
+ #define SEEPROM_ADDR_READ (1 << 31)
+ #define SEEPROM_ADDR_RW_MASK 0x80000000
+ #define SEEPROM_ADDR_COMPLETE (1 << 30)
+ #define SEEPROM_ADDR_FSM_RESET (1 << 29)
+ #define SEEPROM_ADDR_DEV_ID(x) (x << 26)
+ #define SEEPROM_ADDR_DEV_ID_MASK 0x1c000000
+ #define SEEPROM_ADDR_START (1 << 25)
+ #define SEEPROM_ADDR_CLK_PERD(x) (x << 16)
+ #define SEEPROM_ADDR_ADDRESS(x) (x & 0xfffc)
+ #define SEEPROM_ADDR_ADDRESS_MASK 0x0000ffff
+
+ #define SEEPROM_CLOCK_PERIOD 60
+ #define SEEPROM_CHIP_SIZE (64 * 1024)
+
+ T3_32BIT_REGISTER EepromData;
+ T3_32BIT_REGISTER EepromCtrl;
+
+ T3_32BIT_REGISTER MdiCtrl;
+ T3_32BIT_REGISTER SepromDelay;
+
+ /* Unused space. */
+ LM_UINT8 Unused[948];
+} T3_GRC, *PT3_GRC;
+
+
+/******************************************************************************/
+/* NVRAM control registers. */
+/******************************************************************************/
+
+typedef struct
+{
+ T3_32BIT_REGISTER Cmd;
+ #define NVRAM_CMD_RESET BIT_0
+ #define NVRAM_CMD_DONE BIT_3
+ #define NVRAM_CMD_DO_IT BIT_4
+ #define NVRAM_CMD_WR BIT_5
+ #define NVRAM_CMD_RD BIT_NONE
+ #define NVRAM_CMD_ERASE BIT_6
+ #define NVRAM_CMD_FIRST BIT_7
+ #define NVRAM_CMD_LAST BIT_8
+
+ T3_32BIT_REGISTER Status;
+ T3_32BIT_REGISTER WriteData;
+
+ T3_32BIT_REGISTER Addr;
+ #define NVRAM_ADDRESS_MASK 0xffffff
+
+ T3_32BIT_REGISTER ReadData;
+
+ /* Flash config 1 register. */
+ T3_32BIT_REGISTER Config1;
+ #define FLASH_INTERFACE_ENABLE BIT_0
+ #define FLASH_SSRAM_BUFFERRED_MODE BIT_1
+ #define FLASH_PASS_THRU_MODE BIT_2
+ #define FLASH_BIT_BANG_MODE BIT_3
+ #define FLASH_COMPAT_BYPASS BIT_31
+
+ /* Buffered flash (Atmel: AT45DB011B) specific information */
+ #define BUFFERED_FLASH_PAGE_POS 9
+ #define BUFFERED_FLASH_BYTE_ADDR_MASK ((1<<BUFFERED_FLASH_PAGE_POS) - 1)
+ #define BUFFERED_FLASH_PAGE_SIZE 264
+ #define BUFFERED_FLASH_PHY_PAGE_SIZE 512
+
+ T3_32BIT_REGISTER Config2;
+ T3_32BIT_REGISTER Config3;
+ T3_32BIT_REGISTER SwArb;
+ #define SW_ARB_REQ_SET0 BIT_0
+ #define SW_ARB_REQ_SET1 BIT_1
+ #define SW_ARB_REQ_SET2 BIT_2
+ #define SW_ARB_REQ_SET3 BIT_3
+ #define SW_ARB_REQ_CLR0 BIT_4
+ #define SW_ARB_REQ_CLR1 BIT_5
+ #define SW_ARB_REQ_CLR2 BIT_6
+ #define SW_ARB_REQ_CLR3 BIT_7
+ #define SW_ARB_GNT0 BIT_8
+ #define SW_ARB_GNT1 BIT_9
+ #define SW_ARB_GNT2 BIT_10
+ #define SW_ARB_GNT3 BIT_11
+ #define SW_ARB_REQ0 BIT_12
+ #define SW_ARB_REQ1 BIT_13
+ #define SW_ARB_REQ2 BIT_14
+ #define SW_ARB_REQ3 BIT_15
+
+ /* Unused space. */
+ LM_UINT8 Unused[988];
+} T3_NVRAM, *PT3_NVRAM;
+
+
+/******************************************************************************/
+/* NIC's internal memory. */
+/******************************************************************************/
+
+typedef struct {
+ /* Page zero for the internal CPUs. */
+ LM_UINT8 PageZero[0x100]; /* 0x0000 */
+
+ /* Send RCBs. */
+ T3_RCB SendRcb[16]; /* 0x0100 */
+
+ /* Receive Return RCBs. */
+ T3_RCB RcvRetRcb[16]; /* 0x0200 */
+
+ /* Statistics block. */
+ T3_STATS_BLOCK StatsBlk; /* 0x0300 */
+
+ /* Status block. */
+ T3_STATUS_BLOCK StatusBlk; /* 0x0b00 */
+
+ /* Reserved for software. */
+ LM_UINT8 Reserved[1200]; /* 0x0b50 */
+
+ /* Unmapped region. */
+ LM_UINT8 Unmapped[4096]; /* 0x1000 */
+
+ /* DMA descriptors. */
+ LM_UINT8 DmaDesc[8192]; /* 0x2000 */
+
+ /* Buffer descriptors. */
+ LM_UINT8 BufferDesc[16384]; /* 0x4000 */
+} T3_FIRST_32K_SRAM, *PT3_FIRST_32K_SRAM;
+
+
+
+/******************************************************************************/
+/* Memory layout. */
+/******************************************************************************/
+
+typedef struct {
+ /* PCI configuration registers. */
+ T3_PCI_CONFIGURATION PciCfg;
+
+ /* Unused. */
+ LM_UINT8 Unused1[0x100]; /* 0x0100 */
+
+ /* Mailbox . */
+ T3_MAILBOX Mailbox; /* 0x0200 */
+
+ /* MAC control registers. */
+ T3_MAC_CONTROL MacCtrl; /* 0x0400 */
+
+ /* Send data initiator control registers. */
+ T3_SEND_DATA_INITIATOR SndDataIn; /* 0x0c00 */
+
+ /* Send data completion Control registers. */
+ T3_SEND_DATA_COMPLETION SndDataComp; /* 0x1000 */
+
+ /* Send BD ring selector. */
+ T3_SEND_BD_SELECTOR SndBdSel; /* 0x1400 */
+
+ /* Send BD initiator control registers. */
+ T3_SEND_BD_INITIATOR SndBdIn; /* 0x1800 */
+
+ /* Send BD completion control registers. */
+ T3_SEND_BD_COMPLETION SndBdComp; /* 0x1c00 */
+
+ /* Receive list placement control registers. */
+ T3_RCV_LIST_PLACEMENT RcvListPlmt; /* 0x2000 */
+
+ /* Receive Data and Receive BD Initiator Control. */
+ T3_RCV_DATA_BD_INITIATOR RcvDataBdIn; /* 0x2400 */
+
+ /* Receive Data Completion Control */
+ T3_RCV_DATA_COMPLETION RcvDataComp; /* 0x2800 */
+
+ /* Receive BD Initiator Control Registers. */
+ T3_RCV_BD_INITIATOR RcvBdIn; /* 0x2c00 */
+
+ /* Receive BD Completion Control Registers. */
+ T3_RCV_BD_COMPLETION RcvBdComp; /* 0x3000 */
+
+ /* Receive list selector control registers. */
+ T3_RCV_LIST_SELECTOR RcvListSel; /* 0x3400 */
+
+ /* Mbuf cluster free registers. */
+ T3_MBUF_CLUSTER_FREE MbufClusterFree; /* 0x3800 */
+
+ /* Host coalescing control registers. */
+ T3_HOST_COALESCING HostCoalesce; /* 0x3c00 */
+
+ /* Memory arbiter control registers. */
+ T3_MEM_ARBITER MemArbiter; /* 0x4000 */
+
+ /* Buffer manger control registers. */
+ T3_BUFFER_MANAGER BufMgr; /* 0x4400 */
+
+ /* Read DMA control registers. */
+ T3_DMA_READ DmaRead; /* 0x4800 */
+
+ /* Write DMA control registers. */
+ T3_DMA_WRITE DmaWrite; /* 0x4c00 */
+
+ T3_CPU rxCpu; /* 0x5000 */
+ T3_CPU txCpu; /* 0x5400 */
+
+ /* Mailboxes. */
+ T3_GRC_MAILBOX GrcMailbox; /* 0x5800 */
+
+ /* Flow Through queues. */
+ T3_FTQ Ftq; /* 0x5c00 */
+
+ /* Message signaled interrupt registes. */
+ T3_MSG_SIGNALED_INT Msi; /* 0x6000 */
+
+ /* DMA completion registers. */
+ T3_DMA_COMPLETION DmaComp; /* 0x6400 */
+
+ /* GRC registers. */
+ T3_GRC Grc; /* 0x6800 */
+
+ /* Unused space. */
+ LM_UINT8 Unused2[1024]; /* 0x6c00 */
+
+ /* NVRAM registers. */
+ T3_NVRAM Nvram; /* 0x7000 */
+
+ /* Unused space. */
+ LM_UINT8 Unused3[3072]; /* 0x7400 */
+
+ /* The 32k memory window into the NIC's */
+ /* internal memory. The memory window is */
+ /* controlled by the Memory Window Base */
+ /* Address register. This register is located */
+ /* in the PCI configuration space. */
+ union { /* 0x8000 */
+ T3_FIRST_32K_SRAM First32k;
+
+ /* Use the memory window base address register to determine the */
+ /* MBUF segment. */
+ LM_UINT32 Mbuf[32768/4];
+ LM_UINT32 MemBlock32K[32768/4];
+ } uIntMem;
+} T3_STD_MEM_MAP, *PT3_STD_MEM_MAP;
+
+
+/******************************************************************************/
+/* Adapter info. */
+/******************************************************************************/
+
+typedef struct
+{
+ LM_UINT16 Svid;
+ LM_UINT16 Ssid;
+ LM_UINT32 PhyId;
+ LM_UINT32 Serdes; /* 0 = copper PHY, 1 = Serdes */
+} LM_ADAPTER_INFO, *PLM_ADAPTER_INFO;
+
+
+/******************************************************************************/
+/* Packet queues. */
+/******************************************************************************/
+
+DECLARE_QUEUE_TYPE(LM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT);
+DECLARE_QUEUE_TYPE(LM_TX_PACKET_Q, MAX_TX_PACKET_DESC_COUNT);
+
+
+
+/******************************************************************************/
+/* Tx counters. */
+/******************************************************************************/
+
+typedef struct {
+ LM_COUNTER TxPacketGoodCnt;
+ LM_COUNTER TxBytesGoodCnt;
+ LM_COUNTER TxPacketAbortedCnt;
+ LM_COUNTER NoSendBdLeftCnt;
+ LM_COUNTER NoMapRegisterLeftCnt;
+ LM_COUNTER TooManyFragmentsCnt;
+ LM_COUNTER NoTxPacketDescCnt;
+} LM_TX_COUNTERS, *PLM_TX_COUNTERS;
+
+
+
+/******************************************************************************/
+/* Rx counters. */
+/******************************************************************************/
+
+typedef struct {
+ LM_COUNTER RxPacketGoodCnt;
+ LM_COUNTER RxBytesGoodCnt;
+ LM_COUNTER RxPacketErrCnt;
+ LM_COUNTER RxErrCrcCnt;
+ LM_COUNTER RxErrCollCnt;
+ LM_COUNTER RxErrLinkLostCnt;
+ LM_COUNTER RxErrPhyDecodeCnt;
+ LM_COUNTER RxErrOddNibbleCnt;
+ LM_COUNTER RxErrMacAbortCnt;
+ LM_COUNTER RxErrShortPacketCnt;
+ LM_COUNTER RxErrNoResourceCnt;
+ LM_COUNTER RxErrLargePacketCnt;
+} LM_RX_COUNTERS, *PLM_RX_COUNTERS;
+
+
+
+/******************************************************************************/
+/* Receive producer rings. */
+/******************************************************************************/
+
+typedef enum {
+ T3_UNKNOWN_RCV_PROD_RING = 0,
+ T3_STD_RCV_PROD_RING = 1,
+ T3_MINI_RCV_PROD_RING = 2,
+ T3_JUMBO_RCV_PROD_RING = 3
+} T3_RCV_PROD_RING, *PT3_RCV_PROD_RING;
+
+
+
+/******************************************************************************/
+/* Packet descriptor. */
+/******************************************************************************/
+
+#define LM_PACKET_SIGNATURE_TX 0x6861766b
+#define LM_PACKET_SIGNATURE_RX 0x6b766168
+
+typedef struct _LM_PACKET {
+ /* Set in LM. */
+ LM_STATUS PacketStatus;
+
+ /* Set in LM for Rx, in UM for Tx. */
+ LM_UINT32 PacketSize;
+
+ LM_UINT16 Flags;
+
+ LM_UINT16 VlanTag;
+
+ union {
+ /* Send info. */
+ struct {
+ /* Set up by UM. */
+ LM_UINT32 FragCount;
+
+ } Tx;
+
+ /* Receive info. */
+ struct {
+ /* This descriptor belongs to either Std, Mini, or Jumbo ring. */
+ T3_RCV_PROD_RING RcvProdRing;
+
+ /* Receive buffer size */
+ LM_UINT32 RxBufferSize;
+
+ /* Checksum information. */
+ LM_UINT16 IpChecksum;
+ LM_UINT16 TcpUdpChecksum;
+
+ } Rx;
+ } u;
+} LM_PACKET;
+
+
+
+/******************************************************************************/
+/* Tigon3 device block. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK {
+ int index; /* Device ID */
+ /* Memory view. */
+ PT3_STD_MEM_MAP pMemView;
+
+ /* Base address of the block of memory in which the LM_PACKET descriptors */
+ /* are allocated from. */
+ PLM_VOID pPacketDescBase;
+
+ LM_UINT32 MiscHostCtrl;
+ LM_UINT32 GrcLocalCtrl;
+ LM_UINT32 DmaReadWriteCtrl;
+ LM_UINT32 PciState;
+
+ /* Rx info */
+ LM_UINT32 RxStdDescCnt;
+ LM_UINT32 RxStdQueuedCnt;
+ LM_UINT32 RxStdProdIdx;
+
+ PT3_RCV_BD pRxStdBdVirt;
+ LM_PHYSICAL_ADDRESS RxStdBdPhy;
+
+ LM_UINT32 RxPacketDescCnt;
+ LM_RX_PACKET_Q RxPacketFreeQ;
+ LM_RX_PACKET_Q RxPacketReceivedQ;
+
+ /* Receive info. */
+ PT3_RCV_BD pRcvRetBdVirt;
+ LM_PHYSICAL_ADDRESS RcvRetBdPhy;
+ LM_UINT32 RcvRetConIdx;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+ LM_UINT32 RxJumboDescCnt;
+ LM_UINT32 RxJumboBufferSize;
+ LM_UINT32 RxJumboQueuedCnt;
+
+ LM_UINT32 RxJumboProdIdx;
+
+ PT3_RCV_BD pRxJumboBdVirt;
+ LM_PHYSICAL_ADDRESS RxJumboBdPhy;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+ /* These values are used by the upper module to inform the protocol */
+ /* of the maximum transmit/receive packet size. */
+ LM_UINT32 TxMtu; /* Does not include CRC. */
+ LM_UINT32 RxMtu; /* Does not include CRC. */
+
+ /* We need to shadow the EMAC, Rx, Tx mode registers. With B0 silicon, */
+ /* we may have problems reading any MAC registers in 10mb mode. */
+ LM_UINT32 MacMode;
+ LM_UINT32 RxMode;
+ LM_UINT32 TxMode;
+
+ /* MiMode register. */
+ LM_UINT32 MiMode;
+
+ /* Host coalesce mode register. */
+ LM_UINT32 CoalesceMode;
+
+ /* Send info. */
+ LM_UINT32 TxPacketDescCnt;
+
+ /* Tx info. */
+ LM_TX_PACKET_Q TxPacketFreeQ;
+ LM_TX_PACKET_Q TxPacketActiveQ;
+ LM_TX_PACKET_Q TxPacketXmittedQ;
+
+ /* Pointers to SendBd. */
+ PT3_SND_BD pSendBdVirt;
+ LM_PHYSICAL_ADDRESS SendBdPhy; /* Only valid for Host based Send BD. */
+
+ /* Send producer and consumer indices. */
+ LM_UINT32 SendProdIdx;
+ LM_UINT32 SendConIdx;
+
+ /* Number of BD left. */
+ atomic_t SendBdLeft;
+
+ T3_SND_BD ShadowSendBd[T3_SEND_RCB_ENTRY_COUNT];
+
+ /* Counters. */
+ LM_RX_COUNTERS RxCounters;
+ LM_TX_COUNTERS TxCounters;
+
+ /* Host coalescing parameters. */
+ LM_UINT32 RxCoalescingTicks;
+ LM_UINT32 TxCoalescingTicks;
+ LM_UINT32 RxMaxCoalescedFrames;
+ LM_UINT32 TxMaxCoalescedFrames;
+ LM_UINT32 StatsCoalescingTicks;
+ LM_UINT32 RxCoalescingTicksDuringInt;
+ LM_UINT32 TxCoalescingTicksDuringInt;
+ LM_UINT32 RxMaxCoalescedFramesDuringInt;
+ LM_UINT32 TxMaxCoalescedFramesDuringInt;
+
+ /* DMA water marks. */
+ LM_UINT32 DmaMbufLowMark;
+ LM_UINT32 RxMacMbufLowMark;
+ LM_UINT32 MbufHighMark;
+
+ /* Status block. */
+ PT3_STATUS_BLOCK pStatusBlkVirt;
+ LM_PHYSICAL_ADDRESS StatusBlkPhy;
+
+ /* Statistics block. */
+ PT3_STATS_BLOCK pStatsBlkVirt;
+ LM_PHYSICAL_ADDRESS StatsBlkPhy;
+
+ /* Current receive mask. */
+ LM_UINT32 ReceiveMask;
+
+ /* Task offload capabilities. */
+ LM_TASK_OFFLOAD TaskOffloadCap;
+
+ /* Task offload selected. */
+ LM_TASK_OFFLOAD TaskToOffload;
+
+ /* Wake up capability. */
+ LM_WAKE_UP_MODE WakeUpModeCap;
+
+ /* Wake up capability. */
+ LM_WAKE_UP_MODE WakeUpMode;
+
+ /* Flow control. */
+ LM_FLOW_CONTROL FlowControlCap;
+ LM_FLOW_CONTROL FlowControl;
+
+ /* Enable or disable PCI MWI. */
+ LM_UINT32 EnableMWI;
+
+ /* Enable 5701 tagged status mode. */
+ LM_UINT32 UseTaggedStatus;
+
+ /* NIC will not compute the pseudo header checksum. The driver or OS */
+ /* must seed the checksum field with the pseudo checksum. */
+ LM_UINT32 NoTxPseudoHdrChksum;
+
+ /* The receive checksum in the BD does not include the pseudo checksum. */
+ /* The OS or the driver must calculate the pseudo checksum and add it to */
+ /* the checksum in the BD. */
+ LM_UINT32 NoRxPseudoHdrChksum;
+
+ /* Current node address. */
+ LM_UINT8 NodeAddress[8];
+
+ /* The adapter's node address. */
+ LM_UINT8 PermanentNodeAddress[8];
+
+ /* Adapter info. */
+ LM_UINT16 BusNum;
+ LM_UINT8 DevNum;
+ LM_UINT8 FunctNum;
+ LM_UINT16 PciVendorId;
+ LM_UINT16 PciDeviceId;
+ LM_UINT32 BondId;
+ LM_UINT8 Irq;
+ LM_UINT8 IntPin;
+ LM_UINT8 CacheLineSize;
+ LM_UINT8 PciRevId;
+#if PCIX_TARGET_WORKAROUND
+ LM_UINT32 EnablePciXFix;
+#endif
+ LM_UINT32 UndiFix; /* new, jimmy */
+ LM_UINT32 PciCommandStatusWords;
+ LM_UINT32 ChipRevId;
+ LM_UINT16 SubsystemVendorId;
+ LM_UINT16 SubsystemId;
+#if 0 /* Jimmy, deleted in new driver */
+ LM_UINT32 MemBaseLow;
+ LM_UINT32 MemBaseHigh;
+ LM_UINT32 MemBaseSize;
+#endif
+ PLM_UINT8 pMappedMemBase;
+
+ /* Saved PCI configuration registers for restoring after a reset. */
+ LM_UINT32 SavedCacheLineReg;
+
+ /* Phy info. */
+ LM_UINT32 PhyAddr;
+ LM_UINT32 PhyId;
+
+ /* Requested phy settings. */
+ LM_REQUESTED_MEDIA_TYPE RequestedMediaType;
+
+ /* Disable auto-negotiation. */
+ LM_UINT32 DisableAutoNeg;
+
+ /* Ways for the MAC to get link change interrupt. */
+ LM_UINT32 PhyIntMode;
+ #define T3_PHY_INT_MODE_AUTO 0
+ #define T3_PHY_INT_MODE_MI_INTERRUPT 1
+ #define T3_PHY_INT_MODE_LINK_READY 2
+ #define T3_PHY_INT_MODE_AUTO_POLLING 3
+
+ /* Ways to determine link change status. */
+ LM_UINT32 LinkChngMode;
+ #define T3_LINK_CHNG_MODE_AUTO 0
+ #define T3_LINK_CHNG_MODE_USE_STATUS_REG 1
+ #define T3_LINK_CHNG_MODE_USE_STATUS_BLOCK 2
+
+
+ /* LED mode. */
+ LM_UINT32 LedMode;
+
+ #define LED_MODE_AUTO 0
+
+ /* 5700/01 LED mode. */
+ #define LED_MODE_THREE_LINK 1
+ #define LED_MODE_LINK10 2
+
+ /* 5703/02/04 LED mode. */
+ #define LED_MODE_OPEN_DRAIN 1
+ #define LED_MODE_OUTPUT 2
+
+ /* WOL Speed */
+ LM_UINT32 WolSpeed;
+ #define WOL_SPEED_10MB 1
+ #define WOL_SPEED_100MB 2
+
+ /* Reset the PHY on initialization. */
+ LM_UINT32 ResetPhyOnInit;
+
+ LM_UINT32 RestoreOnWakeUp;
+ LM_REQUESTED_MEDIA_TYPE WakeUpRequestedMediaType;
+ LM_UINT32 WakeUpDisableAutoNeg;
+
+ /* Current phy settings. */
+ LM_MEDIA_TYPE MediaType;
+ LM_LINE_SPEED LineSpeed;
+ LM_LINE_SPEED OldLineSpeed;
+ LM_DUPLEX_MODE DuplexMode;
+ LM_STATUS LinkStatus;
+ LM_UINT32 advertising; /* Jimmy, new! */
+ LM_UINT32 advertising1000; /* Jimmy, new! */
+
+ /* Multicast address list. */
+ LM_UINT32 McEntryCount;
+ LM_UINT8 McTable[LM_MAX_MC_TABLE_SIZE][LM_MC_ENTRY_SIZE];
+
+ /* Use NIC or Host based send BD. */
+ LM_UINT32 NicSendBd;
+
+ /* Athlon fix. */
+ LM_UINT32 DelayPciGrant;
+
+ /* Enable OneDmaAtOnce */
+ LM_UINT32 OneDmaAtOnce;
+
+ /* Split Mode flags, Jimmy new */
+ LM_UINT32 SplitModeEnable;
+ LM_UINT32 SplitModeMaxReq;
+
+ /* Init flag. */
+ LM_BOOL InitDone;
+
+ /* Shutdown flag. Set by the upper module. */
+ LM_BOOL ShuttingDown;
+
+ /* Flag to determine whether to call LM_QueueRxPackets or not in */
+ /* LM_ResetAdapter routine. */
+ LM_BOOL QueueRxPackets;
+
+ LM_UINT32 MbufBase;
+ LM_UINT32 MbufSize;
+
+ /* TRUE if we have a SERDES PHY. */
+ LM_UINT32 EnableTbi;
+
+ /* Ethernet@WireSpeed. */
+ LM_UINT32 EnableWireSpeed;
+
+ LM_UINT32 EepromWp;
+
+#if INCLUDE_TBI_SUPPORT
+ /* Autoneg state info. */
+ AN_STATE_INFO AnInfo;
+ LM_UINT32 PollTbiLink;
+ LM_UINT32 IgnoreTbiLinkChange;
+#endif
+ char PartNo[24];
+ char BootCodeVer[16];
+ char BusSpeedStr[24]; /* Jimmy, new! */
+ LM_UINT32 PhyCrcCount;
+} LM_DEVICE_BLOCK;
+
+
+#define T3_REG_CPU_VIEW 0xc0000000
+
+#define T3_BLOCK_DMA_RD (1 << 0)
+#define T3_BLOCK_DMA_COMP (1 << 1)
+#define T3_BLOCK_RX_BD_INITIATOR (1 << 2)
+#define T3_BLOCK_RX_BD_COMP (1 << 3)
+#define T3_BLOCK_DMA_WR (1 << 4)
+#define T3_BLOCK_MSI_HANDLER (1 << 5)
+#define T3_BLOCK_RX_LIST_PLMT (1 << 6)
+#define T3_BLOCK_RX_LIST_SELECTOR (1 << 7)
+#define T3_BLOCK_RX_DATA_INITIATOR (1 << 8)
+#define T3_BLOCK_RX_DATA_COMP (1 << 9)
+#define T3_BLOCK_HOST_COALESING (1 << 10)
+#define T3_BLOCK_MAC_RX_ENGINE (1 << 11)
+#define T3_BLOCK_MBUF_CLUSTER_FREE (1 << 12)
+#define T3_BLOCK_SEND_BD_INITIATOR (1 << 13)
+#define T3_BLOCK_SEND_BD_COMP (1 << 14)
+#define T3_BLOCK_SEND_BD_SELECTOR (1 << 15)
+#define T3_BLOCK_SEND_DATA_INITIATOR (1 << 16)
+#define T3_BLOCK_SEND_DATA_COMP (1 << 17)
+#define T3_BLOCK_MAC_TX_ENGINE (1 << 18)
+#define T3_BLOCK_MEM_ARBITOR (1 << 19)
+#define T3_BLOCK_MBUF_MANAGER (1 << 20)
+#define T3_BLOCK_MAC_GLOBAL (1 << 21)
+
+#define LM_ENABLE 1
+#define LM_DISABLE 2
+
+#define RX_CPU_EVT_SW0 0
+#define RX_CPU_EVT_SW1 1
+#define RX_CPU_EVT_RLP 2
+#define RX_CPU_EVT_SW3 3
+#define RX_CPU_EVT_RLS 4
+#define RX_CPU_EVT_SW4 5
+#define RX_CPU_EVT_RX_BD_COMP 6
+#define RX_CPU_EVT_SW5 7
+#define RX_CPU_EVT_RDI 8
+#define RX_CPU_EVT_DMA_WR 9
+#define RX_CPU_EVT_DMA_RD 10
+#define RX_CPU_EVT_SWQ 11
+#define RX_CPU_EVT_SW6 12
+#define RX_CPU_EVT_RDC 13
+#define RX_CPU_EVT_SW7 14
+#define RX_CPU_EVT_HOST_COALES 15
+#define RX_CPU_EVT_SW8 16
+#define RX_CPU_EVT_HIGH_DMA_WR 17
+#define RX_CPU_EVT_HIGH_DMA_RD 18
+#define RX_CPU_EVT_SW9 19
+#define RX_CPU_EVT_DMA_ATTN 20
+#define RX_CPU_EVT_LOW_P_MBOX 21
+#define RX_CPU_EVT_HIGH_P_MBOX 22
+#define RX_CPU_EVT_SW10 23
+#define RX_CPU_EVT_TX_CPU_ATTN 24
+#define RX_CPU_EVT_MAC_ATTN 25
+#define RX_CPU_EVT_RX_CPU_ATTN 26
+#define RX_CPU_EVT_FLOW_ATTN 27
+#define RX_CPU_EVT_SW11 28
+#define RX_CPU_EVT_TIMER 29
+#define RX_CPU_EVT_SW12 30
+#define RX_CPU_EVT_SW13 31
+
+/* RX-CPU event */
+#define RX_CPU_EVENT_SW_EVENT0 (1 << RX_CPU_EVT_SW0)
+#define RX_CPU_EVENT_SW_EVENT1 (1 << RX_CPU_EVT_SW1)
+#define RX_CPU_EVENT_RLP (1 << RX_CPU_EVT_RLP)
+#define RX_CPU_EVENT_SW_EVENT3 (1 << RX_CPU_EVT_SW3)
+#define RX_CPU_EVENT_RLS (1 << RX_CPU_EVT_RLS)
+#define RX_CPU_EVENT_SW_EVENT4 (1 << RX_CPU_EVT_SW4)
+#define RX_CPU_EVENT_RX_BD_COMP (1 << RX_CPU_EVT_RX_BD_COMP)
+#define RX_CPU_EVENT_SW_EVENT5 (1 << RX_CPU_EVT_SW5)
+#define RX_CPU_EVENT_RDI (1 << RX_CPU_EVT_RDI)
+#define RX_CPU_EVENT_DMA_WR (1 << RX_CPU_EVT_DMA_WR)
+#define RX_CPU_EVENT_DMA_RD (1 << RX_CPU_EVT_DMA_RD)
+#define RX_CPU_EVENT_SWQ (1 << RX_CPU_EVT_SWQ)
+#define RX_CPU_EVENT_SW_EVENT6 (1 << RX_CPU_EVT_SW6)
+#define RX_CPU_EVENT_RDC (1 << RX_CPU_EVT_RDC)
+#define RX_CPU_EVENT_SW_EVENT7 (1 << RX_CPU_EVT_SW7)
+#define RX_CPU_EVENT_HOST_COALES (1 << RX_CPU_EVT_HOST_COALES)
+#define RX_CPU_EVENT_SW_EVENT8 (1 << RX_CPU_EVT_SW8)
+#define RX_CPU_EVENT_HIGH_DMA_WR (1 << RX_CPU_EVT_HIGH_DMA_WR)
+#define RX_CPU_EVENT_HIGH_DMA_RD (1 << RX_CPU_EVT_HIGH_DMA_RD)
+#define RX_CPU_EVENT_SW_EVENT9 (1 << RX_CPU_EVT_SW9)
+#define RX_CPU_EVENT_DMA_ATTN (1 << RX_CPU_EVT_DMA_ATTN)
+#define RX_CPU_EVENT_LOW_P_MBOX (1 << RX_CPU_EVT_LOW_P_MBOX)
+#define RX_CPU_EVENT_HIGH_P_MBOX (1 << RX_CPU_EVT_HIGH_P_MBOX)
+#define RX_CPU_EVENT_SW_EVENT10 (1 << RX_CPU_EVT_SW10)
+#define RX_CPU_EVENT_TX_CPU_ATTN (1 << RX_CPU_EVT_TX_CPU_ATTN)
+#define RX_CPU_EVENT_MAC_ATTN (1 << RX_CPU_EVT_MAC_ATTN)
+#define RX_CPU_EVENT_RX_CPU_ATTN (1 << RX_CPU_EVT_RX_CPU_ATTN)
+#define RX_CPU_EVENT_FLOW_ATTN (1 << RX_CPU_EVT_FLOW_ATTN)
+#define RX_CPU_EVENT_SW_EVENT11 (1 << RX_CPU_EVT_SW11)
+#define RX_CPU_EVENT_TIMER (1 << RX_CPU_EVT_TIMER)
+#define RX_CPU_EVENT_SW_EVENT12 (1 << RX_CPU_EVT_SW12)
+#define RX_CPU_EVENT_SW_EVENT13 (1 << RX_CPU_EVT_SW13)
+
+#define RX_CPU_MASK (RX_CPU_EVENT_SW_EVENT0 | \
+ RX_CPU_EVENT_RLP | \
+ RX_CPU_EVENT_RDI | \
+ RX_CPU_EVENT_RDC)
+
+#define TX_CPU_EVT_SW0 0
+#define TX_CPU_EVT_SW1 1
+#define TX_CPU_EVT_SW2 2
+#define TX_CPU_EVT_SW3 3
+#define TX_CPU_EVT_TX_MAC 4
+#define TX_CPU_EVT_SW4 5
+#define TX_CPU_EVT_SBDC 6
+#define TX_CPU_EVT_SW5 7
+#define TX_CPU_EVT_SDI 8
+#define TX_CPU_EVT_DMA_WR 9
+#define TX_CPU_EVT_DMA_RD 10
+#define TX_CPU_EVT_SWQ 11
+#define TX_CPU_EVT_SW6 12
+#define TX_CPU_EVT_SDC 13
+#define TX_CPU_EVT_SW7 14
+#define TX_CPU_EVT_HOST_COALES 15
+#define TX_CPU_EVT_SW8 16
+#define TX_CPU_EVT_HIGH_DMA_WR 17
+#define TX_CPU_EVT_HIGH_DMA_RD 18
+#define TX_CPU_EVT_SW9 19
+#define TX_CPU_EVT_DMA_ATTN 20
+#define TX_CPU_EVT_LOW_P_MBOX 21
+#define TX_CPU_EVT_HIGH_P_MBOX 22
+#define TX_CPU_EVT_SW10 23
+#define TX_CPU_EVT_RX_CPU_ATTN 24
+#define TX_CPU_EVT_MAC_ATTN 25
+#define TX_CPU_EVT_TX_CPU_ATTN 26
+#define TX_CPU_EVT_FLOW_ATTN 27
+#define TX_CPU_EVT_SW11 28
+#define TX_CPU_EVT_TIMER 29
+#define TX_CPU_EVT_SW12 30
+#define TX_CPU_EVT_SW13 31
+
+
+/* TX-CPU event */
+#define TX_CPU_EVENT_SW_EVENT0 (1 << TX_CPU_EVT_SW0)
+#define TX_CPU_EVENT_SW_EVENT1 (1 << TX_CPU_EVT_SW1)
+#define TX_CPU_EVENT_SW_EVENT2 (1 << TX_CPU_EVT_SW2)
+#define TX_CPU_EVENT_SW_EVENT3 (1 << TX_CPU_EVT_SW3)
+#define TX_CPU_EVENT_TX_MAC (1 << TX_CPU_EVT_TX_MAC)
+#define TX_CPU_EVENT_SW_EVENT4 (1 << TX_CPU_EVT_SW4)
+#define TX_CPU_EVENT_SBDC (1 << TX_CPU_EVT_SBDC)
+#define TX_CPU_EVENT_SW_EVENT5 (1 << TX_CPU_EVT_SW5)
+#define TX_CPU_EVENT_SDI (1 << TX_CPU_EVT_SDI)
+#define TX_CPU_EVENT_DMA_WR (1 << TX_CPU_EVT_DMA_WR)
+#define TX_CPU_EVENT_DMA_RD (1 << TX_CPU_EVT_DMA_RD)
+#define TX_CPU_EVENT_SWQ (1 << TX_CPU_EVT_SWQ)
+#define TX_CPU_EVENT_SW_EVENT6 (1 << TX_CPU_EVT_SW6)
+#define TX_CPU_EVENT_SDC (1 << TX_CPU_EVT_SDC)
+#define TX_CPU_EVENT_SW_EVENT7 (1 << TX_CPU_EVT_SW7)
+#define TX_CPU_EVENT_HOST_COALES (1 << TX_CPU_EVT_HOST_COALES)
+#define TX_CPU_EVENT_SW_EVENT8 (1 << TX_CPU_EVT_SW8)
+#define TX_CPU_EVENT_HIGH_DMA_WR (1 << TX_CPU_EVT_HIGH_DMA_WR)
+#define TX_CPU_EVENT_HIGH_DMA_RD (1 << TX_CPU_EVT_HIGH_DMA_RD)
+#define TX_CPU_EVENT_SW_EVENT9 (1 << TX_CPU_EVT_SW9)
+#define TX_CPU_EVENT_DMA_ATTN (1 << TX_CPU_EVT_DMA_ATTN)
+#define TX_CPU_EVENT_LOW_P_MBOX (1 << TX_CPU_EVT_LOW_P_MBOX)
+#define TX_CPU_EVENT_HIGH_P_MBOX (1 << TX_CPU_EVT_HIGH_P_MBOX)
+#define TX_CPU_EVENT_SW_EVENT10 (1 << TX_CPU_EVT_SW10)
+#define TX_CPU_EVENT_RX_CPU_ATTN (1 << TX_CPU_EVT_RX_CPU_ATTN)
+#define TX_CPU_EVENT_MAC_ATTN (1 << TX_CPU_EVT_MAC_ATTN)
+#define TX_CPU_EVENT_TX_CPU_ATTN (1 << TX_CPU_EVT_TX_CPU_ATTN)
+#define TX_CPU_EVENT_FLOW_ATTN (1 << TX_CPU_EVT_FLOW_ATTN)
+#define TX_CPU_EVENT_SW_EVENT11 (1 << TX_CPU_EVT_SW11)
+#define TX_CPU_EVENT_TIMER (1 << TX_CPU_EVT_TIMER)
+#define TX_CPU_EVENT_SW_EVENT12 (1 << TX_CPU_EVT_SW12)
+#define TX_CPU_EVENT_SW_EVENT13 (1 << TX_CPU_EVT_SW13)
+
+
+#define TX_CPU_MASK (TX_CPU_EVENT_SW_EVENT0 | \
+ TX_CPU_EVENT_SDI | \
+ TX_CPU_EVENT_SDC)
+
+
+#define T3_FTQ_TYPE1_UNDERFLOW_BIT (1 << 29)
+#define T3_FTQ_TYPE1_PASS_BIT (1 << 30)
+#define T3_FTQ_TYPE1_SKIP_BIT (1 << 31)
+
+#define T3_FTQ_TYPE2_UNDERFLOW_BIT (1 << 13)
+#define T3_FTQ_TYPE2_PASS_BIT (1 << 14)
+#define T3_FTQ_TYPE2_SKIP_BIT (1 << 15)
+
+#define T3_QID_DMA_READ 1
+#define T3_QID_DMA_HIGH_PRI_READ 2
+#define T3_QID_DMA_COMP_DX 3
+#define T3_QID_SEND_BD_COMP 4
+#define T3_QID_SEND_DATA_INITIATOR 5
+#define T3_QID_DMA_WRITE 6
+#define T3_QID_DMA_HIGH_PRI_WRITE 7
+#define T3_QID_SW_TYPE_1 8
+#define T3_QID_SEND_DATA_COMP 9
+#define T3_QID_HOST_COALESCING 10
+#define T3_QID_MAC_TX 11
+#define T3_QID_MBUF_CLUSTER_FREE 12
+#define T3_QID_RX_BD_COMP 13
+#define T3_QID_RX_LIST_PLM 14
+#define T3_QID_RX_DATA_BD_INITIATOR 15
+#define T3_QID_RX_DATA_COMP 16
+#define T3_QID_SW_TYPE2 17
+
+LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice,
+ PT3_FWIMG_INFO pFwImg,
+ LM_UINT32 LoadCpu,
+ LM_UINT32 StartCpu);
+
+/******************************************************************************/
+/* NIC register read/write macros. */
+/******************************************************************************/
+
+#if 0 /* Jimmy */
+/* MAC register access. */
+LM_UINT32 LM_RegRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register);
+LM_VOID LM_RegWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register,
+ LM_UINT32 Value32);
+
+/* MAC memory access. */
+LM_UINT32 LM_MemRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr);
+LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
+ LM_UINT32 Value32);
+
+#if PCIX_TARGET_WORKAROUND
+
+/* use memory-mapped accesses for mailboxes and reads, UNDI accesses
+ for writes to all other registers */
+#define REG_RD(pDevice, OffsetName) \
+ readl(&((pDevice)->pMemView->OffsetName))
+
+#define REG_WR(pDevice, OffsetName, Value32) \
+ (((OFFSETOF(T3_STD_MEM_MAP, OffsetName) >=0x200 ) && \
+ (OFFSETOF(T3_STD_MEM_MAP, OffsetName) <0x400)) || \
+ ((pDevice)->EnablePciXFix == FALSE)) ? \
+ (void) writel(Value32, &((pDevice)->pMemView->OffsetName)) : \
+ LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32)
+
+#define MB_REG_RD(pDevice, OffsetName) \
+ readl(&((pDevice)->pMemView->OffsetName))
+
+#define MB_REG_WR(pDevice, OffsetName, Value32) \
+ writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define REG_RD_OFFSET(pDevice, Offset) \
+ readl(&((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+#define REG_WR_OFFSET(pDevice, Offset, Value32) \
+ (((Offset >=0x200 ) && (Offset < 0x400)) || \
+ ((pDevice)->EnablePciXFix == FALSE)) ? \
+ (void) writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) : \
+ LM_RegWrInd(pDevice, Offset, Value32)
+
+#define MEM_RD(pDevice, AddrName) \
+ LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName))
+#define MEM_WR(pDevice, AddrName, Value32) \
+ LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32)
+
+#define MEM_RD_OFFSET(pDevice, Offset) \
+ LM_MemRdInd(pDevice, Offset)
+#define MEM_WR_OFFSET(pDevice, Offset, Value32) \
+ LM_MemWrInd(pDevice, Offset, Value32)
+
+#else /* normal target access path below */
+
+/* Register access. */
+#define REG_RD(pDevice, OffsetName) \
+ readl(&((pDevice)->pMemView->OffsetName))
+#define REG_WR(pDevice, OffsetName, Value32) \
+ writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define REG_RD_OFFSET(pDevice, Offset) \
+ readl(((LM_UINT8 *) (pDevice)->pMemView + Offset))
+#define REG_WR_OFFSET(pDevice, Offset, Value32) \
+ writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+
+/* There could be problem access the memory window directly. For now, */
+/* we have to go through the PCI configuration register. */
+#define MEM_RD(pDevice, AddrName) \
+ LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName))
+#define MEM_WR(pDevice, AddrName, Value32) \
+ LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32)
+
+#define MEM_RD_OFFSET(pDevice, Offset) \
+ LM_MemRdInd(pDevice, Offset)
+#define MEM_WR_OFFSET(pDevice, Offset, Value32) \
+ LM_MemWrInd(pDevice, Offset, Value32)
+
+#endif /* PCIX_TARGET_WORKAROUND */
+
+#endif /* Jimmy, merging */
+
+ /* Jimmy...rest of file is new stuff! */
+/******************************************************************************/
+/* NIC register read/write macros. */
+/******************************************************************************/
+
+/* MAC register access. */
+LM_UINT32 LM_RegRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register);
+LM_VOID LM_RegWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register,
+ LM_UINT32 Value32);
+
+/* MAC memory access. */
+LM_UINT32 LM_MemRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr);
+LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
+ LM_UINT32 Value32);
+
+#define MB_REG_WR(pDevice, OffsetName, Value32) \
+ ((pDevice)->UndiFix) ? \
+ LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600, \
+ Value32) : \
+ (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#define MB_REG_RD(pDevice, OffsetName) \
+ (((pDevice)->UndiFix) ? \
+ LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600) : \
+ __raw_readl(&((pDevice)->pMemView->OffsetName)))
+
+#define REG_RD(pDevice, OffsetName) \
+ (((pDevice)->UndiFix) ? \
+ LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)) : \
+ __raw_readl(&((pDevice)->pMemView->OffsetName)))
+
+#if PCIX_TARGET_WORKAROUND
+
+#define REG_WR(pDevice, OffsetName, Value32) \
+ ((pDevice)->EnablePciXFix == FALSE) ? \
+ (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) : \
+ LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32)
+
+#else
+
+#define REG_WR(pDevice, OffsetName, Value32) \
+ __raw_writel(Value32, &((pDevice)->pMemView->OffsetName))
+
+#endif
+
+#define MEM_RD(pDevice, AddrName) \
+ LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName))
+#define MEM_WR(pDevice, AddrName, Value32) \
+ LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32)
+
+#define MEM_RD_OFFSET(pDevice, Offset) \
+ LM_MemRdInd(pDevice, Offset)
+#define MEM_WR_OFFSET(pDevice, Offset, Value32) \
+ LM_MemWrInd(pDevice, Offset, Value32)
+
+#endif /* TIGON3_H */
+