summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorNobuhiro Iwamatsu <iwamatsu@nigauri.org>2007-09-23 01:29:43 +0900
committerNobuhiro Iwamatsu <iwamatsu@nigauri.org>2007-09-23 01:29:43 +0900
commitb8685affe614ccf5f4ec66252b30e2e524d18948 (patch)
tree05bc55b8a4a0451e6500f1f52651d81c0f48f012 /drivers
parent69df3c4da0c93017cceb25a366e794570bd0ed98 (diff)
parent66dcad3a9a53e0766d90e0084123bd8529522fb0 (diff)
downloadtalos-obmc-uboot-b8685affe614ccf5f4ec66252b30e2e524d18948.tar.gz
talos-obmc-uboot-b8685affe614ccf5f4ec66252b30e2e524d18948.zip
Merge git://www.denx.de/git/u-boot
Conflicts: CREDITS
Diffstat (limited to 'drivers')
-rwxr-xr-x[-rw-r--r--]drivers/Makefile14
-rw-r--r--drivers/ahci.c7
-rwxr-xr-xdrivers/at45.c566
-rw-r--r--drivers/ata_piix.c216
-rw-r--r--drivers/ati_ids.h211
-rw-r--r--drivers/ati_radeon_fb.c486
-rw-r--r--drivers/ati_radeon_fb.h282
-rw-r--r--drivers/bcm570x.c2328
-rw-r--r--drivers/bcm570x_lm.h207
-rw-r--r--drivers/bcm570x_mm.h58
-rw-r--r--drivers/bios_emulator/Makefile37
-rw-r--r--drivers/bios_emulator/atibios.c340
-rw-r--r--drivers/bios_emulator/besys.c724
-rw-r--r--drivers/bios_emulator/bios.c326
-rw-r--r--drivers/bios_emulator/biosemu.c375
-rw-r--r--drivers/bios_emulator/biosemui.h169
-rw-r--r--drivers/bios_emulator/include/biosemu.h392
-rw-r--r--drivers/bios_emulator/include/x86emu.h191
-rw-r--r--drivers/bios_emulator/include/x86emu/debug.h209
-rw-r--r--drivers/bios_emulator/include/x86emu/decode.h88
-rw-r--r--drivers/bios_emulator/include/x86emu/ops.h45
-rw-r--r--drivers/bios_emulator/include/x86emu/prim_asm.h970
-rw-r--r--drivers/bios_emulator/include/x86emu/prim_ops.h141
-rw-r--r--drivers/bios_emulator/include/x86emu/regs.h340
-rw-r--r--drivers/bios_emulator/include/x86emu/x86emui.h101
-rw-r--r--drivers/bios_emulator/x86emu/debug.c467
-rw-r--r--drivers/bios_emulator/x86emu/decode.c1149
-rw-r--r--drivers/bios_emulator/x86emu/ops.c5438
-rw-r--r--drivers/bios_emulator/x86emu/ops2.c1776
-rw-r--r--drivers/bios_emulator/x86emu/prim_ops.c2452
-rw-r--r--drivers/bios_emulator/x86emu/sys.c328
-rw-r--r--drivers/cfb_console.c14
-rw-r--r--drivers/cs8900.c2
-rw-r--r--drivers/dataflash.c279
-rw-r--r--drivers/dc2114x.c6
-rw-r--r--drivers/dm9000x.c33
-rw-r--r--drivers/e1000.c4
-rw-r--r--drivers/eepro100.c10
-rw-r--r--drivers/enc28j60.c983
-rw-r--r--drivers/fsl_i2c.c3
-rw-r--r--drivers/fsl_pci_init.c169
-rw-r--r--drivers/inca-ip_sw.c4
-rw-r--r--drivers/isp116x-hcd.c1413
-rw-r--r--drivers/isp116x.h489
-rw-r--r--drivers/lan91c96.c2
-rw-r--r--drivers/macb.c70
-rw-r--r--drivers/mpc8xx_pcmcia.c10
-rw-r--r--drivers/nand/nand.c2
-rw-r--r--drivers/nand/nand_base.c2
-rw-r--r--drivers/nand/nand_bbt.c2
-rw-r--r--drivers/nand/nand_ecc.c232
-rw-r--r--drivers/nand/nand_ids.c3
-rw-r--r--drivers/nand/nand_util.c38
-rw-r--r--drivers/nand_legacy/nand_legacy.c11
-rw-r--r--drivers/natsemi.c4
-rw-r--r--drivers/net/Makefile45
-rw-r--r--drivers/net/mcffec.c597
-rw-r--r--drivers/netarm_eth.c2
-rw-r--r--drivers/ns8382x.c4
-rw-r--r--drivers/pci.c12
-rw-r--r--drivers/pci_auto.c54
-rw-r--r--drivers/pci_indirect.c4
-rw-r--r--drivers/pcnet.c4
-rw-r--r--drivers/plb2800_eth.c4
-rw-r--r--drivers/pxa_pcmcia.c2
-rw-r--r--drivers/qe/qe.c9
-rw-r--r--drivers/qe/qe.h2
-rw-r--r--drivers/qe/uec.c33
-rw-r--r--drivers/qe/uec.h1
-rw-r--r--drivers/qe/uec_phy.c14
-rw-r--r--drivers/qe/uec_phy.h6
-rw-r--r--drivers/rpx_pcmcia.c8
-rw-r--r--drivers/rtl8019.c2
-rw-r--r--drivers/rtl8139.c13
-rw-r--r--drivers/rtl8169.c2
-rw-r--r--drivers/serial/Makefile45
-rw-r--r--drivers/serial/mcfuart.c133
-rw-r--r--drivers/sil680.c110
-rw-r--r--drivers/sk98lin/uboot_drv.c2
-rw-r--r--drivers/sym53c8xx.c4
-rw-r--r--drivers/systemace.c6
-rw-r--r--drivers/ti_pci1410a.c2
-rw-r--r--drivers/tigon3.c9701
-rw-r--r--drivers/tigon3.h3749
-rw-r--r--drivers/tqm8xx_pcmcia.c8
-rw-r--r--drivers/tsec.c198
-rw-r--r--drivers/tsec.h4
-rw-r--r--drivers/tsi108_eth.c2
-rw-r--r--drivers/tsi108_i2c.c4
-rw-r--r--drivers/usb_ohci.c1918
-rw-r--r--drivers/usb_ohci.h445
-rw-r--r--drivers/usbdcore_ep0.c163
-rw-r--r--drivers/usbdcore_mpc8xx.c1401
-rw-r--r--drivers/usbdcore_omap1510.c27
-rw-r--r--drivers/usbtty.c699
-rw-r--r--drivers/usbtty.h60
96 files changed, 34597 insertions, 9120 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index a3a9986cf4..fe32a74098 100644..100755
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -27,11 +27,11 @@ include $(TOPDIR)/config.mk
LIB = $(obj)libdrivers.a
-COBJS = 3c589.o 5701rls.o ali512x.o atmel_usart.o \
+COBJS = 3c589.o 5701rls.o ali512x.o at45.o ata_piix.o atmel_usart.o \
bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o \
cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \
- e1000.o eepro100.o \
- i8042.o inca-ip_sw.o keyboard.o \
+ e1000.o eepro100.o enc28j60.o \
+ i8042.o inca-ip_sw.o isp116x-hcd.o keyboard.o \
lan91c96.o macb.o \
natsemi.o ne2000.o netarm_eth.o netconsole.o \
ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \
@@ -43,16 +43,18 @@ COBJS = 3c589.o 5701rls.o ali512x.o atmel_usart.o \
sed13806.o sed156x.o \
serial.o serial_max3100.o serial_sh.o \
serial_pl010.o serial_pl011.o serial_xuartlite.o \
- sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
+ sil680.o sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
status_led.o sym53c8xx.o systemace.o ahci.o \
ti_pci1410a.o tigon3.o tsec.o \
tsi108_eth.o tsi108_i2c.o tsi108_pci.o \
- usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o \
+ usb_ohci.o \
+ usbdcore.o usbdcore_ep0.o usbdcore_mpc8xx.o usbdcore_omap1510.o \
+ usbtty.o \
videomodes.o w83c553f.o \
ks8695eth.o \
pxa_pcmcia.o mpc8xx_pcmcia.o tqm8xx_pcmcia.o \
rpx_pcmcia.o \
- fsl_i2c.o
+ fsl_i2c.o fsl_pci_init.o ati_radeon_fb.o
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/ahci.c b/drivers/ahci.c
index 8ceff00925..3d82c625a3 100644
--- a/drivers/ahci.c
+++ b/drivers/ahci.c
@@ -253,13 +253,14 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent)
static int ahci_init_one(pci_dev_t pdev)
{
- u32 iobase, vendor;
+ u32 iobase;
+ u16 vendor;
int rc;
memset((void *)ataid, 0, sizeof(hd_driveid_t *) * AHCI_MAX_PORTS);
- probe_ent = malloc(sizeof(probe_ent));
- memset(probe_ent, 0, sizeof(probe_ent));
+ probe_ent = malloc(sizeof(struct ahci_probe_ent));
+ memset(probe_ent, 0, sizeof(struct ahci_probe_ent));
probe_ent->dev = pdev;
pci_read_config_dword(pdev, AHCI_PCI_BAR, &iobase);
diff --git a/drivers/at45.c b/drivers/at45.c
new file mode 100755
index 0000000000..507ff36d47
--- /dev/null
+++ b/drivers/at45.c
@@ -0,0 +1,566 @@
+/* Driver for ATMEL DataFlash support
+ * Author : Hamid Ikdoumi (Atmel)
+ *
+ * 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>
+#include <common.h>
+
+#ifdef CONFIG_HAS_DATAFLASH
+#include <dataflash.h>
+
+/*
+ * spi.c API
+ */
+extern unsigned int AT91F_SpiWrite (AT91PS_DataflashDesc pDesc);
+extern void AT91F_SpiEnable(int cs);
+
+#define AT91C_TIMEOUT_WRDY 200000
+
+
+/*----------------------------------------------------------------------*/
+/* \fn AT91F_DataFlashSendCommand */
+/* \brief Generic function to send a command to the dataflash */
+/*----------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_DataFlashSendCommand(
+ AT91PS_DataFlash pDataFlash,
+ unsigned char OpCode,
+ unsigned int CmdSize,
+ unsigned int DataflashAddress)
+{
+ unsigned int adr;
+
+ if ( (pDataFlash->pDataFlashDesc->state) != IDLE)
+ return DATAFLASH_BUSY;
+
+ /* process the address to obtain page address and byte address */
+ adr = ((DataflashAddress / (pDataFlash->pDevice->pages_size)) <<
+ pDataFlash->pDevice->page_offset) + (DataflashAddress %
+ (pDataFlash->pDevice->pages_size));
+
+ /* fill the command buffer */
+ pDataFlash->pDataFlashDesc->command[0] = OpCode;
+ if (pDataFlash->pDevice->pages_number >= 16384) {
+ pDataFlash->pDataFlashDesc->command[1] =
+ (unsigned char)((adr & 0x0F000000) >> 24);
+ pDataFlash->pDataFlashDesc->command[2] =
+ (unsigned char)((adr & 0x00FF0000) >> 16);
+ pDataFlash->pDataFlashDesc->command[3] =
+ (unsigned char)((adr & 0x0000FF00) >> 8);
+ pDataFlash->pDataFlashDesc->command[4] =
+ (unsigned char)(adr & 0x000000FF);
+ } else {
+ pDataFlash->pDataFlashDesc->command[1] =
+ (unsigned char)((adr & 0x00FF0000) >> 16);
+ pDataFlash->pDataFlashDesc->command[2] =
+ (unsigned char)((adr & 0x0000FF00) >> 8);
+ pDataFlash->pDataFlashDesc->command[3] =
+ (unsigned char)(adr & 0x000000FF);
+ pDataFlash->pDataFlashDesc->command[4] = 0;
+ }
+ pDataFlash->pDataFlashDesc->command[5] = 0;
+ pDataFlash->pDataFlashDesc->command[6] = 0;
+ pDataFlash->pDataFlashDesc->command[7] = 0;
+
+ /* Initialize the SpiData structure for the spi write fuction */
+ pDataFlash->pDataFlashDesc->tx_cmd_pt =
+ pDataFlash->pDataFlashDesc->command;
+ pDataFlash->pDataFlashDesc->tx_cmd_size = CmdSize;
+ pDataFlash->pDataFlashDesc->rx_cmd_pt =
+ pDataFlash->pDataFlashDesc->command;
+ pDataFlash->pDataFlashDesc->rx_cmd_size = CmdSize;
+
+ /* send the command and read the data */
+ return AT91F_SpiWrite (pDataFlash->pDataFlashDesc); }
+
+
+/*----------------------------------------------------------------------*/
+/* \fn AT91F_DataFlashGetStatus */
+/* \brief Read the status register of the dataflash */
+/*----------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_DataFlashGetStatus(AT91PS_DataflashDesc pDesc)
+{
+ AT91S_DataFlashStatus status;
+
+ /* if a transfert is in progress ==> return 0 */
+ if( (pDesc->state) != IDLE)
+ return DATAFLASH_BUSY;
+
+ /* first send the read status command (D7H) */
+ pDesc->command[0] = DB_STATUS;
+ pDesc->command[1] = 0;
+
+ pDesc->DataFlash_state = GET_STATUS;
+ pDesc->tx_data_size = 0; /* Transmit the command */
+ /* and receive response */
+ pDesc->tx_cmd_pt = pDesc->command;
+ pDesc->rx_cmd_pt = pDesc->command;
+ pDesc->rx_cmd_size = 2;
+ pDesc->tx_cmd_size = 2;
+ status = AT91F_SpiWrite (pDesc);
+
+ pDesc->DataFlash_state = *( (unsigned char *) (pDesc->rx_cmd_pt) +1);
+
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* \fn AT91F_DataFlashWaitReady */
+/* \brief wait for dataflash ready (bit7 of the status register == 1) */
+/*----------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_DataFlashWaitReady(AT91PS_DataflashDesc
+pDataFlashDesc, unsigned int timeout)
+{
+ pDataFlashDesc->DataFlash_state = IDLE;
+
+ do {
+ AT91F_DataFlashGetStatus(pDataFlashDesc);
+ timeout--;
+ } while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) &&
+ (timeout > 0) );
+
+ if((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
+ return DATAFLASH_ERROR;
+
+ return DATAFLASH_OK;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* Function Name : AT91F_DataFlashContinuousRead */
+/* Object : Continuous stream Read */
+/* Input Parameters : DataFlash Service */
+/* : <src> = dataflash address */
+/* : <*dataBuffer> = data buffer pointer */
+/* : <sizeToRead> = data buffer size */
+/* Return value : State of the dataflash */
+/*--------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_DataFlashContinuousRead (
+ AT91PS_DataFlash pDataFlash,
+ int src,
+ unsigned char *dataBuffer,
+ int sizeToRead )
+{
+ AT91S_DataFlashStatus status;
+ /* Test the size to read in the device */
+ if ( (src + sizeToRead) >
+ (pDataFlash->pDevice->pages_size *
+ (pDataFlash->pDevice->pages_number)))
+ return DATAFLASH_MEMORY_OVERFLOW;
+
+ pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
+ pDataFlash->pDataFlashDesc->rx_data_size = sizeToRead;
+ pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
+ pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead;
+
+ status = AT91F_DataFlashSendCommand
+ (pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src);
+ /* Send the command to the dataflash */
+ return(status);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_DataFlashPagePgmBuf */
+/* Object : Main memory page program thru buffer 1 or buffer 2 */
+/* Input Parameters : DataFlash Service */
+/* : <*src> = Source buffer */
+/* : <dest> = dataflash destination address */
+/* : <SizeToWrite> = data buffer size */
+/* Return value : State of the dataflash */
+/*---------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(
+ AT91PS_DataFlash pDataFlash,
+ unsigned char *src,
+ unsigned int dest,
+ unsigned int SizeToWrite)
+{
+ int cmdsize;
+ pDataFlash->pDataFlashDesc->tx_data_pt = src;
+ pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite;
+ pDataFlash->pDataFlashDesc->rx_data_pt = src;
+ pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
+
+ cmdsize = 4;
+ /* Send the command to the dataflash */
+ if (pDataFlash->pDevice->pages_number >= 16384)
+ cmdsize = 5;
+ return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_PGM_BUF1,
+cmdsize, dest)); }
+
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_MainMemoryToBufferTransfert */
+/* Object : Read a page in the SRAM Buffer 1 or 2 */
+/* Input Parameters : DataFlash Service */
+/* : Page concerned */
+/* : */
+/* Return value : State of the dataflash */
+/*---------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfert(
+ AT91PS_DataFlash pDataFlash,
+ unsigned char BufferCommand,
+ unsigned int page)
+{
+ int cmdsize;
+ /* Test if the buffer command is legal */
+ if ((BufferCommand != DB_PAGE_2_BUF1_TRF)
+ && (BufferCommand != DB_PAGE_2_BUF2_TRF))
+ return DATAFLASH_BAD_COMMAND;
+
+ /* no data to transmit or receive */
+ pDataFlash->pDataFlashDesc->tx_data_size = 0;
+ cmdsize = 4;
+ if (pDataFlash->pDevice->pages_number >= 16384)
+ cmdsize = 5;
+ return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize,
+page*pDataFlash->pDevice->pages_size));
+}
+
+
+/*-------------------------------------------------------------------------- */
+/* Function Name : AT91F_DataFlashWriteBuffer */
+/* Object : Write data to the internal sram buffer 1 or 2 */
+/* Input Parameters : DataFlash Service */
+/* : <BufferCommand> = command to write buffer1 or 2 */
+/* : <*dataBuffer> = data buffer to write */
+/* : <bufferAddress> = address in the internal buffer */
+/* : <SizeToWrite> = data buffer size */
+/* Return value : State of the dataflash */
+/*---------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer (
+ AT91PS_DataFlash pDataFlash,
+ unsigned char BufferCommand,
+ unsigned char *dataBuffer,
+ unsigned int bufferAddress,
+ int SizeToWrite )
+{
+ int cmdsize;
+ /* Test if the buffer command is legal */
+ if ((BufferCommand != DB_BUF1_WRITE)
+ && (BufferCommand != DB_BUF2_WRITE))
+ return DATAFLASH_BAD_COMMAND;
+
+ /* buffer address must be lower than page size */
+ if (bufferAddress > pDataFlash->pDevice->pages_size)
+ return DATAFLASH_BAD_ADDRESS;
+
+ if ( (pDataFlash->pDataFlashDesc->state) != IDLE)
+ return DATAFLASH_BUSY;
+
+ /* Send first Write Command */
+ pDataFlash->pDataFlashDesc->command[0] = BufferCommand;
+ pDataFlash->pDataFlashDesc->command[1] = 0;
+ if (pDataFlash->pDevice->pages_number >= 16384) {
+ pDataFlash->pDataFlashDesc->command[2] = 0;
+ pDataFlash->pDataFlashDesc->command[3] =
+ (unsigned char)(((unsigned int)(bufferAddress &
+ pDataFlash->pDevice->byte_mask)) >> 8);
+ pDataFlash->pDataFlashDesc->command[4] =
+ (unsigned char)((unsigned int)bufferAddress & 0x00FF);
+ cmdsize = 5;
+ } else {
+ pDataFlash->pDataFlashDesc->command[2] =
+ (unsigned char)(((unsigned int)(bufferAddress &
+ pDataFlash->pDevice->byte_mask)) >> 8);
+ pDataFlash->pDataFlashDesc->command[3] =
+ (unsigned char)((unsigned int)bufferAddress & 0x00FF);
+ pDataFlash->pDataFlashDesc->command[4] = 0;
+ cmdsize = 4;
+ }
+
+ pDataFlash->pDataFlashDesc->tx_cmd_pt =
+ pDataFlash->pDataFlashDesc->command;
+ pDataFlash->pDataFlashDesc->tx_cmd_size = cmdsize;
+ pDataFlash->pDataFlashDesc->rx_cmd_pt =
+ pDataFlash->pDataFlashDesc->command;
+ pDataFlash->pDataFlashDesc->rx_cmd_size = cmdsize;
+
+ pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
+ pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
+ pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
+ pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite;
+
+ return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_PageErase */
+/* Object : Erase a page */
+/* Input Parameters : DataFlash Service */
+/* : Page concerned */
+/* : */
+/* Return value : State of the dataflash */
+/*---------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_PageErase(
+ AT91PS_DataFlash pDataFlash,
+ unsigned int page)
+{
+ int cmdsize;
+ /* Test if the buffer command is legal */
+ /* no data to transmit or receive */
+ pDataFlash->pDataFlashDesc->tx_data_size = 0;
+
+ cmdsize = 4;
+ if (pDataFlash->pDevice->pages_number >= 16384)
+ cmdsize = 5;
+ return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_ERASE, cmdsize,
+page*pDataFlash->pDevice->pages_size));
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_BlockErase */
+/* Object : Erase a Block */
+/* Input Parameters : DataFlash Service */
+/* : Page concerned */
+/* : */
+/* Return value : State of the dataflash */
+/*---------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_BlockErase(
+ AT91PS_DataFlash pDataFlash,
+ unsigned int block)
+{
+ int cmdsize;
+ /* Test if the buffer command is legal */
+ /* no data to transmit or receive */
+ pDataFlash->pDataFlashDesc->tx_data_size = 0;
+ cmdsize = 4;
+ if (pDataFlash->pDevice->pages_number >= 16384)
+ cmdsize = 5;
+ return(AT91F_DataFlashSendCommand (pDataFlash, DB_BLOCK_ERASE,cmdsize,
+block*8*pDataFlash->pDevice->pages_size));
+}
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_WriteBufferToMain */
+/* Object : Write buffer to the main memory */
+/* Input Parameters : DataFlash Service */
+/* : <BufferCommand> = command to send to buffer1 or buffer2 */
+/* : <dest> = main memory address */
+/* Return value : State of the dataflash */
+/*---------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_WriteBufferToMain (
+ AT91PS_DataFlash pDataFlash,
+ unsigned char BufferCommand,
+ unsigned int dest )
+{
+ int cmdsize;
+ /* Test if the buffer command is correct */
+ if ((BufferCommand != DB_BUF1_PAGE_PGM) &&
+ (BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
+ (BufferCommand != DB_BUF2_PAGE_PGM) &&
+ (BufferCommand != DB_BUF2_PAGE_ERASE_PGM) )
+ return DATAFLASH_BAD_COMMAND;
+
+ /* no data to transmit or receive */
+ pDataFlash->pDataFlashDesc->tx_data_size = 0;
+
+ cmdsize = 4;
+ if (pDataFlash->pDevice->pages_number >= 16384)
+ cmdsize = 5;
+ /* Send the command to the dataflash */
+ return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize,
+ dest)); }
+
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_PartialPageWrite */
+/* Object : Erase partielly a page */
+/* Input Parameters : <page> = page number */
+/* : <AdrInpage> = adr to begin the fading */
+/* : <length> = Number of bytes to erase */
+/*---------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_PartialPageWrite (
+ AT91PS_DataFlash pDataFlash,
+ unsigned char *src,
+ unsigned int dest,
+ unsigned int size)
+{
+ unsigned int page;
+ unsigned int AdrInPage;
+
+ page = dest / (pDataFlash->pDevice->pages_size);
+ AdrInPage = dest % (pDataFlash->pDevice->pages_size);
+
+ /* Read the contents of the page in the Sram Buffer */
+ AT91F_MainMemoryToBufferTransfert(pDataFlash,
+ DB_PAGE_2_BUF1_TRF, page);
+ AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY);
+ /*Update the SRAM buffer */
+ AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src,
+ AdrInPage, size);
+
+ AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY);
+
+ /* Erase page if a 128 Mbits device */
+ if (pDataFlash->pDevice->pages_number >= 16384) {
+ AT91F_PageErase(pDataFlash, page);
+ /* Rewrite the modified Sram Buffer in the main memory */
+ AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY);
+ }
+
+ /* Rewrite the modified Sram Buffer in the main memory */
+ return(AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM,
+ (page*pDataFlash->pDevice->pages_size)));
+}
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_DataFlashWrite */
+/* Object : */
+/* Input Parameters : <*src> = Source buffer */
+/* : <dest> = dataflash adress */
+/* : <size> = data buffer size */
+/*---------------------------------------------------------------------------*/
+AT91S_DataFlashStatus AT91F_DataFlashWrite(
+ AT91PS_DataFlash pDataFlash,
+ unsigned char *src,
+ int dest,
+ int size )
+{
+ unsigned int length;
+ unsigned int page;
+ unsigned int status;
+
+ AT91F_SpiEnable(pDataFlash->pDevice->cs);
+
+ if ( (dest + size) > (pDataFlash->pDevice->pages_size *
+ (pDataFlash->pDevice->pages_number)))
+ return DATAFLASH_MEMORY_OVERFLOW;
+
+ /* If destination does not fit a page start address */
+ if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size))) != 0 )
+ {
+ length = pDataFlash->pDevice->pages_size -
+ (dest %
+ ((unsigned int)
+ (pDataFlash->pDevice->pages_size)));
+
+ if (size < length)
+ length = size;
+
+ if(!AT91F_PartialPageWrite(pDataFlash,src, dest, length))
+ return DATAFLASH_ERROR;
+
+ AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY);
+
+ /* Update size, source and destination pointers */
+ size -= length;
+ dest += length;
+ src += length;
+ }
+
+ while (( size - pDataFlash->pDevice->pages_size ) >= 0 ) {
+ /* program dataflash page */
+ page = (unsigned int)dest / (pDataFlash->pDevice->pages_size);
+
+ status = AT91F_DataFlashWriteBuffer(pDataFlash,
+ DB_BUF1_WRITE, src, 0,
+ pDataFlash->pDevice->pages_size);
+ AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY);
+
+ status = AT91F_PageErase(pDataFlash, page);
+ AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY);
+ if (!status)
+ return DATAFLASH_ERROR;
+
+ status = AT91F_WriteBufferToMain (pDataFlash,
+ DB_BUF1_PAGE_PGM, dest);
+ if(!status)
+ return DATAFLASH_ERROR;
+
+ AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY);
+
+ /* Update size, source and destination pointers */
+ size -= pDataFlash->pDevice->pages_size;
+ dest += pDataFlash->pDevice->pages_size;
+ src += pDataFlash->pDevice->pages_size;
+ }
+
+ /* If still some bytes to read */
+ if ( size > 0 ) {
+ /* program dataflash page */
+ if(!AT91F_PartialPageWrite(pDataFlash, src, dest, size) )
+ return DATAFLASH_ERROR;
+
+ AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY);
+ }
+ return DATAFLASH_OK;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_DataFlashRead */
+/* Object : Read a block in dataflash */
+/* Input Parameters : */
+/* Return value : */
+/*---------------------------------------------------------------------------*/
+int AT91F_DataFlashRead(
+ AT91PS_DataFlash pDataFlash,
+ unsigned long addr,
+ unsigned long size,
+ char *buffer)
+{
+ unsigned long SizeToRead;
+
+ AT91F_SpiEnable(pDataFlash->pDevice->cs);
+
+ if(AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
+ return -1;
+
+ while (size) {
+ SizeToRead = (size < 0x8000)? size:0x8000;
+
+ if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
+ return -1;
+
+ if (AT91F_DataFlashContinuousRead (pDataFlash, addr,
+ (uchar *) buffer, SizeToRead) != DATAFLASH_OK)
+ return -1;
+
+ size -= SizeToRead;
+ addr += SizeToRead;
+ buffer += SizeToRead;
+ }
+
+ return DATAFLASH_OK;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_DataflashProbe */
+/* Object : */
+/* Input Parameters : */
+/* Return value : Dataflash status register */
+/*---------------------------------------------------------------------------*/
+int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc) {
+ AT91F_SpiEnable(cs);
+ AT91F_DataFlashGetStatus(pDesc);
+ return((pDesc->command[1] == 0xFF)? 0: pDesc->command[1] & 0x3C);
+}
+#endif
diff --git a/drivers/ata_piix.c b/drivers/ata_piix.c
new file mode 100644
index 0000000000..42456d7be3
--- /dev/null
+++ b/drivers/ata_piix.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) Procsys. All rights reserved.
+ * Author: Mushtaq Khan <mushtaq_k@procsys.com>
+ * <mushtaqk_921@yahoo.co.in>
+ *
+ * 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
+ *
+ * with the reference to ata_piix driver in kernel 2.4.32
+ */
+
+/*
+ * This file contains SATA controller and SATA drive initialization functions
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <command.h>
+#include <config.h>
+#include <asm/byteorder.h>
+#include <ide.h>
+#include <ata.h>
+
+#ifdef CFG_ATA_PIIX /*ata_piix driver */
+
+#define DEBUG_SATA 0 /*For debug prints set DEBUG_SATA to 1 */
+
+#define DRV_DECL /*For file specific declarations */
+#include <sata.h>
+#undef DRV_DECL
+
+/*Macros realted to PCI*/
+#define PCI_SATA_BUS 0x00
+#define PCI_SATA_DEV 0x1f
+#define PCI_SATA_FUNC 0x02
+
+#define PCI_SATA_BASE1 0x10
+#define PCI_SATA_BASE2 0x14
+#define PCI_SATA_BASE3 0x18
+#define PCI_SATA_BASE4 0x1c
+#define PCI_SATA_BASE5 0x20
+#define PCI_PMR 0x90
+#define PCI_PI 0x09
+#define PCI_PCS 0x92
+#define PCI_DMA_CTL 0x48
+
+#define PORT_PRESENT (1<<0)
+#define PORT_ENABLED (1<<4)
+
+u32 bdf;
+u32 iobase1 = 0; /*Primary cmd block */
+u32 iobase2 = 0; /*Primary ctl block */
+u32 iobase3 = 0; /*Sec cmd block */
+u32 iobase4 = 0; /*sec ctl block */
+u32 iobase5 = 0; /*BMDMA*/
+int
+pci_sata_init (void)
+{
+ u32 bus = PCI_SATA_BUS;
+ u32 dev = PCI_SATA_DEV;
+ u32 fun = PCI_SATA_FUNC;
+ u16 cmd = 0;
+ u8 lat = 0, pcibios_max_latency = 0xff;
+ u8 pmr; /*Port mapping reg */
+ u8 pi; /*Prgming Interface reg */
+
+ bdf = PCI_BDF (bus, dev, fun);
+ pci_read_config_dword (bdf, PCI_SATA_BASE1, &iobase1);
+ pci_read_config_dword (bdf, PCI_SATA_BASE2, &iobase2);
+ pci_read_config_dword (bdf, PCI_SATA_BASE3, &iobase3);
+ pci_read_config_dword (bdf, PCI_SATA_BASE4, &iobase4);
+ pci_read_config_dword (bdf, PCI_SATA_BASE5, &iobase5);
+
+ if ((iobase1 == 0xFFFFFFFF) || (iobase2 == 0xFFFFFFFF) ||
+ (iobase3 == 0xFFFFFFFF) || (iobase4 == 0xFFFFFFFF) ||
+ (iobase5 == 0xFFFFFFFF)) {
+ printf ("error no base addr for SATA controller\n");
+ return 1;
+ /*ERROR*/}
+
+ iobase1 &= 0xFFFFFFFE;
+ iobase2 &= 0xFFFFFFFE;
+ iobase3 &= 0xFFFFFFFE;
+ iobase4 &= 0xFFFFFFFE;
+ iobase5 &= 0xFFFFFFFE;
+
+ /*check for mode */
+ pci_read_config_byte (bdf, PCI_PMR, &pmr);
+ if (pmr > 1) {
+ printf ("combined mode not supported\n");
+ return 1;
+ }
+
+ pci_read_config_byte (bdf, PCI_PI, &pi);
+ if ((pi & 0x05) != 0x05) {
+ printf ("Sata is in Legacy mode\n");
+ return 1;
+ } else {
+ printf ("sata is in Native mode\n");
+ }
+
+ /*MASTER CFG AND IO CFG */
+ pci_read_config_word (bdf, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
+ pci_write_config_word (bdf, PCI_COMMAND, cmd);
+ pci_read_config_byte (dev, PCI_LATENCY_TIMER, &lat);
+
+ if (lat < 16)
+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+ else if (lat > pcibios_max_latency)
+ lat = pcibios_max_latency;
+ pci_write_config_byte (dev, PCI_LATENCY_TIMER, lat);
+
+ return 0;
+}
+
+int
+sata_bus_probe (int port_no)
+{
+ int orig_mask, mask;
+ u16 pcs;
+
+ mask = (PORT_PRESENT << port_no);
+ pci_read_config_word (bdf, PCI_PCS, &pcs);
+ orig_mask = (int) pcs & 0xff;
+ if ((orig_mask & mask) != mask)
+ return 0;
+ else
+ return 1;
+}
+
+int
+init_sata (void)
+{
+ u8 i, rv = 0;
+
+ for (i = 0; i < CFG_SATA_MAXDEVICES; i++) {
+ sata_dev_desc[i].type = DEV_TYPE_UNKNOWN;
+ sata_dev_desc[i].if_type = IF_TYPE_IDE;
+ sata_dev_desc[i].dev = i;
+ sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
+ sata_dev_desc[i].blksz = 0;
+ sata_dev_desc[i].lba = 0;
+ sata_dev_desc[i].block_read = sata_read;
+ }
+
+ rv = pci_sata_init ();
+ if (rv == 1) {
+ printf ("pci initialization failed\n");
+ return 1;
+ }
+
+ port[0].port_no = 0;
+ port[0].ioaddr.cmd_addr = iobase1;
+ port[0].ioaddr.altstatus_addr = port[0].ioaddr.ctl_addr =
+ iobase2 | ATA_PCI_CTL_OFS;
+ port[0].ioaddr.bmdma_addr = iobase5;
+
+ port[1].port_no = 1;
+ port[1].ioaddr.cmd_addr = iobase3;
+ port[1].ioaddr.altstatus_addr = port[1].ioaddr.ctl_addr =
+ iobase4 | ATA_PCI_CTL_OFS;
+ port[1].ioaddr.bmdma_addr = iobase5 + 0x8;
+
+ for (i = 0; i < CFG_SATA_MAXBUS; i++)
+ sata_port (&port[i].ioaddr);
+
+ for (i = 0; i < CFG_SATA_MAXBUS; i++) {
+ if (!(sata_bus_probe (i))) {
+ port[i].port_state = 0;
+ printf ("SATA#%d port is not present \n", i);
+ } else {
+ printf ("SATA#%d port is present\n", i);
+ if (sata_bus_softreset (i)) {
+ port[i].port_state = 0;
+ } else {
+ port[i].port_state = 1;
+ }
+ }
+ }
+
+ for (i = 0; i < CFG_SATA_MAXBUS; i++) {
+ u8 j, devno;
+
+ if (port[i].port_state == 0)
+ continue;
+ for (j = 0; j < CFG_SATA_DEVS_PER_BUS; j++) {
+ sata_identify (i, j);
+ set_Feature_cmd (i, j);
+ devno = i * CFG_SATA_DEVS_PER_BUS + j;
+ if ((sata_dev_desc[devno].lba > 0) &&
+ (sata_dev_desc[devno].blksz > 0)) {
+ dev_print (&sata_dev_desc[devno]);
+ /* initialize partition type */
+ init_part (&sata_dev_desc[devno]);
+ if (curr_dev < 0)
+ curr_dev =
+ i * CFG_SATA_DEVS_PER_BUS + j;
+ }
+ }
+ }
+ return 0;
+}
+#endif
diff --git a/drivers/ati_ids.h b/drivers/ati_ids.h
new file mode 100644
index 0000000000..3e72a7dd4c
--- /dev/null
+++ b/drivers/ati_ids.h
@@ -0,0 +1,211 @@
+/*
+ * ATI PCI IDs from XFree86, kept here to make sync'ing with
+ * XFree much simpler. Currently, this list is only used by
+ * radeonfb
+ */
+
+#define PCI_CHIP_RV380_3150 0x3150
+#define PCI_CHIP_RV380_3151 0x3151
+#define PCI_CHIP_RV380_3152 0x3152
+#define PCI_CHIP_RV380_3153 0x3153
+#define PCI_CHIP_RV380_3154 0x3154
+#define PCI_CHIP_RV380_3156 0x3156
+#define PCI_CHIP_RV380_3E50 0x3E50
+#define PCI_CHIP_RV380_3E51 0x3E51
+#define PCI_CHIP_RV380_3E52 0x3E52
+#define PCI_CHIP_RV380_3E53 0x3E53
+#define PCI_CHIP_RV380_3E54 0x3E54
+#define PCI_CHIP_RV380_3E56 0x3E56
+#define PCI_CHIP_RS100_4136 0x4136
+#define PCI_CHIP_RS200_4137 0x4137
+#define PCI_CHIP_R300_AD 0x4144
+#define PCI_CHIP_R300_AE 0x4145
+#define PCI_CHIP_R300_AF 0x4146
+#define PCI_CHIP_R300_AG 0x4147
+#define PCI_CHIP_R350_AH 0x4148
+#define PCI_CHIP_R350_AI 0x4149
+#define PCI_CHIP_R350_AJ 0x414A
+#define PCI_CHIP_R350_AK 0x414B
+#define PCI_CHIP_RV350_AP 0x4150
+#define PCI_CHIP_RV350_AQ 0x4151
+#define PCI_CHIP_RV360_AR 0x4152
+#define PCI_CHIP_RV350_AS 0x4153
+#define PCI_CHIP_RV350_AT 0x4154
+#define PCI_CHIP_RV350_AV 0x4156
+#define PCI_CHIP_MACH32 0x4158
+#define PCI_CHIP_RS250_4237 0x4237
+#define PCI_CHIP_R200_BB 0x4242
+#define PCI_CHIP_R200_BC 0x4243
+#define PCI_CHIP_RS100_4336 0x4336
+#define PCI_CHIP_RS200_4337 0x4337
+#define PCI_CHIP_MACH64CT 0x4354
+#define PCI_CHIP_MACH64CX 0x4358
+#define PCI_CHIP_RS250_4437 0x4437
+#define PCI_CHIP_MACH64ET 0x4554
+#define PCI_CHIP_MACH64GB 0x4742
+#define PCI_CHIP_MACH64GD 0x4744
+#define PCI_CHIP_MACH64GI 0x4749
+#define PCI_CHIP_MACH64GL 0x474C
+#define PCI_CHIP_MACH64GM 0x474D
+#define PCI_CHIP_MACH64GN 0x474E
+#define PCI_CHIP_MACH64GO 0x474F
+#define PCI_CHIP_MACH64GP 0x4750
+#define PCI_CHIP_MACH64GQ 0x4751
+#define PCI_CHIP_MACH64GR 0x4752
+#define PCI_CHIP_MACH64GS 0x4753
+#define PCI_CHIP_MACH64GT 0x4754
+#define PCI_CHIP_MACH64GU 0x4755
+#define PCI_CHIP_MACH64GV 0x4756
+#define PCI_CHIP_MACH64GW 0x4757
+#define PCI_CHIP_MACH64GX 0x4758
+#define PCI_CHIP_MACH64GY 0x4759
+#define PCI_CHIP_MACH64GZ 0x475A
+#define PCI_CHIP_RV250_Id 0x4964
+#define PCI_CHIP_RV250_Ie 0x4965
+#define PCI_CHIP_RV250_If 0x4966
+#define PCI_CHIP_RV250_Ig 0x4967
+#define PCI_CHIP_R420_JH 0x4A48
+#define PCI_CHIP_R420_JI 0x4A49
+#define PCI_CHIP_R420_JJ 0x4A4A
+#define PCI_CHIP_R420_JK 0x4A4B
+#define PCI_CHIP_R420_JL 0x4A4C
+#define PCI_CHIP_R420_JM 0x4A4D
+#define PCI_CHIP_R420_JN 0x4A4E
+#define PCI_CHIP_R420_JP 0x4A50
+#define PCI_CHIP_MACH64LB 0x4C42
+#define PCI_CHIP_MACH64LD 0x4C44
+#define PCI_CHIP_RAGE128LE 0x4C45
+#define PCI_CHIP_RAGE128LF 0x4C46
+#define PCI_CHIP_MACH64LG 0x4C47
+#define PCI_CHIP_MACH64LI 0x4C49
+#define PCI_CHIP_MACH64LM 0x4C4D
+#define PCI_CHIP_MACH64LN 0x4C4E
+#define PCI_CHIP_MACH64LP 0x4C50
+#define PCI_CHIP_MACH64LQ 0x4C51
+#define PCI_CHIP_MACH64LR 0x4C52
+#define PCI_CHIP_MACH64LS 0x4C53
+#define PCI_CHIP_MACH64LT 0x4C54
+#define PCI_CHIP_RADEON_LW 0x4C57
+#define PCI_CHIP_RADEON_LX 0x4C58
+#define PCI_CHIP_RADEON_LY 0x4C59
+#define PCI_CHIP_RADEON_LZ 0x4C5A
+#define PCI_CHIP_RV250_Ld 0x4C64
+#define PCI_CHIP_RV250_Le 0x4C65
+#define PCI_CHIP_RV250_Lf 0x4C66
+#define PCI_CHIP_RV250_Lg 0x4C67
+#define PCI_CHIP_RV250_Ln 0x4C6E
+#define PCI_CHIP_RAGE128MF 0x4D46
+#define PCI_CHIP_RAGE128ML 0x4D4C
+#define PCI_CHIP_R300_ND 0x4E44
+#define PCI_CHIP_R300_NE 0x4E45
+#define PCI_CHIP_R300_NF 0x4E46
+#define PCI_CHIP_R300_NG 0x4E47
+#define PCI_CHIP_R350_NH 0x4E48
+#define PCI_CHIP_R350_NI 0x4E49
+#define PCI_CHIP_R360_NJ 0x4E4A
+#define PCI_CHIP_R350_NK 0x4E4B
+#define PCI_CHIP_RV350_NP 0x4E50
+#define PCI_CHIP_RV350_NQ 0x4E51
+#define PCI_CHIP_RV350_NR 0x4E52
+#define PCI_CHIP_RV350_NS 0x4E53
+#define PCI_CHIP_RV350_NT 0x4E54
+#define PCI_CHIP_RV350_NV 0x4E56
+#define PCI_CHIP_RAGE128PA 0x5041
+#define PCI_CHIP_RAGE128PB 0x5042
+#define PCI_CHIP_RAGE128PC 0x5043
+#define PCI_CHIP_RAGE128PD 0x5044
+#define PCI_CHIP_RAGE128PE 0x5045
+#define PCI_CHIP_RAGE128PF 0x5046
+#define PCI_CHIP_RAGE128PG 0x5047
+#define PCI_CHIP_RAGE128PH 0x5048
+#define PCI_CHIP_RAGE128PI 0x5049
+#define PCI_CHIP_RAGE128PJ 0x504A
+#define PCI_CHIP_RAGE128PK 0x504B
+#define PCI_CHIP_RAGE128PL 0x504C
+#define PCI_CHIP_RAGE128PM 0x504D
+#define PCI_CHIP_RAGE128PN 0x504E
+#define PCI_CHIP_RAGE128PO 0x504F
+#define PCI_CHIP_RAGE128PP 0x5050
+#define PCI_CHIP_RAGE128PQ 0x5051
+#define PCI_CHIP_RAGE128PR 0x5052
+#define PCI_CHIP_RAGE128PS 0x5053
+#define PCI_CHIP_RAGE128PT 0x5054
+#define PCI_CHIP_RAGE128PU 0x5055
+#define PCI_CHIP_RAGE128PV 0x5056
+#define PCI_CHIP_RAGE128PW 0x5057
+#define PCI_CHIP_RAGE128PX 0x5058
+#define PCI_CHIP_RADEON_QD 0x5144
+#define PCI_CHIP_RADEON_QE 0x5145
+#define PCI_CHIP_RADEON_QF 0x5146
+#define PCI_CHIP_RADEON_QG 0x5147
+#define PCI_CHIP_R200_QH 0x5148
+#define PCI_CHIP_R200_QI 0x5149
+#define PCI_CHIP_R200_QJ 0x514A
+#define PCI_CHIP_R200_QK 0x514B
+#define PCI_CHIP_R200_QL 0x514C
+#define PCI_CHIP_R200_QM 0x514D
+#define PCI_CHIP_R200_QN 0x514E
+#define PCI_CHIP_R200_QO 0x514F
+#define PCI_CHIP_RV200_QW 0x5157
+#define PCI_CHIP_RV200_QX 0x5158
+#define PCI_CHIP_RV100_QY 0x5159
+#define PCI_CHIP_RV100_QZ 0x515A
+#define PCI_CHIP_RN50 0x515E
+#define PCI_CHIP_RAGE128RE 0x5245
+#define PCI_CHIP_RAGE128RF 0x5246
+#define PCI_CHIP_RAGE128RG 0x5247
+#define PCI_CHIP_RAGE128RK 0x524B
+#define PCI_CHIP_RAGE128RL 0x524C
+#define PCI_CHIP_RAGE128SE 0x5345
+#define PCI_CHIP_RAGE128SF 0x5346
+#define PCI_CHIP_RAGE128SG 0x5347
+#define PCI_CHIP_RAGE128SH 0x5348
+#define PCI_CHIP_RAGE128SK 0x534B
+#define PCI_CHIP_RAGE128SL 0x534C
+#define PCI_CHIP_RAGE128SM 0x534D
+#define PCI_CHIP_RAGE128SN 0x534E
+#define PCI_CHIP_RAGE128TF 0x5446
+#define PCI_CHIP_RAGE128TL 0x544C
+#define PCI_CHIP_RAGE128TR 0x5452
+#define PCI_CHIP_RAGE128TS 0x5453
+#define PCI_CHIP_RAGE128TT 0x5454
+#define PCI_CHIP_RAGE128TU 0x5455
+#define PCI_CHIP_RV370_5460 0x5460
+#define PCI_CHIP_RV370_5461 0x5461
+#define PCI_CHIP_RV370_5462 0x5462
+#define PCI_CHIP_RV370_5463 0x5463
+#define PCI_CHIP_RV370_5464 0x5464
+#define PCI_CHIP_RV370_5465 0x5465
+#define PCI_CHIP_RV370_5466 0x5466
+#define PCI_CHIP_RV370_5467 0x5467
+#define PCI_CHIP_R423_UH 0x5548
+#define PCI_CHIP_R423_UI 0x5549
+#define PCI_CHIP_R423_UJ 0x554A
+#define PCI_CHIP_R423_UK 0x554B
+#define PCI_CHIP_R423_UQ 0x5551
+#define PCI_CHIP_R423_UR 0x5552
+#define PCI_CHIP_R423_UT 0x5554
+#define PCI_CHIP_MACH64VT 0x5654
+#define PCI_CHIP_MACH64VU 0x5655
+#define PCI_CHIP_MACH64VV 0x5656
+#define PCI_CHIP_RS300_5834 0x5834
+#define PCI_CHIP_RS300_5835 0x5835
+#define PCI_CHIP_RS300_5836 0x5836
+#define PCI_CHIP_RS300_5837 0x5837
+#define PCI_CHIP_RV370_5B60 0x5B60
+#define PCI_CHIP_RV370_5B61 0x5B61
+#define PCI_CHIP_RV370_5B62 0x5B62
+#define PCI_CHIP_RV370_5B63 0x5B63
+#define PCI_CHIP_RV370_5B64 0x5B64
+#define PCI_CHIP_RV370_5B65 0x5B65
+#define PCI_CHIP_RV370_5B66 0x5B66
+#define PCI_CHIP_RV370_5B67 0x5B67
+#define PCI_CHIP_RV280_5960 0x5960
+#define PCI_CHIP_RV280_5961 0x5961
+#define PCI_CHIP_RV280_5962 0x5962
+#define PCI_CHIP_RV280_5964 0x5964
+#define PCI_CHIP_RV280_5C61 0x5C61
+#define PCI_CHIP_RV280_5C63 0x5C63
+#define PCI_CHIP_R423_5D57 0x5D57
+#define PCI_CHIP_RS350_7834 0x7834
+#define PCI_CHIP_RS350_7835 0x7835
diff --git a/drivers/ati_radeon_fb.c b/drivers/ati_radeon_fb.c
new file mode 100644
index 0000000000..c174f37b3f
--- /dev/null
+++ b/drivers/ati_radeon_fb.c
@@ -0,0 +1,486 @@
+/*
+ * ATI Radeon Video card Framebuffer driver.
+ *
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ * Zhang Wei <wei.zhang@freescale.com>
+ * Jason Jin <jason.jin@freescale.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
+ *
+ * Some codes of this file is partly ported from Linux kernel
+ * ATI video framebuffer driver.
+ *
+ * Now the driver is tested on below ATI chips:
+ * 9200
+ * X300
+ * X700
+ *
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_ATI_RADEON_FB
+
+#include <command.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <video_fb.h>
+
+#include <radeon.h>
+#include "ati_ids.h"
+#include "ati_radeon_fb.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DPRINT(x...) printf(x)
+#else
+#define DPRINT(x...) do{}while(0)
+#endif
+
+#ifndef min_t
+#define min_t(type,x,y) \
+ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+#endif
+
+#define MAX_MAPPED_VRAM (2048*2048*4)
+#define MIN_MAPPED_VRAM (1024*768*1)
+
+/*#define PCI_VENDOR_ID_ATI*/
+#define PCI_CHIP_RV280_5960 0x5960
+#define PCI_CHIP_RV280_5961 0x5961
+#define PCI_CHIP_RV280_5962 0x5962
+#define PCI_CHIP_RV280_5964 0x5964
+#define PCI_CHIP_RV370_5B60 0x5B60
+#define PCI_CHIP_RV380_5657 0x5657
+#define PCI_CHIP_R420_554d 0x554d
+
+static struct pci_device_id ati_radeon_pci_ids[] = {
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5960},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5961},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5962},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5964},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV370_5B60},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV380_5657},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_R420_554d},
+ {0, 0}
+};
+
+static u16 ati_radeon_id_family_table[][2] = {
+ {PCI_CHIP_RV280_5960, CHIP_FAMILY_RV280},
+ {PCI_CHIP_RV280_5961, CHIP_FAMILY_RV280},
+ {PCI_CHIP_RV280_5962, CHIP_FAMILY_RV280},
+ {PCI_CHIP_RV280_5964, CHIP_FAMILY_RV280},
+ {PCI_CHIP_RV370_5B60, CHIP_FAMILY_RV380},
+ {PCI_CHIP_RV380_5657, CHIP_FAMILY_RV380},
+ {PCI_CHIP_R420_554d, CHIP_FAMILY_R420},
+ {0, 0}
+};
+
+u16 get_radeon_id_family(u16 device)
+{
+ int i;
+ for (i=0; ati_radeon_id_family_table[0][i]; i+=2)
+ if (ati_radeon_id_family_table[0][i] == device)
+ return ati_radeon_id_family_table[0][i + 1];
+ return 0;
+}
+
+struct radeonfb_info *rinfo;
+
+static void radeon_identify_vram(struct radeonfb_info *rinfo)
+{
+ u32 tmp;
+
+ /* framebuffer size */
+ if ((rinfo->family == CHIP_FAMILY_RS100) ||
+ (rinfo->family == CHIP_FAMILY_RS200) ||
+ (rinfo->family == CHIP_FAMILY_RS300)) {
+ u32 tom = INREG(NB_TOM);
+ tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
+
+ radeon_fifo_wait(6);
+ OUTREG(MC_FB_LOCATION, tom);
+ OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+ OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+ OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
+
+ /* This is supposed to fix the crtc2 noise problem. */
+ OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
+
+ if ((rinfo->family == CHIP_FAMILY_RS100) ||
+ (rinfo->family == CHIP_FAMILY_RS200)) {
+ /* This is to workaround the asic bug for RMX, some versions
+ of BIOS dosen't have this register initialized correctly.
+ */
+ OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
+ ~CRTC_H_CUTOFF_ACTIVE_EN);
+ }
+ } else {
+ tmp = INREG(CONFIG_MEMSIZE);
+ }
+
+ /* mem size is bits [28:0], mask off the rest */
+ rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
+
+ /*
+ * Hack to get around some busted production M6's
+ * reporting no ram
+ */
+ if (rinfo->video_ram == 0) {
+ switch (rinfo->pdev.device) {
+ case PCI_CHIP_RADEON_LY:
+ case PCI_CHIP_RADEON_LZ:
+ rinfo->video_ram = 8192 * 1024;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Now try to identify VRAM type
+ */
+ if ((rinfo->family >= CHIP_FAMILY_R300) ||
+ (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
+ rinfo->vram_ddr = 1;
+ else
+ rinfo->vram_ddr = 0;
+
+ tmp = INREG(MEM_CNTL);
+ if (IS_R300_VARIANT(rinfo)) {
+ tmp &= R300_MEM_NUM_CHANNELS_MASK;
+ switch (tmp) {
+ case 0: rinfo->vram_width = 64; break;
+ case 1: rinfo->vram_width = 128; break;
+ case 2: rinfo->vram_width = 256; break;
+ default: rinfo->vram_width = 128; break;
+ }
+ } else if ((rinfo->family == CHIP_FAMILY_RV100) ||
+ (rinfo->family == CHIP_FAMILY_RS100) ||
+ (rinfo->family == CHIP_FAMILY_RS200)){
+ if (tmp & RV100_MEM_HALF_MODE)
+ rinfo->vram_width = 32;
+ else
+ rinfo->vram_width = 64;
+ } else {
+ if (tmp & MEM_NUM_CHANNELS_MASK)
+ rinfo->vram_width = 128;
+ else
+ rinfo->vram_width = 64;
+ }
+
+ /* This may not be correct, as some cards can have half of channel disabled
+ * ToDo: identify these cases
+ */
+
+ DPRINT("radeonfb: Found %ldk of %s %d bits wide videoram\n",
+ rinfo->video_ram / 1024,
+ rinfo->vram_ddr ? "DDR" : "SDRAM",
+ rinfo->vram_width);
+
+}
+
+static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
+{
+ int i;
+
+ radeon_fifo_wait(20);
+
+#if 0
+ /* Workaround from XFree */
+ if (rinfo->is_mobility) {
+ /* A temporal workaround for the occational blanking on certain laptop
+ * panels. This appears to related to the PLL divider registers
+ * (fail to lock?). It occurs even when all dividers are the same
+ * with their old settings. In this case we really don't need to
+ * fiddle with PLL registers. By doing this we can avoid the blanking
+ * problem with some panels.
+ */
+ if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
+ (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
+ (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
+ /* We still have to force a switch to selected PPLL div thanks to
+ * an XFree86 driver bug which will switch it away in some cases
+ * even when using UseFDev */
+ OUTREGP(CLOCK_CNTL_INDEX,
+ mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
+ ~PPLL_DIV_SEL_MASK);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
+ return;
+ }
+ }
+#endif
+ if(rinfo->pdev.device == PCI_CHIP_RV370_5B60) return;
+
+ /* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
+ OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
+
+ /* Reset PPLL & enable atomic update */
+ OUTPLLP(PPLL_CNTL,
+ PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
+ ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
+
+ /* Switch to selected PPLL divider */
+ OUTREGP(CLOCK_CNTL_INDEX,
+ mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
+ ~PPLL_DIV_SEL_MASK);
+
+ /* Set PPLL ref. div */
+ if (rinfo->family == CHIP_FAMILY_R300 ||
+ rinfo->family == CHIP_FAMILY_RS300 ||
+ rinfo->family == CHIP_FAMILY_R350 ||
+ rinfo->family == CHIP_FAMILY_RV350) {
+ if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
+ /* When restoring console mode, use saved PPLL_REF_DIV
+ * setting.
+ */
+ OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
+ } else {
+ /* R300 uses ref_div_acc field as real ref divider */
+ OUTPLLP(PPLL_REF_DIV,
+ (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
+ ~R300_PPLL_REF_DIV_ACC_MASK);
+ }
+ } else
+ OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
+
+ /* Set PPLL divider 3 & post divider*/
+ OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
+ OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
+
+ /* Write update */
+ while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
+ ;
+ OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
+
+ /* Wait read update complete */
+ /* FIXME: Certain revisions of R300 can't recover here. Not sure of
+ the cause yet, but this workaround will mask the problem for now.
+ Other chips usually will pass at the very first test, so the
+ workaround shouldn't have any effect on them. */
+ for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
+ ;
+
+ OUTPLL(HTOTAL_CNTL, 0);
+
+ /* Clear reset & atomic update */
+ OUTPLLP(PPLL_CNTL, 0,
+ ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
+
+ /* We may want some locking ... oh well */
+ udelay(5000);
+
+ /* Switch back VCLK source to PPLL */
+ OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
+}
+
+typedef struct {
+ u16 reg;
+ u32 val;
+} reg_val;
+
+
+/* these common regs are cleared before mode setting so they do not
+ * interfere with anything
+ */
+static reg_val common_regs[] = {
+ { OVR_CLR, 0 },
+ { OVR_WID_LEFT_RIGHT, 0 },
+ { OVR_WID_TOP_BOTTOM, 0 },
+ { OV0_SCALE_CNTL, 0 },
+ { SUBPIC_CNTL, 0 },
+ { VIPH_CONTROL, 0 },
+ { I2C_CNTL_1, 0 },
+ { GEN_INT_CNTL, 0 },
+ { CAP0_TRIG_CNTL, 0 },
+ { CAP1_TRIG_CNTL, 0 },
+};
+
+
+void radeon_setmode(void)
+{
+ int i;
+ struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
+
+ mode->crtc_gen_cntl = 0x03000200;
+ mode->crtc_ext_cntl = 0x00008048;
+ mode->dac_cntl = 0xff002100;
+ mode->crtc_h_total_disp = 0x4f0063;
+ mode->crtc_h_sync_strt_wid = 0x8c02a2;
+ mode->crtc_v_total_disp = 0x01df020c;
+ mode->crtc_v_sync_strt_wid = 0x8201ea;
+ mode->crtc_pitch = 0x00500050;
+
+ OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
+ OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
+ ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
+ OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
+ OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
+ OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
+ OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
+ OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
+ OUTREG(CRTC_OFFSET, 0);
+ OUTREG(CRTC_OFFSET_CNTL, 0);
+ OUTREG(CRTC_PITCH, mode->crtc_pitch);
+
+ mode->clk_cntl_index = 0x300;
+ mode->ppll_ref_div = 0xc;
+ mode->ppll_div_3 = 0x00030059;
+
+ radeon_write_pll_regs(rinfo, mode);
+}
+
+int radeon_probe(struct radeonfb_info *rinfo)
+{
+ pci_dev_t pdev;
+ u16 did;
+
+ pdev = pci_find_devices(ati_radeon_pci_ids, 0);
+
+ if (pdev != -1) {
+ pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
+ printf("ATI Radeon video card (%04x, %04x) found @(%d:%d:%d)\n",
+ PCI_VENDOR_ID_ATI, did, (pdev >> 16) & 0xff,
+ (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
+
+ strcpy(rinfo->name, "ATI Radeon");
+ rinfo->pdev.vendor = PCI_VENDOR_ID_ATI;
+ rinfo->pdev.device = did;
+ rinfo->family = get_radeon_id_family(rinfo->pdev.device);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
+ &rinfo->fb_base_phys);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
+ &rinfo->mmio_base_phys);
+ rinfo->fb_base_phys &= 0xfffff000;
+ rinfo->mmio_base_phys &= ~0x04;
+
+ rinfo->mmio_base = (void *)rinfo->mmio_base_phys;
+ DPRINT("rinfo->mmio_base = 0x%x\n",rinfo->mmio_base);
+ rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+ DPRINT("rinfo->fb_local_base = 0x%x\n",rinfo->fb_local_base);
+ /* PostBIOS with x86 emulater */
+ BootVideoCardBIOS(pdev, NULL, 0);
+
+ /*
+ * Check for errata
+ * (These will be added in the future for the chipfamily
+ * R300, RV200, RS200, RV100, RS100.)
+ */
+
+ /* Get VRAM size and type */
+ radeon_identify_vram(rinfo);
+
+ rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM,
+ rinfo->video_ram);
+ rinfo->fb_base = (void *)rinfo->fb_base_phys;
+
+ DPRINT("Radeon: framebuffer base phy address 0x%08x," \
+ "MMIO base phy address 0x%08x," \
+ "framebuffer local base 0x%08x.\n ",
+ rinfo->fb_base_phys, rinfo->mmio_base_phys,
+ rinfo->fb_local_base);
+
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+
+#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 */
+
+void *video_hw_init(void)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ int i;
+ u32 *vm;
+
+ rinfo = malloc(sizeof(struct radeonfb_info));
+
+ if(radeon_probe(rinfo)) {
+ printf("No radeon video card found!\n");
+ return NULL;
+ }
+
+ /* fill in Graphic device struct */
+ sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", 640,
+ 480, 16, (1000 / 1000),
+ (2000 / 1000));
+ printf ("%s\n", pGD->modeIdent);
+
+ pGD->winSizeX = 640;
+ pGD->winSizeY = 480;
+ pGD->plnSizeX = 640;
+ pGD->plnSizeY = 480;
+
+ pGD->gdfBytesPP = 1;
+ pGD->gdfIndex = GDF__8BIT_INDEX;
+
+ pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
+ pGD->pciBase = rinfo->fb_base_phys;
+ pGD->frameAdrs = rinfo->fb_base_phys;
+ pGD->memSize = 64 * 1024 * 1024;
+
+ /* Cursor Start Address */
+ pGD->dprBase =
+ (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + rinfo->fb_base_phys;
+ if ((pGD->dprBase & 0x0fff) != 0) {
+ /* allign it */
+ pGD->dprBase &= 0xfffff000;
+ pGD->dprBase += 0x00001000;
+ }
+ DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
+ PATTERN_ADR);
+ pGD->vprBase = rinfo->fb_base_phys; /* Dummy */
+ pGD->cprBase = rinfo->fb_base_phys; /* Dummy */
+ /* set up Hardware */
+
+ /* Clear video memory */
+ i = pGD->memSize / 4;
+ vm = (unsigned int *) pGD->pciBase;
+ while (i--)
+ *vm++ = 0;
+ /*SetDrawingEngine (bits_per_pixel);*/
+
+ radeon_setmode();
+
+ return ((void *) pGD);
+}
+
+void video_set_lut (unsigned int index, /* color number */
+ unsigned char r, /* red */
+ unsigned char g, /* green */
+ unsigned char b /* blue */
+ )
+{
+ OUTREG(PALETTE_INDEX, index);
+ OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);
+}
+#endif
diff --git a/drivers/ati_radeon_fb.h b/drivers/ati_radeon_fb.h
new file mode 100644
index 0000000000..b5c4b8b577
--- /dev/null
+++ b/drivers/ati_radeon_fb.h
@@ -0,0 +1,282 @@
+#ifndef __ATI_RADEON_FB_H
+#define __ATI_RADEON_FB_H
+
+/***************************************************************
+ * Most of the definitions here are adapted right from XFree86 *
+ ***************************************************************/
+
+/*
+ * Chip families. Must fit in the low 16 bits of a long word
+ */
+enum radeon_family {
+ CHIP_FAMILY_UNKNOW,
+ CHIP_FAMILY_LEGACY,
+ CHIP_FAMILY_RADEON,
+ CHIP_FAMILY_RV100,
+ CHIP_FAMILY_RS100, /* U1 (IGP320M) or A3 (IGP320)*/
+ CHIP_FAMILY_RV200,
+ CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350),
+ RS250 (IGP 7000) */
+ CHIP_FAMILY_R200,
+ CHIP_FAMILY_RV250,
+ CHIP_FAMILY_RS300, /* Radeon 9000 IGP */
+ CHIP_FAMILY_RV280,
+ CHIP_FAMILY_R300,
+ CHIP_FAMILY_R350,
+ CHIP_FAMILY_RV350,
+ CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
+ CHIP_FAMILY_R420, /* R420/R423/M18 */
+ CHIP_FAMILY_LAST,
+};
+
+#define IS_RV100_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_RV100) || \
+ ((rinfo)->family == CHIP_FAMILY_RV200) || \
+ ((rinfo)->family == CHIP_FAMILY_RS100) || \
+ ((rinfo)->family == CHIP_FAMILY_RS200) || \
+ ((rinfo)->family == CHIP_FAMILY_RV250) || \
+ ((rinfo)->family == CHIP_FAMILY_RV280) || \
+ ((rinfo)->family == CHIP_FAMILY_RS300))
+
+#define IS_R300_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_R300) || \
+ ((rinfo)->family == CHIP_FAMILY_RV350) || \
+ ((rinfo)->family == CHIP_FAMILY_R350) || \
+ ((rinfo)->family == CHIP_FAMILY_RV380) || \
+ ((rinfo)->family == CHIP_FAMILY_R420))
+
+struct radeonfb_info {
+ char name[20];
+
+ struct pci_device_id pdev;
+ u16 family;
+
+ u32 fb_base_phys;
+ u32 mmio_base_phys;
+
+ void *mmio_base;
+ void *fb_base;
+
+ u32 video_ram;
+ u32 mapped_vram;
+ int vram_width;
+ int vram_ddr;
+
+ u32 fb_local_base;
+};
+
+#define INREG8(addr) readb((rinfo->mmio_base)+addr)
+#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
+#define INREG16(addr) readw((rinfo->mmio_base)+addr)
+#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr)
+#define INREG(addr) readl((rinfo->mmio_base)+addr)
+#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
+
+static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
+ u32 val, u32 mask)
+{
+ unsigned int tmp;
+
+ tmp = INREG(addr);
+ tmp &= (mask);
+ tmp |= (val);
+ OUTREG(addr, tmp);
+}
+
+#define OUTREGP(addr,val,mask) _OUTREGP(rinfo, addr, val,mask)
+
+/*
+ * 2D Engine helper routines
+ */
+static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* initiate flush */
+ OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
+ ~RB2D_DC_FLUSH_ALL);
+
+ for (i=0; i < 2000000; i++) {
+ if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
+ return;
+ udelay(1);
+ }
+ printf("radeonfb: Flush Timeout !\n");
+}
+
+static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
+{
+ int i;
+
+ for (i=0; i<2000000; i++) {
+ if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
+ return;
+ udelay(1);
+ }
+ printf("radeonfb: FIFO Timeout !\n");
+}
+
+static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* ensure FIFO is empty before waiting for idle */
+ _radeon_fifo_wait (rinfo, 64);
+
+ for (i=0; i<2000000; i++) {
+ if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
+ radeon_engine_flush (rinfo);
+ return;
+ }
+ udelay(1);
+ }
+ printf("radeonfb: Idle Timeout !\n");
+}
+
+#define radeon_engine_idle() _radeon_engine_idle(rinfo)
+#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
+#define radeon_msleep(ms) _radeon_msleep(rinfo,ms)
+
+/*
+ * This structure contains the various registers manipulated by this
+ * driver for setting or restoring a mode. It's mostly copied from
+ * XFree's RADEONSaveRec structure. A few chip settings might still be
+ * tweaked without beeing reflected or saved in these registers though
+ */
+struct radeon_regs {
+ /* Common registers */
+ u32 ovr_clr;
+ u32 ovr_wid_left_right;
+ u32 ovr_wid_top_bottom;
+ u32 ov0_scale_cntl;
+ u32 mpp_tb_config;
+ u32 mpp_gp_config;
+ u32 subpic_cntl;
+ u32 viph_control;
+ u32 i2c_cntl_1;
+ u32 gen_int_cntl;
+ u32 cap0_trig_cntl;
+ u32 cap1_trig_cntl;
+ u32 bus_cntl;
+ u32 surface_cntl;
+ u32 bios_5_scratch;
+
+ /* Other registers to save for VT switches or driver load/unload */
+ u32 dp_datatype;
+ u32 rbbm_soft_reset;
+ u32 clock_cntl_index;
+ u32 amcgpio_en_reg;
+ u32 amcgpio_mask;
+
+ /* Surface/tiling registers */
+ u32 surf_lower_bound[8];
+ u32 surf_upper_bound[8];
+ u32 surf_info[8];
+
+ /* CRTC registers */
+ u32 crtc_gen_cntl;
+ u32 crtc_ext_cntl;
+ u32 dac_cntl;
+ u32 crtc_h_total_disp;
+ u32 crtc_h_sync_strt_wid;
+ u32 crtc_v_total_disp;
+ u32 crtc_v_sync_strt_wid;
+ u32 crtc_offset;
+ u32 crtc_offset_cntl;
+ u32 crtc_pitch;
+ u32 disp_merge_cntl;
+ u32 grph_buffer_cntl;
+ u32 crtc_more_cntl;
+
+ /* CRTC2 registers */
+ u32 crtc2_gen_cntl;
+ u32 dac2_cntl;
+ u32 disp_output_cntl;
+ u32 disp_hw_debug;
+ u32 disp2_merge_cntl;
+ u32 grph2_buffer_cntl;
+ u32 crtc2_h_total_disp;
+ u32 crtc2_h_sync_strt_wid;
+ u32 crtc2_v_total_disp;
+ u32 crtc2_v_sync_strt_wid;
+ u32 crtc2_offset;
+ u32 crtc2_offset_cntl;
+ u32 crtc2_pitch;
+
+ /* Flat panel regs */
+ u32 fp_crtc_h_total_disp;
+ u32 fp_crtc_v_total_disp;
+ u32 fp_gen_cntl;
+ u32 fp2_gen_cntl;
+ u32 fp_h_sync_strt_wid;
+ u32 fp2_h_sync_strt_wid;
+ u32 fp_horz_stretch;
+ u32 fp_panel_cntl;
+ u32 fp_v_sync_strt_wid;
+ u32 fp2_v_sync_strt_wid;
+ u32 fp_vert_stretch;
+ u32 lvds_gen_cntl;
+ u32 lvds_pll_cntl;
+ u32 tmds_crc;
+ u32 tmds_transmitter_cntl;
+
+ /* Computed values for PLL */
+ u32 dot_clock_freq;
+ int feedback_div;
+ int post_div;
+
+ /* PLL registers */
+ u32 ppll_div_3;
+ u32 ppll_ref_div;
+ u32 vclk_ecp_cntl;
+ u32 clk_cntl_index;
+
+ /* Computed values for PLL2 */
+ u32 dot_clock_freq_2;
+ int feedback_div_2;
+ int post_div_2;
+
+ /* PLL2 registers */
+ u32 p2pll_ref_div;
+ u32 p2pll_div_0;
+ u32 htotal_cntl2;
+
+ /* Palette */
+ int palette_valid;
+};
+
+static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
+{
+ u32 data;
+
+ OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
+ /* radeon_pll_errata_after_index(rinfo); */
+ data = INREG(CLOCK_CNTL_DATA);
+ /* radeon_pll_errata_after_data(rinfo); */
+ return data;
+}
+
+static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val)
+{
+
+ OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+ /* radeon_pll_errata_after_index(rinfo); */
+ OUTREG(CLOCK_CNTL_DATA, val);
+ /* radeon_pll_errata_after_data(rinfo); */
+}
+
+static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val, u32 mask)
+{
+ unsigned int tmp;
+
+ tmp = __INPLL(rinfo, index);
+ tmp &= (mask);
+ tmp |= (val);
+ __OUTPLL(rinfo, index, tmp);
+}
+
+#define INPLL(addr) __INPLL(rinfo, addr)
+#define OUTPLL(index, val) __OUTPLL(rinfo, index, val)
+#define OUTPLLP(index, val, mask) __OUTPLLP(rinfo, index, val, mask)
+
+#endif
diff --git a/drivers/bcm570x.c b/drivers/bcm570x.c
index 5f632a6469..c8f4064224 100644
--- a/drivers/bcm570x.c
+++ b/drivers/bcm570x.c
@@ -6,8 +6,8 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && (!defined(CONFIG_NET_MULTI)) && \
- defined(CONFIG_BCM570x)
+#if defined(CONFIG_CMD_NET) \
+ && (!defined(CONFIG_NET_MULTI)) && defined(CONFIG_BCM570x)
#ifdef CONFIG_BMW
#include <mpc824x.h>
@@ -18,7 +18,6 @@
#include <pci.h>
#include <malloc.h>
-
/*
* PCI Registers and definitions.
*/
@@ -31,7 +30,6 @@
#define BCM570X_MBAR 0x80100000
#define BCM570X_ILINE 1
-
#define SECOND_USEC 1000000
#define MAX_PACKET_SIZE 1600
#define MAX_UNITS 4
@@ -39,62 +37,61 @@
/* Globals to this module */
int initialized = 0;
unsigned int ioBase = 0;
-volatile PLM_DEVICE_BLOCK pDevice = NULL; /* 570x softc */
-volatile PUM_DEVICE_BLOCK pUmDevice = NULL;
+volatile PLM_DEVICE_BLOCK pDevice = NULL; /* 570x softc */
+volatile PUM_DEVICE_BLOCK pUmDevice = NULL;
/* Used to pass the full-duplex flag, etc. */
-int line_speed[MAX_UNITS] = {0,0,0,0};
-static int full_duplex[MAX_UNITS] = {1,1,1,1};
-static int rx_flow_control[MAX_UNITS] = {0,0,0,0};
-static int tx_flow_control[MAX_UNITS] = {0,0,0,0};
-static int auto_flow_control[MAX_UNITS] = {0,0,0,0};
-static int tx_checksum[MAX_UNITS] = {1,1,1,1};
-static int rx_checksum[MAX_UNITS] = {1,1,1,1};
-static int auto_speed[MAX_UNITS] = {1,1,1,1};
+int line_speed[MAX_UNITS] = { 0, 0, 0, 0 };
+static int full_duplex[MAX_UNITS] = { 1, 1, 1, 1 };
+static int rx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
+static int tx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
+static int auto_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
+static int tx_checksum[MAX_UNITS] = { 1, 1, 1, 1 };
+static int rx_checksum[MAX_UNITS] = { 1, 1, 1, 1 };
+static int auto_speed[MAX_UNITS] = { 1, 1, 1, 1 };
#if JUMBO_FRAMES
/* Jumbo MTU for interfaces. */
-static int mtu[MAX_UNITS] = {0,0,0,0};
+static int mtu[MAX_UNITS] = { 0, 0, 0, 0 };
#endif
/* Turn on Wake-on lan for a device unit */
-static int enable_wol[MAX_UNITS] = {0,0,0,0};
+static int enable_wol[MAX_UNITS] = { 0, 0, 0, 0 };
#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
- {TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT, TX_DESC_CNT};
+ { TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT };
#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
static unsigned int rx_std_desc_cnt[MAX_UNITS] =
- {RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT};
+ { RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT };
-static unsigned int rx_adaptive_coalesce[MAX_UNITS] = {1,1,1,1};
+static unsigned int rx_adaptive_coalesce[MAX_UNITS] = { 1, 1, 1, 1 };
#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
- {JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT};
+ { JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT };
#endif
#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
static unsigned int rx_coalesce_ticks[MAX_UNITS] =
- {RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK};
+ { RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK };
#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
- {RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM};
+ { RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM };
#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
static unsigned int tx_coalesce_ticks[MAX_UNITS] =
- {TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK};
+ { TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK };
#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
- {TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM};
+ { TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM };
#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
static unsigned int stats_coalesce_ticks[MAX_UNITS] =
- {ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK};
-
+ { ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK };
/*
* Legitimate values for BCM570x device types
@@ -134,707 +131,701 @@ typedef enum {
/* Chip-Rev names for each device-type */
static struct {
- char* name;
+ char *name;
} chip_rev[] = {
- {"BCM5700VIGIL"},
- {"BCM5700A6"},
- {"BCM5700T6"},
- {"BCM5700A9"},
- {"BCM5700T9"},
- {"BCM5700"},
- {"BCM5701A5"},
- {"BCM5701T1"},
- {"BCM5701T8"},
- {"BCM5701A7"},
- {"BCM5701A10"},
- {"BCM5701A12"},
- {"BCM5701"},
- {"BCM5702"},
- {"BCM5703"},
- {"BCM5703A31"},
- {"TC996T"},
- {"TC996ST"},
- {"TC996SSX"},
- {"TC996SX"},
- {"TC996BT"},
- {"TC997T"},
- {"TC997SX"},
- {"TC1000T"},
- {"TC940BR01"},
- {"TC942BR01"},
- {"NC6770"},
- {"NC7760"},
- {"NC7770"},
- {"NC7780"},
- {0}
+ {
+ "BCM5700VIGIL"}, {
+ "BCM5700A6"}, {
+ "BCM5700T6"}, {
+ "BCM5700A9"}, {
+ "BCM5700T9"}, {
+ "BCM5700"}, {
+ "BCM5701A5"}, {
+ "BCM5701T1"}, {
+ "BCM5701T8"}, {
+ "BCM5701A7"}, {
+ "BCM5701A10"}, {
+ "BCM5701A12"}, {
+ "BCM5701"}, {
+ "BCM5702"}, {
+ "BCM5703"}, {
+ "BCM5703A31"}, {
+ "TC996T"}, {
+ "TC996ST"}, {
+ "TC996SSX"}, {
+ "TC996SX"}, {
+ "TC996BT"}, {
+ "TC997T"}, {
+ "TC997SX"}, {
+ "TC1000T"}, {
+ "TC940BR01"}, {
+ "TC942BR01"}, {
+ "NC6770"}, {
+ "NC7760"}, {
+ "NC7770"}, {
+ "NC7780"}, {
+ 0}
};
-
/* indexed by board_t, above */
static struct {
- char *name;
+ char *name;
} board_info[] = {
- { "Broadcom Vigil B5700 1000Base-T" },
- { "Broadcom BCM5700 1000Base-T" },
- { "Broadcom BCM5700 1000Base-SX" },
- { "Broadcom BCM5700 1000Base-SX" },
- { "Broadcom BCM5700 1000Base-T" },
- { "Broadcom BCM5700" },
- { "Broadcom BCM5701 1000Base-T" },
- { "Broadcom BCM5701 1000Base-T" },
- { "Broadcom BCM5701 1000Base-T" },
- { "Broadcom BCM5701 1000Base-SX" },
- { "Broadcom BCM5701 1000Base-T" },
- { "Broadcom BCM5701 1000Base-T" },
- { "Broadcom BCM5701" },
- { "Broadcom BCM5702 1000Base-T" },
- { "Broadcom BCM5703 1000Base-T" },
- { "Broadcom BCM5703 1000Base-SX" },
- { "3Com 3C996 10/100/1000 Server NIC" },
- { "3Com 3C996 10/100/1000 Server NIC" },
- { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
- { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
- { "3Com 3C996B Gigabit Server NIC" },
- { "3Com 3C997 Gigabit Server NIC" },
- { "3Com 3C997 Gigabit Fiber-SX Server NIC" },
- { "3Com 3C1000 Gigabit NIC" },
- { "3Com 3C940 Gigabit LOM (21X21)" },
- { "3Com 3C942 Gigabit LOM (31X31)" },
- { "Compaq NC6770 Gigabit Server Adapter" },
- { "Compaq NC7760 Gigabit Server Adapter" },
- { "Compaq NC7770 Gigabit Server Adapter" },
- { "Compaq NC7780 Gigabit Server Adapter" },
- { 0 },
-};
+ {
+ "Broadcom Vigil B5700 1000Base-T"}, {
+ "Broadcom BCM5700 1000Base-T"}, {
+ "Broadcom BCM5700 1000Base-SX"}, {
+ "Broadcom BCM5700 1000Base-SX"}, {
+ "Broadcom BCM5700 1000Base-T"}, {
+ "Broadcom BCM5700"}, {
+ "Broadcom BCM5701 1000Base-T"}, {
+ "Broadcom BCM5701 1000Base-T"}, {
+ "Broadcom BCM5701 1000Base-T"}, {
+ "Broadcom BCM5701 1000Base-SX"}, {
+ "Broadcom BCM5701 1000Base-T"}, {
+ "Broadcom BCM5701 1000Base-T"}, {
+ "Broadcom BCM5701"}, {
+ "Broadcom BCM5702 1000Base-T"}, {
+ "Broadcom BCM5703 1000Base-T"}, {
+ "Broadcom BCM5703 1000Base-SX"}, {
+ "3Com 3C996 10/100/1000 Server NIC"}, {
+ "3Com 3C996 10/100/1000 Server NIC"}, {
+ "3Com 3C996 Gigabit Fiber-SX Server NIC"}, {
+ "3Com 3C996 Gigabit Fiber-SX Server NIC"}, {
+ "3Com 3C996B Gigabit Server NIC"}, {
+ "3Com 3C997 Gigabit Server NIC"}, {
+ "3Com 3C997 Gigabit Fiber-SX Server NIC"}, {
+ "3Com 3C1000 Gigabit NIC"}, {
+ "3Com 3C940 Gigabit LOM (21X21)"}, {
+ "3Com 3C942 Gigabit LOM (31X31)"}, {
+ "Compaq NC6770 Gigabit Server Adapter"}, {
+ "Compaq NC7760 Gigabit Server Adapter"}, {
+ "Compaq NC7770 Gigabit Server Adapter"}, {
+ "Compaq NC7780 Gigabit Server Adapter"}, {
+0},};
/* PCI Devices which use the 570x chipset */
struct pci_device_table {
- unsigned short vendor_id, device_id; /* Vendor/DeviceID */
- unsigned short subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
- unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
- unsigned long board_id; /* Data private to the driver */
- int io_size, min_latency;
+ unsigned short vendor_id, device_id; /* Vendor/DeviceID */
+ unsigned short subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
+ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
+ unsigned long board_id; /* Data private to the driver */
+ int io_size, min_latency;
} bcm570xDevices[] = {
- {0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL ,128,32},
- {0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 ,128,32},
- {0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 ,128,32},
- {0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 ,128,32},
- {0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 ,128,32},
- {0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 ,128,32},
- {0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 ,128,32},
- {0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 ,128,32},
- {0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 ,128,32},
- {0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T ,128,32},
- {0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST ,128,32},
- {0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX ,128,32},
- {0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T ,128,32},
- {0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX ,128,32},
- {0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 ,128,32},
- {0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 ,128,32},
- {0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 ,128,32},
- {0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 ,128,32},
- {0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 ,128,32},
- {0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 ,128,32},
- {0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 ,128,32},
- {0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 ,128,32},
- {0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 ,128,32},
- {0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 ,128,32},
- {0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 ,128,32},
- {0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 ,128,32},
- {0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX ,128,32},
- {0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT ,128,32},
- {0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T ,128,32},
- {0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 ,128,32},
- {0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 ,128,32},
- {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
- {0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
- {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
- {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
- {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
- {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
- {0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 ,128,32},
- {0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 ,128,32},
- {0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 ,128,32},
- {0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 ,128,32},
- {0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770 ,128,32},
- {0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780 ,128,32},
- {0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 ,128,32},
- {0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 ,128,32},
- {0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 ,128,32},
- {0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 ,128,32},
- {0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 ,128,32},
- {0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770 ,128,32},
- {0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780 ,128,32},
- {0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 ,128,32}
+ {
+ 0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL, 128, 32}, {
+ 0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6, 128, 32}, {
+ 0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6, 128, 32}, {
+ 0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9, 128, 32}, {
+ 0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9, 128, 32}, {
+ 0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700, 128, 32}, {
+ 0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700, 128, 32}, {
+ 0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700, 128, 32}, {
+ 0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700, 128, 32}, {
+ 0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T, 128, 32}, {
+ 0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST, 128, 32}, {
+ 0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX, 128, 32}, {
+ 0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T, 128, 32}, {
+ 0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX, 128, 32}, {
+ 0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01, 128, 32}, {
+ 0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700, 128, 32}, {
+ 0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5, 128, 32}, {
+ 0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1, 128, 32}, {
+ 0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8, 128, 32}, {
+ 0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7, 128, 32}, {
+ 0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10, 128, 32}, {
+ 0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12, 128, 32}, {
+ 0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770, 128, 32}, {
+ 0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770, 128, 32}, {
+ 0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780, 128, 32}, {
+ 0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701, 128, 32}, {
+ 0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX, 128, 32}, {
+ 0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT, 128, 32}, {
+ 0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T, 128, 32}, {
+ 0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01, 128, 32}, {
+ 0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701, 128, 32}, {
+ 0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, {
+ 0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, {
+ 0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, {
+ 0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, {
+ 0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, {
+ 0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, {
+ 0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, {
+ 0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, {
+ 0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, {
+ 0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, {
+ 0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, {
+ 0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, {
+ 0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}, {
+ 0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, {
+ 0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, {
+ 0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, {
+ 0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, {
+ 0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, {
+ 0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, {
+ 0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}
};
#define n570xDevices (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0]))
-
/*
* Allocate a packet buffer from the bcm570x packet pool.
*/
-void *
-bcm570xPktAlloc(int u, int pksize)
+void *bcm570xPktAlloc (int u, int pksize)
{
- return malloc(pksize);
+ return malloc (pksize);
}
/*
* Free a packet previously allocated from the bcm570x packet
* buffer pool.
*/
-void
-bcm570xPktFree(int u, void *p)
+void bcm570xPktFree (int u, void *p)
{
- free(p);
+ free (p);
}
-int
-bcm570xReplenishRxBuffers(PUM_DEVICE_BLOCK pUmDevice)
+int bcm570xReplenishRxBuffers (PUM_DEVICE_BLOCK pUmDevice)
{
- PLM_PACKET pPacket;
- PUM_PACKET pUmPacket;
- void *skb;
- int queue_rx = 0;
- int ret = 0;
-
- while ((pUmPacket = (PUM_PACKET)
- QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
-
- pPacket = (PLM_PACKET) pUmPacket;
-
- /* reuse an old skb */
- if (pUmPacket->skbuff) {
- QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
- queue_rx = 1;
- continue;
- }
- if ( ( skb = bcm570xPktAlloc(pUmDevice->index,
- pPacket->u.Rx.RxBufferSize + 2)) == 0) {
- QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,pPacket);
- printf("NOTICE: Out of RX memory.\n");
- ret = 1;
- break;
- }
+ PLM_PACKET pPacket;
+ PUM_PACKET pUmPacket;
+ void *skb;
+ int queue_rx = 0;
+ int ret = 0;
+
+ while ((pUmPacket = (PUM_PACKET)
+ QQ_PopHead (&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
+
+ pPacket = (PLM_PACKET) pUmPacket;
+
+ /* reuse an old skb */
+ if (pUmPacket->skbuff) {
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container,
+ pPacket);
+ queue_rx = 1;
+ continue;
+ }
+ if ((skb = bcm570xPktAlloc (pUmDevice->index,
+ pPacket->u.Rx.RxBufferSize + 2)) ==
+ 0) {
+ QQ_PushHead (&pUmDevice->rx_out_of_buf_q.Container,
+ pPacket);
+ printf ("NOTICE: Out of RX memory.\n");
+ ret = 1;
+ break;
+ }
- pUmPacket->skbuff = skb;
- QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
- queue_rx = 1;
- }
+ pUmPacket->skbuff = skb;
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
+ queue_rx = 1;
+ }
- if (queue_rx) {
- LM_QueueRxPackets(pDevice);
- }
+ if (queue_rx) {
+ LM_QueueRxPackets (pDevice);
+ }
- return ret;
+ return ret;
}
/*
* Probe, Map, and Init 570x device.
*/
-int eth_init(bd_t *bis)
+int eth_init (bd_t * bis)
{
- int i, rv, devFound = FALSE;
- pci_dev_t devbusfn;
- unsigned short status;
-
- /* Find PCI device, if it exists, configure ... */
- for( i = 0; i < n570xDevices; i++){
- devbusfn = pci_find_device(bcm570xDevices[i].vendor_id,
- bcm570xDevices[i].device_id, 0);
- if(devbusfn == -1) {
- continue; /* No device of that vendor/device ID */
+ int i, rv, devFound = FALSE;
+ pci_dev_t devbusfn;
+ unsigned short status;
+
+ /* Find PCI device, if it exists, configure ... */
+ for (i = 0; i < n570xDevices; i++) {
+ devbusfn = pci_find_device (bcm570xDevices[i].vendor_id,
+ bcm570xDevices[i].device_id, 0);
+ if (devbusfn == -1) {
+ continue; /* No device of that vendor/device ID */
+ } else {
+
+ /* Set ILINE */
+ pci_write_config_byte (devbusfn,
+ PCI_INTERRUPT_LINE,
+ BCM570X_ILINE);
+
+ /*
+ * 0x10 - 0x14 define one 64-bit MBAR.
+ * 0x14 is the higher-order address bits of the BAR.
+ */
+ pci_write_config_dword (devbusfn,
+ PCI_BASE_ADDRESS_1, 0);
+
+ ioBase = BCM570X_MBAR;
+
+ pci_write_config_dword (devbusfn,
+ PCI_BASE_ADDRESS_0, ioBase);
+
+ /*
+ * Enable PCI memory, IO, and Master -- don't
+ * reset any status bits in doing so.
+ */
+ pci_read_config_word (devbusfn, PCI_COMMAND, &status);
+
+ status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+
+ pci_write_config_word (devbusfn, PCI_COMMAND, status);
+
+ printf
+ ("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n",
+ board_info[bcm570xDevices[i].board_id].name,
+ PCI_BUS (devbusfn), PCI_DEV (devbusfn),
+ PCI_FUNC (devbusfn), ioBase);
+
+ /* Allocate once, but always clear on init */
+ if (!pDevice) {
+ pDevice = malloc (sizeof (UM_DEVICE_BLOCK));
+ pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ memset (pDevice, 0x0, sizeof (UM_DEVICE_BLOCK));
+ }
+
+ /* Configure pci dev structure */
+ pUmDevice->pdev = devbusfn;
+ pUmDevice->index = 0;
+ pUmDevice->tx_pkt = 0;
+ pUmDevice->rx_pkt = 0;
+ devFound = TRUE;
+ break;
+ }
+ }
+
+ if (!devFound) {
+ printf
+ ("eth_init: FAILURE: no BCM570x Ethernet devices found.\n");
+ return -1;
+ }
+
+ /* Setup defaults for chip */
+ pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+
+ if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) {
+ pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
} else {
- /* Set ILINE */
- pci_write_config_byte(devbusfn,
- PCI_INTERRUPT_LINE, BCM570X_ILINE);
-
- /*
- * 0x10 - 0x14 define one 64-bit MBAR.
- * 0x14 is the higher-order address bits of the BAR.
- */
- pci_write_config_dword(devbusfn,
- PCI_BASE_ADDRESS_1, 0);
-
- ioBase = BCM570X_MBAR;
-
- pci_write_config_dword(devbusfn,
- PCI_BASE_ADDRESS_0, ioBase);
-
- /*
- * Enable PCI memory, IO, and Master -- don't
- * reset any status bits in doing so.
- */
- pci_read_config_word(devbusfn,
- PCI_COMMAND, &status);
-
- status |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
-
- pci_write_config_word(devbusfn,
- PCI_COMMAND, status);
-
- printf("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n",
- board_info[bcm570xDevices[i].board_id].name,
- PCI_BUS(devbusfn),
- PCI_DEV(devbusfn),
- PCI_FUNC(devbusfn),
- ioBase);
-
- /* Allocate once, but always clear on init */
- if (!pDevice) {
- pDevice = malloc(sizeof(UM_DEVICE_BLOCK));
- pUmDevice = (PUM_DEVICE_BLOCK)pDevice;
- memset(pDevice, 0x0, sizeof(UM_DEVICE_BLOCK));
- }
-
- /* Configure pci dev structure */
- pUmDevice->pdev = devbusfn;
- pUmDevice->index = 0;
- pUmDevice->tx_pkt = 0;
- pUmDevice->rx_pkt = 0;
- devFound = TRUE;
- break;
+ if (rx_checksum[i]) {
+ pDevice->TaskToOffload |=
+ LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
+ LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
+ }
+
+ if (tx_checksum[i]) {
+ pDevice->TaskToOffload |=
+ LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+ LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
+ pDevice->NoTxPseudoHdrChksum = TRUE;
+ }
}
- }
- if(!devFound){
- printf("eth_init: FAILURE: no BCM570x Ethernet devices found.\n");
- return -1;
- }
+ /* Set Device PCI Memory base address */
+ pDevice->pMappedMemBase = (PLM_UINT8) ioBase;
- /* Setup defaults for chip */
- pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+ /* Pull down adapter info */
+ if ((rv = LM_GetAdapterInfo (pDevice)) != LM_STATUS_SUCCESS) {
+ printf ("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv);
+ return -2;
+ }
- if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) {
- pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
- } else {
+ /* Lock not needed */
+ pUmDevice->do_global_lock = 0;
+
+ if (T3_ASIC_REV (pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
+ /* The 5700 chip works best without interleaved register */
+ /* accesses on certain machines. */
+ pUmDevice->do_global_lock = 1;
+ }
+
+ /* Setup timer delays */
+ if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+ pDevice->UseTaggedStatus = TRUE;
+ pUmDevice->timer_interval = CFG_HZ;
+ } else {
+ pUmDevice->timer_interval = CFG_HZ / 50;
+ }
- if (rx_checksum[i]) {
- pDevice->TaskToOffload |=
- LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
- LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
+ /* Grab name .... */
+ pUmDevice->name =
+ (char *)malloc (strlen (board_info[bcm570xDevices[i].board_id].name)
+ + 1);
+ strcpy (pUmDevice->name, board_info[bcm570xDevices[i].board_id].name);
+
+ memcpy (pDevice->NodeAddress, bis->bi_enetaddr, 6);
+ LM_SetMacAddress (pDevice, bis->bi_enetaddr);
+ /* Init queues .. */
+ QQ_InitQueue (&pUmDevice->rx_out_of_buf_q.Container,
+ MAX_RX_PACKET_DESC_COUNT);
+ pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0;
+
+ /* delay for 4 seconds */
+ pUmDevice->delayed_link_ind = (4 * CFG_HZ) / pUmDevice->timer_interval;
+
+ pUmDevice->adaptive_expiry = CFG_HZ / pUmDevice->timer_interval;
+
+ /* Sometimes we get spurious ints. after reset when link is down. */
+ /* This field tells the isr to service the int. even if there is */
+ /* no status block update. */
+ pUmDevice->adapter_just_inited =
+ (3 * CFG_HZ) / pUmDevice->timer_interval;
+
+ /* Initialize 570x */
+ if (LM_InitializeAdapter (pDevice) != LM_STATUS_SUCCESS) {
+ printf ("ERROR: Adapter initialization failed.\n");
+ return ERROR;
}
- if (tx_checksum[i]) {
- pDevice->TaskToOffload |=
- LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
- LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
- pDevice->NoTxPseudoHdrChksum = TRUE;
+ /* Enable chip ISR */
+ LM_EnableInterrupt (pDevice);
+
+ /* Clear MC table */
+ LM_MulticastClear (pDevice);
+
+ /* Enable Multicast */
+ LM_SetReceiveMask (pDevice,
+ pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
+
+ pUmDevice->opened = 1;
+ pUmDevice->tx_full = 0;
+ pUmDevice->tx_pkt = 0;
+ pUmDevice->rx_pkt = 0;
+ printf ("eth%d: %s @0x%lx,",
+ pDevice->index, pUmDevice->name, (unsigned long)ioBase);
+ printf ("node addr ");
+ for (i = 0; i < 6; i++) {
+ printf ("%2.2x", pDevice->NodeAddress[i]);
}
- }
-
- /* Set Device PCI Memory base address */
- pDevice->pMappedMemBase = (PLM_UINT8) ioBase;
-
- /* Pull down adapter info */
- if ((rv = LM_GetAdapterInfo(pDevice)) != LM_STATUS_SUCCESS) {
- printf("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv );
- return -2;
- }
-
- /* Lock not needed */
- pUmDevice->do_global_lock = 0;
-
- if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
- /* The 5700 chip works best without interleaved register */
- /* accesses on certain machines. */
- pUmDevice->do_global_lock = 1;
- }
-
- /* Setup timer delays */
- if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
- pDevice->UseTaggedStatus = TRUE;
- pUmDevice->timer_interval = CFG_HZ;
- }
- else {
- pUmDevice->timer_interval = CFG_HZ / 50;
- }
-
- /* Grab name .... */
- pUmDevice->name =
- (char*)malloc(strlen(board_info[bcm570xDevices[i].board_id].name)+1);
- strcpy(pUmDevice->name,board_info[bcm570xDevices[i].board_id].name);
-
- memcpy(pDevice->NodeAddress, bis->bi_enetaddr, 6);
- LM_SetMacAddress(pDevice, bis->bi_enetaddr);
- /* Init queues .. */
- QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
- MAX_RX_PACKET_DESC_COUNT);
- pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0;
-
- /* delay for 4 seconds */
- pUmDevice->delayed_link_ind =
- (4 * CFG_HZ) / pUmDevice->timer_interval;
-
- pUmDevice->adaptive_expiry =
- CFG_HZ / pUmDevice->timer_interval;
-
- /* Sometimes we get spurious ints. after reset when link is down. */
- /* This field tells the isr to service the int. even if there is */
- /* no status block update. */
- pUmDevice->adapter_just_inited =
- (3 * CFG_HZ) / pUmDevice->timer_interval;
-
- /* Initialize 570x */
- if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
- printf("ERROR: Adapter initialization failed.\n");
- return ERROR;
- }
-
- /* Enable chip ISR */
- LM_EnableInterrupt(pDevice);
-
- /* Clear MC table */
- LM_MulticastClear(pDevice);
-
- /* Enable Multicast */
- LM_SetReceiveMask(pDevice,
- pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
-
- pUmDevice->opened = 1;
- pUmDevice->tx_full = 0;
- pUmDevice->tx_pkt = 0;
- pUmDevice->rx_pkt = 0;
- printf("eth%d: %s @0x%lx,",
- pDevice->index, pUmDevice->name, (unsigned long)ioBase);
- printf( "node addr ");
- for (i = 0; i < 6; i++) {
- printf("%2.2x", pDevice->NodeAddress[i]);
- }
- printf("\n");
-
- printf("eth%d: ", pDevice->index);
- printf("%s with ",
- chip_rev[bcm570xDevices[i].board_id].name);
-
- if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
- printf("Broadcom BCM5400 Copper ");
- else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
- printf("Broadcom BCM5401 Copper ");
- else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
- printf("Broadcom BCM5411 Copper ");
- else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID)
- printf("Broadcom BCM5701 Integrated Copper ");
- else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
- printf("Broadcom BCM5703 Integrated Copper ");
- else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
- printf("Broadcom BCM8002 SerDes ");
- else if (pDevice->EnableTbi)
- printf("Agilent HDMP-1636 SerDes ");
- else
- printf("Unknown ");
- printf("transceiver found\n");
-
- printf("eth%d: %s, MTU: %d,",
- pDevice->index, pDevice->BusSpeedStr, 1500);
-
- if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) &&
- rx_checksum[i])
- printf("Rx Checksum ON\n");
- else
- printf("Rx Checksum OFF\n");
- initialized++;
-
- return 0;
+ printf ("\n");
+
+ printf ("eth%d: ", pDevice->index);
+ printf ("%s with ", chip_rev[bcm570xDevices[i].board_id].name);
+
+ if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
+ printf ("Broadcom BCM5400 Copper ");
+ else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+ printf ("Broadcom BCM5401 Copper ");
+ else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
+ printf ("Broadcom BCM5411 Copper ");
+ else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID)
+ printf ("Broadcom BCM5701 Integrated Copper ");
+ else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
+ printf ("Broadcom BCM5703 Integrated Copper ");
+ else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
+ printf ("Broadcom BCM8002 SerDes ");
+ else if (pDevice->EnableTbi)
+ printf ("Agilent HDMP-1636 SerDes ");
+ else
+ printf ("Unknown ");
+ printf ("transceiver found\n");
+
+ printf ("eth%d: %s, MTU: %d,",
+ pDevice->index, pDevice->BusSpeedStr, 1500);
+
+ if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) && rx_checksum[i])
+ printf ("Rx Checksum ON\n");
+ else
+ printf ("Rx Checksum OFF\n");
+ initialized++;
+
+ return 0;
}
/* Ethernet Interrupt service routine */
-void
-eth_isr(void)
+void eth_isr (void)
{
- LM_UINT32 oldtag, newtag;
- int i;
-
- pUmDevice->interrupt = 1;
-
- if (pDevice->UseTaggedStatus) {
- if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
- pUmDevice->adapter_just_inited) {
- MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
- oldtag = pDevice->pStatusBlkVirt->StatusTag;
-
- for (i = 0; ; i++) {
- pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
- LM_ServiceInterrupts(pDevice);
- newtag = pDevice->pStatusBlkVirt->StatusTag;
- if ((newtag == oldtag) || (i > 50)) {
- MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, newtag << 24);
- if (pDevice->UndiFix) {
- REG_WR(pDevice, Grc.LocalCtrl,
- pDevice->GrcLocalCtrl | 0x2);
- }
- break;
- }
- oldtag = newtag;
- }
+ LM_UINT32 oldtag, newtag;
+ int i;
+
+ pUmDevice->interrupt = 1;
+
+ if (pDevice->UseTaggedStatus) {
+ if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
+ pUmDevice->adapter_just_inited) {
+ MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1);
+ oldtag = pDevice->pStatusBlkVirt->StatusTag;
+
+ for (i = 0;; i++) {
+ pDevice->pStatusBlkVirt->Status &=
+ ~STATUS_BLOCK_UPDATED;
+ LM_ServiceInterrupts (pDevice);
+ newtag = pDevice->pStatusBlkVirt->StatusTag;
+ if ((newtag == oldtag) || (i > 50)) {
+ MB_REG_WR (pDevice,
+ Mailbox.Interrupt[0].Low,
+ newtag << 24);
+ if (pDevice->UndiFix) {
+ REG_WR (pDevice, Grc.LocalCtrl,
+ pDevice->
+ GrcLocalCtrl | 0x2);
+ }
+ break;
+ }
+ oldtag = newtag;
+ }
+ }
+ } else {
+ while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
+ unsigned int dummy;
+
+ pDevice->pMemView->Mailbox.Interrupt[0].Low = 1;
+ pDevice->pStatusBlkVirt->Status &=
+ ~STATUS_BLOCK_UPDATED;
+ LM_ServiceInterrupts (pDevice);
+ pDevice->pMemView->Mailbox.Interrupt[0].Low = 0;
+ dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low;
+ }
}
- }
- else {
- while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
- unsigned int dummy;
-
- pDevice->pMemView->Mailbox.Interrupt[0].Low = 1;
- pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
- LM_ServiceInterrupts(pDevice);
- pDevice->pMemView->Mailbox.Interrupt[0].Low = 0;
- dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low;
+
+ /* Allocate new RX buffers */
+ if (QQ_GetEntryCnt (&pUmDevice->rx_out_of_buf_q.Container)) {
+ bcm570xReplenishRxBuffers (pUmDevice);
+ }
+
+ /* Queue packets */
+ if (QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container)) {
+ LM_QueueRxPackets (pDevice);
}
- }
-
- /* Allocate new RX buffers */
- if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
- bcm570xReplenishRxBuffers(pUmDevice);
- }
-
- /* Queue packets */
- if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container)) {
- LM_QueueRxPackets(pDevice);
- }
-
- if (pUmDevice->tx_queued) {
- pUmDevice->tx_queued = 0;
- }
-
- if(pUmDevice->tx_full){
- if(pDevice->LinkStatus != LM_STATUS_LINK_DOWN){
- printf("NOTICE: tx was previously blocked, restarting MUX\n");
- pUmDevice->tx_full = 0;
+
+ if (pUmDevice->tx_queued) {
+ pUmDevice->tx_queued = 0;
+ }
+
+ if (pUmDevice->tx_full) {
+ if (pDevice->LinkStatus != LM_STATUS_LINK_DOWN) {
+ printf
+ ("NOTICE: tx was previously blocked, restarting MUX\n");
+ pUmDevice->tx_full = 0;
+ }
}
- }
- pUmDevice->interrupt = 0;
+ pUmDevice->interrupt = 0;
}
-int
-eth_send(volatile void *packet, int length)
+int eth_send (volatile void *packet, int length)
{
- int status = 0;
+ int status = 0;
#if ET_DEBUG
- unsigned char* ptr = (unsigned char*)packet;
+ unsigned char *ptr = (unsigned char *)packet;
#endif
- PLM_PACKET pPacket;
- PUM_PACKET pUmPacket;
+ PLM_PACKET pPacket;
+ PUM_PACKET pUmPacket;
- /* Link down, return */
- while(pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
+ /* Link down, return */
+ while (pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
#if 0
- printf("eth%d: link down - check cable or link partner.\n",
- pUmDevice->index);
+ printf ("eth%d: link down - check cable or link partner.\n",
+ pUmDevice->index);
#endif
- eth_isr();
+ eth_isr ();
- /* Wait to see link for one-half a second before sending ... */
- udelay(1500000);
+ /* Wait to see link for one-half a second before sending ... */
+ udelay (1500000);
- }
+ }
- /* Clear sent flag */
- pUmDevice->tx_pkt = 0;
+ /* Clear sent flag */
+ pUmDevice->tx_pkt = 0;
- /* Previously blocked */
- if(pUmDevice->tx_full){
- printf("eth%d: tx blocked.\n", pUmDevice->index);
- return 0;
- }
+ /* Previously blocked */
+ if (pUmDevice->tx_full) {
+ printf ("eth%d: tx blocked.\n", pUmDevice->index);
+ return 0;
+ }
- pPacket = (PLM_PACKET)
- QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
+ pPacket = (PLM_PACKET)
+ QQ_PopHead (&pDevice->TxPacketFreeQ.Container);
- if (pPacket == 0) {
- pUmDevice->tx_full = 1;
- printf("bcm570xEndSend: TX full!\n");
- return 0;
- }
+ if (pPacket == 0) {
+ pUmDevice->tx_full = 1;
+ printf ("bcm570xEndSend: TX full!\n");
+ return 0;
+ }
- if (pDevice->SendBdLeft.counter == 0) {
- pUmDevice->tx_full = 1;
- printf("bcm570xEndSend: no more TX descriptors!\n");
- QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
- return 0;
- }
-
- if (length <= 0){
- printf("eth: bad packet size: %d\n", length);
- goto out;
- }
-
- /* Get packet buffers and fragment list */
- pUmPacket = (PUM_PACKET) pPacket;
- /* Single DMA Descriptor transmit.
- * Fragments may be provided, but one DMA descriptor max is
- * used to send the packet.
- */
- if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) {
- if (pUmPacket->skbuff == NULL){
- /* Packet was discarded */
- printf("TX: failed (1)\n");
- status = 1;
- } else{
- printf("TX: failed (2)\n");
- status = 2;
+ if (pDevice->SendBdLeft.counter == 0) {
+ pUmDevice->tx_full = 1;
+ printf ("bcm570xEndSend: no more TX descriptors!\n");
+ QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
+ return 0;
}
- QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
- return status;
- }
-
- /* Copy packet to DMA buffer */
- memset(pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
- memcpy((void*)pUmPacket->skbuff, (void*)packet, length);
- pPacket->PacketSize = length;
- pPacket->Flags |= SND_BD_FLAG_END|SND_BD_FLAG_COAL_NOW;
- pPacket->u.Tx.FragCount = 1;
- /* We've already provided a frame ready for transmission */
- pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
-
- if ( LM_SendPacket(pDevice, pPacket) == LM_STATUS_FAILURE){
- /*
- * A lower level send failure will push the packet descriptor back
- * in the free queue, so just deal with the VxWorks clusters.
+
+ if (length <= 0) {
+ printf ("eth: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ /* Get packet buffers and fragment list */
+ pUmPacket = (PUM_PACKET) pPacket;
+ /* Single DMA Descriptor transmit.
+ * Fragments may be provided, but one DMA descriptor max is
+ * used to send the packet.
*/
- if (pUmPacket->skbuff == NULL){
- printf("TX failed (1)!\n");
- /* Packet was discarded */
- status = 3;
- } else {
- /* A resource problem ... */
- printf("TX failed (2)!\n");
- status = 4;
+ if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) {
+ if (pUmPacket->skbuff == NULL) {
+ /* Packet was discarded */
+ printf ("TX: failed (1)\n");
+ status = 1;
+ } else {
+ printf ("TX: failed (2)\n");
+ status = 2;
+ }
+ QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
+ return status;
}
- if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) == 0) {
- printf("TX: emptyQ!\n");
- pUmDevice->tx_full = 1;
+ /* Copy packet to DMA buffer */
+ memset (pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
+ memcpy ((void *)pUmPacket->skbuff, (void *)packet, length);
+ pPacket->PacketSize = length;
+ pPacket->Flags |= SND_BD_FLAG_END | SND_BD_FLAG_COAL_NOW;
+ pPacket->u.Tx.FragCount = 1;
+ /* We've already provided a frame ready for transmission */
+ pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
+
+ if (LM_SendPacket (pDevice, pPacket) == LM_STATUS_FAILURE) {
+ /*
+ * A lower level send failure will push the packet descriptor back
+ * in the free queue, so just deal with the VxWorks clusters.
+ */
+ if (pUmPacket->skbuff == NULL) {
+ printf ("TX failed (1)!\n");
+ /* Packet was discarded */
+ status = 3;
+ } else {
+ /* A resource problem ... */
+ printf ("TX failed (2)!\n");
+ status = 4;
+ }
+
+ if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) == 0) {
+ printf ("TX: emptyQ!\n");
+ pUmDevice->tx_full = 1;
+ }
}
- }
- while(pUmDevice->tx_pkt == 0){
- /* Service TX */
- eth_isr();
- }
+ while (pUmDevice->tx_pkt == 0) {
+ /* Service TX */
+ eth_isr ();
+ }
#if ET_DEBUG
- printf("eth_send: 0x%x, %d bytes\n"
- "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n",
- (int)pPacket, length,
- ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],
- ptr[6],ptr[7],ptr[8],ptr[9],ptr[10],ptr[11],ptr[12],
- ptr[13],ptr[14],ptr[15]);
+ printf ("eth_send: 0x%x, %d bytes\n"
+ "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n",
+ (int)pPacket, length,
+ ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5],
+ ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12],
+ ptr[13], ptr[14], ptr[15]);
#endif
- pUmDevice->tx_pkt = 0;
- QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+ pUmDevice->tx_pkt = 0;
+ QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
- /* Done with send */
- out:
- return status;
+ /* Done with send */
+ out:
+ return status;
}
-
/* Ethernet receive */
-int
-eth_rx(void)
+int eth_rx (void)
{
- PLM_PACKET pPacket = NULL;
- PUM_PACKET pUmPacket = NULL;
- void *skb;
- int size=0;
+ PLM_PACKET pPacket = NULL;
+ PUM_PACKET pUmPacket = NULL;
+ void *skb;
+ int size = 0;
- while(TRUE) {
+ while (TRUE) {
- bcm570x_service_isr:
- /* Pull down packet if it is there */
- eth_isr();
+ bcm570x_service_isr:
+ /* Pull down packet if it is there */
+ eth_isr ();
- /* Indicate RX packets called */
- if(pUmDevice->rx_pkt){
- /* printf("eth_rx: got a packet...\n"); */
- pUmDevice->rx_pkt = 0;
- } else {
- /* printf("eth_rx: waiting for packet...\n"); */
- goto bcm570x_service_isr;
- }
+ /* Indicate RX packets called */
+ if (pUmDevice->rx_pkt) {
+ /* printf("eth_rx: got a packet...\n"); */
+ pUmDevice->rx_pkt = 0;
+ } else {
+ /* printf("eth_rx: waiting for packet...\n"); */
+ goto bcm570x_service_isr;
+ }
- pPacket = (PLM_PACKET)
- QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
+ pPacket = (PLM_PACKET)
+ QQ_PopHead (&pDevice->RxPacketReceivedQ.Container);
- if (pPacket == 0){
- printf("eth_rx: empty packet!\n");
- goto bcm570x_service_isr;
- }
+ if (pPacket == 0) {
+ printf ("eth_rx: empty packet!\n");
+ goto bcm570x_service_isr;
+ }
- pUmPacket = (PUM_PACKET) pPacket;
+ pUmPacket = (PUM_PACKET) pPacket;
#if ET_DEBUG
- printf("eth_rx: packet @0x%x\n",
- (int)pPacket);
+ printf ("eth_rx: packet @0x%x\n", (int)pPacket);
#endif
- /* If the packet generated an error, reuse buffer */
- if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
- ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
-
- /* reuse skb */
- QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
- printf("eth_rx: error in packet dma!\n");
- goto bcm570x_service_isr;
- }
+ /* If the packet generated an error, reuse buffer */
+ if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
+ ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
+
+ /* reuse skb */
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container,
+ pPacket);
+ printf ("eth_rx: error in packet dma!\n");
+ goto bcm570x_service_isr;
+ }
- /* Set size and address */
- skb = pUmPacket->skbuff;
- size = pPacket->PacketSize;
+ /* Set size and address */
+ skb = pUmPacket->skbuff;
+ size = pPacket->PacketSize;
- /* Pass the packet up to the protocol
- * layers.
- */
- NetReceive(skb, size);
+ /* Pass the packet up to the protocol
+ * layers.
+ */
+ NetReceive (skb, size);
- /* Free packet buffer */
- bcm570xPktFree (pUmDevice->index, skb);
- pUmPacket->skbuff = NULL;
+ /* Free packet buffer */
+ bcm570xPktFree (pUmDevice->index, skb);
+ pUmPacket->skbuff = NULL;
- /* Reuse SKB */
- QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+ /* Reuse SKB */
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
- return 0; /* Got a packet, bail ... */
- }
- return size;
+ return 0; /* Got a packet, bail ... */
+ }
+ return size;
}
-
/* Shut down device */
-void
-eth_halt(void)
+void eth_halt (void)
{
- int i;
- if ( initialized)
- if (pDevice && pUmDevice && pUmDevice->opened){
- printf("\neth%d:%s,", pUmDevice->index, pUmDevice->name);
- printf("HALT,");
- /* stop device */
- LM_Halt(pDevice);
- printf("POWER DOWN,");
- LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
-
- /* Free the memory allocated by the device in tigon3 */
- for (i = 0; i < pUmDevice->mem_list_num; i++) {
- if (pUmDevice->mem_list[i]) {
- /* sanity check */
- if (pUmDevice->dma_list[i]) { /* cache-safe memory */
- free(pUmDevice->mem_list[i]);
- } else {
- free(pUmDevice->mem_list[i]); /* normal memory */
+ int i;
+ if (initialized)
+ if (pDevice && pUmDevice && pUmDevice->opened) {
+ printf ("\neth%d:%s,", pUmDevice->index,
+ pUmDevice->name);
+ printf ("HALT,");
+ /* stop device */
+ LM_Halt (pDevice);
+ printf ("POWER DOWN,");
+ LM_SetPowerState (pDevice, LM_POWER_STATE_D3);
+
+ /* Free the memory allocated by the device in tigon3 */
+ for (i = 0; i < pUmDevice->mem_list_num; i++) {
+ if (pUmDevice->mem_list[i]) {
+ /* sanity check */
+ if (pUmDevice->dma_list[i]) { /* cache-safe memory */
+ free (pUmDevice->mem_list[i]);
+ } else {
+ free (pUmDevice->mem_list[i]); /* normal memory */
+ }
+ }
+ }
+ pUmDevice->opened = 0;
+ free (pDevice);
+ pDevice = NULL;
+ pUmDevice = NULL;
+ initialized = 0;
+ printf ("done - offline.\n");
}
- }
- }
- pUmDevice->opened = 0;
- free(pDevice);
- pDevice = NULL;
- pUmDevice = NULL;
- initialized = 0;
- printf("done - offline.\n");
- }
}
-
/*
*
* Middle Module: Interface between the HW driver (tigon3 modules) and
@@ -843,409 +834,380 @@ eth_halt(void)
*/
/* Middle module dependency - size of a packet descriptor */
-int MM_Packet_Desc_Size = sizeof(UM_PACKET);
-
+int MM_Packet_Desc_Size = sizeof (UM_PACKET);
LM_STATUS
-MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice,
- LM_UINT32 Offset,
- LM_UINT32 *pValue32)
+MM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice,
+ LM_UINT32 Offset, LM_UINT32 * pValue32)
{
- UM_DEVICE_BLOCK *pUmDevice;
- pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
- pci_read_config_dword(pUmDevice->pdev,
- Offset, (u32 *) pValue32);
- return LM_STATUS_SUCCESS;
+ UM_DEVICE_BLOCK *pUmDevice;
+ pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+ pci_read_config_dword (pUmDevice->pdev, Offset, (u32 *) pValue32);
+ return LM_STATUS_SUCCESS;
}
-
LM_STATUS
-MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice,
- LM_UINT32 Offset,
- LM_UINT32 Value32)
+MM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 Value32)
{
- UM_DEVICE_BLOCK *pUmDevice;
- pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
- pci_write_config_dword(pUmDevice->pdev,
- Offset, Value32);
- return LM_STATUS_SUCCESS;
+ UM_DEVICE_BLOCK *pUmDevice;
+ pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+ pci_write_config_dword (pUmDevice->pdev, Offset, Value32);
+ return LM_STATUS_SUCCESS;
}
-
LM_STATUS
-MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice,
- LM_UINT32 Offset,
- LM_UINT16 *pValue16)
+MM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice,
+ LM_UINT32 Offset, LM_UINT16 * pValue16)
{
- UM_DEVICE_BLOCK *pUmDevice;
- pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
- pci_read_config_word(pUmDevice->pdev,
- Offset, (u16*) pValue16);
- return LM_STATUS_SUCCESS;
+ UM_DEVICE_BLOCK *pUmDevice;
+ pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+ pci_read_config_word (pUmDevice->pdev, Offset, (u16 *) pValue16);
+ return LM_STATUS_SUCCESS;
}
LM_STATUS
-MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice,
- LM_UINT32 Offset,
- LM_UINT16 Value16)
+MM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT16 Value16)
{
- UM_DEVICE_BLOCK *pUmDevice;
- pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
- pci_write_config_word(pUmDevice->pdev,
- Offset, Value16);
- return LM_STATUS_SUCCESS;
+ UM_DEVICE_BLOCK *pUmDevice;
+ pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+ pci_write_config_word (pUmDevice->pdev, Offset, Value16);
+ return LM_STATUS_SUCCESS;
}
-
LM_STATUS
-MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
- PLM_VOID *pMemoryBlockVirt,
- PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
- LM_BOOL Cached)
+MM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+ PLM_VOID * pMemoryBlockVirt,
+ PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, LM_BOOL Cached)
{
- PLM_VOID pvirt;
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- dma_addr_t mapping;
+ PLM_VOID pvirt;
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ dma_addr_t mapping;
- pvirt = malloc(BlockSize);
- mapping = (dma_addr_t)(pvirt);
- if (!pvirt)
- return LM_STATUS_FAILURE;
+ pvirt = malloc (BlockSize);
+ mapping = (dma_addr_t) (pvirt);
+ if (!pvirt)
+ return LM_STATUS_FAILURE;
- pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
- pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
- pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
- memset(pvirt, 0, BlockSize);
+ pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+ pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
+ pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+ memset (pvirt, 0, BlockSize);
- *pMemoryBlockVirt = (PLM_VOID) pvirt;
- MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping);
+ *pMemoryBlockVirt = (PLM_VOID) pvirt;
+ MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping);
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-
LM_STATUS
-MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
- PLM_VOID *pMemoryBlockVirt)
+MM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+ PLM_VOID * pMemoryBlockVirt)
{
- PLM_VOID pvirt;
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ PLM_VOID pvirt;
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- pvirt = malloc(BlockSize);
+ pvirt = malloc (BlockSize);
- if (!pvirt)
- return LM_STATUS_FAILURE;
+ if (!pvirt)
+ return LM_STATUS_FAILURE;
- pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
- pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
- pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
- memset(pvirt, 0, BlockSize);
- *pMemoryBlockVirt = pvirt;
+ pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+ pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
+ pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+ memset (pvirt, 0, BlockSize);
+ *pMemoryBlockVirt = pvirt;
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-LM_STATUS
-MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
+LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice)
{
- printf("BCM570x PCI Memory base address @0x%x\n",
- (unsigned int)pDevice->pMappedMemBase);
- return LM_STATUS_SUCCESS;
+ printf ("BCM570x PCI Memory base address @0x%x\n",
+ (unsigned int)pDevice->pMappedMemBase);
+ return LM_STATUS_SUCCESS;
}
-LM_STATUS
-MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
+LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice)
{
- int i;
- void* skb;
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- PUM_PACKET pUmPacket = NULL;
- PLM_PACKET pPacket = NULL;
-
- for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
- pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
- pUmPacket = (PUM_PACKET) pPacket;
+ int i;
+ void *skb;
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ PUM_PACKET pUmPacket = NULL;
+ PLM_PACKET pPacket = NULL;
+
+ for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
+ pPacket = QQ_PopHead (&pDevice->RxPacketFreeQ.Container);
+ pUmPacket = (PUM_PACKET) pPacket;
+
+ if (pPacket == 0) {
+ printf ("MM_InitializeUmPackets: Bad RxPacketFreeQ\n");
+ }
- if (pPacket == 0) {
- printf("MM_InitializeUmPackets: Bad RxPacketFreeQ\n");
- }
+ skb = bcm570xPktAlloc (pUmDevice->index,
+ pPacket->u.Rx.RxBufferSize + 2);
- skb = bcm570xPktAlloc(pUmDevice->index,
- pPacket->u.Rx.RxBufferSize + 2);
+ if (skb == 0) {
+ pUmPacket->skbuff = 0;
+ QQ_PushTail (&pUmDevice->rx_out_of_buf_q.Container,
+ pPacket);
+ printf ("MM_InitializeUmPackets: out of buffer.\n");
+ continue;
+ }
- if (skb == 0) {
- pUmPacket->skbuff = 0;
- QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
- printf("MM_InitializeUmPackets: out of buffer.\n");
- continue;
+ pUmPacket->skbuff = skb;
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
}
- pUmPacket->skbuff = skb;
- QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
- }
+ pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8;
- pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8;
-
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-LM_STATUS
-MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
+LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice)
{
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- int index = pDevice->index;
-
- if (auto_speed[index] == 0)
- pDevice->DisableAutoNeg = TRUE;
- else
- pDevice->DisableAutoNeg = FALSE;
-
- if (line_speed[index] == 0) {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_AUTO;
- pDevice->DisableAutoNeg = FALSE;
- }
- else {
- if (line_speed[index] == 1000) {
- if (pDevice->EnableTbi) {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX;
- }
- else if (full_duplex[index]) {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX;
- }
- else {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS;
- }
- if (!pDevice->EnableTbi)
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ int index = pDevice->index;
+
+ if (auto_speed[index] == 0)
+ pDevice->DisableAutoNeg = TRUE;
+ else
pDevice->DisableAutoNeg = FALSE;
+
+ if (line_speed[index] == 0) {
+ pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO;
+ pDevice->DisableAutoNeg = FALSE;
+ } else {
+ if (line_speed[index] == 1000) {
+ if (pDevice->EnableTbi) {
+ pDevice->RequestedMediaType =
+ LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX;
+ } else if (full_duplex[index]) {
+ pDevice->RequestedMediaType =
+ LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX;
+ } else {
+ pDevice->RequestedMediaType =
+ LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS;
+ }
+ if (!pDevice->EnableTbi)
+ pDevice->DisableAutoNeg = FALSE;
+ } else if (line_speed[index] == 100) {
+ if (full_duplex[index]) {
+ pDevice->RequestedMediaType =
+ LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX;
+ } else {
+ pDevice->RequestedMediaType =
+ LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS;
+ }
+ } else if (line_speed[index] == 10) {
+ if (full_duplex[index]) {
+ pDevice->RequestedMediaType =
+ LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX;
+ } else {
+ pDevice->RequestedMediaType =
+ LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
+ }
+ } else {
+ pDevice->RequestedMediaType =
+ LM_REQUESTED_MEDIA_TYPE_AUTO;
+ pDevice->DisableAutoNeg = FALSE;
+ }
+
}
- else if (line_speed[index] == 100) {
- if (full_duplex[index]) {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX;
- }
- else {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS;
- }
- }
- else if (line_speed[index] == 10) {
- if (full_duplex[index]) {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX;
- }
- else {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
- }
+ pDevice->FlowControlCap = 0;
+ if (rx_flow_control[index] != 0) {
+ pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
}
- else {
- pDevice->RequestedMediaType =
- LM_REQUESTED_MEDIA_TYPE_AUTO;
- pDevice->DisableAutoNeg = FALSE;
+ if (tx_flow_control[index] != 0) {
+ pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
}
-
- }
- pDevice->FlowControlCap = 0;
- if (rx_flow_control[index] != 0) {
- pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
- }
- if (tx_flow_control[index] != 0) {
- pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
- }
- if ((auto_flow_control[index] != 0) &&
- (pDevice->DisableAutoNeg == FALSE)) {
-
- pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
- if ((tx_flow_control[index] == 0) &&
- (rx_flow_control[index] == 0)) {
- pDevice->FlowControlCap |=
- LM_FLOW_CONTROL_TRANSMIT_PAUSE |
- LM_FLOW_CONTROL_RECEIVE_PAUSE;
+ if ((auto_flow_control[index] != 0) &&
+ (pDevice->DisableAutoNeg == FALSE)) {
+
+ pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
+ if ((tx_flow_control[index] == 0) &&
+ (rx_flow_control[index] == 0)) {
+ pDevice->FlowControlCap |=
+ LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+ LM_FLOW_CONTROL_RECEIVE_PAUSE;
+ }
}
- }
- /* Default MTU for now */
- pUmDevice->mtu = 1500;
+ /* Default MTU for now */
+ pUmDevice->mtu = 1500;
#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
- if (pUmDevice->mtu > 1500) {
- pDevice->RxMtu = pUmDevice->mtu;
- pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
- }
- else {
- pDevice->RxJumboDescCnt = 0;
- }
- pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
+ if (pUmDevice->mtu > 1500) {
+ pDevice->RxMtu = pUmDevice->mtu;
+ pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+ } else {
+ pDevice->RxJumboDescCnt = 0;
+ }
+ pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
#else
- pDevice->RxMtu = pUmDevice->mtu;
+ pDevice->RxMtu = pUmDevice->mtu;
#endif
- if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
- pDevice->UseTaggedStatus = TRUE;
- pUmDevice->timer_interval = CFG_HZ;
- }
- else {
- pUmDevice->timer_interval = CFG_HZ/50;
- }
-
- pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
- pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
- /* Note: adaptive coalescence really isn't adaptive in this driver */
- pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index];
- if (!pUmDevice->rx_adaptive_coalesce) {
- pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
- if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS)
- pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS;
- pUmDevice->rx_curr_coalesce_ticks =pDevice->RxCoalescingTicks;
-
- pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
- if (pDevice->RxMaxCoalescedFrames>MAX_RX_MAX_COALESCED_FRAMES)
- pDevice->RxMaxCoalescedFrames =
- MAX_RX_MAX_COALESCED_FRAMES;
- pUmDevice->rx_curr_coalesce_frames =
- pDevice->RxMaxCoalescedFrames;
- pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
- if (pDevice->StatsCoalescingTicks>MAX_STATS_COALESCING_TICKS)
- pDevice->StatsCoalescingTicks=
- MAX_STATS_COALESCING_TICKS;
- }
- else {
- pUmDevice->rx_curr_coalesce_frames =
- DEFAULT_RX_MAX_COALESCED_FRAMES;
- pUmDevice->rx_curr_coalesce_ticks =
- DEFAULT_RX_COALESCING_TICKS;
+ if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+ pDevice->UseTaggedStatus = TRUE;
+ pUmDevice->timer_interval = CFG_HZ;
+ } else {
+ pUmDevice->timer_interval = CFG_HZ / 50;
}
- pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
- if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS)
- pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS;
- pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
- if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES)
- pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES;
- if (enable_wol[index]) {
- pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
- pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
- }
- pDevice->NicSendBd = TRUE;
+ pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
+ pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
+ /* Note: adaptive coalescence really isn't adaptive in this driver */
+ pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index];
+ if (!pUmDevice->rx_adaptive_coalesce) {
+ pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
+ if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS)
+ pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS;
+ pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks;
+
+ pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
+ if (pDevice->RxMaxCoalescedFrames > MAX_RX_MAX_COALESCED_FRAMES)
+ pDevice->RxMaxCoalescedFrames =
+ MAX_RX_MAX_COALESCED_FRAMES;
+ pUmDevice->rx_curr_coalesce_frames =
+ pDevice->RxMaxCoalescedFrames;
+ pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
+ if (pDevice->StatsCoalescingTicks > MAX_STATS_COALESCING_TICKS)
+ pDevice->StatsCoalescingTicks =
+ MAX_STATS_COALESCING_TICKS;
+ } else {
+ pUmDevice->rx_curr_coalesce_frames =
+ DEFAULT_RX_MAX_COALESCED_FRAMES;
+ pUmDevice->rx_curr_coalesce_ticks = DEFAULT_RX_COALESCING_TICKS;
+ }
+ pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
+ if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS)
+ pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS;
+ pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
+ if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES)
+ pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES;
+
+ if (enable_wol[index]) {
+ pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
+ pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
+ }
+ pDevice->NicSendBd = TRUE;
- /* Don't update status blocks during interrupt */
- pDevice->RxCoalescingTicksDuringInt = 0;
- pDevice->TxCoalescingTicksDuringInt = 0;
+ /* Don't update status blocks during interrupt */
+ pDevice->RxCoalescingTicksDuringInt = 0;
+ pDevice->TxCoalescingTicksDuringInt = 0;
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-
-LM_STATUS
-MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+LM_STATUS MM_StartTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
{
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- printf("Start TX DMA: dev=%d packet @0x%x\n",
- (int)pUmDevice->index, (unsigned int)pPacket);
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ printf ("Start TX DMA: dev=%d packet @0x%x\n",
+ (int)pUmDevice->index, (unsigned int)pPacket);
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-LM_STATUS
-MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+LM_STATUS MM_CompleteTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
{
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- printf("Complete TX DMA: dev=%d packet @0x%x\n",
- (int)pUmDevice->index, (unsigned int)pPacket);
- return LM_STATUS_SUCCESS;
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ printf ("Complete TX DMA: dev=%d packet @0x%x\n",
+ (int)pUmDevice->index, (unsigned int)pPacket);
+ return LM_STATUS_SUCCESS;
}
-
-LM_STATUS
-MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
+LM_STATUS MM_IndicateStatus (PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
{
- char buf[128];
- char lcd[4];
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- LM_FLOW_CONTROL flow_control;
-
- pUmDevice->delayed_link_ind = 0;
- memset(lcd, 0x0, 4);
-
- if (Status == LM_STATUS_LINK_DOWN) {
- sprintf(buf,"eth%d: %s: NIC Link is down\n",
- pUmDevice->index,pUmDevice->name);
- lcd[0] = 'L';lcd[1]='N';lcd[2]='K';lcd[3] = '?';
- } else if (Status == LM_STATUS_LINK_ACTIVE) {
- sprintf(buf,"eth%d:%s: ", pUmDevice->index, pUmDevice->name);
-
- if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS){
- strcat(buf,"1000 Mbps ");
- lcd[0] = '1';lcd[1]='G';lcd[2]='B';
- } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS){
- strcat(buf,"100 Mbps ");
- lcd[0] = '1';lcd[1]='0';lcd[2]='0';
- } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS){
- strcat(buf,"10 Mbps ");
- lcd[0] = '1';lcd[1]='0';lcd[2]=' ';
- }
- if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL){
- strcat(buf, "full duplex");
- lcd[3] = 'F';
- } else {
- strcat(buf, "half duplex");
- lcd[3] = 'H';
- }
- strcat(buf, " link up");
-
- flow_control = pDevice->FlowControl &
- (LM_FLOW_CONTROL_RECEIVE_PAUSE |
- LM_FLOW_CONTROL_TRANSMIT_PAUSE);
-
- if (flow_control) {
- if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
- strcat(buf,", receive ");
- if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
- strcat(buf," & transmit ");
- }
- else {
- strcat(buf,", transmit ");
- }
- strcat(buf,"flow control ON");
- } else {
- strcat(buf, ", flow control OFF");
+ char buf[128];
+ char lcd[4];
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ LM_FLOW_CONTROL flow_control;
+
+ pUmDevice->delayed_link_ind = 0;
+ memset (lcd, 0x0, 4);
+
+ if (Status == LM_STATUS_LINK_DOWN) {
+ sprintf (buf, "eth%d: %s: NIC Link is down\n",
+ pUmDevice->index, pUmDevice->name);
+ lcd[0] = 'L';
+ lcd[1] = 'N';
+ lcd[2] = 'K';
+ lcd[3] = '?';
+ } else if (Status == LM_STATUS_LINK_ACTIVE) {
+ sprintf (buf, "eth%d:%s: ", pUmDevice->index, pUmDevice->name);
+
+ if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) {
+ strcat (buf, "1000 Mbps ");
+ lcd[0] = '1';
+ lcd[1] = 'G';
+ lcd[2] = 'B';
+ } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) {
+ strcat (buf, "100 Mbps ");
+ lcd[0] = '1';
+ lcd[1] = '0';
+ lcd[2] = '0';
+ } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) {
+ strcat (buf, "10 Mbps ");
+ lcd[0] = '1';
+ lcd[1] = '0';
+ lcd[2] = ' ';
+ }
+ if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) {
+ strcat (buf, "full duplex");
+ lcd[3] = 'F';
+ } else {
+ strcat (buf, "half duplex");
+ lcd[3] = 'H';
+ }
+ strcat (buf, " link up");
+
+ flow_control = pDevice->FlowControl &
+ (LM_FLOW_CONTROL_RECEIVE_PAUSE |
+ LM_FLOW_CONTROL_TRANSMIT_PAUSE);
+
+ if (flow_control) {
+ if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
+ strcat (buf, ", receive ");
+ if (flow_control &
+ LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+ strcat (buf, " & transmit ");
+ } else {
+ strcat (buf, ", transmit ");
+ }
+ strcat (buf, "flow control ON");
+ } else {
+ strcat (buf, ", flow control OFF");
+ }
+ strcat (buf, "\n");
+ printf ("%s", buf);
}
- strcat(buf,"\n");
- printf("%s",buf);
- }
#if 0
- sysLedDsply(lcd[0],lcd[1],lcd[2],lcd[3]);
+ sysLedDsply (lcd[0], lcd[1], lcd[2], lcd[3]);
#endif
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-LM_STATUS
-MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+LM_STATUS MM_FreeRxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
{
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- PUM_PACKET pUmPacket;
- void *skb;
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ PUM_PACKET pUmPacket;
+ void *skb;
- pUmPacket = (PUM_PACKET) pPacket;
+ pUmPacket = (PUM_PACKET) pPacket;
- if ((skb = pUmPacket->skbuff))
- bcm570xPktFree(pUmDevice->index, skb);
+ if ((skb = pUmPacket->skbuff))
+ bcm570xPktFree (pUmDevice->index, skb);
- pUmPacket->skbuff = 0;
+ pUmPacket->skbuff = 0;
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-unsigned long
-MM_AnGetCurrentTime_us(PAN_STATE_INFO pAnInfo)
+unsigned long MM_AnGetCurrentTime_us (PAN_STATE_INFO pAnInfo)
{
- return get_timer(0);
+ return get_timer (0);
}
/*
@@ -1258,86 +1220,82 @@ MM_AnGetCurrentTime_us(PAN_STATE_INFO pAnInfo)
* non-fatal. The incoming cluster chain is not freed, giving
* the caller the choice of whether to try a retransmit later.
*/
-LM_STATUS
-MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+LM_STATUS MM_CoalesceTxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
{
- PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- void *skbnew;
- int len = 0;
-
- if (len == 0)
- return (LM_STATUS_SUCCESS);
-
- if (len > MAX_PACKET_SIZE){
- printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
- pUmDevice->index, len);
- return (LM_STATUS_FAILURE);
- }
+ PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ void *skbnew;
+ int len = 0;
+
+ if (len == 0)
+ return (LM_STATUS_SUCCESS);
+
+ if (len > MAX_PACKET_SIZE) {
+ printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
+ pUmDevice->index, len);
+ return (LM_STATUS_FAILURE);
+ }
- skbnew = bcm570xPktAlloc(pUmDevice->index, MAX_PACKET_SIZE);
+ skbnew = bcm570xPktAlloc (pUmDevice->index, MAX_PACKET_SIZE);
- if (skbnew == NULL) {
- pUmDevice->tx_full = 1;
- printf ("eth%d: out of transmit buffers", pUmDevice->index);
- return (LM_STATUS_FAILURE);
- }
+ if (skbnew == NULL) {
+ pUmDevice->tx_full = 1;
+ printf ("eth%d: out of transmit buffers", pUmDevice->index);
+ return (LM_STATUS_FAILURE);
+ }
- /* New packet values */
- pUmPacket->skbuff = skbnew;
- pUmPacket->lm_packet.u.Tx.FragCount = 1;
+ /* New packet values */
+ pUmPacket->skbuff = skbnew;
+ pUmPacket->lm_packet.u.Tx.FragCount = 1;
- return (LM_STATUS_SUCCESS);
+ return (LM_STATUS_SUCCESS);
}
-
-LM_STATUS
-MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
+LM_STATUS MM_IndicateRxPackets (PLM_DEVICE_BLOCK pDevice)
{
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- pUmDevice->rx_pkt = 1;
- return LM_STATUS_SUCCESS;
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ pUmDevice->rx_pkt = 1;
+ return LM_STATUS_SUCCESS;
}
-LM_STATUS
-MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
+LM_STATUS MM_IndicateTxPackets (PLM_DEVICE_BLOCK pDevice)
{
- PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
- PLM_PACKET pPacket;
- PUM_PACKET pUmPacket;
- void *skb;
- while ( TRUE ) {
-
- pPacket = (PLM_PACKET)
- QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
-
- if (pPacket == 0)
- break;
-
- pUmPacket = (PUM_PACKET) pPacket;
- skb = (void*)pUmPacket->skbuff;
-
- /*
- * Free MBLK if we transmitted a fragmented packet or a
- * non-fragmented packet straight from the VxWorks
- * buffer pool. If packet was copied to a local transmit
- * buffer, then there's no MBUF to free, just free
- * the transmit buffer back to the cluster pool.
- */
-
- if (skb)
- bcm570xPktFree (pUmDevice->index, skb);
-
- pUmPacket->skbuff = 0;
- QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
- pUmDevice->tx_pkt = 1;
- }
- if (pUmDevice->tx_full) {
- if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
- (QQ_GetSize(&pDevice->TxPacketFreeQ.Container) >> 1))
- pUmDevice->tx_full = 0;
- }
- return LM_STATUS_SUCCESS;
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+ PLM_PACKET pPacket;
+ PUM_PACKET pUmPacket;
+ void *skb;
+ while (TRUE) {
+
+ pPacket = (PLM_PACKET)
+ QQ_PopHead (&pDevice->TxPacketXmittedQ.Container);
+
+ if (pPacket == 0)
+ break;
+
+ pUmPacket = (PUM_PACKET) pPacket;
+ skb = (void *)pUmPacket->skbuff;
+
+ /*
+ * Free MBLK if we transmitted a fragmented packet or a
+ * non-fragmented packet straight from the VxWorks
+ * buffer pool. If packet was copied to a local transmit
+ * buffer, then there's no MBUF to free, just free
+ * the transmit buffer back to the cluster pool.
+ */
+
+ if (skb)
+ bcm570xPktFree (pUmDevice->index, skb);
+
+ pUmPacket->skbuff = 0;
+ QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket);
+ pUmDevice->tx_pkt = 1;
+ }
+ if (pUmDevice->tx_full) {
+ if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) >=
+ (QQ_GetSize (&pDevice->TxPacketFreeQ.Container) >> 1))
+ pUmDevice->tx_full = 0;
+ }
+ return LM_STATUS_SUCCESS;
}
/*
@@ -1345,16 +1303,12 @@ MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
* Return its length and physical address.
*/
void MM_MapTxDma
- (
- PLM_DEVICE_BLOCK pDevice,
- struct _LM_PACKET *pPacket,
- T3_64BIT_HOST_ADDR *paddr,
- LM_UINT32 *len,
- int frag)
-{
- PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
- *len = pPacket->PacketSize;
- MM_SetT3Addr(paddr, (dma_addr_t) pUmPacket->skbuff);
+ (PLM_DEVICE_BLOCK pDevice,
+ struct _LM_PACKET *pPacket,
+ T3_64BIT_HOST_ADDR * paddr, LM_UINT32 * len, int frag) {
+ PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+ *len = pPacket->PacketSize;
+ MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff);
}
/*
@@ -1362,35 +1316,31 @@ void MM_MapTxDma
* to a physical address as seen from a PCI device. Store the
* result at paddr.
*/
-void MM_MapRxDma(
- PLM_DEVICE_BLOCK pDevice,
- struct _LM_PACKET *pPacket,
- T3_64BIT_HOST_ADDR *paddr)
+void MM_MapRxDma (PLM_DEVICE_BLOCK pDevice,
+ struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR * paddr)
{
- PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
- MM_SetT3Addr(paddr, (dma_addr_t) pUmPacket->skbuff);
+ PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+ MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff);
}
-void
-MM_SetAddr (LM_PHYSICAL_ADDRESS *paddr, dma_addr_t addr)
+void MM_SetAddr (LM_PHYSICAL_ADDRESS * paddr, dma_addr_t addr)
{
#if (BITS_PER_LONG == 64)
- paddr->High = ((unsigned long) addr) >> 32;
- paddr->Low = ((unsigned long) addr) & 0xffffffff;
+ paddr->High = ((unsigned long)addr) >> 32;
+ paddr->Low = ((unsigned long)addr) & 0xffffffff;
#else
paddr->High = 0;
- paddr->Low = (unsigned long) addr;
+ paddr->Low = (unsigned long)addr;
#endif
}
-void
-MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr)
+void MM_SetT3Addr (T3_64BIT_HOST_ADDR * paddr, dma_addr_t addr)
{
- unsigned long baddr = (unsigned long) addr;
+ unsigned long baddr = (unsigned long)addr;
#if (BITS_PER_LONG == 64)
- set_64bit_addr(paddr, baddr & 0xffffffff, baddr >> 32);
+ set_64bit_addr (paddr, baddr & 0xffffffff, baddr >> 32);
#else
- set_64bit_addr(paddr, baddr, 0);
+ set_64bit_addr (paddr, baddr, 0);
#endif
}
@@ -1403,42 +1353,38 @@ MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr)
* If any uses of the function remain, they will refer to the single copy
* in the library.
*/
-void
-atomic_set(atomic_t* entry, int val)
+void atomic_set (atomic_t * entry, int val)
{
- entry->counter = val;
+ entry->counter = val;
}
-int
-atomic_read(atomic_t* entry)
+
+int atomic_read (atomic_t * entry)
{
- return entry->counter;
+ return entry->counter;
}
-void
-atomic_inc(atomic_t* entry)
+
+void atomic_inc (atomic_t * entry)
{
- if(entry)
- entry->counter++;
+ if (entry)
+ entry->counter++;
}
-void
-atomic_dec(atomic_t* entry)
+void atomic_dec (atomic_t * entry)
{
- if(entry)
- entry->counter--;
+ if (entry)
+ entry->counter--;
}
-void
-atomic_sub(int a, atomic_t* entry)
+void atomic_sub (int a, atomic_t * entry)
{
- if(entry)
- entry->counter -= a;
+ if (entry)
+ entry->counter -= a;
}
-void
-atomic_add(int a, atomic_t* entry)
+void atomic_add (int a, atomic_t * entry)
{
- if(entry)
- entry->counter += a;
+ if (entry)
+ entry->counter += a;
}
/******************************************************************************/
@@ -1446,68 +1392,57 @@ atomic_add(int a, atomic_t* entry)
/* */
/* Return: */
/******************************************************************************/
-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 */
-
+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: */
/******************************************************************************/
-char
-QQ_Full(
-PQQ_CONTAINER pQueue) {
- unsigned int NewHead;
-
- NewHead = (pQueue->Head + 1) % pQueue->Size;
+char QQ_Full (PQQ_CONTAINER pQueue)
+{
+ unsigned int NewHead;
- return(NewHead == pQueue->Tail);
-} /* QQ_Full */
+ NewHead = (pQueue->Head + 1) % pQueue->Size;
+ return (NewHead == pQueue->Tail);
+} /* QQ_Full */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-char
-QQ_Empty(
-PQQ_CONTAINER pQueue) {
- return(pQueue->Head == pQueue->Tail);
-} /* QQ_Empty */
-
+char QQ_Empty (PQQ_CONTAINER pQueue)
+{
+ return (pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-unsigned int
-QQ_GetSize(
-PQQ_CONTAINER pQueue) {
- return pQueue->Size;
-} /* QQ_GetSize */
-
+unsigned int QQ_GetSize (PQQ_CONTAINER pQueue)
+{
+ return pQueue->Size;
+} /* QQ_GetSize */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-unsigned int
-QQ_GetEntryCnt(
-PQQ_CONTAINER pQueue) {
- return atomic_read(&pQueue->EntryCnt);
-} /* QQ_GetEntryCnt */
-
+unsigned int QQ_GetEntryCnt (PQQ_CONTAINER pQueue)
+{
+ return atomic_read (&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
/******************************************************************************/
/* Description: */
@@ -1516,28 +1451,25 @@ PQQ_CONTAINER pQueue) {
/* TRUE entry was added successfully. */
/* FALSE queue is full. */
/******************************************************************************/
-char
-QQ_PushHead(
-PQQ_CONTAINER pQueue,
-PQQ_ENTRY pEntry) {
- unsigned int Head;
+char QQ_PushHead (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)
+{
+ unsigned int Head;
- Head = (pQueue->Head + 1) % pQueue->Size;
+ 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);
+ if (Head == pQueue->Tail) {
+ return 0;
+ } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
- return -1;
-} /* QQ_PushHead */
+ pQueue->Array[pQueue->Head] = pEntry;
+ wmb ();
+ pQueue->Head = Head;
+ atomic_inc (&pQueue->EntryCnt);
+ return -1;
+} /* QQ_PushHead */
/******************************************************************************/
/* Description: */
@@ -1546,146 +1478,126 @@ PQQ_ENTRY pEntry) {
/* TRUE entry was added successfully. */
/* FALSE queue is full. */
/******************************************************************************/
-char
-QQ_PushTail(
-PQQ_CONTAINER pQueue,
-PQQ_ENTRY pEntry) {
- unsigned int Tail;
-
- Tail = pQueue->Tail;
- if(Tail == 0) {
- Tail = pQueue->Size;
- } /* if */
- Tail--;
+char QQ_PushTail (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)
+{
+ unsigned int Tail;
-#if !defined(QQ_NO_OVERFLOW_CHECK)
- if(Tail == pQueue->Head) {
- return 0;
- } /* if */
-#endif /* QQ_NO_OVERFLOW_CHECK */
+ Tail = pQueue->Tail;
+ if (Tail == 0) {
+ Tail = pQueue->Size;
+ } /* if */
+ Tail--;
- pQueue->Array[Tail] = pEntry;
- wmb();
- pQueue->Tail = Tail;
- atomic_inc(&pQueue->EntryCnt);
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+ if (Tail == pQueue->Head) {
+ return 0;
+ } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
- return -1;
-} /* QQ_PushTail */
+ pQueue->Array[Tail] = pEntry;
+ wmb ();
+ pQueue->Tail = Tail;
+ atomic_inc (&pQueue->EntryCnt);
+ return -1;
+} /* QQ_PushTail */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-PQQ_ENTRY
-QQ_PopHead(
-PQQ_CONTAINER pQueue) {
- unsigned int Head;
- PQQ_ENTRY Entry;
+PQQ_ENTRY QQ_PopHead (PQQ_CONTAINER pQueue)
+{
+ unsigned int Head;
+ PQQ_ENTRY Entry;
- Head = pQueue->Head;
+ 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--;
+ if (Head == pQueue->Tail) {
+ return (PQQ_ENTRY) 0;
+ } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
- Entry = pQueue->Array[Head];
- membar();
+ if (Head == 0) {
+ Head = pQueue->Size;
+ } /* if */
+ Head--;
- pQueue->Head = Head;
- atomic_dec(&pQueue->EntryCnt);
+ Entry = pQueue->Array[Head];
+ membar ();
- return Entry;
-} /* QQ_PopHead */
+ pQueue->Head = Head;
+ atomic_dec (&pQueue->EntryCnt);
+ return Entry;
+} /* QQ_PopHead */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-PQQ_ENTRY
-QQ_PopTail(
-PQQ_CONTAINER pQueue) {
- unsigned int Tail;
- PQQ_ENTRY Entry;
+PQQ_ENTRY QQ_PopTail (PQQ_CONTAINER pQueue)
+{
+ unsigned int Tail;
+ PQQ_ENTRY Entry;
- Tail = pQueue->Tail;
+ Tail = pQueue->Tail;
#if !defined(QQ_NO_UNDERFLOW_CHECK)
- if(Tail == pQueue->Head) {
- return (PQQ_ENTRY) 0;
- } /* if */
-#endif /* QQ_NO_UNDERFLOW_CHECK */
+ if (Tail == pQueue->Head) {
+ return (PQQ_ENTRY) 0;
+ } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
- Entry = pQueue->Array[Tail];
- membar();
- pQueue->Tail = (Tail + 1) % pQueue->Size;
- atomic_dec(&pQueue->EntryCnt);
-
- return Entry;
-} /* QQ_PopTail */
+ Entry = pQueue->Array[Tail];
+ membar ();
+ pQueue->Tail = (Tail + 1) % pQueue->Size;
+ atomic_dec (&pQueue->EntryCnt);
+ return Entry;
+} /* QQ_PopTail */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-PQQ_ENTRY
-QQ_GetHead(
- PQQ_CONTAINER pQueue,
- unsigned int Idx)
+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];
-}
+ 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: */
/******************************************************************************/
-PQQ_ENTRY
-QQ_GetTail(
- PQQ_CONTAINER pQueue,
- unsigned int Idx)
+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];
+ 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 /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_BCM570x */
+#endif
diff --git a/drivers/bcm570x_lm.h b/drivers/bcm570x_lm.h
index 607f3fd067..2ea6ca8fa9 100644
--- a/drivers/bcm570x_lm.h
+++ b/drivers/bcm570x_lm.h
@@ -19,29 +19,28 @@
#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;
+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_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;
@@ -58,15 +57,13 @@ typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS;
} \
}
-
#ifndef NULL
#define NULL ((void *) 0)
-#endif /* NULL */
+#endif /* NULL */
#ifndef OFFSETOF
#define OFFSETOF(_s, _m) (MM_UINT_PTR(&(((_s *) 0)->_m)))
-#endif /* OFFSETOF */
-
+#endif /* OFFSETOF */
/******************************************************************************/
/* Simple macros. */
@@ -100,26 +97,24 @@ typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS;
((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 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. */
+#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 */
+#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
@@ -129,7 +124,6 @@ typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS;
#define LM_PROMISCUOUS_MODE 0x10000
-
/******************************************************************************/
/* PCI registers. */
/******************************************************************************/
@@ -169,20 +163,20 @@ typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS;
/******************************************************************************/
typedef struct {
- LM_UINT32 FragSize;
- LM_PHYSICAL_ADDRESS FragBuf;
+ 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;
+ /* 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;
+ /* Total buffer size. */
+ LM_UINT32 TotalSize;
- /* Fragment array buffer. */
- LM_FRAG Fragments[1];
+ /* 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) \
@@ -191,7 +185,6 @@ typedef struct {
LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1]; \
} _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME
-
/******************************************************************************/
/* Status codes. */
/******************************************************************************/
@@ -217,7 +210,6 @@ typedef struct {
typedef LM_UINT LM_STATUS, *PLM_STATUS;
-
/******************************************************************************/
/* Requested media type. */
/******************************************************************************/
@@ -240,7 +232,6 @@ typedef LM_UINT LM_STATUS, *PLM_STATUS;
typedef LM_UINT32 LM_REQUESTED_MEDIA_TYPE, *PLM_REQUESTED_MEDIA_TYPE;
-
/******************************************************************************/
/* Media type. */
/******************************************************************************/
@@ -254,7 +245,6 @@ typedef LM_UINT32 LM_REQUESTED_MEDIA_TYPE, *PLM_REQUESTED_MEDIA_TYPE;
typedef LM_UINT32 LM_MEDIA_TYPE, *PLM_MEDIA_TYPE;
-
/******************************************************************************/
/* Line speed. */
/******************************************************************************/
@@ -266,7 +256,6 @@ typedef LM_UINT32 LM_MEDIA_TYPE, *PLM_MEDIA_TYPE;
typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED;
-
/******************************************************************************/
/* Duplex mode. */
/******************************************************************************/
@@ -277,7 +266,6 @@ typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED;
typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE;
-
/******************************************************************************/
/* Power state. */
/******************************************************************************/
@@ -289,7 +277,6 @@ typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE;
typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE;
-
/******************************************************************************/
/* Task offloading. */
/******************************************************************************/
@@ -305,7 +292,6 @@ typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE;
typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD;
-
/******************************************************************************/
/* Flow control. */
/******************************************************************************/
@@ -324,7 +310,6 @@ typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD;
typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL;
-
/******************************************************************************/
/* Wake up mode. */
/******************************************************************************/
@@ -336,7 +321,6 @@ typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL;
typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE;
-
/******************************************************************************/
/* Counters. */
/******************************************************************************/
@@ -362,7 +346,6 @@ typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE;
typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE;
-
/******************************************************************************/
/* Forward definition. */
/******************************************************************************/
@@ -370,82 +353,82 @@ typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE;
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);
-
+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);
+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);
+LM_STATUS LM_Load5703DmaWFirmware (PLM_DEVICE_BLOCK pDevice);
#endif
-
-#endif /* LM_H */
+#endif /* LM_H */
diff --git a/drivers/bcm570x_mm.h b/drivers/bcm570x_mm.h
index b7cbf8abd4..ff5302f47c 100644
--- a/drivers/bcm570x_mm.h
+++ b/drivers/bcm570x_mm.h
@@ -45,7 +45,7 @@ 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);
+DECLARE_QUEUE_TYPE (UM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT + 1);
#define MAX_MEM 16
@@ -65,51 +65,50 @@ typedef struct _UM_DEVICE_BLOCK {
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 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 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_low_buf_thresh; /* changed to rx_buf_repl_thresh */
int rx_buf_repl_panic_thresh;
- int rx_buf_align; /* new -- unsupported */
+ 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 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 */
+#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 */
+ 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 */
+ 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;
@@ -117,9 +116,9 @@ typedef union {
/* Packet */
typedef struct
-_UM_PACKET {
- LM_PACKET lm_packet;
- void* skbuff; /* Address of packet buffer */
+ _UM_PACKET {
+ LM_PACKET lm_packet;
+ void *skbuff; /* Address of packet buffer */
} UM_PACKET, *PUM_PACKET;
#define MM_ACQUIRE_UNDI_LOCK(_pDevice)
@@ -137,15 +136,14 @@ _UM_PACKET {
#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_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);
-
+ 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);
@@ -157,4 +155,4 @@ extern void sysSerialPrintString (char *s);
#if 0
#define cpu_to_le32(val) LONGSWAP(val)
#endif
-#endif /* MM_H */
+#endif /* MM_H */
diff --git a/drivers/bios_emulator/Makefile b/drivers/bios_emulator/Makefile
new file mode 100644
index 0000000000..90c64dad60
--- /dev/null
+++ b/drivers/bios_emulator/Makefile
@@ -0,0 +1,37 @@
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libatibiosemu.a
+
+X86DIR = x86emu
+
+$(shell mkdir -p $(obj)$(X86DIR))
+
+COBJS = atibios.o biosemu.o besys.o bios.o \
+ $(X86DIR)/decode.o \
+ $(X86DIR)/ops2.o \
+ $(X86DIR)/ops.o \
+ $(X86DIR)/prim_ops.o \
+ $(X86DIR)/sys.o \
+ $(X86DIR)/debug.o
+
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+EXTRA_CFLAGS += -I. -I./include -I$(TOPDIR)/include \
+ -D__PPC__ -D__BIG_ENDIAN__
+
+CFLAGS += $(EXTRA_CFLAGS)
+HOST_CFLAGS += $(EXTRA_CFLAGS)
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c
new file mode 100644
index 0000000000..5779f99f1f
--- /dev/null
+++ b/drivers/bios_emulator/atibios.c
@@ -0,0 +1,340 @@
+/****************************************************************************
+*
+* Video BOOT Graphics Card POST Module
+*
+* ========================================================================
+* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+* Jason Jin <Jason.jin@freescale.com>
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* This file may be distributed and/or modified under the terms of the
+* GNU General Public License version 2.0 as published by the Free
+* Software Foundation and appearing in the file LICENSE.GPL included
+* in the packaging of this file.
+*
+* Licensees holding a valid Commercial License for this product from
+* SciTech Software, Inc. may use this file in accordance with the
+* Commercial License Agreement provided with the Software.
+*
+* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
+* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE.
+*
+* See http://www.scitechsoft.com/license/ for information about
+* the licensing options available and how to purchase a Commercial
+* License Agreement.
+*
+* Contact license@scitechsoft.com if any conditions of this licensing
+* are not clear to you, or you have questions about licensing options.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Linux Kernel
+* Developer: Kendall Bennett
+*
+* Description: Module to implement booting PCI/AGP controllers on the
+* bus. We use the x86 real mode emulator to run the BIOS on
+* graphics controllers to bring the cards up.
+*
+* Note that at present this module does *not* support
+* multiple controllers.
+*
+* The orignal name of this file is warmboot.c.
+* Jason ported this file to u-boot to run the ATI video card
+* BIOS in u-boot.
+****************************************************************************/
+#include <common.h>
+
+#ifdef CONFIG_BIOSEMU
+
+#include "biosemui.h"
+#include <malloc.h>
+
+/* Length of the BIOS image */
+#define MAX_BIOSLEN (128 * 1024L)
+
+/* Define some useful types and macros */
+#define true 1
+#define false 0
+
+/* Place to save PCI BAR's that we change and later restore */
+static u32 saveROMBaseAddress;
+static u32 saveBaseAddress10;
+static u32 saveBaseAddress14;
+static u32 saveBaseAddress18;
+static u32 saveBaseAddress20;
+
+/****************************************************************************
+PARAMETERS:
+pcidev - PCI device info for the video card on the bus to boot
+VGAInfo - BIOS emulator VGA info structure
+
+REMARKS:
+This function executes the BIOS POST code on the controller. We assume that
+at this stage the controller has its I/O and memory space enabled and
+that all other controllers are in a disabled state.
+****************************************************************************/
+static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo * VGAInfo)
+{
+ RMREGS regs;
+ RMSREGS sregs;
+
+ /* Determine the value to store in AX for BIOS POST. Per the PCI specs,
+ AH must contain the bus and AL must contain the devfn, encoded as
+ (dev << 3) | fn
+ */
+ memset(&regs, 0, sizeof(regs));
+ memset(&sregs, 0, sizeof(sregs));
+ regs.x.ax = ((int)PCI_BUS(pcidev) << 8) |
+ ((int)PCI_DEV(pcidev) << 3) | (int)PCI_FUNC(pcidev);
+
+ /*Setup the X86 emulator for the VGA BIOS*/
+ BE_setVGA(VGAInfo);
+
+ /*Execute the BIOS POST code*/
+ BE_callRealMode(0xC000, 0x0003, &regs, &sregs);
+
+ /*Cleanup and exit*/
+ BE_getVGA(VGAInfo);
+}
+
+/****************************************************************************
+PARAMETERS:
+pcidev - PCI device info for the video card on the bus
+bar - Place to return the base address register offset to use
+
+RETURNS:
+The address to use to map the secondary BIOS (AGP devices)
+
+REMARKS:
+Searches all the PCI base address registers for the device looking for a
+memory mapping that is large enough to hold our ROM BIOS. We usually end up
+finding the framebuffer mapping (usually BAR 0x10), and we use this mapping
+to map the BIOS for the device into. We use a mapping that is already
+assigned to the device to ensure the memory range will be passed through
+by any PCI->PCI or AGP->PCI bridge that may be present.
+
+NOTE: Usually this function is only used for AGP devices, but it may be
+ used for PCI devices that have already been POST'ed and the BIOS
+ ROM base address has been zero'ed out.
+
+NOTE: This function leaves the original memory aperture disabled by leaving
+ it programmed to all 1's. It must be restored to the correct value
+ later.
+****************************************************************************/
+static u32 PCI_findBIOSAddr(pci_dev_t pcidev, int *bar)
+{
+ u32 base, size;
+
+ for (*bar = 0x10; *bar <= 0x14; (*bar) += 4) {
+ pci_read_config_dword(pcidev, *bar, &base);
+ if (!(base & 0x1)) {
+ pci_write_config_dword(pcidev, *bar, 0xFFFFFFFF);
+ pci_read_config_dword(pcidev, *bar, &size);
+ size = ~(size & ~0xFF) + 1;
+ if (size >= MAX_BIOSLEN)
+ return base & ~0xFF;
+ }
+ }
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Some non-x86 Linux kernels map PCI relocateable I/O to values that
+are above 64K, which will not work with the BIOS image that requires
+the offset for the I/O ports to be a maximum of 16-bits. Ideally
+someone should fix the kernel to map the I/O ports for VGA compatible
+devices to a different location (or just all I/O ports since it is
+unlikely you can have enough devices in the machine to use up all
+64K of the I/O space - a total of more than 256 cards would be
+necessary).
+
+Anyway to fix this we change all I/O mapped base registers and
+chop off the top bits.
+****************************************************************************/
+static void PCI_fixupIObase(pci_dev_t pcidev, int reg, u32 * base)
+{
+ if ((*base & 0x1) && (*base > 0xFFFE)) {
+ *base &= 0xFFFF;
+ pci_write_config_dword(pcidev, reg, *base);
+
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+pcidev - PCI device info for the video card on the bus
+
+RETURNS:
+Pointers to the mapped BIOS image
+
+REMARKS:
+Maps a pointer to the BIOS image on the graphics card on the PCI bus.
+****************************************************************************/
+void *PCI_mapBIOSImage(pci_dev_t pcidev)
+{
+ u32 BIOSImagePhys;
+ int BIOSImageBAR;
+ u8 *BIOSImage;
+
+ /*Save PCI BAR registers that might get changed*/
+ pci_read_config_dword(pcidev, PCI_ROM_ADDRESS, &saveROMBaseAddress);
+ pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &saveBaseAddress10);
+ pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_1, &saveBaseAddress14);
+ pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_2, &saveBaseAddress18);
+ pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_4, &saveBaseAddress20);
+
+ /*Fix up I/O base registers to less than 64K */
+ if(saveBaseAddress14 != 0)
+ PCI_fixupIObase(pcidev, PCI_BASE_ADDRESS_1, &saveBaseAddress14);
+ else
+ PCI_fixupIObase(pcidev, PCI_BASE_ADDRESS_4, &saveBaseAddress20);
+
+ /* Some cards have problems that stop us from being able to read the
+ BIOS image from the ROM BAR. To fix this we have to do some chipset
+ specific programming for different cards to solve this problem.
+ */
+
+ if ((BIOSImagePhys = PCI_findBIOSAddr(pcidev, &BIOSImageBAR)) == 0) {
+ printf("Find bios addr error\n");
+ return NULL;
+ }
+
+ BIOSImage = (u8 *) BIOSImagePhys;
+
+ /*Change the PCI BAR registers to map it onto the bus.*/
+ pci_write_config_dword(pcidev, BIOSImageBAR, 0);
+ pci_write_config_dword(pcidev, PCI_ROM_ADDRESS, BIOSImagePhys | 0x1);
+
+ udelay(1);
+
+ /*Check that the BIOS image is valid. If not fail, or return the
+ compiled in BIOS image if that option was enabled
+ */
+ if (BIOSImage[0] != 0x55 || BIOSImage[1] != 0xAA || BIOSImage[2] == 0) {
+ return NULL;
+ }
+
+ return BIOSImage;
+}
+
+/****************************************************************************
+PARAMETERS:
+pcidev - PCI device info for the video card on the bus
+
+REMARKS:
+Unmaps the BIOS image for the device and restores framebuffer mappings
+****************************************************************************/
+void PCI_unmapBIOSImage(pci_dev_t pcidev, void *BIOSImage)
+{
+ pci_write_config_dword(pcidev, PCI_ROM_ADDRESS, saveROMBaseAddress);
+ pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_0, saveBaseAddress10);
+ pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_1, saveBaseAddress14);
+ pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_2, saveBaseAddress18);
+ pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_4, saveBaseAddress20);
+}
+
+/****************************************************************************
+PARAMETERS:
+pcidev - PCI device info for the video card on the bus to boot
+VGAInfo - BIOS emulator VGA info structure
+
+RETURNS:
+True if successfully initialised, false if not.
+
+REMARKS:
+Loads and POST's the display controllers BIOS, directly from the BIOS
+image we can extract over the PCI bus.
+****************************************************************************/
+static int PCI_postController(pci_dev_t pcidev, BE_VGAInfo * VGAInfo)
+{
+ u32 BIOSImageLen;
+ uchar *mappedBIOS;
+ uchar *copyOfBIOS;
+
+ /*Allocate memory to store copy of BIOS from display controller*/
+ if ((mappedBIOS = PCI_mapBIOSImage(pcidev)) == NULL) {
+ printf("videoboot: Video ROM failed to map!\n");
+ return false;
+ }
+
+ BIOSImageLen = mappedBIOS[2] * 512;
+
+ if ((copyOfBIOS = malloc(BIOSImageLen)) == NULL) {
+ printf("videoboot: Out of memory!\n");
+ return false;
+ }
+ memcpy(copyOfBIOS, mappedBIOS, BIOSImageLen);
+
+ PCI_unmapBIOSImage(pcidev, mappedBIOS);
+
+ /*Save information in VGAInfo structure*/
+ VGAInfo->function = PCI_FUNC(pcidev);
+ VGAInfo->device = PCI_DEV(pcidev);
+ VGAInfo->bus = PCI_BUS(pcidev);
+ VGAInfo->pcidev = pcidev;
+ VGAInfo->BIOSImage = copyOfBIOS;
+ VGAInfo->BIOSImageLen = BIOSImageLen;
+
+ /*Now execute the BIOS POST for the device*/
+ if (copyOfBIOS[0] != 0x55 || copyOfBIOS[1] != 0xAA) {
+ printf("videoboot: Video ROM image is invalid!\n");
+ return false;
+ }
+
+ PCI_doBIOSPOST(pcidev, VGAInfo);
+
+ /*Reset the size of the BIOS image to the final size*/
+ VGAInfo->BIOSImageLen = copyOfBIOS[2] * 512;
+ return true;
+}
+
+/****************************************************************************
+PARAMETERS:
+pcidev - PCI device info for the video card on the bus to boot
+pVGAInfo - Place to return VGA info structure is requested
+cleanUp - True to clean up on exit, false to leave emulator active
+
+REMARKS:
+Boots the PCI/AGP video card on the bus using the Video ROM BIOS image
+and the X86 BIOS emulator module.
+****************************************************************************/
+int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp)
+{
+ BE_VGAInfo *VGAInfo;
+
+ printf("videoboot: Booting PCI video card bus %d, function %d, device %d\n",
+ PCI_BUS(pcidev), PCI_FUNC(pcidev), PCI_DEV(pcidev));
+
+ /*Initialise the x86 BIOS emulator*/
+ if ((VGAInfo = malloc(sizeof(*VGAInfo))) == NULL) {
+ printf("videoboot: Out of memory!\n");
+ return false;
+ }
+ memset(VGAInfo, 0, sizeof(*VGAInfo));
+ BE_init(0, 65536, VGAInfo, 0);
+
+ /*Post all the display controller BIOS'es*/
+ PCI_postController(pcidev, VGAInfo);
+
+ /*Cleanup and exit the emulator if requested. If the BIOS emulator
+ is needed after booting the card, we will not call BE_exit and
+ leave it enabled for further use (ie: VESA driver etc).
+ */
+ if (cleanUp) {
+ BE_exit();
+ if (VGAInfo->BIOSImage)
+ free(VGAInfo->BIOSImage);
+ free(VGAInfo);
+ VGAInfo = NULL;
+ }
+ /*Return VGA info pointer if the caller requested it*/
+ if (pVGAInfo)
+ *pVGAInfo = VGAInfo;
+ return true;
+}
+
+#endif
diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c
new file mode 100644
index 0000000000..8f1d8b29d5
--- /dev/null
+++ b/drivers/bios_emulator/besys.c
@@ -0,0 +1,724 @@
+/****************************************************************************
+*
+* BIOS emulator and interface
+* to Realmode X86 Emulator Library
+*
+* ========================================================================
+*
+* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+* Jason Jin<Jason.jin@freescale.com>
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* This file may be distributed and/or modified under the terms of the
+* GNU General Public License version 2.0 as published by the Free
+* Software Foundation and appearing in the file LICENSE.GPL included
+* in the packaging of this file.
+*
+* Licensees holding a valid Commercial License for this product from
+* SciTech Software, Inc. may use this file in accordance with the
+* Commercial License Agreement provided with the Software.
+*
+* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
+* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE.
+*
+* See http://www.scitechsoft.com/license/ for information about
+* the licensing options available and how to purchase a Commercial
+* License Agreement.
+*
+* Contact license@scitechsoft.com if any conditions of this licensing
+* are not clear to you, or you have questions about licensing options.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes BIOS emulator I/O and memory access
+* functions.
+*
+* Jason ported this file to u-boot to run the ATI video card
+* BIOS in u-boot. Removed some emulate functions such as the
+* timer port access. Made all the VGA port except reading 0x3c3
+* be emulated. Seems like reading 0x3c3 should return the high
+* 16 bit of the io port.
+*
+****************************************************************************/
+
+#include <common.h>
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "biosemui.h"
+
+/*------------------------- Global Variables ------------------------------*/
+
+#ifndef __i386__
+static char *BE_biosDate = "08/14/99";
+static u8 BE_model = 0xFC;
+static u8 BE_submodel = 0x00;
+#endif
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to convert
+
+RETURNS:
+Actual memory address to read or write the data
+
+REMARKS:
+This function converts an emulator memory address in a 32-bit range to
+a real memory address that we wish to access. It handles splitting up the
+memory address space appropriately to access the emulator BIOS image, video
+memory and system BIOS etc.
+****************************************************************************/
+static u8 *BE_memaddr(u32 addr)
+{
+ if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
+ return (u8*)(_BE_env.biosmem_base + addr - 0xC0000);
+ } else if (addr > _BE_env.biosmem_limit && addr < 0xD0000) {
+ DB(printf("BE_memaddr: address %#lx may be invalid!\n", addr);)
+ return M.mem_base;
+ } else if (addr >= 0xA0000 && addr <= 0xBFFFF) {
+ return (u8*)(_BE_env.busmem_base + addr - 0xA0000);
+ }
+#ifdef __i386__
+ else if (addr >= 0xD0000 && addr <= 0xFFFFF) {
+ /* We map the real System BIOS directly on real PC's */
+ DB(printf("BE_memaddr: System BIOS address %#lx\n", addr);)
+ return _BE_env.busmem_base + addr - 0xA0000;
+ }
+#else
+ else if (addr >= 0xFFFF5 && addr < 0xFFFFE) {
+ /* Return a faked BIOS date string for non-x86 machines */
+ DB(printf("BE_memaddr - Returning BIOS date\n");)
+ return BE_biosDate + addr - 0xFFFF5;
+ } else if (addr == 0xFFFFE) {
+ /* Return system model identifier for non-x86 machines */
+ DB(printf("BE_memaddr - Returning model\n");)
+ return &BE_model;
+ } else if (addr == 0xFFFFF) {
+ /* Return system submodel identifier for non-x86 machines */
+ DB(printf("BE_memaddr - Returning submodel\n");)
+ return &BE_submodel;
+ }
+#endif
+ else if (addr > M.mem_size - 1) {
+ HALT_SYS();
+ return M.mem_base;
+ }
+
+ return M.mem_base + addr;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Byte value read from emulator memory.
+
+REMARKS:
+Reads a byte value from the emulator memory. We have three distinct memory
+regions that are handled differently, which this function handles.
+****************************************************************************/
+u8 X86API BE_rdb(u32 addr)
+{
+ if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
+ return 0;
+ else {
+ u8 val = readb_le(BE_memaddr(addr));
+ return val;
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Word value read from emulator memory.
+
+REMARKS:
+Reads a word value from the emulator memory. We have three distinct memory
+regions that are handled differently, which this function handles.
+****************************************************************************/
+u16 X86API BE_rdw(u32 addr)
+{
+ if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
+ return 0;
+ else {
+ u8 *base = BE_memaddr(addr);
+ u16 val = readw_le(base);
+ return val;
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Long value read from emulator memory.
+
+REMARKS:
+Reads a 32-bit value from the emulator memory. We have three distinct memory
+regions that are handled differently, which this function handles.
+****************************************************************************/
+u32 X86API BE_rdl(u32 addr)
+{
+ if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
+ return 0;
+ else {
+ u8 *base = BE_memaddr(addr);
+ u32 val = readl_le(base);
+ return val;
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a byte value to emulator memory. We have three distinct memory
+regions that are handled differently, which this function handles.
+****************************************************************************/
+void X86API BE_wrb(u32 addr, u8 val)
+{
+ if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
+ writeb_le(BE_memaddr(addr), val);
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a word value to emulator memory. We have three distinct memory
+regions that are handled differently, which this function handles.
+****************************************************************************/
+void X86API BE_wrw(u32 addr, u16 val)
+{
+ if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
+ u8 *base = BE_memaddr(addr);
+ writew_le(base, val);
+
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a 32-bit value to emulator memory. We have three distinct memory
+regions that are handled differently, which this function handles.
+****************************************************************************/
+void X86API BE_wrl(u32 addr, u32 val)
+{
+ if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
+ u8 *base = BE_memaddr(addr);
+ writel_le(base, val);
+ }
+}
+
+#if defined(DEBUG) || !defined(__i386__)
+
+/* For Non-Intel machines we may need to emulate some I/O port accesses that
+ * the BIOS may try to access, such as the PCI config registers.
+ */
+
+#define IS_TIMER_PORT(port) (0x40 <= port && port <= 0x43)
+#define IS_CMOS_PORT(port) (0x70 <= port && port <= 0x71)
+/*#define IS_VGA_PORT(port) (_BE_env.emulateVGA && 0x3C0 <= port && port <= 0x3DA)*/
+#define IS_VGA_PORT(port) (0x3C0 <= port && port <= 0x3DA)
+#define IS_PCI_PORT(port) (0xCF8 <= port && port <= 0xCFF)
+#define IS_SPKR_PORT(port) (port == 0x61)
+
+/****************************************************************************
+PARAMETERS:
+port - Port to read from
+type - Type of access to perform
+
+REMARKS:
+Performs an emulated read from the Standard VGA I/O ports. If the target
+hardware does not support mapping the VGA I/O and memory (such as some
+PowerPC systems), we emulate the VGA so that the BIOS will still be able to
+set NonVGA display modes such as on ATI hardware.
+****************************************************************************/
+static u8 VGA_inpb (const int port)
+{
+ u8 val = 0xff;
+
+ switch (port) {
+ case 0x3C0:
+ /* 3C0 has funky characteristics because it can act as either
+ a data register or index register depending on the state
+ of an internal flip flop in the hardware. Hence we have
+ to emulate that functionality in here. */
+ if (_BE_env.flipFlop3C0 == 0) {
+ /* Access 3C0 as index register */
+ val = _BE_env.emu3C0;
+ } else {
+ /* Access 3C0 as data register */
+ if (_BE_env.emu3C0 < ATT_C)
+ val = _BE_env.emu3C1[_BE_env.emu3C0];
+ }
+ _BE_env.flipFlop3C0 ^= 1;
+ break;
+ case 0x3C1:
+ if (_BE_env.emu3C0 < ATT_C)
+ return _BE_env.emu3C1[_BE_env.emu3C0];
+ break;
+ case 0x3CC:
+ return _BE_env.emu3C2;
+ case 0x3C4:
+ return _BE_env.emu3C4;
+ case 0x3C5:
+ if (_BE_env.emu3C4 < ATT_C)
+ return _BE_env.emu3C5[_BE_env.emu3C4];
+ break;
+ case 0x3C6:
+ return _BE_env.emu3C6;
+ case 0x3C7:
+ return _BE_env.emu3C7;
+ case 0x3C8:
+ return _BE_env.emu3C8;
+ case 0x3C9:
+ if (_BE_env.emu3C7 < PAL_C)
+ return _BE_env.emu3C9[_BE_env.emu3C7++];
+ break;
+ case 0x3CE:
+ return _BE_env.emu3CE;
+ case 0x3CF:
+ if (_BE_env.emu3CE < GRA_C)
+ return _BE_env.emu3CF[_BE_env.emu3CE];
+ break;
+ case 0x3D4:
+ if (_BE_env.emu3C2 & 0x1)
+ return _BE_env.emu3D4;
+ break;
+ case 0x3D5:
+ if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
+ return _BE_env.emu3D5[_BE_env.emu3D4];
+ break;
+ case 0x3DA:
+ _BE_env.flipFlop3C0 = 0;
+ val = _BE_env.emu3DA;
+ _BE_env.emu3DA ^= 0x9;
+ break;
+ }
+ return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+port - Port to write to
+type - Type of access to perform
+
+REMARKS:
+Performs an emulated write to one of the 8253 timer registers. For now
+we only emulate timer 0 which is the only timer that the BIOS code appears
+to use.
+****************************************************************************/
+static void VGA_outpb (int port, u8 val)
+{
+ switch (port) {
+ case 0x3C0:
+ /* 3C0 has funky characteristics because it can act as either
+ a data register or index register depending on the state
+ of an internal flip flop in the hardware. Hence we have
+ to emulate that functionality in here. */
+ if (_BE_env.flipFlop3C0 == 0) {
+ /* Access 3C0 as index register */
+ _BE_env.emu3C0 = val;
+ } else {
+ /* Access 3C0 as data register */
+ if (_BE_env.emu3C0 < ATT_C)
+ _BE_env.emu3C1[_BE_env.emu3C0] = val;
+ }
+ _BE_env.flipFlop3C0 ^= 1;
+ break;
+ case 0x3C2:
+ _BE_env.emu3C2 = val;
+ break;
+ case 0x3C4:
+ _BE_env.emu3C4 = val;
+ break;
+ case 0x3C5:
+ if (_BE_env.emu3C4 < ATT_C)
+ _BE_env.emu3C5[_BE_env.emu3C4] = val;
+ break;
+ case 0x3C6:
+ _BE_env.emu3C6 = val;
+ break;
+ case 0x3C7:
+ _BE_env.emu3C7 = (int) val *3;
+
+ break;
+ case 0x3C8:
+ _BE_env.emu3C8 = (int) val *3;
+
+ break;
+ case 0x3C9:
+ if (_BE_env.emu3C8 < PAL_C)
+ _BE_env.emu3C9[_BE_env.emu3C8++] = val;
+ break;
+ case 0x3CE:
+ _BE_env.emu3CE = val;
+ break;
+ case 0x3CF:
+ if (_BE_env.emu3CE < GRA_C)
+ _BE_env.emu3CF[_BE_env.emu3CE] = val;
+ break;
+ case 0x3D4:
+ if (_BE_env.emu3C2 & 0x1)
+ _BE_env.emu3D4 = val;
+ break;
+ case 0x3D5:
+ if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
+ _BE_env.emu3D5[_BE_env.emu3D4] = val;
+ break;
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+regOffset - Offset into register space for non-DWORD accesses
+value - Value to write to register for PCI_WRITE_* operations
+func - Function to perform (PCIAccessRegFlags)
+
+RETURNS:
+Value read from configuration register for PCI_READ_* operations
+
+REMARKS:
+Accesses a PCI configuration space register by decoding the value currently
+stored in the _BE_env.configAddress variable and passing it through to the
+portable PCI_accessReg function.
+****************************************************************************/
+static u32 BE_accessReg(int regOffset, u32 value, int func)
+{
+#ifdef __KERNEL__
+ int function, device, bus;
+ u8 val8;
+ u16 val16;
+ u32 val32;
+
+
+ /* Decode the configuration register values for the register we wish to
+ * access
+ */
+ regOffset += (_BE_env.configAddress & 0xFF);
+ function = (_BE_env.configAddress >> 8) & 0x7;
+ device = (_BE_env.configAddress >> 11) & 0x1F;
+ bus = (_BE_env.configAddress >> 16) & 0xFF;
+
+ /* Ignore accesses to all devices other than the one we're POSTing */
+ if ((function == _BE_env.vgaInfo.function) &&
+ (device == _BE_env.vgaInfo.device) &&
+ (bus == _BE_env.vgaInfo.bus)) {
+ switch (func) {
+ case REG_READ_BYTE:
+ pci_read_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
+ &val8);
+ return val8;
+ case REG_READ_WORD:
+ pci_read_config_word(_BE_env.vgaInfo.pcidev, regOffset,
+ &val16);
+ return val16;
+ case REG_READ_DWORD:
+ pci_read_config_dword(_BE_env.vgaInfo.pcidev, regOffset,
+ &val32);
+ return val32;
+ case REG_WRITE_BYTE:
+ pci_write_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
+ value);
+
+ return 0;
+ case REG_WRITE_WORD:
+ pci_write_config_word(_BE_env.vgaInfo.pcidev, regOffset,
+ value);
+
+ return 0;
+ case REG_WRITE_DWORD:
+ pci_write_config_dword(_BE_env.vgaInfo.pcidev,
+ regOffset, value);
+
+ return 0;
+ }
+ }
+ return 0;
+#else
+ PCIDeviceInfo pciInfo;
+
+ pciInfo.mech1 = 1;
+ pciInfo.slot.i = 0;
+ pciInfo.slot.p.Function = (_BE_env.configAddress >> 8) & 0x7;
+ pciInfo.slot.p.Device = (_BE_env.configAddress >> 11) & 0x1F;
+ pciInfo.slot.p.Bus = (_BE_env.configAddress >> 16) & 0xFF;
+ pciInfo.slot.p.Enable = 1;
+
+ /* Ignore accesses to all devices other than the one we're POSTing */
+ if ((pciInfo.slot.p.Function ==
+ _BE_env.vgaInfo.pciInfo->slot.p.Function)
+ && (pciInfo.slot.p.Device == _BE_env.vgaInfo.pciInfo->slot.p.Device)
+ && (pciInfo.slot.p.Bus == _BE_env.vgaInfo.pciInfo->slot.p.Bus))
+ return PCI_accessReg((_BE_env.configAddress & 0xFF) + regOffset,
+ value, func, &pciInfo);
+ return 0;
+#endif
+}
+
+/****************************************************************************
+PARAMETERS:
+port - Port to read from
+type - Type of access to perform
+
+REMARKS:
+Performs an emulated read from one of the PCI configuration space registers.
+We emulate this using our PCI_accessReg function which will access the PCI
+configuration space registers in a portable fashion.
+****************************************************************************/
+static u32 PCI_inp(int port, int type)
+{
+ switch (type) {
+ case REG_READ_BYTE:
+ if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
+ && port <= 0xCFF)
+ return BE_accessReg(port - 0xCFC, 0, REG_READ_BYTE);
+ break;
+ case REG_READ_WORD:
+ if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
+ && port <= 0xCFF)
+ return BE_accessReg(port - 0xCFC, 0, REG_READ_WORD);
+ break;
+ case REG_READ_DWORD:
+ if (port == 0xCF8)
+ return _BE_env.configAddress;
+ else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
+ return BE_accessReg(0, 0, REG_READ_DWORD);
+ break;
+ }
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+port - Port to write to
+type - Type of access to perform
+
+REMARKS:
+Performs an emulated write to one of the PCI control registers.
+****************************************************************************/
+static void PCI_outp(int port, u32 val, int type)
+{
+ switch (type) {
+ case REG_WRITE_BYTE:
+ if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
+ && port <= 0xCFF)
+ BE_accessReg(port - 0xCFC, val, REG_WRITE_BYTE);
+ break;
+ case REG_WRITE_WORD:
+ if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
+ && port <= 0xCFF)
+ BE_accessReg(port - 0xCFC, val, REG_WRITE_WORD);
+ break;
+ case REG_WRITE_DWORD:
+ if (port == 0xCF8)
+ {
+ _BE_env.configAddress = val & 0x80FFFFFC;
+ }
+ else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
+ BE_accessReg(0, val, REG_WRITE_DWORD);
+ break;
+ }
+}
+
+#endif
+
+/****************************************************************************
+PARAMETERS:
+port - Port to write to
+
+RETURNS:
+Value read from the I/O port
+
+REMARKS:
+Performs an emulated 8-bit read from an I/O port. We handle special cases
+that we need to emulate in here, and fall through to reflecting the write
+through to the real hardware if we don't need to special case it.
+****************************************************************************/
+u8 X86API BE_inb(X86EMU_pioAddr port)
+{
+ u8 val = 0;
+
+#if defined(DEBUG) || !defined(__i386__)
+ if (IS_VGA_PORT(port)){
+ /*seems reading port 0x3c3 return the high 16 bit of io port*/
+ if(port == 0x3c3)
+ val = LOG_inpb(port);
+ else
+ val = VGA_inpb(port);
+ }
+ else if (IS_TIMER_PORT(port))
+ DB(printf("Can not interept TIMER port now!\n");)
+ else if (IS_SPKR_PORT(port))
+ DB(printf("Can not interept SPEAKER port now!\n");)
+ else if (IS_CMOS_PORT(port))
+ DB(printf("Can not interept CMOS port now!\n");)
+ else if (IS_PCI_PORT(port))
+ val = PCI_inp(port, REG_READ_BYTE);
+ else if (port < 0x100) {
+ DB(printf("WARN: INVALID inb.%04X -> %02X\n", (u16) port, val);)
+ val = LOG_inpb(port);
+ } else
+#endif
+ val = LOG_inpb(port);
+ return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+port - Port to write to
+
+RETURNS:
+Value read from the I/O port
+
+REMARKS:
+Performs an emulated 16-bit read from an I/O port. We handle special cases
+that we need to emulate in here, and fall through to reflecting the write
+through to the real hardware if we don't need to special case it.
+****************************************************************************/
+u16 X86API BE_inw(X86EMU_pioAddr port)
+{
+ u16 val = 0;
+
+#if defined(DEBUG) || !defined(__i386__)
+ if (IS_PCI_PORT(port))
+ val = PCI_inp(port, REG_READ_WORD);
+ else if (port < 0x100) {
+ DB(printf("WARN: Maybe INVALID inw.%04X -> %04X\n", (u16) port, val);)
+ val = LOG_inpw(port);
+ } else
+#endif
+ val = LOG_inpw(port);
+ return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+port - Port to write to
+
+RETURNS:
+Value read from the I/O port
+
+REMARKS:
+Performs an emulated 32-bit read from an I/O port. We handle special cases
+that we need to emulate in here, and fall through to reflecting the write
+through to the real hardware if we don't need to special case it.
+****************************************************************************/
+u32 X86API BE_inl(X86EMU_pioAddr port)
+{
+ u32 val = 0;
+
+#if defined(DEBUG) || !defined(__i386__)
+ if (IS_PCI_PORT(port))
+ val = PCI_inp(port, REG_READ_DWORD);
+ else if (port < 0x100) {
+ val = LOG_inpd(port);
+ } else
+#endif
+ val = LOG_inpd(port);
+ return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+port - Port to write to
+val - Value to write to port
+
+REMARKS:
+Performs an emulated 8-bit write to an I/O port. We handle special cases
+that we need to emulate in here, and fall through to reflecting the write
+through to the real hardware if we don't need to special case it.
+****************************************************************************/
+void X86API BE_outb(X86EMU_pioAddr port, u8 val)
+{
+#if defined(DEBUG) || !defined(__i386__)
+ if (IS_VGA_PORT(port))
+ VGA_outpb(port, val);
+ else if (IS_TIMER_PORT(port))
+ DB(printf("Can not interept TIMER port now!\n");)
+ else if (IS_SPKR_PORT(port))
+ DB(printf("Can not interept SPEAKER port now!\n");)
+ else if (IS_CMOS_PORT(port))
+ DB(printf("Can not interept CMOS port now!\n");)
+ else if (IS_PCI_PORT(port))
+ PCI_outp(port, val, REG_WRITE_BYTE);
+ else if (port < 0x100) {
+ DB(printf("WARN:Maybe INVALID outb.%04X <- %02X\n", (u16) port, val);)
+ LOG_outpb(port, val);
+ } else
+#endif
+ LOG_outpb(port, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+port - Port to write to
+val - Value to write to port
+
+REMARKS:
+Performs an emulated 16-bit write to an I/O port. We handle special cases
+that we need to emulate in here, and fall through to reflecting the write
+through to the real hardware if we don't need to special case it.
+****************************************************************************/
+void X86API BE_outw(X86EMU_pioAddr port, u16 val)
+{
+#if defined(DEBUG) || !defined(__i386__)
+ if (IS_VGA_PORT(port)) {
+ VGA_outpb(port, val);
+ VGA_outpb(port + 1, val >> 8);
+ } else if (IS_PCI_PORT(port))
+ PCI_outp(port, val, REG_WRITE_WORD);
+ else if (port < 0x100) {
+ DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16) port,
+ val);)
+ LOG_outpw(port, val);
+ } else
+#endif
+ LOG_outpw(port, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+port - Port to write to
+val - Value to write to port
+
+REMARKS:
+Performs an emulated 32-bit write to an I/O port. We handle special cases
+that we need to emulate in here, and fall through to reflecting the write
+through to the real hardware if we don't need to special case it.
+****************************************************************************/
+void X86API BE_outl(X86EMU_pioAddr port, u32 val)
+{
+#if defined(DEBUG) || !defined(__i386__)
+ if (IS_PCI_PORT(port))
+ PCI_outp(port, val, REG_WRITE_DWORD);
+ else if (port < 0x100) {
+ DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);)
+ LOG_outpd(port, val);
+ } else
+#endif
+ LOG_outpd(port, val);
+}
+#endif
diff --git a/drivers/bios_emulator/bios.c b/drivers/bios_emulator/bios.c
new file mode 100644
index 0000000000..70e9ce143b
--- /dev/null
+++ b/drivers/bios_emulator/bios.c
@@ -0,0 +1,326 @@
+/****************************************************************************
+*
+* BIOS emulator and interface
+* to Realmode X86 Emulator Library
+*
+* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+* Jason Jin <Jason.jin@freescale.com>
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Module implementing the BIOS specific functions.
+*
+* Jason ported this file to u-boot to run the ATI video card
+* video BIOS.
+*
+****************************************************************************/
+
+#include <common.h>
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "biosemui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+intno - Interrupt number being serviced
+
+REMARKS:
+Handler for undefined interrupts.
+****************************************************************************/
+static void X86API undefined_intr(int intno)
+{
+ if (BE_rdw(intno * 4 + 2) == BIOS_SEG) {
+ DB(printf("biosEmu: undefined interrupt %xh called!\n", intno);)
+ } else
+ X86EMU_prepareForInt(intno);
+}
+
+/****************************************************************************
+PARAMETERS:
+intno - Interrupt number being serviced
+
+REMARKS:
+This function handles the default system BIOS Int 10h (the default is stored
+in the Int 42h vector by the system BIOS at bootup). We only need to handle
+a small number of special functions used by the BIOS during POST time.
+****************************************************************************/
+static void X86API int42(int intno)
+{
+ if (M.x86.R_AH == 0x12 && M.x86.R_BL == 0x32) {
+ if (M.x86.R_AL == 0) {
+ /* Enable CPU accesses to video memory */
+ PM_outpb(0x3c2, PM_inpb(0x3cc) | (u8) 0x02);
+ return;
+ } else if (M.x86.R_AL == 1) {
+ /* Disable CPU accesses to video memory */
+ PM_outpb(0x3c2, PM_inpb(0x3cc) & (u8) ~ 0x02);
+ return;
+ }
+#ifdef DEBUG
+ else {
+ printf("int42: unknown function AH=0x12, BL=0x32, AL=%#02x\n",
+ M.x86.R_AL);
+ }
+#endif
+ }
+#ifdef DEBUG
+ else {
+ printf("int42: unknown function AH=%#02x, AL=%#02x, BL=%#02x\n",
+ M.x86.R_AH, M.x86.R_AL, M.x86.R_BL);
+ }
+#endif
+}
+
+/****************************************************************************
+PARAMETERS:
+intno - Interrupt number being serviced
+
+REMARKS:
+This function handles the default system BIOS Int 10h. If the POST code
+has not yet re-vectored the Int 10h BIOS interrupt vector, we handle this
+by simply calling the int42 interrupt handler above. Very early in the
+BIOS POST process, the vector gets replaced and we simply let the real
+mode interrupt handler process the interrupt.
+****************************************************************************/
+static void X86API int10(int intno)
+{
+ if (BE_rdw(intno * 4 + 2) == BIOS_SEG)
+ int42(intno);
+ else
+ X86EMU_prepareForInt(intno);
+}
+
+/* Result codes returned by the PCI BIOS */
+
+#define SUCCESSFUL 0x00
+#define FUNC_NOT_SUPPORT 0x81
+#define BAD_VENDOR_ID 0x83
+#define DEVICE_NOT_FOUND 0x86
+#define BAD_REGISTER_NUMBER 0x87
+#define SET_FAILED 0x88
+#define BUFFER_TOO_SMALL 0x89
+
+/****************************************************************************
+PARAMETERS:
+intno - Interrupt number being serviced
+
+REMARKS:
+This function handles the default Int 1Ah interrupt handler for the real
+mode code, which provides support for the PCI BIOS functions. Since we only
+want to allow the real mode BIOS code *only* see the PCI config space for
+its own device, we only return information for the specific PCI config
+space that we have passed in to the init function. This solves problems
+when using the BIOS to warm boot a secondary adapter when there is an
+identical adapter before it on the bus (some BIOS'es get confused in this
+case).
+****************************************************************************/
+static void X86API int1A(int unused)
+{
+ u16 pciSlot;
+
+#ifdef __KERNEL__
+ u8 interface, subclass, baseclass;
+
+ /* Initialise the PCI slot number */
+ pciSlot = ((int)_BE_env.vgaInfo.bus << 8) |
+ ((int)_BE_env.vgaInfo.device << 3) | (int)_BE_env.vgaInfo.function;
+#else
+/* Fail if no PCI device information has been registered */
+ if (!_BE_env.vgaInfo.pciInfo)
+ return;
+
+ pciSlot = (u16) (_BE_env.vgaInfo.pciInfo->slot.i >> 8);
+#endif
+ switch (M.x86.R_AX) {
+ case 0xB101: /* PCI bios present? */
+ M.x86.R_AL = 0x00; /* no config space/special cycle generation support */
+ M.x86.R_EDX = 0x20494350; /* " ICP" */
+ M.x86.R_BX = 0x0210; /* Version 2.10 */
+ M.x86.R_CL = 0; /* Max bus number in system */
+ CLEAR_FLAG(F_CF);
+ break;
+ case 0xB102: /* Find PCI device */
+ M.x86.R_AH = DEVICE_NOT_FOUND;
+#ifdef __KERNEL__
+ if (M.x86.R_DX == _BE_env.vgaInfo.VendorID &&
+ M.x86.R_CX == _BE_env.vgaInfo.DeviceID && M.x86.R_SI == 0) {
+#else
+ if (M.x86.R_DX == _BE_env.vgaInfo.pciInfo->VendorID &&
+ M.x86.R_CX == _BE_env.vgaInfo.pciInfo->DeviceID &&
+ M.x86.R_SI == 0) {
+#endif
+ M.x86.R_AH = SUCCESSFUL;
+ M.x86.R_BX = pciSlot;
+ }
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
+ break;
+ case 0xB103: /* Find PCI class code */
+ M.x86.R_AH = DEVICE_NOT_FOUND;
+#ifdef __KERNEL__
+ pci_read_config_byte(_BE_env.vgaInfo.pcidev, PCI_CLASS_PROG,
+ &interface);
+ pci_read_config_byte(_BE_env.vgaInfo.pcidev, PCI_CLASS_DEVICE,
+ &subclass);
+ pci_read_config_byte(_BE_env.vgaInfo.pcidev,
+ PCI_CLASS_DEVICE + 1, &baseclass);
+ if (M.x86.R_CL == interface && M.x86.R_CH == subclass
+ && (u8) (M.x86.R_ECX >> 16) == baseclass) {
+#else
+ if (M.x86.R_CL == _BE_env.vgaInfo.pciInfo->Interface &&
+ M.x86.R_CH == _BE_env.vgaInfo.pciInfo->SubClass &&
+ (u8) (M.x86.R_ECX >> 16) ==
+ _BE_env.vgaInfo.pciInfo->BaseClass) {
+#endif
+ M.x86.R_AH = SUCCESSFUL;
+ M.x86.R_BX = pciSlot;
+ }
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
+ break;
+ case 0xB108: /* Read configuration byte */
+ M.x86.R_AH = BAD_REGISTER_NUMBER;
+ if (M.x86.R_BX == pciSlot) {
+ M.x86.R_AH = SUCCESSFUL;
+#ifdef __KERNEL__
+ pci_read_config_byte(_BE_env.vgaInfo.pcidev, M.x86.R_DI,
+ &M.x86.R_CL);
+#else
+ M.x86.R_CL =
+ (u8) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_BYTE,
+ _BE_env.vgaInfo.pciInfo);
+#endif
+ }
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
+ break;
+ case 0xB109: /* Read configuration word */
+ M.x86.R_AH = BAD_REGISTER_NUMBER;
+ if (M.x86.R_BX == pciSlot) {
+ M.x86.R_AH = SUCCESSFUL;
+#ifdef __KERNEL__
+ pci_read_config_word(_BE_env.vgaInfo.pcidev, M.x86.R_DI,
+ &M.x86.R_CX);
+#else
+ M.x86.R_CX =
+ (u16) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_WORD,
+ _BE_env.vgaInfo.pciInfo);
+#endif
+ }
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
+ break;
+ case 0xB10A: /* Read configuration dword */
+ M.x86.R_AH = BAD_REGISTER_NUMBER;
+ if (M.x86.R_BX == pciSlot) {
+ M.x86.R_AH = SUCCESSFUL;
+#ifdef __KERNEL__
+ pci_read_config_dword(_BE_env.vgaInfo.pcidev,
+ M.x86.R_DI, &M.x86.R_ECX);
+#else
+ M.x86.R_ECX =
+ (u32) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_DWORD,
+ _BE_env.vgaInfo.pciInfo);
+#endif
+ }
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
+ break;
+ case 0xB10B: /* Write configuration byte */
+ M.x86.R_AH = BAD_REGISTER_NUMBER;
+ if (M.x86.R_BX == pciSlot) {
+ M.x86.R_AH = SUCCESSFUL;
+#ifdef __KERNEL__
+ pci_write_config_byte(_BE_env.vgaInfo.pcidev,
+ M.x86.R_DI, M.x86.R_CL);
+#else
+ PCI_accessReg(M.x86.R_DI, M.x86.R_CL, PCI_WRITE_BYTE,
+ _BE_env.vgaInfo.pciInfo);
+#endif
+ }
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
+ break;
+ case 0xB10C: /* Write configuration word */
+ M.x86.R_AH = BAD_REGISTER_NUMBER;
+ if (M.x86.R_BX == pciSlot) {
+ M.x86.R_AH = SUCCESSFUL;
+#ifdef __KERNEL__
+ pci_write_config_word(_BE_env.vgaInfo.pcidev,
+ M.x86.R_DI, M.x86.R_CX);
+#else
+ PCI_accessReg(M.x86.R_DI, M.x86.R_CX, PCI_WRITE_WORD,
+ _BE_env.vgaInfo.pciInfo);
+#endif
+ }
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
+ break;
+ case 0xB10D: /* Write configuration dword */
+ M.x86.R_AH = BAD_REGISTER_NUMBER;
+ if (M.x86.R_BX == pciSlot) {
+ M.x86.R_AH = SUCCESSFUL;
+#ifdef __KERNEL__
+ pci_write_config_dword(_BE_env.vgaInfo.pcidev,
+ M.x86.R_DI, M.x86.R_ECX);
+#else
+ PCI_accessReg(M.x86.R_DI, M.x86.R_ECX, PCI_WRITE_DWORD,
+ _BE_env.vgaInfo.pciInfo);
+#endif
+ }
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
+ break;
+ default:
+ printf("biosEmu/bios.int1a: unknown function AX=%#04x\n",
+ M.x86.R_AX);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+This function initialises the BIOS emulation functions for the specific
+PCI display device. We insulate the real mode BIOS from any other devices
+on the bus, so that it will work correctly thinking that it is the only
+device present on the bus (ie: avoiding any adapters present in from of
+the device we are trying to control).
+****************************************************************************/
+#define BE_constLE_32(v) ((((((v)&0xff00)>>8)|(((v)&0xff)<<8))<<16)|(((((v)&0xff000000)>>8)|(((v)&0x00ff0000)<<8))>>16))
+
+void _BE_bios_init(u32 * intrTab)
+{
+ int i;
+ X86EMU_intrFuncs bios_intr_tab[256];
+
+ for (i = 0; i < 256; ++i) {
+ intrTab[i] = BE_constLE_32(BIOS_SEG << 16);
+ bios_intr_tab[i] = undefined_intr;
+ }
+ bios_intr_tab[0x10] = int10;
+ bios_intr_tab[0x1A] = int1A;
+ bios_intr_tab[0x42] = int42;
+ bios_intr_tab[0x6D] = int10;
+ X86EMU_setupIntrFuncs(bios_intr_tab);
+}
+#endif
diff --git a/drivers/bios_emulator/biosemu.c b/drivers/bios_emulator/biosemu.c
new file mode 100644
index 0000000000..ccfc872f78
--- /dev/null
+++ b/drivers/bios_emulator/biosemu.c
@@ -0,0 +1,375 @@
+/****************************************************************************
+*
+* BIOS emulator and interface
+* to Realmode X86 Emulator Library
+*
+* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+* Jason Jin <Jason.jin@freescale.com>
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Module implementing the system specific functions. This
+* module is always compiled and linked in the OS depedent
+* libraries, and never in a binary portable driver.
+*
+* Jason ported this file to u-boot to run the ATI video card BIOS
+* in u-boot. Made all the video memory be emulated during the
+* BIOS runing process which may affect the VGA function but the
+* frambuffer function can work after run the BIOS.
+*
+****************************************************************************/
+
+#include <malloc.h>
+#include <common.h>
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "biosemui.h"
+
+BE_sysEnv _BE_env = {{0}};
+static X86EMU_memFuncs _BE_mem __attribute__((section(".got2"))) = {
+ BE_rdb,
+ BE_rdw,
+ BE_rdl,
+ BE_wrb,
+ BE_wrw,
+ BE_wrl,
+ };
+
+static X86EMU_pioFuncs _BE_pio __attribute__((section(".got2"))) = {
+ BE_inb,
+ BE_inw,
+ BE_inl,
+ BE_outb,
+ BE_outw,
+ BE_outl,
+ };
+
+#define OFF(addr) (u16)(((addr) >> 0) & 0xffff)
+#define SEG(addr) (u16)(((addr) >> 4) & 0xf000)
+
+/****************************************************************************
+PARAMETERS:
+debugFlags - Flags to enable debugging options (debug builds only)
+memSize - Amount of memory to allocate for real mode machine
+info - Pointer to default VGA device information
+
+REMARKS:
+This functions initialises the BElib, and uses the passed in
+BIOS image as the BIOS that is used and emulated at 0xC0000.
+****************************************************************************/
+int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
+{
+#if !defined(__DRIVER__) && !defined(__KERNEL__)
+
+ PM_init();
+#endif
+ memset(&M, 0, sizeof(M));
+ if (memSize < 20480){
+ printf("Emulator requires at least 20Kb of memory!\n");
+ return 0;
+ }
+
+ M.mem_base = (unsigned long)malloc(memSize);
+
+ if (M.mem_base == NULL){
+ printf("Biosemu:Out of memory!");
+ return 0;
+ }
+ M.mem_size = memSize;
+
+ _BE_env.emulateVGA = 0;
+ _BE_env.busmem_base = (unsigned long)malloc(128 * 1024);
+ if (_BE_env.busmem_base == NULL){
+ printf("Biosemu:Out of memory!");
+ return 0;
+ }
+ M.x86.debug = debugFlags;
+ _BE_bios_init((u32*)info->LowMem);
+ X86EMU_setupMemFuncs(&_BE_mem);
+ X86EMU_setupPioFuncs(&_BE_pio);
+ BE_setVGA(info);
+ return 1;
+}
+
+/****************************************************************************
+PARAMETERS:
+info - Pointer to VGA device information to make current
+
+REMARKS:
+This function sets the VGA BIOS functions in the emulator to point to the
+specific VGA BIOS in use. This includes swapping the BIOS interrupt
+vectors, BIOS image and BIOS data area to the new BIOS. This allows the
+real mode BIOS to be swapped without resetting the entire emulator.
+****************************************************************************/
+void X86API BE_setVGA(BE_VGAInfo * info)
+{
+
+#ifdef __KERNEL__
+ _BE_env.vgaInfo.function = info->function;
+ _BE_env.vgaInfo.device = info->device;
+ _BE_env.vgaInfo.bus = info->bus;
+ _BE_env.vgaInfo.pcidev = info->pcidev;
+#else
+ _BE_env.vgaInfo.pciInfo = info->pciInfo;
+#endif
+ _BE_env.vgaInfo.BIOSImage = info->BIOSImage;
+ if (info->BIOSImage) {
+ _BE_env.biosmem_base = (ulong) info->BIOSImage;
+ _BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen - 1;
+ } else {
+ _BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
+ _BE_env.biosmem_limit = 0xC7FFF;
+ }
+ if (*((u32 *) info->LowMem) == 0)
+ _BE_bios_init((u32 *) info->LowMem);
+ memcpy((u8 *) M.mem_base, info->LowMem, sizeof(info->LowMem));
+}
+
+/****************************************************************************
+PARAMETERS:
+info - Pointer to VGA device information to retrieve current
+
+REMARKS:
+This function returns the VGA BIOS functions currently active in the
+emulator, so they can be restored at a later date.
+****************************************************************************/
+void X86API BE_getVGA(BE_VGAInfo * info)
+{
+#ifdef __KERNEL__
+ info->function = _BE_env.vgaInfo.function;
+ info->device = _BE_env.vgaInfo.device;
+ info->bus = _BE_env.vgaInfo.bus;
+ info->pcidev = _BE_env.vgaInfo.pcidev;
+#else
+ info->pciInfo = _BE_env.vgaInfo.pciInfo;
+#endif
+ info->BIOSImage = _BE_env.vgaInfo.BIOSImage;
+ memcpy(info->LowMem, (u8 *) M.mem_base, sizeof(info->LowMem));
+}
+
+/****************************************************************************
+PARAMETERS:
+r_seg - Segment for pointer to convert
+r_off - Offset for pointer to convert
+
+REMARKS:
+This function maps a real mode pointer in the emulator memory to a protected
+mode pointer that can be used to directly access the memory.
+
+NOTE: The memory is *always* in little endian format, son on non-x86
+ systems you will need to do endian translations to access this
+ memory.
+****************************************************************************/
+void *X86API BE_mapRealPointer(uint r_seg, uint r_off)
+{
+ u32 addr = ((u32) r_seg << 4) + r_off;
+
+ if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
+ return (void *)(_BE_env.biosmem_base + addr - 0xC0000);
+ } else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
+ return (void *)(_BE_env.busmem_base + addr - 0xA0000);
+ }
+ return (void *)(M.mem_base + addr);
+}
+
+/****************************************************************************
+PARAMETERS:
+len - Return the length of the VESA buffer
+rseg - Place to store VESA buffer segment
+roff - Place to store VESA buffer offset
+
+REMARKS:
+This function returns the address of the VESA transfer buffer in real
+_BE_piomode emulator memory. The VESA transfer buffer is always 1024 bytes long,
+and located at 15Kb into the start of the real mode memory (16Kb is where
+we put the real mode code we execute for issuing interrupts).
+
+NOTE: The memory is *always* in little endian format, son on non-x86
+ systems you will need to do endian translations to access this
+ memory.
+****************************************************************************/
+void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff)
+{
+ *len = 1024;
+ *rseg = SEG(0x03C00);
+ *roff = OFF(0x03C00);
+ return (void *)(M.mem_base + ((u32) * rseg << 4) + *roff);
+}
+
+/****************************************************************************
+REMARKS:
+Cleans up and exits the emulator.
+****************************************************************************/
+void X86API BE_exit(void)
+{
+ free(M.mem_base);
+ free(_BE_env.busmem_base);
+}
+
+/****************************************************************************
+PARAMETERS:
+seg - Segment of code to call
+off - Offset of code to call
+regs - Real mode registers to load
+sregs - Real mode segment registers to load
+
+REMARKS:
+This functions calls a real mode far function at the specified address,
+and loads all the x86 registers from the passed in registers structure.
+On exit the registers returned from the call are returned in the same
+structures.
+****************************************************************************/
+void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs, RMSREGS * sregs)
+{
+ M.x86.R_EAX = regs->e.eax;
+ M.x86.R_EBX = regs->e.ebx;
+ M.x86.R_ECX = regs->e.ecx;
+ M.x86.R_EDX = regs->e.edx;
+ M.x86.R_ESI = regs->e.esi;
+ M.x86.R_EDI = regs->e.edi;
+ M.x86.R_DS = sregs->ds;
+ M.x86.R_ES = sregs->es;
+ M.x86.R_FS = sregs->fs;
+ M.x86.R_GS = sregs->gs;
+
+ ((u8 *) M.mem_base)[0x4000] = 0x9A;
+ ((u8 *) M.mem_base)[0x4001] = (u8) off;
+ ((u8 *) M.mem_base)[0x4002] = (u8) (off >> 8);
+ ((u8 *) M.mem_base)[0x4003] = (u8) seg;
+ ((u8 *) M.mem_base)[0x4004] = (u8) (seg >> 8);
+ ((u8 *) M.mem_base)[0x4005] = 0xF1; /* Illegal op-code */
+ M.x86.R_CS = SEG(0x04000);
+ M.x86.R_IP = OFF(0x04000);
+
+ M.x86.R_SS = SEG(M.mem_size - 2);
+ M.x86.R_SP = OFF(M.mem_size - 2) + 2;
+
+ X86EMU_exec();
+
+ regs->e.cflag = M.x86.R_EFLG & F_CF;
+ regs->e.eax = M.x86.R_EAX;
+ regs->e.ebx = M.x86.R_EBX;
+ regs->e.ecx = M.x86.R_ECX;
+ regs->e.edx = M.x86.R_EDX;
+ regs->e.esi = M.x86.R_ESI;
+ regs->e.edi = M.x86.R_EDI;
+ sregs->ds = M.x86.R_DS;
+ sregs->es = M.x86.R_ES;
+ sregs->fs = M.x86.R_FS;
+ sregs->gs = M.x86.R_GS;
+}
+
+/****************************************************************************
+PARAMETERS:
+intno - Interrupt number to execute
+in - Real mode registers to load
+out - Place to store resulting real mode registers
+
+REMARKS:
+This functions calls a real mode interrupt function at the specified address,
+and loads all the x86 registers from the passed in registers structure.
+On exit the registers returned from the call are returned in out stucture.
+****************************************************************************/
+int X86API BE_int86(int intno, RMREGS * in, RMREGS * out)
+{
+ M.x86.R_EAX = in->e.eax;
+ M.x86.R_EBX = in->e.ebx;
+ M.x86.R_ECX = in->e.ecx;
+ M.x86.R_EDX = in->e.edx;
+ M.x86.R_ESI = in->e.esi;
+ M.x86.R_EDI = in->e.edi;
+ ((u8 *) M.mem_base)[0x4000] = 0xCD;
+ ((u8 *) M.mem_base)[0x4001] = (u8) intno;
+ ((u8 *) M.mem_base)[0x4002] = 0xF1;
+ M.x86.R_CS = SEG(0x04000);
+ M.x86.R_IP = OFF(0x04000);
+
+ M.x86.R_SS = SEG(M.mem_size - 1);
+ M.x86.R_SP = OFF(M.mem_size - 1) - 1;
+
+ X86EMU_exec();
+ out->e.cflag = M.x86.R_EFLG & F_CF;
+ out->e.eax = M.x86.R_EAX;
+ out->e.ebx = M.x86.R_EBX;
+ out->e.ecx = M.x86.R_ECX;
+ out->e.edx = M.x86.R_EDX;
+ out->e.esi = M.x86.R_ESI;
+ out->e.edi = M.x86.R_EDI;
+ return out->x.ax;
+}
+
+/****************************************************************************
+PARAMETERS:
+intno - Interrupt number to execute
+in - Real mode registers to load
+out - Place to store resulting real mode registers
+sregs - Real mode segment registers to load
+
+REMARKS:
+This functions calls a real mode interrupt function at the specified address,
+and loads all the x86 registers from the passed in registers structure.
+On exit the registers returned from the call are returned in out stucture.
+****************************************************************************/
+int X86API BE_int86x(int intno, RMREGS * in, RMREGS * out, RMSREGS * sregs)
+{
+ M.x86.R_EAX = in->e.eax;
+ M.x86.R_EBX = in->e.ebx;
+ M.x86.R_ECX = in->e.ecx;
+ M.x86.R_EDX = in->e.edx;
+ M.x86.R_ESI = in->e.esi;
+ M.x86.R_EDI = in->e.edi;
+ M.x86.R_DS = sregs->ds;
+ M.x86.R_ES = sregs->es;
+ M.x86.R_FS = sregs->fs;
+ M.x86.R_GS = sregs->gs;
+ ((u8 *) M.mem_base)[0x4000] = 0xCD;
+ ((u8 *) M.mem_base)[0x4001] = (u8) intno;
+ ((u8 *) M.mem_base)[0x4002] = 0xF1;
+ M.x86.R_CS = SEG(0x04000);
+ M.x86.R_IP = OFF(0x04000);
+
+ M.x86.R_SS = SEG(M.mem_size - 1);
+ M.x86.R_SP = OFF(M.mem_size - 1) - 1;
+
+ X86EMU_exec();
+ out->e.cflag = M.x86.R_EFLG & F_CF;
+ out->e.eax = M.x86.R_EAX;
+ out->e.ebx = M.x86.R_EBX;
+ out->e.ecx = M.x86.R_ECX;
+ out->e.edx = M.x86.R_EDX;
+ out->e.esi = M.x86.R_ESI;
+ out->e.edi = M.x86.R_EDI;
+ sregs->ds = M.x86.R_DS;
+ sregs->es = M.x86.R_ES;
+ sregs->fs = M.x86.R_FS;
+ sregs->gs = M.x86.R_GS;
+ return out->x.ax;
+}
+#endif
diff --git a/drivers/bios_emulator/biosemui.h b/drivers/bios_emulator/biosemui.h
new file mode 100644
index 0000000000..e85e656cb4
--- /dev/null
+++ b/drivers/bios_emulator/biosemui.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+*
+* BIOS emulator and interface
+* to Realmode X86 Emulator Library
+*
+* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+* Jason Jin <Jason.jin@freescale.com>
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Internal header file for the BIOS emulator library.
+*
+* Jason ported this file to u-boot, Added some architecture
+* related Macro.
+*
+****************************************************************************/
+
+#ifndef __BIOSEMUI_H
+#define __BIOSEMUI_H
+
+#include "biosemu.h"
+#include <asm/io.h>
+/*---------------------- Macros and type definitions ----------------------*/
+
+#ifdef DEBUG
+#define DB(x) x
+#else
+#define DB(x) do{}while(0);
+#endif
+
+#define BIOS_SEG 0xfff0
+extern X86EMU_sysEnv _X86EMU_env;
+#define M _X86EMU_env
+
+/* Macros to read and write values to x86 emulator memory. Memory is always
+ * considered to be little endian, so we use macros to do endian swapping
+ * where necessary.
+ */
+
+#ifdef __BIG_ENDIAN__
+#define readb_le(base) *((u8*)(base))
+#define readw_le(base) ((u16)readb_le(base) | ((u16)readb_le((base) + 1) << 8))
+#define readl_le(base) ((u32)readb_le((base) + 0) | ((u32)readb_le((base) + 1) << 8) | \
+ ((u32)readb_le((base) + 2) << 16) | ((u32)readb_le((base) + 3) << 24))
+#define writeb_le(base, v) *((u8*)(base)) = (v)
+#define writew_le(base, v) writeb_le(base + 0, (v >> 0) & 0xff), \
+ writeb_le(base + 1, (v >> 8) & 0xff)
+#define writel_le(base, v) writeb_le(base + 0, (v >> 0) & 0xff), \
+ writeb_le(base + 1, (v >> 8) & 0xff), \
+ writeb_le(base + 2, (v >> 16) & 0xff), \
+ writeb_le(base + 3, (v >> 24) & 0xff)
+#else
+#define readb_le(base) *((u8*)(base))
+#define readw_le(base) *((u16*)(base))
+#define readl_le(base) *((u32*)(base))
+#define writeb_le(base, v) *((u8*)(base)) = (v)
+#define writew_le(base, v) *((u16*)(base)) = (v)
+#define writel_le(base, v) *((u32*)(base)) = (v)
+#endif
+
+/****************************************************************************
+REMARKS:
+Function codes passed to the emulated I/O port functions to determine the
+type of operation to perform.
+****************************************************************************/
+typedef enum {
+ REG_READ_BYTE = 0,
+ REG_READ_WORD = 1,
+ REG_READ_DWORD = 2,
+ REG_WRITE_BYTE = 3,
+ REG_WRITE_WORD = 4,
+ REG_WRITE_DWORD = 5
+} RegisterFlags;
+
+/****************************************************************************
+REMARKS:
+Function codes passed to the emulated I/O port functions to determine the
+type of operation to perform.
+****************************************************************************/
+typedef enum {
+ PORT_BYTE = 1,
+ PORT_WORD = 2,
+ PORT_DWORD = 3,
+} PortInfoFlags;
+
+/****************************************************************************
+REMARKS:
+Data structure used to describe the details for the BIOS emulator system
+environment as used by the X86 emulator library.
+
+HEADER:
+biosemu.h
+
+MEMBERS:
+type - Type of port access (1 = byte, 2 = word, 3 = dword)
+defVal - Default power on value
+finalVal - Final value
+****************************************************************************/
+typedef struct {
+ u8 type;
+ u32 defVal;
+ u32 finalVal;
+} BE_portInfo;
+
+#define PM_inpb(port) inb(port+VIDEO_IO_OFFSET)
+#define PM_inpw(port) inw(port+VIDEO_IO_OFFSET)
+#define PM_inpd(port) inl(port+VIDEO_IO_OFFSET)
+#define PM_outpb(port,val) outb(val,port+VIDEO_IO_OFFSET)
+#define PM_outpw(port,val) outw(val,port+VIDEO_IO_OFFSET)
+#define PM_outpd(port,val) outl(val,port+VIDEO_IO_OFFSET)
+
+#define LOG_inpb(port) PM_inpb(port)
+#define LOG_inpw(port) PM_inpw(port)
+#define LOG_inpd(port) PM_inpd(port)
+#define LOG_outpb(port,val) PM_outpb(port,val)
+#define LOG_outpw(port,val) PM_outpw(port,val)
+#define LOG_outpd(port,val) PM_outpd(port,val)
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+/* bios.c */
+
+void _BE_bios_init(u32 * intrTab);
+void _BE_setup_funcs(void);
+
+/* besys.c */
+#define DEBUG_IO() (M.x86.debug & DEBUG_IO_TRACE_F)
+
+u8 X86API BE_rdb(u32 addr);
+u16 X86API BE_rdw(u32 addr);
+u32 X86API BE_rdl(u32 addr);
+void X86API BE_wrb(u32 addr, u8 val);
+void X86API BE_wrw(u32 addr, u16 val);
+void X86API BE_wrl(u32 addr, u32 val);
+
+u8 X86API BE_inb(X86EMU_pioAddr port);
+u16 X86API BE_inw(X86EMU_pioAddr port);
+u32 X86API BE_inl(X86EMU_pioAddr port);
+void X86API BE_outb(X86EMU_pioAddr port, u8 val);
+void X86API BE_outw(X86EMU_pioAddr port, u16 val);
+void X86API BE_outl(X86EMU_pioAddr port, u32 val);
+#endif
+/* __BIOSEMUI_H */
diff --git a/drivers/bios_emulator/include/biosemu.h b/drivers/bios_emulator/include/biosemu.h
new file mode 100644
index 0000000000..13cb3170c1
--- /dev/null
+++ b/drivers/bios_emulator/include/biosemu.h
@@ -0,0 +1,392 @@
+/****************************************************************************
+*
+* BIOS emulator and interface
+* to Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for the real mode x86 BIOS emulator, which is
+* used to warmboot any number of VGA compatible PCI/AGP
+* controllers under any OS, on any processor family that
+* supports PCI. We also allow the user application to call
+* real mode BIOS functions and Int 10h functions (including
+* the VESA BIOS).
+*
+****************************************************************************/
+
+#ifndef __BIOSEMU_H
+#define __BIOSEMU_H
+
+#ifdef __KERNEL__
+#include "x86emu.h"
+#else
+#include "x86emu.h"
+#include "pmapi.h"
+#include "pcilib.h"
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#pragma pack(1)
+
+#ifndef __KERNEL__
+/****************************************************************************
+REMARKS:
+Data structure used to describe the details specific to a particular VGA
+controller. This information is used to allow the VGA controller to be
+swapped on the fly within the BIOS emulator.
+
+HEADER:
+biosemu.h
+
+MEMBERS:
+pciInfo - PCI device information block for the controller
+BIOSImage - Pointer to a read/write copy of the BIOS image
+BIOSImageLen - Length of the BIOS image
+LowMem - Copy of key low memory areas
+****************************************************************************/
+typedef struct {
+ PCIDeviceInfo *pciInfo;
+ void *BIOSImage;
+ ulong BIOSImageLen;
+ uchar LowMem[1536];
+} BE_VGAInfo;
+#else
+/****************************************************************************
+REMARKS:
+Data structure used to describe the details for the BIOS emulator system
+environment as used by the X86 emulator library.
+
+HEADER:
+biosemu.h
+
+MEMBERS:
+vgaInfo - VGA BIOS information structure
+biosmem_base - Base of the BIOS image
+biosmem_limit - Limit of the BIOS image
+busmem_base - Base of the VGA bus memory
+****************************************************************************/
+typedef struct {
+ int function;
+ int device;
+ int bus;
+ u32 VendorID;
+ u32 DeviceID;
+ pci_dev_t pcidev;
+ void *BIOSImage;
+ u32 BIOSImageLen;
+ u8 LowMem[1536];
+} BE_VGAInfo;
+
+#endif /* __KERNEL__ */
+
+#define CRT_C 24 /* 24 CRT Controller Registers */
+#define ATT_C 21 /* 21 Attribute Controller Registers */
+#define GRA_C 9 /* 9 Graphics Controller Registers */
+#define SEQ_C 5 /* 5 Sequencer Registers */
+#define PAL_C 768 /* 768 Palette Registers */
+
+/****************************************************************************
+REMARKS:
+Data structure used to describe the details for the BIOS emulator system
+environment as used by the X86 emulator library.
+
+HEADER:
+biosemu.h
+
+MEMBERS:
+vgaInfo - VGA BIOS information structure
+biosmem_base - Base of the BIOS image
+biosmem_limit - Limit of the BIOS image
+busmem_base - Base of the VGA bus memory
+timer - Timer used to emulate PC timer ports
+timer0 - Latched value for timer 0
+timer0Latched - True if timer 0 value was just latched
+timer2 - Current value for timer 2
+emulateVGA - True to emulate VGA I/O and memory accesses
+****************************************************************************/
+
+typedef struct {
+ BE_VGAInfo vgaInfo;
+ ulong biosmem_base;
+ ulong biosmem_limit;
+ ulong busmem_base;
+
+ u32 timer0;
+ int timer0Latched;
+ u32 timer1;
+ int timer1Latched;
+ u32 timer2;
+ int timer2Latched;
+
+ int emulateVGA;
+ u8 emu61;
+ u8 emu70;
+ int flipFlop3C0;
+ u32 configAddress;
+ u8 emu3C0;
+ u8 emu3C1[ATT_C];
+ u8 emu3C2;
+ u8 emu3C4;
+ u8 emu3C5[SEQ_C];
+ u8 emu3C6;
+ uint emu3C7;
+ uint emu3C8;
+ u8 emu3C9[PAL_C];
+ u8 emu3CE;
+ u8 emu3CF[GRA_C];
+ u8 emu3D4;
+ u8 emu3D5[CRT_C];
+ u8 emu3DA;
+
+} BE_sysEnv;
+
+#ifdef __KERNEL__
+
+/* Define some types when compiling for the Linux kernel that normally
+ * come from the SciTech PM library.
+ */
+
+/****************************************************************************
+REMARKS:
+Structure describing the 32-bit extended x86 CPU registers
+
+HEADER:
+pmapi.h
+
+MEMBERS:
+eax - Value of the EAX register
+ebx - Value of the EBX register
+ecx - Value of the ECX register
+edx - Value of the EDX register
+esi - Value of the ESI register
+edi - Value of the EDI register
+cflag - Value of the carry flag
+****************************************************************************/
+typedef struct {
+ u32 eax;
+ u32 ebx;
+ u32 ecx;
+ u32 edx;
+ u32 esi;
+ u32 edi;
+ u32 cflag;
+} RMDWORDREGS;
+
+/****************************************************************************
+REMARKS:
+Structure describing the 16-bit x86 CPU registers
+
+HEADER:
+pmapi.h
+
+MEMBERS:
+ax - Value of the AX register
+bx - Value of the BX register
+cx - Value of the CX register
+dx - Value of the DX register
+si - Value of the SI register
+di - Value of the DI register
+cflag - Value of the carry flag
+****************************************************************************/
+#ifdef __BIG_ENDIAN__
+typedef struct {
+ u16 ax_hi, ax;
+ u16 bx_hi, bx;
+ u16 cx_hi, cx;
+ u16 dx_hi, dx;
+ u16 si_hi, si;
+ u16 di_hi, di;
+ u16 cflag_hi, cflag;
+} RMWORDREGS;
+#else
+typedef struct {
+ u16 ax, ax_hi;
+ u16 bx, bx_hi;
+ u16 cx, cx_hi;
+ u16 dx, dx_hi;
+ u16 si, si_hi;
+ u16 di, di_hi;
+ u16 cflag, cflag_hi;
+} RMWORDREGS;
+#endif
+
+/****************************************************************************
+REMARKS:
+Structure describing the 8-bit x86 CPU registers
+
+HEADER:
+pmapi.h
+
+MEMBERS:
+al - Value of the AL register
+ah - Value of the AH register
+bl - Value of the BL register
+bh - Value of the BH register
+cl - Value of the CL register
+ch - Value of the CH register
+dl - Value of the DL register
+dh - Value of the DH register
+****************************************************************************/
+#ifdef __BIG_ENDIAN__
+typedef struct {
+ u16 ax_hi;
+ u8 ah, al;
+ u16 bx_hi;
+ u8 bh, bl;
+ u16 cx_hi;
+ u8 ch, cl;
+ u16 dx_hi;
+ u8 dh, dl;
+} RMBYTEREGS;
+#else
+typedef struct {
+ u8 al;
+ u8 ah;
+ u16 ax_hi;
+ u8 bl;
+ u8 bh;
+ u16 bx_hi;
+ u8 cl;
+ u8 ch;
+ u16 cx_hi;
+ u8 dl;
+ u8 dh;
+ u16 dx_hi;
+} RMBYTEREGS;
+#endif
+
+/****************************************************************************
+REMARKS:
+Structure describing all the x86 CPU registers
+
+HEADER:
+pmapi.h
+
+MEMBERS:
+e - Member to access registers as 32-bit values
+x - Member to access registers as 16-bit values
+h - Member to access registers as 8-bit values
+****************************************************************************/
+typedef union {
+ RMDWORDREGS e;
+ RMWORDREGS x;
+ RMBYTEREGS h;
+} RMREGS;
+
+/****************************************************************************
+REMARKS:
+Structure describing all the x86 segment registers
+
+HEADER:
+pmapi.h
+
+MEMBERS:
+es - ES segment register
+cs - CS segment register
+ss - SS segment register
+ds - DS segment register
+fs - FS segment register
+gs - GS segment register
+****************************************************************************/
+typedef struct {
+ u16 es;
+ u16 cs;
+ u16 ss;
+ u16 ds;
+ u16 fs;
+ u16 gs;
+} RMSREGS;
+
+#endif /* __KERNEL__ */
+
+#ifndef __KERNEL__
+
+/****************************************************************************
+REMARKS:
+Structure defining all the BIOS Emulator API functions as exported from
+the Binary Portable DLL.
+{secret}
+****************************************************************************/
+typedef struct {
+ ulong dwSize;
+ ibool(PMAPIP BE_init) (u32 debugFlags, int memSize, BE_VGAInfo * info);
+ void (PMAPIP BE_setVGA) (BE_VGAInfo * info);
+ void (PMAPIP BE_getVGA) (BE_VGAInfo * info);
+ void *(PMAPIP BE_mapRealPointer) (uint r_seg, uint r_off);
+ void *(PMAPIP BE_getVESABuf) (uint * len, uint * rseg, uint * roff);
+ void (PMAPIP BE_callRealMode) (uint seg, uint off, RMREGS * regs,
+ RMSREGS * sregs);
+ int (PMAPIP BE_int86) (int intno, RMREGS * in, RMREGS * out);
+ int (PMAPIP BE_int86x) (int intno, RMREGS * in, RMREGS * out,
+ RMSREGS * sregs);
+ void *reserved1;
+ void (PMAPIP BE_exit) (void);
+} BE_exports;
+
+/****************************************************************************
+REMARKS:
+Function pointer type for the Binary Portable DLL initialisation entry point.
+{secret}
+****************************************************************************/
+typedef BE_exports *(PMAPIP BE_initLibrary_t) (PM_imports * PMImp);
+#endif
+
+#pragma pack()
+
+/*---------------------------- Global variables ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+/* {secret} Global BIOS emulator system environment */
+ extern BE_sysEnv _BE_env;
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+/* BIOS emulator library entry points */
+ int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info,
+ int shared);
+ void X86API BE_setVGA(BE_VGAInfo * info);
+ void X86API BE_getVGA(BE_VGAInfo * info);
+ void X86API BE_setDebugFlags(u32 debugFlags);
+ void *X86API BE_mapRealPointer(uint r_seg, uint r_off);
+ void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff);
+ void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs,
+ RMSREGS * sregs);
+ int X86API BE_int86(int intno, RMREGS * in, RMREGS * out);
+ int X86API BE_int86x(int intno, RMREGS * in, RMREGS * out,
+ RMSREGS * sregs);
+ void X86API BE_exit(void);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+#endif /* __BIOSEMU_H */
diff --git a/drivers/bios_emulator/include/x86emu.h b/drivers/bios_emulator/include/x86emu.h
new file mode 100644
index 0000000000..6004beb05d
--- /dev/null
+++ b/drivers/bios_emulator/include/x86emu.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for public specific functions.
+* Any application linking against us should only
+* include this header
+*
+****************************************************************************/
+
+#ifndef __X86EMU_X86EMU_H
+#define __X86EMU_X86EMU_H
+
+#include <asm/types.h>
+#include <common.h>
+#include <pci.h>
+#include <asm/io.h>
+#define X86API
+#define X86APIP *
+typedef u16 X86EMU_pioAddr;
+
+#include "x86emu/regs.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#pragma pack(1)
+
+/****************************************************************************
+REMARKS:
+Data structure containing ponters to programmed I/O functions used by the
+emulator. This is used so that the user program can hook all programmed
+I/O for the emulator to handled as necessary by the user program. By
+default the emulator contains simple functions that do not do access the
+hardware in any way. To allow the emualtor access the hardware, you will
+need to override the programmed I/O functions using the X86EMU_setupPioFuncs
+function.
+
+HEADER:
+x86emu.h
+
+MEMBERS:
+inb - Function to read a byte from an I/O port
+inw - Function to read a word from an I/O port
+inl - Function to read a dword from an I/O port
+outb - Function to write a byte to an I/O port
+outw - Function to write a word to an I/O port
+outl - Function to write a dword to an I/O port
+****************************************************************************/
+typedef struct {
+ u8(X86APIP inb) (X86EMU_pioAddr addr);
+ u16(X86APIP inw) (X86EMU_pioAddr addr);
+ u32(X86APIP inl) (X86EMU_pioAddr addr);
+ void (X86APIP outb) (X86EMU_pioAddr addr, u8 val);
+ void (X86APIP outw) (X86EMU_pioAddr addr, u16 val);
+ void (X86APIP outl) (X86EMU_pioAddr addr, u32 val);
+} X86EMU_pioFuncs;
+
+/****************************************************************************
+REMARKS:
+Data structure containing ponters to memory access functions used by the
+emulator. This is used so that the user program can hook all memory
+access functions as necessary for the emulator. By default the emulator
+contains simple functions that only access the internal memory of the
+emulator. If you need specialised functions to handle access to different
+types of memory (ie: hardware framebuffer accesses and BIOS memory access
+etc), you will need to override this using the X86EMU_setupMemFuncs
+function.
+
+HEADER:
+x86emu.h
+
+MEMBERS:
+rdb - Function to read a byte from an address
+rdw - Function to read a word from an address
+rdl - Function to read a dword from an address
+wrb - Function to write a byte to an address
+wrw - Function to write a word to an address
+wrl - Function to write a dword to an address
+****************************************************************************/
+typedef struct {
+ u8(X86APIP rdb) (u32 addr);
+ u16(X86APIP rdw) (u32 addr);
+ u32(X86APIP rdl) (u32 addr);
+ void (X86APIP wrb) (u32 addr, u8 val);
+ void (X86APIP wrw) (u32 addr, u16 val);
+ void (X86APIP wrl) (u32 addr, u32 val);
+} X86EMU_memFuncs;
+
+/****************************************************************************
+ Here are the default memory read and write
+ function in case they are needed as fallbacks.
+***************************************************************************/
+extern u8 X86API rdb(u32 addr);
+extern u16 X86API rdw(u32 addr);
+extern u32 X86API rdl(u32 addr);
+extern void X86API wrb(u32 addr, u8 val);
+extern void X86API wrw(u32 addr, u16 val);
+extern void X86API wrl(u32 addr, u32 val);
+
+#pragma pack()
+
+/*--------------------- type definitions -----------------------------------*/
+
+typedef void (X86APIP X86EMU_intrFuncs) (int num);
+extern X86EMU_intrFuncs _X86EMU_intrTab[256];
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+ void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs);
+ void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs);
+ void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]);
+ void X86EMU_prepareForInt(int num);
+
+/* decode.c */
+
+ void X86EMU_exec(void);
+ void X86EMU_halt_sys(void);
+
+#ifdef DEBUG
+#define HALT_SYS() \
+ printf("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \
+ X86EMU_halt_sys()
+#else
+#define HALT_SYS() X86EMU_halt_sys()
+#endif
+
+/* Debug options */
+
+#define DEBUG_DECODE_F 0x0001 /* print decoded instruction */
+#define DEBUG_TRACE_F 0x0002 /* dump regs before/after execution */
+#define DEBUG_STEP_F 0x0004
+#define DEBUG_DISASSEMBLE_F 0x0008
+#define DEBUG_BREAK_F 0x0010
+#define DEBUG_SVC_F 0x0020
+#define DEBUG_SAVE_CS_IP 0x0040
+#define DEBUG_FS_F 0x0080
+#define DEBUG_PROC_F 0x0100
+#define DEBUG_SYSINT_F 0x0200 /* bios system interrupts. */
+#define DEBUG_TRACECALL_F 0x0400
+#define DEBUG_INSTRUMENT_F 0x0800
+#define DEBUG_MEM_TRACE_F 0x1000
+#define DEBUG_IO_TRACE_F 0x2000
+#define DEBUG_TRACECALL_REGS_F 0x4000
+#define DEBUG_DECODE_NOPRINT_F 0x8000
+#define DEBUG_EXIT 0x10000
+#define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F)
+
+ void X86EMU_trace_regs(void);
+ void X86EMU_trace_xregs(void);
+ void X86EMU_dump_memory(u16 seg, u16 off, u32 amt);
+ int X86EMU_trace_on(void);
+ int X86EMU_trace_off(void);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+#endif /* __X86EMU_X86EMU_H */
diff --git a/drivers/bios_emulator/include/x86emu/debug.h b/drivers/bios_emulator/include/x86emu/debug.h
new file mode 100644
index 0000000000..268c9d391e
--- /dev/null
+++ b/drivers/bios_emulator/include/x86emu/debug.h
@@ -0,0 +1,209 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for debug definitions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_DEBUG_H
+#define __X86EMU_DEBUG_H
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+/* checks to be enabled for "runtime" */
+
+#define CHECK_IP_FETCH_F 0x1
+#define CHECK_SP_ACCESS_F 0x2
+#define CHECK_MEM_ACCESS_F 0x4 /*using regular linear pointer */
+#define CHECK_DATA_ACCESS_F 0x8 /*using segment:offset */
+
+#ifdef DEBUG
+# define CHECK_IP_FETCH() (M.x86.check & CHECK_IP_FETCH_F)
+# define CHECK_SP_ACCESS() (M.x86.check & CHECK_SP_ACCESS_F)
+# define CHECK_MEM_ACCESS() (M.x86.check & CHECK_MEM_ACCESS_F)
+# define CHECK_DATA_ACCESS() (M.x86.check & CHECK_DATA_ACCESS_F)
+#else
+# define CHECK_IP_FETCH()
+# define CHECK_SP_ACCESS()
+# define CHECK_MEM_ACCESS()
+# define CHECK_DATA_ACCESS()
+#endif
+
+#ifdef DEBUG
+# define DEBUG_INSTRUMENT() (M.x86.debug & DEBUG_INSTRUMENT_F)
+# define DEBUG_DECODE() (M.x86.debug & DEBUG_DECODE_F)
+# define DEBUG_TRACE() (M.x86.debug & DEBUG_TRACE_F)
+# define DEBUG_STEP() (M.x86.debug & DEBUG_STEP_F)
+# define DEBUG_DISASSEMBLE() (M.x86.debug & DEBUG_DISASSEMBLE_F)
+# define DEBUG_BREAK() (M.x86.debug & DEBUG_BREAK_F)
+# define DEBUG_SVC() (M.x86.debug & DEBUG_SVC_F)
+# define DEBUG_SAVE_IP_CS() (M.x86.debug & DEBUG_SAVE_CS_IP)
+
+# define DEBUG_FS() (M.x86.debug & DEBUG_FS_F)
+# define DEBUG_PROC() (M.x86.debug & DEBUG_PROC_F)
+# define DEBUG_SYSINT() (M.x86.debug & DEBUG_SYSINT_F)
+# define DEBUG_TRACECALL() (M.x86.debug & DEBUG_TRACECALL_F)
+# define DEBUG_TRACECALLREGS() (M.x86.debug & DEBUG_TRACECALL_REGS_F)
+# define DEBUG_SYS() (M.x86.debug & DEBUG_SYS_F)
+# define DEBUG_MEM_TRACE() (M.x86.debug & DEBUG_MEM_TRACE_F)
+# define DEBUG_IO_TRACE() (M.x86.debug & DEBUG_IO_TRACE_F)
+# define DEBUG_DECODE_NOPRINT() (M.x86.debug & DEBUG_DECODE_NOPRINT_F)
+#else
+# define DEBUG_INSTRUMENT() 0
+# define DEBUG_DECODE() 0
+# define DEBUG_TRACE() 0
+# define DEBUG_STEP() 0
+# define DEBUG_DISASSEMBLE() 0
+# define DEBUG_BREAK() 0
+# define DEBUG_SVC() 0
+# define DEBUG_SAVE_IP_CS() 0
+# define DEBUG_FS() 0
+# define DEBUG_PROC() 0
+# define DEBUG_SYSINT() 0
+# define DEBUG_TRACECALL() 0
+# define DEBUG_TRACECALLREGS() 0
+# define DEBUG_SYS() 0
+# define DEBUG_MEM_TRACE() 0
+# define DEBUG_IO_TRACE() 0
+# define DEBUG_DECODE_NOPRINT() 0
+#endif
+
+#ifdef DEBUG
+
+# define DECODE_PRINTF(x) if (DEBUG_DECODE()) \
+ x86emu_decode_printf(x)
+# define DECODE_PRINTF2(x,y) if (DEBUG_DECODE()) \
+ x86emu_decode_printf2(x,y)
+
+/*
+ * The following allow us to look at the bytes of an instruction. The
+ * first INCR_INSTRN_LEN, is called everytime bytes are consumed in
+ * the decoding process. The SAVE_IP_CS is called initially when the
+ * major opcode of the instruction is accessed.
+ */
+#define INC_DECODED_INST_LEN(x) \
+ if (DEBUG_DECODE()) \
+ x86emu_inc_decoded_inst_len(x)
+
+#define SAVE_IP_CS(x,y) \
+ if (DEBUG_DECODE() | DEBUG_TRACECALL() | DEBUG_BREAK() \
+ | DEBUG_IO_TRACE() | DEBUG_SAVE_IP_CS()) { \
+ M.x86.saved_cs = x; \
+ M.x86.saved_ip = y; \
+ }
+#else
+# define INC_DECODED_INST_LEN(x)
+# define DECODE_PRINTF(x)
+# define DECODE_PRINTF2(x,y)
+# define SAVE_IP_CS(x,y)
+#endif
+
+#ifdef DEBUG
+#define TRACE_REGS() \
+ if (DEBUG_DISASSEMBLE()) { \
+ x86emu_just_disassemble(); \
+ goto EndOfTheInstructionProcedure; \
+ } \
+ if (DEBUG_TRACE() || DEBUG_DECODE()) X86EMU_trace_regs()
+#else
+# define TRACE_REGS()
+#endif
+
+#ifdef DEBUG
+# define SINGLE_STEP() if (DEBUG_STEP()) x86emu_single_step()
+#else
+# define SINGLE_STEP()
+#endif
+
+#define TRACE_AND_STEP() \
+ TRACE_REGS(); \
+ SINGLE_STEP()
+
+#ifdef DEBUG
+# define START_OF_INSTR()
+# define END_OF_INSTR() EndOfTheInstructionProcedure: x86emu_end_instr();
+# define END_OF_INSTR_NO_TRACE() x86emu_end_instr();
+#else
+# define START_OF_INSTR()
+# define END_OF_INSTR()
+# define END_OF_INSTR_NO_TRACE()
+#endif
+
+#ifdef DEBUG
+# define CALL_TRACE(u,v,w,x,s) \
+ if (DEBUG_TRACECALLREGS()) \
+ x86emu_dump_regs(); \
+ if (DEBUG_TRACECALL()) \
+ printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x);
+# define RETURN_TRACE(n,u,v) \
+ if (DEBUG_TRACECALLREGS()) \
+ x86emu_dump_regs(); \
+ if (DEBUG_TRACECALL()) \
+ printk("%04x:%04x: %s\n",u,v,n);
+#else
+# define CALL_TRACE(u,v,w,x,s)
+# define RETURN_TRACE(n,u,v)
+#endif
+
+#ifdef DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+ extern void x86emu_inc_decoded_inst_len(int x);
+ extern void x86emu_decode_printf(char *x);
+ extern void x86emu_decode_printf2(char *x, int y);
+ extern void x86emu_just_disassemble(void);
+ extern void x86emu_single_step(void);
+ extern void x86emu_end_instr(void);
+ extern void x86emu_dump_regs(void);
+ extern void x86emu_dump_xregs(void);
+ extern void x86emu_print_int_vect(u16 iv);
+ extern void x86emu_instrument_instruction(void);
+ extern void x86emu_check_ip_access(void);
+ extern void x86emu_check_sp_access(void);
+ extern void x86emu_check_mem_access(u32 p);
+ extern void x86emu_check_data_access(uint s, uint o);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+#endif /* __X86EMU_DEBUG_H */
diff --git a/drivers/bios_emulator/include/x86emu/decode.h b/drivers/bios_emulator/include/x86emu/decode.h
new file mode 100644
index 0000000000..77769f0094
--- /dev/null
+++ b/drivers/bios_emulator/include/x86emu/decode.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for instruction decoding logic.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_DECODE_H
+#define __X86EMU_DECODE_H
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+/* Instruction Decoding Stuff */
+
+#define FETCH_DECODE_MODRM(mod,rh,rl) fetch_decode_modrm(&mod,&rh,&rl)
+#define DECODE_RM_BYTE_REGISTER(r) decode_rm_byte_register(r)
+#define DECODE_RM_WORD_REGISTER(r) decode_rm_word_register(r)
+#define DECODE_RM_LONG_REGISTER(r) decode_rm_long_register(r)
+#define DECODE_CLEAR_SEGOVR() M.x86.mode &= ~SYSMODE_CLRMASK
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+void x86emu_intr_raise (u8 type);
+void fetch_decode_modrm (int *mod,int *regh,int *regl);
+u8 fetch_byte_imm (void);
+u16 fetch_word_imm (void);
+u32 fetch_long_imm (void);
+u8 fetch_data_byte (uint offset);
+u8 fetch_data_byte_abs (uint segment, uint offset);
+u16 fetch_data_word (uint offset);
+u16 fetch_data_word_abs (uint segment, uint offset);
+u32 fetch_data_long (uint offset);
+u32 fetch_data_long_abs (uint segment, uint offset);
+void store_data_byte (uint offset, u8 val);
+void store_data_byte_abs (uint segment, uint offset, u8 val);
+void store_data_word (uint offset, u16 val);
+void store_data_word_abs (uint segment, uint offset, u16 val);
+void store_data_long (uint offset, u32 val);
+void store_data_long_abs (uint segment, uint offset, u32 val);
+u8* decode_rm_byte_register(int reg);
+u16* decode_rm_word_register(int reg);
+u32* decode_rm_long_register(int reg);
+u16* decode_rm_seg_register(int reg);
+unsigned decode_rm00_address(int rm);
+unsigned decode_rm01_address(int rm);
+unsigned decode_rm10_address(int rm);
+unsigned decode_rmXX_address(int mod, int rm);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+#endif /* __X86EMU_DECODE_H */
diff --git a/drivers/bios_emulator/include/x86emu/ops.h b/drivers/bios_emulator/include/x86emu/ops.h
new file mode 100644
index 0000000000..a4f2316ba0
--- /dev/null
+++ b/drivers/bios_emulator/include/x86emu/ops.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for operand decoding functions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_OPS_H
+#define __X86EMU_OPS_H
+
+extern void (*x86emu_optab[0x100])(u8 op1);
+extern void (*x86emu_optab2[0x100])(u8 op2);
+
+#endif /* __X86EMU_OPS_H */
diff --git a/drivers/bios_emulator/include/x86emu/prim_asm.h b/drivers/bios_emulator/include/x86emu/prim_asm.h
new file mode 100644
index 0000000000..4cb4cab5d5
--- /dev/null
+++ b/drivers/bios_emulator/include/x86emu/prim_asm.h
@@ -0,0 +1,970 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: Watcom C++ 10.6 or later
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Inline assembler versions of the primitive operand
+* functions for faster performance. At the moment this is
+* x86 inline assembler, but these functions could be replaced
+* with native inline assembler for each supported processor
+* platform.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_PRIM_ASM_H
+#define __X86EMU_PRIM_ASM_H
+
+#ifdef __WATCOMC__
+
+#ifndef VALIDATE
+#define __HAVE_INLINE_ASSEMBLER__
+#endif
+
+u32 get_flags_asm(void);
+#pragma aux get_flags_asm = \
+ "pushf" \
+ "pop eax" \
+ value [eax] \
+ modify exact [eax];
+
+u16 aaa_word_asm(u32 * flags, u16 d);
+#pragma aux aaa_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "aaa" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u16 aas_word_asm(u32 * flags, u16 d);
+#pragma aux aas_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "aas" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u16 aad_word_asm(u32 * flags, u16 d);
+#pragma aux aad_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "aad" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u16 aam_word_asm(u32 * flags, u8 d);
+#pragma aux aam_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "aam" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [ax] \
+ modify exact [ax];
+
+u8 adc_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux adc_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "adc al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 adc_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux adc_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "adc ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 adc_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux adc_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "adc eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 add_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux add_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "add al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 add_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux add_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "add ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 add_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux add_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "add eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 and_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux and_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "and al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 and_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux and_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "and ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 and_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux and_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "and eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 cmp_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux cmp_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "cmp al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 cmp_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux cmp_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "cmp ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 cmp_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux cmp_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "cmp eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 daa_byte_asm(u32 * flags, u8 d);
+#pragma aux daa_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "daa" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u8 das_byte_asm(u32 * flags, u8 d);
+#pragma aux das_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "das" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u8 dec_byte_asm(u32 * flags, u8 d);
+#pragma aux dec_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "dec al" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u16 dec_word_asm(u32 * flags, u16 d);
+#pragma aux dec_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "dec ax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u32 dec_long_asm(u32 * flags, u32 d);
+#pragma aux dec_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "dec eax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] \
+ value [eax] \
+ modify exact [eax];
+
+u8 inc_byte_asm(u32 * flags, u8 d);
+#pragma aux inc_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "inc al" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u16 inc_word_asm(u32 * flags, u16 d);
+#pragma aux inc_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "inc ax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u32 inc_long_asm(u32 * flags, u32 d);
+#pragma aux inc_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "inc eax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] \
+ value [eax] \
+ modify exact [eax];
+
+u8 or_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux or_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "or al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 or_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux or_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "or ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 or_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux or_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "or eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 neg_byte_asm(u32 * flags, u8 d);
+#pragma aux neg_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "neg al" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u16 neg_word_asm(u32 * flags, u16 d);
+#pragma aux neg_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "neg ax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u32 neg_long_asm(u32 * flags, u32 d);
+#pragma aux neg_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "neg eax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] \
+ value [eax] \
+ modify exact [eax];
+
+u8 not_byte_asm(u32 * flags, u8 d);
+#pragma aux not_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "not al" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u16 not_word_asm(u32 * flags, u16 d);
+#pragma aux not_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "not ax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u32 not_long_asm(u32 * flags, u32 d);
+#pragma aux not_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "not eax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] \
+ value [eax] \
+ modify exact [eax];
+
+u8 rcl_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux rcl_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcl al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 rcl_word_asm(u32 * flags, u16 d, u8 s);
+#pragma aux rcl_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcl ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 rcl_long_asm(u32 * flags, u32 d, u8 s);
+#pragma aux rcl_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcl eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 rcr_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux rcr_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcr al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 rcr_word_asm(u32 * flags, u16 d, u8 s);
+#pragma aux rcr_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcr ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 rcr_long_asm(u32 * flags, u32 d, u8 s);
+#pragma aux rcr_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcr eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 rol_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux rol_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "rol al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 rol_word_asm(u32 * flags, u16 d, u8 s);
+#pragma aux rol_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "rol ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 rol_long_asm(u32 * flags, u32 d, u8 s);
+#pragma aux rol_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "rol eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 ror_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux ror_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "ror al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 ror_word_asm(u32 * flags, u16 d, u8 s);
+#pragma aux ror_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "ror ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 ror_long_asm(u32 * flags, u32 d, u8 s);
+#pragma aux ror_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "ror eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 shl_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux shl_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "shl al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 shl_word_asm(u32 * flags, u16 d, u8 s);
+#pragma aux shl_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "shl ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 shl_long_asm(u32 * flags, u32 d, u8 s);
+#pragma aux shl_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "shl eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 shr_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux shr_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "shr al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 shr_word_asm(u32 * flags, u16 d, u8 s);
+#pragma aux shr_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "shr ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 shr_long_asm(u32 * flags, u32 d, u8 s);
+#pragma aux shr_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "shr eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 sar_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux sar_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "sar al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 sar_word_asm(u32 * flags, u16 d, u8 s);
+#pragma aux sar_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "sar ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 sar_long_asm(u32 * flags, u32 d, u8 s);
+#pragma aux sar_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "sar eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u16 shld_word_asm(u32 * flags, u16 d, u16 fill, u8 s);
+#pragma aux shld_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "shld ax,dx,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [dx] [cl] \
+ value [ax] \
+ modify exact [ax dx cl];
+
+u32 shld_long_asm(u32 * flags, u32 d, u32 fill, u8 s);
+#pragma aux shld_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "shld eax,edx,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [edx] [cl] \
+ value [eax] \
+ modify exact [eax edx cl];
+
+u16 shrd_word_asm(u32 * flags, u16 d, u16 fill, u8 s);
+#pragma aux shrd_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "shrd ax,dx,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [dx] [cl] \
+ value [ax] \
+ modify exact [ax dx cl];
+
+u32 shrd_long_asm(u32 * flags, u32 d, u32 fill, u8 s);
+#pragma aux shrd_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "shrd eax,edx,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [edx] [cl] \
+ value [eax] \
+ modify exact [eax edx cl];
+
+u8 sbb_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux sbb_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "sbb al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 sbb_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux sbb_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "sbb ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 sbb_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux sbb_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "sbb eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 sub_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux sub_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "sub al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 sub_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux sub_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "sub ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 sub_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux sub_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "sub eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+void test_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux test_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "test al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ modify exact [al bl];
+
+void test_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux test_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "test ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ modify exact [ax bx];
+
+void test_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux test_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "test eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ modify exact [eax ebx];
+
+u8 xor_byte_asm(u32 * flags, u8 d, u8 s);
+#pragma aux xor_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "xor al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 xor_word_asm(u32 * flags, u16 d, u16 s);
+#pragma aux xor_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "xor ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 xor_long_asm(u32 * flags, u32 d, u32 s);
+#pragma aux xor_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "xor eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+void imul_byte_asm(u32 * flags, u16 * ax, u8 d, u8 s);
+#pragma aux imul_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "imul bl" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ parm [edi] [esi] [al] [bl] \
+ modify exact [esi ax bl];
+
+void imul_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 d, u16 s);
+#pragma aux imul_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "imul bx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ "mov [ecx],dx" \
+ parm [edi] [esi] [ecx] [ax] [bx]\
+ modify exact [esi edi ax bx dx];
+
+void imul_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 d, u32 s);
+#pragma aux imul_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "imul ebx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],eax" \
+ "mov [ecx],edx" \
+ parm [edi] [esi] [ecx] [eax] [ebx] \
+ modify exact [esi edi eax ebx edx];
+
+void mul_byte_asm(u32 * flags, u16 * ax, u8 d, u8 s);
+#pragma aux mul_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "mul bl" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ parm [edi] [esi] [al] [bl] \
+ modify exact [esi ax bl];
+
+void mul_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 d, u16 s);
+#pragma aux mul_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "mul bx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ "mov [ecx],dx" \
+ parm [edi] [esi] [ecx] [ax] [bx]\
+ modify exact [esi edi ax bx dx];
+
+void mul_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 d, u32 s);
+#pragma aux mul_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "mul ebx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],eax" \
+ "mov [ecx],edx" \
+ parm [edi] [esi] [ecx] [eax] [ebx] \
+ modify exact [esi edi eax ebx edx];
+
+void idiv_byte_asm(u32 * flags, u8 * al, u8 * ah, u16 d, u8 s);
+#pragma aux idiv_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "idiv bl" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],al" \
+ "mov [ecx],ah" \
+ parm [edi] [esi] [ecx] [ax] [bl]\
+ modify exact [esi edi ax bl];
+
+void idiv_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 dlo, u16 dhi, u16 s);
+#pragma aux idiv_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "idiv bx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ "mov [ecx],dx" \
+ parm [edi] [esi] [ecx] [ax] [dx] [bx]\
+ modify exact [esi edi ax dx bx];
+
+void idiv_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 dlo, u32 dhi, u32 s);
+#pragma aux idiv_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "idiv ebx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],eax" \
+ "mov [ecx],edx" \
+ parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
+ modify exact [esi edi eax edx ebx];
+
+void div_byte_asm(u32 * flags, u8 * al, u8 * ah, u16 d, u8 s);
+#pragma aux div_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "div bl" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],al" \
+ "mov [ecx],ah" \
+ parm [edi] [esi] [ecx] [ax] [bl]\
+ modify exact [esi edi ax bl];
+
+void div_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 dlo, u16 dhi, u16 s);
+#pragma aux div_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "div bx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ "mov [ecx],dx" \
+ parm [edi] [esi] [ecx] [ax] [dx] [bx]\
+ modify exact [esi edi ax dx bx];
+
+void div_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 dlo, u32 dhi, u32 s);
+#pragma aux div_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "div ebx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],eax" \
+ "mov [ecx],edx" \
+ parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
+ modify exact [esi edi eax edx ebx];
+
+#endif
+
+#endif /* __X86EMU_PRIM_ASM_H */
diff --git a/drivers/bios_emulator/include/x86emu/prim_ops.h b/drivers/bios_emulator/include/x86emu/prim_ops.h
new file mode 100644
index 0000000000..2291e8488a
--- /dev/null
+++ b/drivers/bios_emulator/include/x86emu/prim_ops.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for primitive operation functions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_PRIM_OPS_H
+#define __X86EMU_PRIM_OPS_H
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+u16 aaa_word (u16 d);
+u16 aas_word (u16 d);
+u16 aad_word (u16 d);
+u16 aam_word (u8 d);
+u8 adc_byte (u8 d, u8 s);
+u16 adc_word (u16 d, u16 s);
+u32 adc_long (u32 d, u32 s);
+u8 add_byte (u8 d, u8 s);
+u16 add_word (u16 d, u16 s);
+u32 add_long (u32 d, u32 s);
+u8 and_byte (u8 d, u8 s);
+u16 and_word (u16 d, u16 s);
+u32 and_long (u32 d, u32 s);
+u8 cmp_byte (u8 d, u8 s);
+u16 cmp_word (u16 d, u16 s);
+u32 cmp_long (u32 d, u32 s);
+u8 daa_byte (u8 d);
+u8 das_byte (u8 d);
+u8 dec_byte (u8 d);
+u16 dec_word (u16 d);
+u32 dec_long (u32 d);
+u8 inc_byte (u8 d);
+u16 inc_word (u16 d);
+u32 inc_long (u32 d);
+u8 or_byte (u8 d, u8 s);
+u16 or_word (u16 d, u16 s);
+u32 or_long (u32 d, u32 s);
+u8 neg_byte (u8 s);
+u16 neg_word (u16 s);
+u32 neg_long (u32 s);
+u8 not_byte (u8 s);
+u16 not_word (u16 s);
+u32 not_long (u32 s);
+u8 rcl_byte (u8 d, u8 s);
+u16 rcl_word (u16 d, u8 s);
+u32 rcl_long (u32 d, u8 s);
+u8 rcr_byte (u8 d, u8 s);
+u16 rcr_word (u16 d, u8 s);
+u32 rcr_long (u32 d, u8 s);
+u8 rol_byte (u8 d, u8 s);
+u16 rol_word (u16 d, u8 s);
+u32 rol_long (u32 d, u8 s);
+u8 ror_byte (u8 d, u8 s);
+u16 ror_word (u16 d, u8 s);
+u32 ror_long (u32 d, u8 s);
+u8 shl_byte (u8 d, u8 s);
+u16 shl_word (u16 d, u8 s);
+u32 shl_long (u32 d, u8 s);
+u8 shr_byte (u8 d, u8 s);
+u16 shr_word (u16 d, u8 s);
+u32 shr_long (u32 d, u8 s);
+u8 sar_byte (u8 d, u8 s);
+u16 sar_word (u16 d, u8 s);
+u32 sar_long (u32 d, u8 s);
+u16 shld_word (u16 d, u16 fill, u8 s);
+u32 shld_long (u32 d, u32 fill, u8 s);
+u16 shrd_word (u16 d, u16 fill, u8 s);
+u32 shrd_long (u32 d, u32 fill, u8 s);
+u8 sbb_byte (u8 d, u8 s);
+u16 sbb_word (u16 d, u16 s);
+u32 sbb_long (u32 d, u32 s);
+u8 sub_byte (u8 d, u8 s);
+u16 sub_word (u16 d, u16 s);
+u32 sub_long (u32 d, u32 s);
+void test_byte (u8 d, u8 s);
+void test_word (u16 d, u16 s);
+void test_long (u32 d, u32 s);
+u8 xor_byte (u8 d, u8 s);
+u16 xor_word (u16 d, u16 s);
+u32 xor_long (u32 d, u32 s);
+void imul_byte (u8 s);
+void imul_word (u16 s);
+void imul_long (u32 s);
+void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s);
+void mul_byte (u8 s);
+void mul_word (u16 s);
+void mul_long (u32 s);
+void idiv_byte (u8 s);
+void idiv_word (u16 s);
+void idiv_long (u32 s);
+void div_byte (u8 s);
+void div_word (u16 s);
+void div_long (u32 s);
+void ins (int size);
+void outs (int size);
+u16 mem_access_word (int addr);
+void push_word (u16 w);
+void push_long (u32 w);
+u16 pop_word (void);
+u32 pop_long (void);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+#endif /* __X86EMU_PRIM_OPS_H */
diff --git a/drivers/bios_emulator/include/x86emu/regs.h b/drivers/bios_emulator/include/x86emu/regs.h
new file mode 100644
index 0000000000..a7fedd2f6c
--- /dev/null
+++ b/drivers/bios_emulator/include/x86emu/regs.h
@@ -0,0 +1,340 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for x86 register definitions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_REGS_H
+#define __X86EMU_REGS_H
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#pragma pack(1)
+
+/*
+ * General EAX, EBX, ECX, EDX type registers. Note that for
+ * portability, and speed, the issue of byte swapping is not addressed
+ * in the registers. All registers are stored in the default format
+ * available on the host machine. The only critical issue is that the
+ * registers should line up EXACTLY in the same manner as they do in
+ * the 386. That is:
+ *
+ * EAX & 0xff === AL
+ * EAX & 0xffff == AX
+ *
+ * etc. The result is that alot of the calculations can then be
+ * done using the native instruction set fully.
+ */
+
+#ifdef __BIG_ENDIAN__
+
+typedef struct {
+ u32 e_reg;
+} I32_reg_t;
+
+typedef struct {
+ u16 filler0, x_reg;
+} I16_reg_t;
+
+typedef struct {
+ u8 filler0, filler1, h_reg, l_reg;
+} I8_reg_t;
+
+#else /* !__BIG_ENDIAN__ */
+
+typedef struct {
+ u32 e_reg;
+} I32_reg_t;
+
+typedef struct {
+ u16 x_reg;
+} I16_reg_t;
+
+typedef struct {
+ u8 l_reg, h_reg;
+} I8_reg_t;
+
+#endif /* BIG_ENDIAN */
+
+typedef union {
+ I32_reg_t I32_reg;
+ I16_reg_t I16_reg;
+ I8_reg_t I8_reg;
+} i386_general_register;
+
+struct i386_general_regs {
+ i386_general_register A, B, C, D;
+};
+
+typedef struct i386_general_regs Gen_reg_t;
+
+struct i386_special_regs {
+ i386_general_register SP, BP, SI, DI, IP;
+ u32 FLAGS;
+};
+
+/*
+ * Segment registers here represent the 16 bit quantities
+ * CS, DS, ES, SS.
+ */
+
+#undef CS
+#undef DS
+#undef SS
+#undef ES
+#undef FS
+#undef GS
+
+struct i386_segment_regs {
+ u16 CS, DS, SS, ES, FS, GS;
+};
+
+/* 8 bit registers */
+#define R_AH gen.A.I8_reg.h_reg
+#define R_AL gen.A.I8_reg.l_reg
+#define R_BH gen.B.I8_reg.h_reg
+#define R_BL gen.B.I8_reg.l_reg
+#define R_CH gen.C.I8_reg.h_reg
+#define R_CL gen.C.I8_reg.l_reg
+#define R_DH gen.D.I8_reg.h_reg
+#define R_DL gen.D.I8_reg.l_reg
+
+/* 16 bit registers */
+#define R_AX gen.A.I16_reg.x_reg
+#define R_BX gen.B.I16_reg.x_reg
+#define R_CX gen.C.I16_reg.x_reg
+#define R_DX gen.D.I16_reg.x_reg
+
+/* 32 bit extended registers */
+#define R_EAX gen.A.I32_reg.e_reg
+#define R_EBX gen.B.I32_reg.e_reg
+#define R_ECX gen.C.I32_reg.e_reg
+#define R_EDX gen.D.I32_reg.e_reg
+
+/* special registers */
+#define R_SP spc.SP.I16_reg.x_reg
+#define R_BP spc.BP.I16_reg.x_reg
+#define R_SI spc.SI.I16_reg.x_reg
+#define R_DI spc.DI.I16_reg.x_reg
+#define R_IP spc.IP.I16_reg.x_reg
+#define R_FLG spc.FLAGS
+
+/* special registers */
+#define R_SP spc.SP.I16_reg.x_reg
+#define R_BP spc.BP.I16_reg.x_reg
+#define R_SI spc.SI.I16_reg.x_reg
+#define R_DI spc.DI.I16_reg.x_reg
+#define R_IP spc.IP.I16_reg.x_reg
+#define R_FLG spc.FLAGS
+
+/* special registers */
+#define R_ESP spc.SP.I32_reg.e_reg
+#define R_EBP spc.BP.I32_reg.e_reg
+#define R_ESI spc.SI.I32_reg.e_reg
+#define R_EDI spc.DI.I32_reg.e_reg
+#define R_EIP spc.IP.I32_reg.e_reg
+#define R_EFLG spc.FLAGS
+
+/* segment registers */
+#define R_CS seg.CS
+#define R_DS seg.DS
+#define R_SS seg.SS
+#define R_ES seg.ES
+#define R_FS seg.FS
+#define R_GS seg.GS
+
+/* flag conditions */
+#define FB_CF 0x0001 /* CARRY flag */
+#define FB_PF 0x0004 /* PARITY flag */
+#define FB_AF 0x0010 /* AUX flag */
+#define FB_ZF 0x0040 /* ZERO flag */
+#define FB_SF 0x0080 /* SIGN flag */
+#define FB_TF 0x0100 /* TRAP flag */
+#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */
+#define FB_DF 0x0400 /* DIR flag */
+#define FB_OF 0x0800 /* OVERFLOW flag */
+
+/* 80286 and above always have bit#1 set */
+#define F_ALWAYS_ON (0x0002) /* flag bits always on */
+
+/*
+ * Define a mask for only those flag bits we will ever pass back
+ * (via PUSHF)
+ */
+#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF)
+
+/* following bits masked in to a 16bit quantity */
+
+#define F_CF 0x0001 /* CARRY flag */
+#define F_PF 0x0004 /* PARITY flag */
+#define F_AF 0x0010 /* AUX flag */
+#define F_ZF 0x0040 /* ZERO flag */
+#define F_SF 0x0080 /* SIGN flag */
+#define F_TF 0x0100 /* TRAP flag */
+#define F_IF 0x0200 /* INTERRUPT ENABLE flag */
+#define F_DF 0x0400 /* DIR flag */
+#define F_OF 0x0800 /* OVERFLOW flag */
+
+#define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag))
+#define SET_FLAG(flag) (M.x86.R_FLG |= (flag))
+#define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag))
+#define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag))
+#define CLEARALL_FLAG(m) (M.x86.R_FLG = 0)
+
+#define CONDITIONAL_SET_FLAG(COND,FLAG) \
+ if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG)
+
+#define F_PF_CALC 0x010000 /* PARITY flag has been calced */
+#define F_ZF_CALC 0x020000 /* ZERO flag has been calced */
+#define F_SF_CALC 0x040000 /* SIGN flag has been calced */
+
+#define F_ALL_CALC 0xff0000 /* All have been calced */
+
+/*
+ * Emulator machine state.
+ * Segment usage control.
+ */
+#define SYSMODE_SEG_DS_SS 0x00000001
+#define SYSMODE_SEGOVR_CS 0x00000002
+#define SYSMODE_SEGOVR_DS 0x00000004
+#define SYSMODE_SEGOVR_ES 0x00000008
+#define SYSMODE_SEGOVR_FS 0x00000010
+#define SYSMODE_SEGOVR_GS 0x00000020
+#define SYSMODE_SEGOVR_SS 0x00000040
+#define SYSMODE_PREFIX_REPE 0x00000080
+#define SYSMODE_PREFIX_REPNE 0x00000100
+#define SYSMODE_PREFIX_DATA 0x00000200
+#define SYSMODE_PREFIX_ADDR 0x00000400
+#define SYSMODE_INTR_PENDING 0x10000000
+#define SYSMODE_EXTRN_INTR 0x20000000
+#define SYSMODE_HALTED 0x40000000
+
+#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \
+ SYSMODE_SEGOVR_CS | \
+ SYSMODE_SEGOVR_DS | \
+ SYSMODE_SEGOVR_ES | \
+ SYSMODE_SEGOVR_FS | \
+ SYSMODE_SEGOVR_GS | \
+ SYSMODE_SEGOVR_SS)
+#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \
+ SYSMODE_SEGOVR_CS | \
+ SYSMODE_SEGOVR_DS | \
+ SYSMODE_SEGOVR_ES | \
+ SYSMODE_SEGOVR_FS | \
+ SYSMODE_SEGOVR_GS | \
+ SYSMODE_SEGOVR_SS | \
+ SYSMODE_PREFIX_DATA | \
+ SYSMODE_PREFIX_ADDR)
+
+#define INTR_SYNCH 0x1
+#define INTR_ASYNCH 0x2
+#define INTR_HALTED 0x4
+
+typedef struct {
+ struct i386_general_regs gen;
+ struct i386_special_regs spc;
+ struct i386_segment_regs seg;
+ /*
+ * MODE contains information on:
+ * REPE prefix 2 bits repe,repne
+ * SEGMENT overrides 5 bits normal,DS,SS,CS,ES
+ * Delayed flag set 3 bits (zero, signed, parity)
+ * reserved 6 bits
+ * interrupt # 8 bits instruction raised interrupt
+ * BIOS video segregs 4 bits
+ * Interrupt Pending 1 bits
+ * Extern interrupt 1 bits
+ * Halted 1 bits
+ */
+ long mode;
+ u8 intno;
+ volatile int intr; /* mask of pending interrupts */
+ int debug;
+#ifdef DEBUG
+ int check;
+ u16 saved_ip;
+ u16 saved_cs;
+ int enc_pos;
+ int enc_str_pos;
+ char decode_buf[32]; /* encoded byte stream */
+ char decoded_buf[256]; /* disassembled strings */
+#endif
+} X86EMU_regs;
+
+/****************************************************************************
+REMARKS:
+Structure maintaining the emulator machine state.
+
+MEMBERS:
+x86 - X86 registers
+mem_base - Base real mode memory for the emulator
+mem_size - Size of the real mode memory block for the emulator
+****************************************************************************/
+#undef x86
+typedef struct {
+ X86EMU_regs x86;
+ u8 *mem_base;
+ u32 mem_size;
+ void *private;
+} X86EMU_sysEnv;
+
+#pragma pack()
+
+/*----------------------------- Global Variables --------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+/* Global emulator machine state.
+ *
+ * We keep it global to avoid pointer dereferences in the code for speed.
+ */
+
+ extern X86EMU_sysEnv _X86EMU_env;
+#define M _X86EMU_env
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+/* Function to log information at runtime */
+
+#ifndef __KERNEL__
+ void printk(const char *fmt, ...);
+#endif
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+#endif /* __X86EMU_REGS_H */
diff --git a/drivers/bios_emulator/include/x86emu/x86emui.h b/drivers/bios_emulator/include/x86emu/x86emui.h
new file mode 100644
index 0000000000..a74957d992
--- /dev/null
+++ b/drivers/bios_emulator/include/x86emu/x86emui.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for system specific functions. These functions
+* are always compiled and linked in the OS depedent libraries,
+* and never in a binary portable driver.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_X86EMUI_H
+#define __X86EMU_X86EMUI_H
+
+/* If we are compiling in C++ mode, we can compile some functions as
+ * inline to increase performance (however the code size increases quite
+ * dramatically in this case).
+ */
+
+#if defined(__cplusplus) && !defined(_NO_INLINE)
+#define _INLINE inline
+#else
+#define _INLINE static
+#endif
+
+/* Get rid of unused parameters in C++ compilation mode */
+
+#ifdef __cplusplus
+#define X86EMU_UNUSED(v)
+#else
+#define X86EMU_UNUSED(v) v
+#endif
+
+#include "x86emu.h"
+#include "x86emu/regs.h"
+#include "x86emu/debug.h"
+#include "x86emu/decode.h"
+#include "x86emu/ops.h"
+#include "x86emu/prim_ops.h"
+#ifndef __KERNEL__
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define printk printf
+
+
+/*--------------------------- Inline Functions ----------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+ extern u8(X86APIP sys_rdb) (u32 addr);
+ extern u16(X86APIP sys_rdw) (u32 addr);
+ extern u32(X86APIP sys_rdl) (u32 addr);
+ extern void (X86APIP sys_wrb) (u32 addr, u8 val);
+ extern void (X86APIP sys_wrw) (u32 addr, u16 val);
+ extern void (X86APIP sys_wrl) (u32 addr, u32 val);
+
+ extern u8(X86APIP sys_inb) (X86EMU_pioAddr addr);
+ extern u16(X86APIP sys_inw) (X86EMU_pioAddr addr);
+ extern u32(X86APIP sys_inl) (X86EMU_pioAddr addr);
+ extern void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val);
+ extern void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val);
+ extern void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+#endif /* __X86EMU_X86EMUI_H */
diff --git a/drivers/bios_emulator/x86emu/debug.c b/drivers/bios_emulator/x86emu/debug.c
new file mode 100644
index 0000000000..5cbcc95018
--- /dev/null
+++ b/drivers/bios_emulator/x86emu/debug.c
@@ -0,0 +1,467 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file contains the code to handle debugging of the
+* emulator.
+*
+****************************************************************************/
+
+#include <stdarg.h>
+#include <common.h>
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "x86emu/x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+#ifdef DEBUG
+
+static void print_encoded_bytes(u16 s, u16 o);
+static void print_decoded_instruction(void);
+static int parse_line(char *s, int *ps, int *n);
+
+/* should look something like debug's output. */
+void X86EMU_trace_regs(void)
+{
+ if (DEBUG_TRACE()) {
+ x86emu_dump_regs();
+ }
+ if (DEBUG_DECODE() && !DEBUG_DECODE_NOPRINT()) {
+ printk("%04x:%04x ", M.x86.saved_cs, M.x86.saved_ip);
+ print_encoded_bytes(M.x86.saved_cs, M.x86.saved_ip);
+ print_decoded_instruction();
+ }
+}
+
+void X86EMU_trace_xregs(void)
+{
+ if (DEBUG_TRACE()) {
+ x86emu_dump_xregs();
+ }
+}
+
+void x86emu_just_disassemble(void)
+{
+ /*
+ * This routine called if the flag DEBUG_DISASSEMBLE is set kind
+ * of a hack!
+ */
+ printk("%04x:%04x ", M.x86.saved_cs, M.x86.saved_ip);
+ print_encoded_bytes(M.x86.saved_cs, M.x86.saved_ip);
+ print_decoded_instruction();
+}
+
+static void disassemble_forward(u16 seg, u16 off, int n)
+{
+ X86EMU_sysEnv tregs;
+ int i;
+ u8 op1;
+ /*
+ * hack, hack, hack. What we do is use the exact machinery set up
+ * for execution, except that now there is an additional state
+ * flag associated with the "execution", and we are using a copy
+ * of the register struct. All the major opcodes, once fully
+ * decoded, have the following two steps: TRACE_REGS(r,m);
+ * SINGLE_STEP(r,m); which disappear if DEBUG is not defined to
+ * the preprocessor. The TRACE_REGS macro expands to:
+ *
+ * if (debug&DEBUG_DISASSEMBLE)
+ * {just_disassemble(); goto EndOfInstruction;}
+ * if (debug&DEBUG_TRACE) trace_regs(r,m);
+ *
+ * ...... and at the last line of the routine.
+ *
+ * EndOfInstruction: end_instr();
+ *
+ * Up to the point where TRACE_REG is expanded, NO modifications
+ * are done to any register EXCEPT the IP register, for fetch and
+ * decoding purposes.
+ *
+ * This was done for an entirely different reason, but makes a
+ * nice way to get the system to help debug codes.
+ */
+ tregs = M;
+ tregs.x86.R_IP = off;
+ tregs.x86.R_CS = seg;
+
+ /* reset the decoding buffers */
+ tregs.x86.enc_str_pos = 0;
+ tregs.x86.enc_pos = 0;
+
+ /* turn on the "disassemble only, no execute" flag */
+ tregs.x86.debug |= DEBUG_DISASSEMBLE_F;
+
+ /* DUMP NEXT n instructions to screen in straight_line fashion */
+ /*
+ * This looks like the regular instruction fetch stream, except
+ * that when this occurs, each fetched opcode, upon seeing the
+ * DEBUG_DISASSEMBLE flag set, exits immediately after decoding
+ * the instruction. XXX --- CHECK THAT MEM IS NOT AFFECTED!!!
+ * Note the use of a copy of the register structure...
+ */
+ for (i = 0; i < n; i++) {
+ op1 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
+ (x86emu_optab[op1]) (op1);
+ }
+ /* end major hack mode. */
+}
+
+void x86emu_check_ip_access(void)
+{
+ /* NULL as of now */
+}
+
+void x86emu_check_sp_access(void)
+{
+}
+
+void x86emu_check_mem_access(u32 dummy)
+{
+ /* check bounds, etc */
+}
+
+void x86emu_check_data_access(uint dummy1, uint dummy2)
+{
+ /* check bounds, etc */
+}
+
+void x86emu_inc_decoded_inst_len(int x)
+{
+ M.x86.enc_pos += x;
+}
+
+void x86emu_decode_printf(char *x)
+{
+ sprintf(M.x86.decoded_buf + M.x86.enc_str_pos, "%s", x);
+ M.x86.enc_str_pos += strlen(x);
+}
+
+void x86emu_decode_printf2(char *x, int y)
+{
+ char temp[100];
+ sprintf(temp, x, y);
+ sprintf(M.x86.decoded_buf + M.x86.enc_str_pos, "%s", temp);
+ M.x86.enc_str_pos += strlen(temp);
+}
+
+void x86emu_end_instr(void)
+{
+ M.x86.enc_str_pos = 0;
+ M.x86.enc_pos = 0;
+}
+
+static void print_encoded_bytes(u16 s, u16 o)
+{
+ int i;
+ char buf1[64];
+ for (i = 0; i < M.x86.enc_pos; i++) {
+ sprintf(buf1 + 2 * i, "%02x", fetch_data_byte_abs(s, o + i));
+ }
+ printk("%-20s", buf1);
+}
+
+static void print_decoded_instruction(void)
+{
+ printk("%s", M.x86.decoded_buf);
+}
+
+void x86emu_print_int_vect(u16 iv)
+{
+ u16 seg, off;
+
+ if (iv > 256)
+ return;
+ seg = fetch_data_word_abs(0, iv * 4);
+ off = fetch_data_word_abs(0, iv * 4 + 2);
+ printk("%04x:%04x ", seg, off);
+}
+
+void X86EMU_dump_memory(u16 seg, u16 off, u32 amt)
+{
+ u32 start = off & 0xfffffff0;
+ u32 end = (off + 16) & 0xfffffff0;
+ u32 i;
+ u32 current;
+
+ current = start;
+ while (end <= off + amt) {
+ printk("%04x:%04x ", seg, start);
+ for (i = start; i < off; i++)
+ printk(" ");
+ for (; i < end; i++)
+ printk("%02x ", fetch_data_byte_abs(seg, i));
+ printk("\n");
+ start = end;
+ end = start + 16;
+ }
+}
+
+void x86emu_single_step(void)
+{
+ char s[1024];
+ int ps[10];
+ int ntok;
+ int cmd;
+ int done;
+ int segment;
+ int offset;
+ static int breakpoint;
+ static int noDecode = 1;
+
+ char *p;
+
+ if (DEBUG_BREAK()) {
+ if (M.x86.saved_ip != breakpoint) {
+ return;
+ } else {
+ M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
+ M.x86.debug |= DEBUG_TRACE_F;
+ M.x86.debug &= ~DEBUG_BREAK_F;
+ print_decoded_instruction();
+ X86EMU_trace_regs();
+ }
+ }
+ done = 0;
+ offset = M.x86.saved_ip;
+ while (!done) {
+ printk("-");
+ cmd = parse_line(s, ps, &ntok);
+ switch (cmd) {
+ case 'u':
+ disassemble_forward(M.x86.saved_cs, (u16) offset, 10);
+ break;
+ case 'd':
+ if (ntok == 2) {
+ segment = M.x86.saved_cs;
+ offset = ps[1];
+ X86EMU_dump_memory(segment, (u16) offset, 16);
+ offset += 16;
+ } else if (ntok == 3) {
+ segment = ps[1];
+ offset = ps[2];
+ X86EMU_dump_memory(segment, (u16) offset, 16);
+ offset += 16;
+ } else {
+ segment = M.x86.saved_cs;
+ X86EMU_dump_memory(segment, (u16) offset, 16);
+ offset += 16;
+ }
+ break;
+ case 'c':
+ M.x86.debug ^= DEBUG_TRACECALL_F;
+ break;
+ case 's':
+ M.x86.debug ^=
+ DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F;
+ break;
+ case 'r':
+ X86EMU_trace_regs();
+ break;
+ case 'x':
+ X86EMU_trace_xregs();
+ break;
+ case 'g':
+ if (ntok == 2) {
+ breakpoint = ps[1];
+ if (noDecode) {
+ M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
+ } else {
+ M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
+ }
+ M.x86.debug &= ~DEBUG_TRACE_F;
+ M.x86.debug |= DEBUG_BREAK_F;
+ done = 1;
+ }
+ break;
+ case 'q':
+ M.x86.debug |= DEBUG_EXIT;
+ return;
+ case 'P':
+ noDecode = (noDecode) ? 0 : 1;
+ printk("Toggled decoding to %s\n",
+ (noDecode) ? "FALSE" : "TRUE");
+ break;
+ case 't':
+ case 0:
+ done = 1;
+ break;
+ }
+ }
+}
+
+int X86EMU_trace_on(void)
+{
+ return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
+}
+
+int X86EMU_trace_off(void)
+{
+ return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F);
+}
+
+static int parse_line(char *s, int *ps, int *n)
+{
+ int cmd;
+
+ *n = 0;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ ps[*n] = *s;
+ switch (*s) {
+ case '\n':
+ *n += 1;
+ return 0;
+ default:
+ cmd = *s;
+ *n += 1;
+ }
+
+ while (1) {
+ while (*s != ' ' && *s != '\t' && *s != '\n')
+ s++;
+
+ if (*s == '\n')
+ return cmd;
+
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ *n += 1;
+ }
+}
+
+#endif /* DEBUG */
+
+void x86emu_dump_regs(void)
+{
+ printk("\tAX=%04x ", M.x86.R_AX);
+ printk("BX=%04x ", M.x86.R_BX);
+ printk("CX=%04x ", M.x86.R_CX);
+ printk("DX=%04x ", M.x86.R_DX);
+ printk("SP=%04x ", M.x86.R_SP);
+ printk("BP=%04x ", M.x86.R_BP);
+ printk("SI=%04x ", M.x86.R_SI);
+ printk("DI=%04x\n", M.x86.R_DI);
+ printk("\tDS=%04x ", M.x86.R_DS);
+ printk("ES=%04x ", M.x86.R_ES);
+ printk("SS=%04x ", M.x86.R_SS);
+ printk("CS=%04x ", M.x86.R_CS);
+ printk("IP=%04x ", M.x86.R_IP);
+ if (ACCESS_FLAG(F_OF))
+ printk("OV "); /* CHECKED... */
+ else
+ printk("NV ");
+ if (ACCESS_FLAG(F_DF))
+ printk("DN ");
+ else
+ printk("UP ");
+ if (ACCESS_FLAG(F_IF))
+ printk("EI ");
+ else
+ printk("DI ");
+ if (ACCESS_FLAG(F_SF))
+ printk("NG ");
+ else
+ printk("PL ");
+ if (ACCESS_FLAG(F_ZF))
+ printk("ZR ");
+ else
+ printk("NZ ");
+ if (ACCESS_FLAG(F_AF))
+ printk("AC ");
+ else
+ printk("NA ");
+ if (ACCESS_FLAG(F_PF))
+ printk("PE ");
+ else
+ printk("PO ");
+ if (ACCESS_FLAG(F_CF))
+ printk("CY ");
+ else
+ printk("NC ");
+ printk("\n");
+}
+
+void x86emu_dump_xregs(void)
+{
+ printk("\tEAX=%08x ", M.x86.R_EAX);
+ printk("EBX=%08x ", M.x86.R_EBX);
+ printk("ECX=%08x ", M.x86.R_ECX);
+ printk("EDX=%08x \n", M.x86.R_EDX);
+ printk("\tESP=%08x ", M.x86.R_ESP);
+ printk("EBP=%08x ", M.x86.R_EBP);
+ printk("ESI=%08x ", M.x86.R_ESI);
+ printk("EDI=%08x\n", M.x86.R_EDI);
+ printk("\tDS=%04x ", M.x86.R_DS);
+ printk("ES=%04x ", M.x86.R_ES);
+ printk("SS=%04x ", M.x86.R_SS);
+ printk("CS=%04x ", M.x86.R_CS);
+ printk("EIP=%08x\n\t", M.x86.R_EIP);
+ if (ACCESS_FLAG(F_OF))
+ printk("OV "); /* CHECKED... */
+ else
+ printk("NV ");
+ if (ACCESS_FLAG(F_DF))
+ printk("DN ");
+ else
+ printk("UP ");
+ if (ACCESS_FLAG(F_IF))
+ printk("EI ");
+ else
+ printk("DI ");
+ if (ACCESS_FLAG(F_SF))
+ printk("NG ");
+ else
+ printk("PL ");
+ if (ACCESS_FLAG(F_ZF))
+ printk("ZR ");
+ else
+ printk("NZ ");
+ if (ACCESS_FLAG(F_AF))
+ printk("AC ");
+ else
+ printk("NA ");
+ if (ACCESS_FLAG(F_PF))
+ printk("PE ");
+ else
+ printk("PO ");
+ if (ACCESS_FLAG(F_CF))
+ printk("CY ");
+ else
+ printk("NC ");
+ printk("\n");
+}
+
+#endif
diff --git a/drivers/bios_emulator/x86emu/decode.c b/drivers/bios_emulator/x86emu/decode.c
new file mode 100644
index 0000000000..7a9a1ddbff
--- /dev/null
+++ b/drivers/bios_emulator/x86emu/decode.c
@@ -0,0 +1,1149 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines which are related to
+* instruction decoding and accessess of immediate data via IP. etc.
+*
+****************************************************************************/
+#include <common.h>
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "x86emu/x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Handles any pending asychronous interrupts.
+****************************************************************************/
+static void x86emu_intr_handle(void)
+{
+ u8 intno;
+
+ if (M.x86.intr & INTR_SYNCH) {
+ intno = M.x86.intno;
+ if (_X86EMU_intrTab[intno]) {
+ (*_X86EMU_intrTab[intno])(intno);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(intno * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(intno * 4);
+ M.x86.intr = 0;
+ }
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+intrnum - Interrupt number to raise
+
+REMARKS:
+Raise the specified interrupt to be handled before the execution of the
+next instruction.
+****************************************************************************/
+void x86emu_intr_raise(
+ u8 intrnum)
+{
+ M.x86.intno = intrnum;
+ M.x86.intr |= INTR_SYNCH;
+}
+
+/****************************************************************************
+REMARKS:
+Main execution loop for the emulator. We return from here when the system
+halts, which is normally caused by a stack fault when we return from the
+original real mode call.
+****************************************************************************/
+void X86EMU_exec(void)
+{
+ u8 op1;
+
+ M.x86.intr = 0;
+ DB(x86emu_end_instr();)
+
+ for (;;) {
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ /* If debugging, save the IP and CS values. */
+ SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
+ INC_DECODED_INST_LEN(1);
+ if (M.x86.intr) {
+ if (M.x86.intr & INTR_HALTED) {
+DB( if (M.x86.R_SP != 0) {
+ printk("halted\n");
+ X86EMU_trace_regs();
+ }
+ else {
+ if (M.x86.debug)
+ printk("Service completed successfully\n");
+ })
+ return;
+ }
+ if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
+ !ACCESS_FLAG(F_IF)) {
+ x86emu_intr_handle();
+ }
+ }
+ op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ (*x86emu_optab[op1])(op1);
+ if (M.x86.debug & DEBUG_EXIT) {
+ M.x86.debug &= ~DEBUG_EXIT;
+ return;
+ }
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Halts the system by setting the halted system flag.
+****************************************************************************/
+void X86EMU_halt_sys(void)
+{
+ M.x86.intr |= INTR_HALTED;
+}
+
+/****************************************************************************
+PARAMETERS:
+mod - Mod value from decoded byte
+regh - Reg h value from decoded byte
+regl - Reg l value from decoded byte
+
+REMARKS:
+Raise the specified interrupt to be handled before the execution of the
+next instruction.
+
+NOTE: Do not inline this function, as (*sys_rdb) is already inline!
+****************************************************************************/
+void fetch_decode_modrm(
+ int *mod,
+ int *regh,
+ int *regl)
+{
+ int fetched;
+
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ INC_DECODED_INST_LEN(1);
+ *mod = (fetched >> 6) & 0x03;
+ *regh = (fetched >> 3) & 0x07;
+ *regl = (fetched >> 0) & 0x07;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate byte value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdb) is already inline!
+****************************************************************************/
+u8 fetch_byte_imm(void)
+{
+ u8 fetched;
+
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ INC_DECODED_INST_LEN(1);
+ return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate word value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdw) is already inline!
+****************************************************************************/
+u16 fetch_word_imm(void)
+{
+ u16 fetched;
+
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
+ M.x86.R_IP += 2;
+ INC_DECODED_INST_LEN(2);
+ return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate lone value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdw) is already inline!
+****************************************************************************/
+u32 fetch_long_imm(void)
+{
+ u32 fetched;
+
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
+ M.x86.R_IP += 4;
+ INC_DECODED_INST_LEN(4);
+ return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Value of the default data segment
+
+REMARKS:
+Inline function that returns the default data segment for the current
+instruction.
+
+On the x86 processor, the default segment is not always DS if there is
+no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
+addresses relative to SS (ie: on the stack). So, at the minimum, all
+decodings of addressing modes would have to set/clear a bit describing
+whether the access is relative to DS or SS. That is the function of the
+cpu-state-varible M.x86.mode. There are several potential states:
+
+ repe prefix seen (handled elsewhere)
+ repne prefix seen (ditto)
+
+ cs segment override
+ ds segment override
+ es segment override
+ fs segment override
+ gs segment override
+ ss segment override
+
+ ds/ss select (in absense of override)
+
+Each of the above 7 items are handled with a bit in the mode field.
+****************************************************************************/
+_INLINE u32 get_data_segment(void)
+{
+#define GET_SEGMENT(segment)
+ switch (M.x86.mode & SYSMODE_SEGMASK) {
+ case 0: /* default case: use ds register */
+ case SYSMODE_SEGOVR_DS:
+ case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_DS;
+ case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
+ return M.x86.R_SS;
+ case SYSMODE_SEGOVR_CS:
+ case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_CS;
+ case SYSMODE_SEGOVR_ES:
+ case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
+ return M.x86.R_ES;
+ case SYSMODE_SEGOVR_FS:
+ case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_FS;
+ case SYSMODE_SEGOVR_GS:
+ case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_GS;
+ case SYSMODE_SEGOVR_SS:
+ case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_SS;
+ default:
+#ifdef DEBUG
+ printk("error: should not happen: multiple overrides.\n");
+#endif
+ HALT_SYS();
+ return 0;
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to load data from
+
+RETURNS:
+Byte value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u8 fetch_data_byte(
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ return (*sys_rdb)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to load data from
+
+RETURNS:
+Word value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u16 fetch_data_word(
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ return (*sys_rdw)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to load data from
+
+RETURNS:
+Long value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u32 fetch_data_long(
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ return (*sys_rdl)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset - Offset to load data from
+
+RETURNS:
+Byte value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u8 fetch_data_byte_abs(
+ uint segment,
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ return (*sys_rdb)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset - Offset to load data from
+
+RETURNS:
+Word value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u16 fetch_data_word_abs(
+ uint segment,
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ return (*sys_rdw)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset - Offset to load data from
+
+RETURNS:
+Long value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u32 fetch_data_long_abs(
+ uint segment,
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ return (*sys_rdl)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a word value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_byte(
+ uint offset,
+ u8 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ (*sys_wrb)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a word value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_word(
+ uint offset,
+ u16 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ (*sys_wrw)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a long value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_long(
+ uint offset,
+ u32 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ (*sys_wrl)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a byte value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_byte_abs(
+ uint segment,
+ uint offset,
+ u8 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ (*sys_wrb)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a word value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_word_abs(
+ uint segment,
+ uint offset,
+ u16 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ (*sys_wrw)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a long value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_long_abs(
+ uint segment,
+ uint offset,
+ u32 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ (*sys_wrl)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for byte operands. Also enables the decoding of instructions.
+****************************************************************************/
+u8* decode_rm_byte_register(
+ int reg)
+{
+ switch (reg) {
+ case 0:
+ DECODE_PRINTF("AL");
+ return &M.x86.R_AL;
+ case 1:
+ DECODE_PRINTF("CL");
+ return &M.x86.R_CL;
+ case 2:
+ DECODE_PRINTF("DL");
+ return &M.x86.R_DL;
+ case 3:
+ DECODE_PRINTF("BL");
+ return &M.x86.R_BL;
+ case 4:
+ DECODE_PRINTF("AH");
+ return &M.x86.R_AH;
+ case 5:
+ DECODE_PRINTF("CH");
+ return &M.x86.R_CH;
+ case 6:
+ DECODE_PRINTF("DH");
+ return &M.x86.R_DH;
+ case 7:
+ DECODE_PRINTF("BH");
+ return &M.x86.R_BH;
+ }
+ HALT_SYS();
+ return NULL; /* NOT REACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for word operands. Also enables the decoding of instructions.
+****************************************************************************/
+u16* decode_rm_word_register(
+ int reg)
+{
+ switch (reg) {
+ case 0:
+ DECODE_PRINTF("AX");
+ return &M.x86.R_AX;
+ case 1:
+ DECODE_PRINTF("CX");
+ return &M.x86.R_CX;
+ case 2:
+ DECODE_PRINTF("DX");
+ return &M.x86.R_DX;
+ case 3:
+ DECODE_PRINTF("BX");
+ return &M.x86.R_BX;
+ case 4:
+ DECODE_PRINTF("SP");
+ return &M.x86.R_SP;
+ case 5:
+ DECODE_PRINTF("BP");
+ return &M.x86.R_BP;
+ case 6:
+ DECODE_PRINTF("SI");
+ return &M.x86.R_SI;
+ case 7:
+ DECODE_PRINTF("DI");
+ return &M.x86.R_DI;
+ }
+ HALT_SYS();
+ return NULL; /* NOTREACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for dword operands. Also enables the decoding of instructions.
+****************************************************************************/
+u32* decode_rm_long_register(
+ int reg)
+{
+ switch (reg) {
+ case 0:
+ DECODE_PRINTF("EAX");
+ return &M.x86.R_EAX;
+ case 1:
+ DECODE_PRINTF("ECX");
+ return &M.x86.R_ECX;
+ case 2:
+ DECODE_PRINTF("EDX");
+ return &M.x86.R_EDX;
+ case 3:
+ DECODE_PRINTF("EBX");
+ return &M.x86.R_EBX;
+ case 4:
+ DECODE_PRINTF("ESP");
+ return &M.x86.R_ESP;
+ case 5:
+ DECODE_PRINTF("EBP");
+ return &M.x86.R_EBP;
+ case 6:
+ DECODE_PRINTF("ESI");
+ return &M.x86.R_ESI;
+ case 7:
+ DECODE_PRINTF("EDI");
+ return &M.x86.R_EDI;
+ }
+ HALT_SYS();
+ return NULL; /* NOTREACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for word operands, modified from above for the weirdo
+special case of segreg operands. Also enables the decoding of instructions.
+****************************************************************************/
+u16* decode_rm_seg_register(
+ int reg)
+{
+ switch (reg) {
+ case 0:
+ DECODE_PRINTF("ES");
+ return &M.x86.R_ES;
+ case 1:
+ DECODE_PRINTF("CS");
+ return &M.x86.R_CS;
+ case 2:
+ DECODE_PRINTF("SS");
+ return &M.x86.R_SS;
+ case 3:
+ DECODE_PRINTF("DS");
+ return &M.x86.R_DS;
+ case 4:
+ DECODE_PRINTF("FS");
+ return &M.x86.R_FS;
+ case 5:
+ DECODE_PRINTF("GS");
+ return &M.x86.R_GS;
+ case 6:
+ case 7:
+ DECODE_PRINTF("ILLEGAL SEGREG");
+ break;
+ }
+ HALT_SYS();
+ return NULL; /* NOT REACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+scale - scale value of SIB byte
+index - index value of SIB byte
+
+RETURNS:
+Value of scale * index
+
+REMARKS:
+Decodes scale/index of SIB byte and returns relevant offset part of
+effective address.
+****************************************************************************/
+unsigned decode_sib_si(
+ int scale,
+ int index)
+{
+ scale = 1 << scale;
+ if (scale > 1) {
+ DECODE_PRINTF2("[%d*", scale);
+ } else {
+ DECODE_PRINTF("[");
+ }
+ switch (index) {
+ case 0:
+ DECODE_PRINTF("EAX]");
+ return M.x86.R_EAX * index;
+ case 1:
+ DECODE_PRINTF("ECX]");
+ return M.x86.R_ECX * index;
+ case 2:
+ DECODE_PRINTF("EDX]");
+ return M.x86.R_EDX * index;
+ case 3:
+ DECODE_PRINTF("EBX]");
+ return M.x86.R_EBX * index;
+ case 4:
+ DECODE_PRINTF("0]");
+ return 0;
+ case 5:
+ DECODE_PRINTF("EBP]");
+ return M.x86.R_EBP * index;
+ case 6:
+ DECODE_PRINTF("ESI]");
+ return M.x86.R_ESI * index;
+ case 7:
+ DECODE_PRINTF("EDI]");
+ return M.x86.R_EDI * index;
+ }
+ HALT_SYS();
+ return 0; /* NOT REACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+mod - MOD value of preceding ModR/M byte
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Decodes SIB addressing byte and returns calculated effective address.
+****************************************************************************/
+unsigned decode_sib_address(
+ int mod)
+{
+ int sib = fetch_byte_imm();
+ int ss = (sib >> 6) & 0x03;
+ int index = (sib >> 3) & 0x07;
+ int base = sib & 0x07;
+ int offset = 0;
+ int displacement;
+
+ switch (base) {
+ case 0:
+ DECODE_PRINTF("[EAX]");
+ offset = M.x86.R_EAX;
+ break;
+ case 1:
+ DECODE_PRINTF("[ECX]");
+ offset = M.x86.R_ECX;
+ break;
+ case 2:
+ DECODE_PRINTF("[EDX]");
+ offset = M.x86.R_EDX;
+ break;
+ case 3:
+ DECODE_PRINTF("[EBX]");
+ offset = M.x86.R_EBX;
+ break;
+ case 4:
+ DECODE_PRINTF("[ESP]");
+ offset = M.x86.R_ESP;
+ break;
+ case 5:
+ switch (mod) {
+ case 0:
+ displacement = (s32)fetch_long_imm();
+ DECODE_PRINTF2("[%d]", displacement);
+ offset = displacement;
+ break;
+ case 1:
+ displacement = (s8)fetch_byte_imm();
+ DECODE_PRINTF2("[%d][EBP]", displacement);
+ offset = M.x86.R_EBP + displacement;
+ break;
+ case 2:
+ displacement = (s32)fetch_long_imm();
+ DECODE_PRINTF2("[%d][EBP]", displacement);
+ offset = M.x86.R_EBP + displacement;
+ break;
+ default:
+ HALT_SYS();
+ }
+ DECODE_PRINTF("[EAX]");
+ offset = M.x86.R_EAX;
+ break;
+ case 6:
+ DECODE_PRINTF("[ESI]");
+ offset = M.x86.R_ESI;
+ break;
+ case 7:
+ DECODE_PRINTF("[EDI]");
+ offset = M.x86.R_EDI;
+ break;
+ default:
+ HALT_SYS();
+ }
+ offset += decode_sib_si(ss, index);
+ return offset;
+
+}
+
+/****************************************************************************
+PARAMETERS:
+rm - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=00 addressing. Also enables the
+decoding of instructions.
+
+NOTE: The code which specifies the corresponding segment (ds vs ss)
+ below in the case of [BP+..]. The assumption here is that at the
+ point that this subroutine is called, the bit corresponding to
+ SYSMODE_SEG_DS_SS will be zero. After every instruction
+ except the segment override instructions, this bit (as well
+ as any bits indicating segment overrides) will be clear. So
+ if a SS access is needed, set this bit. Otherwise, DS access
+ occurs (unless any of the segment override bits are set).
+****************************************************************************/
+unsigned decode_rm00_address(
+ int rm)
+{
+ unsigned offset;
+
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+ /* 32-bit addressing */
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF("[EAX]");
+ return M.x86.R_EAX;
+ case 1:
+ DECODE_PRINTF("[ECX]");
+ return M.x86.R_ECX;
+ case 2:
+ DECODE_PRINTF("[EDX]");
+ return M.x86.R_EDX;
+ case 3:
+ DECODE_PRINTF("[EBX]");
+ return M.x86.R_EBX;
+ case 4:
+ return decode_sib_address(0);
+ case 5:
+ offset = fetch_long_imm();
+ DECODE_PRINTF2("[%08x]", offset);
+ return offset;
+ case 6:
+ DECODE_PRINTF("[ESI]");
+ return M.x86.R_ESI;
+ case 7:
+ DECODE_PRINTF("[EDI]");
+ return M.x86.R_EDI;
+ }
+ } else {
+ /* 16-bit addressing */
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF("[BX+SI]");
+ return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
+ case 1:
+ DECODE_PRINTF("[BX+DI]");
+ return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
+ case 2:
+ DECODE_PRINTF("[BP+SI]");
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
+ case 3:
+ DECODE_PRINTF("[BP+DI]");
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
+ case 4:
+ DECODE_PRINTF("[SI]");
+ return M.x86.R_SI;
+ case 5:
+ DECODE_PRINTF("[DI]");
+ return M.x86.R_DI;
+ case 6:
+ offset = fetch_word_imm();
+ DECODE_PRINTF2("[%04x]", offset);
+ return offset;
+ case 7:
+ DECODE_PRINTF("[BX]");
+ return M.x86.R_BX;
+ }
+ }
+ HALT_SYS();
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+rm - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=01 addressing. Also enables the
+decoding of instructions.
+****************************************************************************/
+unsigned decode_rm01_address(
+ int rm)
+{
+ int displacement;
+
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+ /* 32-bit addressing */
+ if (rm != 4)
+ displacement = (s8)fetch_byte_imm();
+ else
+ displacement = 0;
+
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF2("%d[EAX]", displacement);
+ return M.x86.R_EAX + displacement;
+ case 1:
+ DECODE_PRINTF2("%d[ECX]", displacement);
+ return M.x86.R_ECX + displacement;
+ case 2:
+ DECODE_PRINTF2("%d[EDX]", displacement);
+ return M.x86.R_EDX + displacement;
+ case 3:
+ DECODE_PRINTF2("%d[EBX]", displacement);
+ return M.x86.R_EBX + displacement;
+ case 4: {
+ int offset = decode_sib_address(1);
+ displacement = (s8)fetch_byte_imm();
+ DECODE_PRINTF2("[%d]", displacement);
+ return offset + displacement;
+ }
+ case 5:
+ DECODE_PRINTF2("%d[EBP]", displacement);
+ return M.x86.R_EBP + displacement;
+ case 6:
+ DECODE_PRINTF2("%d[ESI]", displacement);
+ return M.x86.R_ESI + displacement;
+ case 7:
+ DECODE_PRINTF2("%d[EDI]", displacement);
+ return M.x86.R_EDI + displacement;
+ }
+ } else {
+ /* 16-bit addressing */
+ displacement = (s8)fetch_byte_imm();
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF2("%d[BX+SI]", displacement);
+ return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
+ case 1:
+ DECODE_PRINTF2("%d[BX+DI]", displacement);
+ return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
+ case 2:
+ DECODE_PRINTF2("%d[BP+SI]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
+ case 3:
+ DECODE_PRINTF2("%d[BP+DI]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
+ case 4:
+ DECODE_PRINTF2("%d[SI]", displacement);
+ return (M.x86.R_SI + displacement) & 0xffff;
+ case 5:
+ DECODE_PRINTF2("%d[DI]", displacement);
+ return (M.x86.R_DI + displacement) & 0xffff;
+ case 6:
+ DECODE_PRINTF2("%d[BP]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return (M.x86.R_BP + displacement) & 0xffff;
+ case 7:
+ DECODE_PRINTF2("%d[BX]", displacement);
+ return (M.x86.R_BX + displacement) & 0xffff;
+ }
+ }
+ HALT_SYS();
+ return 0; /* SHOULD NOT HAPPEN */
+}
+
+/****************************************************************************
+PARAMETERS:
+rm - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=10 addressing. Also enables the
+decoding of instructions.
+****************************************************************************/
+unsigned decode_rm10_address(
+ int rm)
+{
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+ int displacement;
+
+ /* 32-bit addressing */
+ if (rm != 4)
+ displacement = (s32)fetch_long_imm();
+ else
+ displacement = 0;
+
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF2("%d[EAX]", displacement);
+ return M.x86.R_EAX + displacement;
+ case 1:
+ DECODE_PRINTF2("%d[ECX]", displacement);
+ return M.x86.R_ECX + displacement;
+ case 2:
+ DECODE_PRINTF2("%d[EDX]", displacement);
+ return M.x86.R_EDX + displacement;
+ case 3:
+ DECODE_PRINTF2("%d[EBX]", displacement);
+ return M.x86.R_EBX + displacement;
+ case 4: {
+ int offset = decode_sib_address(2);
+ displacement = (s32)fetch_long_imm();
+ DECODE_PRINTF2("[%d]", displacement);
+ return offset + displacement;
+ }
+ case 5:
+ DECODE_PRINTF2("%d[EBP]", displacement);
+ return M.x86.R_EBP + displacement;
+ case 6:
+ DECODE_PRINTF2("%d[ESI]", displacement);
+ return M.x86.R_ESI + displacement;
+ case 7:
+ DECODE_PRINTF2("%d[EDI]", displacement);
+ return M.x86.R_EDI + displacement;
+ }
+ } else {
+ int displacement = (s16)fetch_word_imm();
+
+ /* 16-bit addressing */
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF2("%d[BX+SI]", displacement);
+ return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
+ case 1:
+ DECODE_PRINTF2("%d[BX+DI]", displacement);
+ return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
+ case 2:
+ DECODE_PRINTF2("%d[BP+SI]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
+ case 3:
+ DECODE_PRINTF2("%d[BP+DI]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
+ case 4:
+ DECODE_PRINTF2("%d[SI]", displacement);
+ return (M.x86.R_SI + displacement) & 0xffff;
+ case 5:
+ DECODE_PRINTF2("%d[DI]", displacement);
+ return (M.x86.R_DI + displacement) & 0xffff;
+ case 6:
+ DECODE_PRINTF2("%d[BP]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return (M.x86.R_BP + displacement) & 0xffff;
+ case 7:
+ DECODE_PRINTF2("%d[BX]", displacement);
+ return (M.x86.R_BX + displacement) & 0xffff;
+ }
+ }
+ HALT_SYS();
+ return 0; /* SHOULD NOT HAPPEN */
+}
+
+/****************************************************************************
+PARAMETERS:
+mod - modifier
+rm - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding, multiplexing calls to
+the decode_rmXX_address functions
+
+REMARKS:
+Return the offset given by "mod" addressing.
+****************************************************************************/
+
+unsigned decode_rmXX_address(int mod, int rm)
+{
+ if(mod == 0)
+ return decode_rm00_address(rm);
+ if(mod == 1)
+ return decode_rm01_address(rm);
+ return decode_rm10_address(rm);
+}
+
+#endif
diff --git a/drivers/bios_emulator/x86emu/ops.c b/drivers/bios_emulator/x86emu/ops.c
new file mode 100644
index 0000000000..a77bd9b492
--- /dev/null
+++ b/drivers/bios_emulator/x86emu/ops.c
@@ -0,0 +1,5438 @@
+/****************************************************************************
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+* Jason Jin <Jason.jin@freescale.com>
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines to implement the decoding
+* and emulation of all the x86 processor instructions.
+*
+* There are approximately 250 subroutines in here, which correspond
+* to the 256 byte-"opcodes" found on the 8086. The table which
+* dispatches this is found in the files optab.[ch].
+*
+* Each opcode proc has a comment preceeding it which gives it's table
+* address. Several opcodes are missing (undefined) in the table.
+*
+* Each proc includes information for decoding (DECODE_PRINTF and
+* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
+* functions (START_OF_INSTR, END_OF_INSTR).
+*
+* Many of the procedures are *VERY* similar in coding. This has
+* allowed for a very large amount of code to be generated in a fairly
+* short amount of time (i.e. cut, paste, and modify). The result is
+* that much of the code below could have been folded into subroutines
+* for a large reduction in size of this file. The downside would be
+* that there would be a penalty in execution speed. The file could
+* also have been *MUCH* larger by inlining certain functions which
+* were called. This could have resulted even faster execution. The
+* prime directive I used to decide whether to inline the code or to
+* modularize it, was basically: 1) no unnecessary subroutine calls,
+* 2) no routines more than about 200 lines in size, and 3) modularize
+* any code that I might not get right the first time. The fetch_*
+* subroutines fall into the latter category. The The decode_* fall
+* into the second category. The coding of the "switch(mod){ .... }"
+* in many of the subroutines below falls into the first category.
+* Especially, the coding of {add,and,or,sub,...}_{byte,word}
+* subroutines are an especially glaring case of the third guideline.
+* Since so much of the code is cloned from other modules (compare
+* opcode #00 to opcode #01), making the basic operations subroutine
+* calls is especially important; otherwise mistakes in coding an
+* "add" would represent a nightmare in maintenance.
+*
+* Jason ported this file to u-boot. place all the function pointer in
+* the got2 sector. Removed some opcode.
+*
+****************************************************************************/
+
+#include <common.h>
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "x86emu/x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/* constant arrays to do several instructions in just one function */
+
+#ifdef DEBUG
+static char *x86emu_GenOpName[8] = {
+ "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
+#endif
+
+/* used by several opcodes */
+static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
+{
+ add_byte, /* 00 */
+ or_byte, /* 01 */
+ adc_byte, /* 02 */
+ sbb_byte, /* 03 */
+ and_byte, /* 04 */
+ sub_byte, /* 05 */
+ xor_byte, /* 06 */
+ cmp_byte, /* 07 */
+};
+
+static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(".got2"))) =
+{
+ add_word, /*00 */
+ or_word, /*01 */
+ adc_word, /*02 */
+ sbb_word, /*03 */
+ and_word, /*04 */
+ sub_word, /*05 */
+ xor_word, /*06 */
+ cmp_word, /*07 */
+};
+
+static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(".got2"))) =
+{
+ add_long, /*00 */
+ or_long, /*01 */
+ adc_long, /*02 */
+ sbb_long, /*03 */
+ and_long, /*04 */
+ sub_long, /*05 */
+ xor_long, /*06 */
+ cmp_long, /*07 */
+};
+
+/* used by opcodes 80, c0, d0, and d2. */
+static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
+{
+ rol_byte,
+ ror_byte,
+ rcl_byte,
+ rcr_byte,
+ shl_byte,
+ shr_byte,
+ shl_byte, /* sal_byte === shl_byte by definition */
+ sar_byte,
+};
+
+/* used by opcodes c1, d1, and d3. */
+static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(".got2"))) =
+{
+ rol_word,
+ ror_word,
+ rcl_word,
+ rcr_word,
+ shl_word,
+ shr_word,
+ shl_word, /* sal_byte === shl_byte by definition */
+ sar_word,
+};
+
+/* used by opcodes c1, d1, and d3. */
+static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(".got2"))) =
+{
+ rol_long,
+ ror_long,
+ rcl_long,
+ rcr_long,
+ shl_long,
+ shr_long,
+ shl_long, /* sal_byte === shl_byte by definition */
+ sar_long,
+};
+
+#ifdef DEBUG
+
+static char *opF6_names[8] =
+ { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
+
+#endif
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+void x86emuOp_illegal_op(
+ u8 op1)
+{
+ START_OF_INSTR();
+ if (M.x86.R_SP != 0) {
+ DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
+ TRACE_REGS();
+ DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
+ M.x86.R_CS, M.x86.R_IP-1,op1));
+ HALT_SYS();
+ }
+ else {
+ /* If we get here, it means the stack pointer is back to zero
+ * so we are just returning from an emulator service call
+ * so therte is no need to display an error message. We trap
+ * the emulator with an 0xF1 opcode to finish the service
+ * call.
+ */
+ X86EMU_halt_sys();
+ }
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
+****************************************************************************/
+void x86emuOp_genop_byte_RM_R(u8 op1)
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 *destreg, *srcreg;
+ u8 destval;
+
+ op1 = (op1 >> 3) & 0x7;
+
+ START_OF_INSTR();
+ DECODE_PRINTF(x86emu_GenOpName[op1]);
+ DECODE_PRINTF("\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if(mod<3)
+ { destoffset = decode_rmXX_address(mod,rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = genop_byte_operation[op1](destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ }
+ else
+ { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = genop_byte_operation[op1](*destreg, *srcreg);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
+****************************************************************************/
+void x86emuOp_genop_word_RM_R(u8 op1)
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ op1 = (op1 >> 3) & 0x7;
+
+ START_OF_INSTR();
+ DECODE_PRINTF(x86emu_GenOpName[op1]);
+ DECODE_PRINTF("\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+
+ if(mod<3) {
+ destoffset = decode_rmXX_address(mod,rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = genop_long_operation[op1](destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = genop_word_operation[op1](destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = genop_long_operation[op1](*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = genop_word_operation[op1](*destreg, *srcreg);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
+****************************************************************************/
+void x86emuOp_genop_byte_R_RM(u8 op1)
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ op1 = (op1 >> 3) & 0x7;
+
+ START_OF_INSTR();
+ DECODE_PRINTF(x86emu_GenOpName[op1]);
+ DECODE_PRINTF("\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod,rl);
+ srcval = fetch_data_byte(srcoffset);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ srcval = *srcreg;
+ }
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = genop_byte_operation[op1](*destreg, srcval);
+
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
+****************************************************************************/
+void x86emuOp_genop_word_R_RM(u8 op1)
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ u32 *destreg32, srcval;
+ u16 *destreg;
+
+ op1 = (op1 >> 3) & 0x7;
+
+ START_OF_INSTR();
+ DECODE_PRINTF(x86emu_GenOpName[op1]);
+ DECODE_PRINTF("\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod,rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ destreg32 = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg32 = genop_long_operation[op1](*destreg32, srcval);
+ } else {
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = genop_word_operation[op1](*destreg, srcval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ destreg32 = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
+ } else {
+ u16 *srcreg;
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = genop_word_operation[op1](*destreg, *srcreg);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
+****************************************************************************/
+void x86emuOp_genop_byte_AL_IMM(u8 op1)
+{
+ u8 srcval;
+
+ op1 = (op1 >> 3) & 0x7;
+
+ START_OF_INSTR();
+ DECODE_PRINTF(x86emu_GenOpName[op1]);
+ DECODE_PRINTF("\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
+****************************************************************************/
+void x86emuOp_genop_word_AX_IMM(u8 op1)
+{
+ u32 srcval;
+
+ op1 = (op1 >> 3) & 0x7;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF(x86emu_GenOpName[op1]);
+ DECODE_PRINTF("\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF(x86emu_GenOpName[op1]);
+ DECODE_PRINTF("\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x06
+****************************************************************************/
+void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tES\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_ES);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x07
+****************************************************************************/
+void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tES\n");
+ TRACE_AND_STEP();
+ M.x86.R_ES = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0e
+****************************************************************************/
+void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tCS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
+****************************************************************************/
+void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
+{
+ u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ INC_DECODED_INST_LEN(1);
+ (*x86emu_optab2[op2])(op2);
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x16
+****************************************************************************/
+void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tSS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_SS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x17
+****************************************************************************/
+void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tSS\n");
+ TRACE_AND_STEP();
+ M.x86.R_SS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1e
+****************************************************************************/
+void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tDS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_DS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1f
+****************************************************************************/
+void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tDS\n");
+ TRACE_AND_STEP();
+ M.x86.R_DS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x26
+****************************************************************************/
+void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ES:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_ES;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x27
+****************************************************************************/
+void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DAA\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = daa_byte(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2e
+****************************************************************************/
+void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("CS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_CS;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2f
+****************************************************************************/
+void x86emuOp_das(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DAS\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = das_byte(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x36
+****************************************************************************/
+void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("SS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_SS;
+ /* no DECODE_CLEAR_SEGOVR ! */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x37
+****************************************************************************/
+void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("AAA\n");
+ TRACE_AND_STEP();
+ M.x86.R_AX = aaa_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3e
+****************************************************************************/
+void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_DS;
+ /* NO DECODE_CLEAR_SEGOVR! */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3f
+****************************************************************************/
+void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("AAS\n");
+ TRACE_AND_STEP();
+ M.x86.R_AX = aas_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x40 - 0x47
+****************************************************************************/
+void x86emuOp_inc_register(u8 op1)
+{
+ START_OF_INSTR();
+ op1 &= 0x7;
+ DECODE_PRINTF("INC\t");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *reg;
+ reg = DECODE_RM_LONG_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *reg = inc_long(*reg);
+ } else {
+ u16 *reg;
+ reg = DECODE_RM_WORD_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *reg = inc_word(*reg);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x48 - 0x4F
+****************************************************************************/
+void x86emuOp_dec_register(u8 op1)
+{
+ START_OF_INSTR();
+ op1 &= 0x7;
+ DECODE_PRINTF("DEC\t");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *reg;
+ reg = DECODE_RM_LONG_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *reg = dec_long(*reg);
+ } else {
+ u16 *reg;
+ reg = DECODE_RM_WORD_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *reg = dec_word(*reg);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x50 - 0x57
+****************************************************************************/
+void x86emuOp_push_register(u8 op1)
+{
+ START_OF_INSTR();
+ op1 &= 0x7;
+ DECODE_PRINTF("PUSH\t");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *reg;
+ reg = DECODE_RM_LONG_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_long(*reg);
+ } else {
+ u16 *reg;
+ reg = DECODE_RM_WORD_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_word(*reg);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x58 - 0x5F
+****************************************************************************/
+void x86emuOp_pop_register(u8 op1)
+{
+ START_OF_INSTR();
+ op1 &= 0x7;
+ DECODE_PRINTF("POP\t");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *reg;
+ reg = DECODE_RM_LONG_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *reg = pop_long();
+ } else {
+ u16 *reg;
+ reg = DECODE_RM_WORD_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *reg = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x60
+****************************************************************************/
+void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSHAD\n");
+ } else {
+ DECODE_PRINTF("PUSHA\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 old_sp = M.x86.R_ESP;
+
+ push_long(M.x86.R_EAX);
+ push_long(M.x86.R_ECX);
+ push_long(M.x86.R_EDX);
+ push_long(M.x86.R_EBX);
+ push_long(old_sp);
+ push_long(M.x86.R_EBP);
+ push_long(M.x86.R_ESI);
+ push_long(M.x86.R_EDI);
+ } else {
+ u16 old_sp = M.x86.R_SP;
+
+ push_word(M.x86.R_AX);
+ push_word(M.x86.R_CX);
+ push_word(M.x86.R_DX);
+ push_word(M.x86.R_BX);
+ push_word(old_sp);
+ push_word(M.x86.R_BP);
+ push_word(M.x86.R_SI);
+ push_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x61
+****************************************************************************/
+void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POPAD\n");
+ } else {
+ DECODE_PRINTF("POPA\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = pop_long();
+ M.x86.R_ESI = pop_long();
+ M.x86.R_EBP = pop_long();
+ M.x86.R_ESP += 4; /* skip ESP */
+ M.x86.R_EBX = pop_long();
+ M.x86.R_EDX = pop_long();
+ M.x86.R_ECX = pop_long();
+ M.x86.R_EAX = pop_long();
+ } else {
+ M.x86.R_DI = pop_word();
+ M.x86.R_SI = pop_word();
+ M.x86.R_BP = pop_word();
+ M.x86.R_SP += 2; /* skip SP */
+ M.x86.R_BX = pop_word();
+ M.x86.R_DX = pop_word();
+ M.x86.R_CX = pop_word();
+ M.x86.R_AX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
+/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x64
+****************************************************************************/
+void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("FS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_FS;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x65
+****************************************************************************/
+void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("GS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_GS;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x66 - prefix for 32-bit register
+****************************************************************************/
+void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DATA:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_DATA;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x67 - prefix for 32-bit address
+****************************************************************************/
+void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ADDR:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_ADDR;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x68
+****************************************************************************/
+void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 imm;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ imm = fetch_long_imm();
+ } else {
+ imm = fetch_word_imm();
+ }
+ DECODE_PRINTF2("PUSH\t%x\n", imm);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(imm);
+ } else {
+ push_word((u16)imm);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x69
+****************************************************************************/
+void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IMUL\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
+ (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
+ (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
+ if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
+ (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg,*srcreg;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ res = (s16)*srcreg * (s16)imm;
+ if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
+ (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6a
+****************************************************************************/
+void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ s16 imm;
+
+ START_OF_INSTR();
+ imm = (s8)fetch_byte_imm();
+ DECODE_PRINTF2("PUSH\t%d\n", imm);
+ TRACE_AND_STEP();
+ push_word(imm);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6b
+****************************************************************************/
+void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ s8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IMUL\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
+ (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
+ (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
+ if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
+ (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg,*srcreg;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)*srcreg * (s16)imm;
+ if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
+ (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6c
+****************************************************************************/
+void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("INSB\n");
+ ins(1);
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6d
+****************************************************************************/
+void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INSD\n");
+ ins(4);
+ } else {
+ DECODE_PRINTF("INSW\n");
+ ins(2);
+ }
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6e
+****************************************************************************/
+void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("OUTSB\n");
+ outs(1);
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6f
+****************************************************************************/
+void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("OUTSD\n");
+ outs(4);
+ } else {
+ DECODE_PRINTF("OUTSW\n");
+ outs(2);
+ }
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x70 - 0x7F
+****************************************************************************/
+int x86emu_check_jump_condition(u8 op);
+
+void x86emuOp_jump_near_cond(u8 op1)
+{
+ s8 offset;
+ u16 target;
+ int cond;
+
+ /* jump to byte offset if overflow flag is set */
+ START_OF_INSTR();
+ cond = x86emu_check_jump_condition(op1 & 0xF);
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (cond)
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x80
+****************************************************************************/
+void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+ u8 destval;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ if (mod < 3) {
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_byte_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x81
+****************************************************************************/
+void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /*
+ * Know operation, decode the mod byte to find the addressing
+ * mode.
+ */
+ if (mod < 3) {
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 destval,imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_long_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ } else {
+ u16 *destreg;
+ u16 destval,imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_word_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x82
+****************************************************************************/
+void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+ u8 destval;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction Similar to opcode 81, except that
+ * the immediate byte is sign extended to a word length.
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ if (mod < 3) {
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_byte_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x83
+****************************************************************************/
+void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction Similar to opcode 81, except that
+ * the immediate byte is sign extended to a word length.
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ if (mod < 3) {
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rmXX_address(mod,rl);
+
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ destval = fetch_data_long(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ destval = fetch_data_word(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 destval,imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_long_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ } else {
+ u16 *destreg;
+ u16 destval,imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*genop_word_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x84
+****************************************************************************/
+void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(destval, *srcreg);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(*destreg, *srcreg);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x85
+****************************************************************************/
+void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(destval, *srcreg);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(*destreg, *srcreg);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x86
+****************************************************************************/
+void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+ u8 tmp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XCHG\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_byte(destoffset, destval);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x87
+****************************************************************************/
+void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XCHG\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 destval,tmp;
+
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_long(destoffset, destval);
+ } else {
+ u16 *srcreg;
+ u16 destval,tmp;
+
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 tmp;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ } else {
+ u16 *destreg,*srcreg;
+ u16 tmp;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x88
+****************************************************************************/
+void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, *srcreg);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x89
+****************************************************************************/
+void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_long(destoffset, *srcreg);
+ } else {
+ u16 *srcreg;
+
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_word(destoffset, *srcreg);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8a
+****************************************************************************/
+void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8b
+****************************************************************************/
+void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg, *srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ } else {
+ u16 *destreg, *srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8c
+****************************************************************************/
+void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u16 *destreg, *srcreg;
+ uint destoffset;
+ u16 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = *srcreg;
+ store_data_word(destoffset, destval);
+ } else { /* register to register */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8d
+****************************************************************************/
+void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u16 *srcreg;
+ uint destoffset;
+
+/*
+ * TODO: Need to handle address size prefix!
+ *
+ * lea eax,[eax+ebx*2] ??
+ */
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LEA\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u16)destoffset;
+ }
+ /* } else { undefined. Do nothing. } */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8e
+****************************************************************************/
+void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u16 *destreg, *srcreg;
+ uint srcoffset;
+ u16 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else { /* register to register */
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ /*
+ * Clean up, and reset all the R_xSP pointers to the correct
+ * locations. This is about 3x too much overhead (doing all the
+ * segreg ptrs when only one is needed, but this instruction
+ * *cannot* be that common, and this isn't too much work anyway.
+ */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8f
+****************************************************************************/
+void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+ HALT_SYS();
+ }
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_long();
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_word();
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = pop_long();
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = pop_word();
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x90
+****************************************************************************/
+void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("NOP\n");
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x91-0x97
+****************************************************************************/
+void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ op1 &= 0x7;
+
+ START_OF_INSTR();
+
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *reg32;
+ DECODE_PRINTF("XCHG\tEAX,");
+ reg32 = DECODE_RM_LONG_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = *reg32;
+ *reg32 = tmp;
+ } else {
+ u16 *reg16;
+ DECODE_PRINTF("XCHG\tAX,");
+ reg16 = DECODE_RM_WORD_REGISTER(op1);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = M.x86.R_AX;
+ M.x86.R_EAX = *reg16;
+ *reg16 = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x98
+****************************************************************************/
+void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CWDE\n");
+ } else {
+ DECODE_PRINTF("CBW\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ if (M.x86.R_AX & 0x8000) {
+ M.x86.R_EAX |= 0xffff0000;
+ } else {
+ M.x86.R_EAX &= 0x0000ffff;
+ }
+ } else {
+ if (M.x86.R_AL & 0x80) {
+ M.x86.R_AH = 0xff;
+ } else {
+ M.x86.R_AH = 0x0;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x99
+****************************************************************************/
+void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CDQ\n");
+ } else {
+ DECODE_PRINTF("CWD\n");
+ }
+ DECODE_PRINTF("CWD\n");
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ if (M.x86.R_EAX & 0x80000000) {
+ M.x86.R_EDX = 0xffffffff;
+ } else {
+ M.x86.R_EDX = 0x0;
+ }
+ } else {
+ if (M.x86.R_AX & 0x8000) {
+ M.x86.R_DX = 0xffff;
+ } else {
+ M.x86.R_DX = 0x0;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9a
+****************************************************************************/
+void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 farseg, faroff;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CALL\t");
+ faroff = fetch_word_imm();
+ farseg = fetch_word_imm();
+ DECODE_PRINTF2("%04x:", farseg);
+ DECODE_PRINTF2("%04x\n", faroff);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
+
+ /* XXX
+ *
+ * Hooked interrupt vectors calling into our "BIOS" will cause
+ * problems unless all intersegment stuff is checked for BIOS
+ * access. Check needed here. For moment, let it alone.
+ */
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = farseg;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = faroff;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9b
+****************************************************************************/
+void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("WAIT");
+ TRACE_AND_STEP();
+ /* NADA. */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9c
+****************************************************************************/
+void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 flags;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSHFD\n");
+ } else {
+ DECODE_PRINTF("PUSHF\n");
+ }
+ TRACE_AND_STEP();
+
+ /* clear out *all* bits not representing flags, and turn on real bits */
+ flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(flags);
+ } else {
+ push_word((u16)flags);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9d
+****************************************************************************/
+void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POPFD\n");
+ } else {
+ DECODE_PRINTF("POPF\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EFLG = pop_long();
+ } else {
+ M.x86.R_FLG = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9e
+****************************************************************************/
+void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("SAHF\n");
+ TRACE_AND_STEP();
+ /* clear the lower bits of the flag register */
+ M.x86.R_FLG &= 0xffffff00;
+ /* or in the AH register into the flags register */
+ M.x86.R_FLG |= M.x86.R_AH;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9f
+****************************************************************************/
+void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LAHF\n");
+ TRACE_AND_STEP();
+ M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
+ /*undocumented TC++ behavior??? Nope. It's documented, but
+ you have too look real hard to notice it. */
+ M.x86.R_AH |= 0x2;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa0
+****************************************************************************/
+void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tAL,");
+ offset = fetch_word_imm();
+ DECODE_PRINTF2("[%04x]\n", offset);
+ TRACE_AND_STEP();
+ M.x86.R_AL = fetch_data_byte(offset);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa1
+****************************************************************************/
+void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ offset = fetch_word_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
+ } else {
+ DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = fetch_data_long(offset);
+ } else {
+ M.x86.R_AX = fetch_data_word(offset);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa2
+****************************************************************************/
+void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ offset = fetch_word_imm();
+ DECODE_PRINTF2("[%04x],AL\n", offset);
+ TRACE_AND_STEP();
+ store_data_byte(offset, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa3
+****************************************************************************/
+void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ offset = fetch_word_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
+ } else {
+ DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ store_data_long(offset, M.x86.R_EAX);
+ } else {
+ store_data_word(offset, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa4
+****************************************************************************/
+void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
+{
+ u8 val;
+ u32 count;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVS\tBYTE\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ val = fetch_data_byte(M.x86.R_SI);
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa5
+****************************************************************************/
+void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 val;
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOVS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("MOVS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long(M.x86.R_SI);
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
+ } else {
+ val = fetch_data_word(M.x86.R_SI);
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
+ }
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa6
+****************************************************************************/
+void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
+{
+ s8 val1, val2;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMPS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val1 = fetch_data_byte(M.x86.R_SI);
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(val1, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
+ if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ val1 = fetch_data_byte(M.x86.R_SI);
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(val1, val2);
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa7
+****************************************************************************/
+void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 val1,val2;
+ int inc;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CMPS\tDWORD\n");
+ inc = 4;
+ } else {
+ DECODE_PRINTF("CMPS\tWORD\n");
+ inc = 2;
+ }
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -inc;
+
+ TRACE_AND_STEP();
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val1 = fetch_data_long(M.x86.R_SI);
+ val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(val1, val2);
+ } else {
+ val1 = fetch_data_word(M.x86.R_SI);
+ val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word((u16)val1, (u16)val2);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
+ if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val1 = fetch_data_long(M.x86.R_SI);
+ val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(val1, val2);
+ } else {
+ val1 = fetch_data_word(M.x86.R_SI);
+ val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word((u16)val1, (u16)val2);
+ }
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa8
+****************************************************************************/
+void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\tAL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%04x\n", imm);
+ TRACE_AND_STEP();
+ test_byte(M.x86.R_AL, (u8)imm);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa9
+****************************************************************************/
+void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("TEST\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("TEST\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ test_long(M.x86.R_EAX, srcval);
+ } else {
+ test_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xaa
+****************************************************************************/
+void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("STOS\tBYTE\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ TRACE_AND_STEP();
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xab
+****************************************************************************/
+void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("STOS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("STOS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
+ } else {
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
+ }
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xac
+****************************************************************************/
+void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LODS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+ M.x86.R_SI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xad
+****************************************************************************/
+void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("LODS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("LODS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
+ } else {
+ M.x86.R_AX = fetch_data_word(M.x86.R_SI);
+ }
+ M.x86.R_SI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xae
+****************************************************************************/
+void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
+{
+ s8 val2;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SCAS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xaf
+****************************************************************************/
+void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 val;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("SCAS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("SCAS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb0 - 0xb7
+****************************************************************************/
+void x86emuOp_mov_byte_register_IMM(u8 op1)
+{
+ u8 imm, *ptr;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
+ DECODE_PRINTF(",");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ *ptr = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb8 - 0xbf
+****************************************************************************/
+void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ op1 &= 0x7;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *reg32;
+ reg32 = DECODE_RM_LONG_REGISTER(op1);
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", srcval);
+ TRACE_AND_STEP();
+ *reg32 = srcval;
+ } else {
+ u16 *reg16;
+ reg16 = DECODE_RM_WORD_REGISTER(op1);
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", srcval);
+ TRACE_AND_STEP();
+ *reg16 = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc0
+****************************************************************************/
+void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ if (mod < 3) {
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
+ *destreg = destval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc1
+****************************************************************************/
+void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ if (mod < 3) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc2
+****************************************************************************/
+void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("RET\t");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_SP += imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc3
+****************************************************************************/
+void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("RET\n");
+ RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc4
+****************************************************************************/
+void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LES\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_ES = fetch_data_word(srcoffset + 2);
+ }
+ /* else UNDEFINED! register to register */
+
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc5
+****************************************************************************/
+void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LDS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_DS = fetch_data_word(srcoffset + 2);
+ }
+ /* else UNDEFINED! */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc6
+****************************************************************************/
+void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
+ HALT_SYS();
+ }
+ if (mod < 3) {
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, imm);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc7
+****************************************************************************/
+void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+ HALT_SYS();
+ }
+ if (mod < 3) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_long(destoffset, imm);
+ } else {
+ u16 imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_word(destoffset, imm);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ } else {
+ u16 *destreg;
+ u16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc8
+****************************************************************************/
+void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
+{
+ u16 local,frame_pointer;
+ u8 nesting;
+ int i;
+
+ START_OF_INSTR();
+ local = fetch_word_imm();
+ nesting = fetch_byte_imm();
+ DECODE_PRINTF2("ENTER %x\n", local);
+ DECODE_PRINTF2(",%x\n", nesting);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_BP);
+ frame_pointer = M.x86.R_SP;
+ if (nesting > 0) {
+ for (i = 1; i < nesting; i++) {
+ M.x86.R_BP -= 2;
+ push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
+ }
+ push_word(frame_pointer);
+ }
+ M.x86.R_BP = frame_pointer;
+ M.x86.R_SP = (u16)(M.x86.R_SP - local);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc9
+****************************************************************************/
+void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LEAVE\n");
+ TRACE_AND_STEP();
+ M.x86.R_SP = M.x86.R_BP;
+ M.x86.R_BP = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xca
+****************************************************************************/
+void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("RETF\t");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ M.x86.R_SP += imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcb
+****************************************************************************/
+void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("RETF\n");
+ RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcc
+****************************************************************************/
+void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
+{
+ u16 tmp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("INT 3\n");
+ tmp = (u16) mem_access_word(3 * 4 + 2);
+ /* access the segment register */
+ TRACE_AND_STEP();
+ if (_X86EMU_intrTab[3]) {
+ (*_X86EMU_intrTab[3])(3);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(3 * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(3 * 4);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcd
+****************************************************************************/
+void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 tmp;
+ u8 intnum;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("INT\t");
+ intnum = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", intnum);
+ tmp = mem_access_word(intnum * 4 + 2);
+ TRACE_AND_STEP();
+ if (_X86EMU_intrTab[intnum]) {
+ (*_X86EMU_intrTab[intnum])(intnum);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(intnum * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(intnum * 4);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xce
+****************************************************************************/
+void x86emuOp_into(u8 X86EMU_UNUSED(op1))
+{
+ u16 tmp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("INTO\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_OF)) {
+ tmp = mem_access_word(4 * 4 + 2);
+ if (_X86EMU_intrTab[4]) {
+ (*_X86EMU_intrTab[4])(4);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(4 * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(4 * 4);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcf
+****************************************************************************/
+void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("IRET\n");
+
+ TRACE_AND_STEP();
+
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ M.x86.R_FLG = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd0
+****************************************************************************/
+void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ if (mod < 3) {
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, 1);
+ store_data_byte(destoffset, destval);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd1
+****************************************************************************/
+void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ if (mod < 3) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, 1);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, 1);
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ } else {
+ u16 destval;
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd2
+****************************************************************************/
+void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ amt = M.x86.R_CL;
+ if (mod < 3) {
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
+ *destreg = destval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd3
+****************************************************************************/
+void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ amt = M.x86.R_CL;
+ if (mod < 3) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd4
+****************************************************************************/
+void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
+{
+ u8 a;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AAM\n");
+ a = fetch_byte_imm(); /* this is a stupid encoding. */
+ if (a != 10) {
+ DECODE_PRINTF("ERROR DECODING AAM\n");
+ TRACE_REGS();
+ HALT_SYS();
+ }
+ TRACE_AND_STEP();
+ /* note the type change here --- returning AL and AH in AX. */
+ M.x86.R_AX = aam_word(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd5
+****************************************************************************/
+void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
+{
+ u8 a;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AAD\n");
+ a = fetch_byte_imm();
+ TRACE_AND_STEP();
+ M.x86.R_AX = aad_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* opcode 0xd6 ILLEGAL OPCODE */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd7
+****************************************************************************/
+void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
+{
+ u16 addr;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XLAT\n");
+ TRACE_AND_STEP();
+ addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
+ M.x86.R_AL = fetch_data_byte(addr);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* instuctions D8 .. DF are in i87_ops.c */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe0
+****************************************************************************/
+void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOPNE\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe1
+****************************************************************************/
+void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOPE\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe2
+****************************************************************************/
+void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOP\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0)
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe3
+****************************************************************************/
+void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
+{
+ u16 target;
+ s8 offset;
+
+ /* jump to byte offset if overflow flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JCXZ\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (M.x86.R_CX == 0)
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe4
+****************************************************************************/
+void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\t");
+ port = (u8) fetch_byte_imm();
+ DECODE_PRINTF2("%x,AL\n", port);
+ TRACE_AND_STEP();
+ M.x86.R_AL = (*sys_inb)(port);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe5
+****************************************************************************/
+void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\t");
+ port = (u8) fetch_byte_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("EAX,%x\n", port);
+ } else {
+ DECODE_PRINTF2("AX,%x\n", port);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = (*sys_inl)(port);
+ } else {
+ M.x86.R_AX = (*sys_inw)(port);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe6
+****************************************************************************/
+void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\t");
+ port = (u8) fetch_byte_imm();
+ DECODE_PRINTF2("%x,AL\n", port);
+ TRACE_AND_STEP();
+ (*sys_outb)(port, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe7
+****************************************************************************/
+void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\t");
+ port = (u8) fetch_byte_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("%x,EAX\n", port);
+ } else {
+ DECODE_PRINTF2("%x,AX\n", port);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ (*sys_outl)(port, M.x86.R_EAX);
+ } else {
+ (*sys_outw)(port, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe8
+****************************************************************************/
+void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CALL\t");
+ ip = (s16) fetch_word_imm();
+ ip += (s16) M.x86.R_IP; /* CHECK SIGN */
+ DECODE_PRINTF2("%04x\n", ip);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe9
+****************************************************************************/
+void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\t");
+ ip = (s16)fetch_word_imm();
+ ip += (s16)M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = (u16)ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xea
+****************************************************************************/
+void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 cs, ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\tFAR ");
+ ip = fetch_word_imm();
+ cs = fetch_word_imm();
+ DECODE_PRINTF2("%04x:", cs);
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = ip;
+ M.x86.R_CS = cs;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xeb
+****************************************************************************/
+void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 target;
+ s8 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xec
+****************************************************************************/
+void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\tAL,DX\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xed
+****************************************************************************/
+void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("IN\tEAX,DX\n");
+ } else {
+ DECODE_PRINTF("IN\tAX,DX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
+ } else {
+ M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xee
+****************************************************************************/
+void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\tDX,AL\n");
+ TRACE_AND_STEP();
+ (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xef
+****************************************************************************/
+void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("OUT\tDX,EAX\n");
+ } else {
+ DECODE_PRINTF("OUT\tDX,AX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
+ } else {
+ (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf0
+****************************************************************************/
+void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LOCK:\n");
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/*opcode 0xf1 ILLEGAL OPERATION */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf2
+****************************************************************************/
+void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("REPNE\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_REPNE;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf3
+****************************************************************************/
+void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("REPE\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_REPE;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf4
+****************************************************************************/
+void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("HALT\n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf5
+****************************************************************************/
+void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
+{
+ /* complement the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CMC\n");
+ TRACE_AND_STEP();
+ TOGGLE_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf6
+****************************************************************************/
+void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval, srcval;
+
+ /* long, drawn out code follows. Double switch for a total
+ of 32 cases. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ DECODE_PRINTF(opF6_names[rh]);
+ if (mod < 3) {
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ destval = fetch_data_byte(destoffset);
+
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ TRACE_AND_STEP();
+ test_byte(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = not_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = neg_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_byte(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_byte(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_byte(destval);
+ break;
+ default:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_byte(destval);
+ break;
+ }
+ } else { /* mod=11 */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ TRACE_AND_STEP();
+ test_byte(*destreg, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_byte(*destreg);
+ break;
+ case 3:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_byte(*destreg);
+ break;
+ case 4:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_byte(*destreg); /*!!! */
+ break;
+ case 5:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_byte(*destreg);
+ break;
+ case 6:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_byte(*destreg);
+ break;
+ default:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_byte(*destreg);
+ break;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf7
+****************************************************************************/
+void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ DECODE_PRINTF(opF6_names[rh]);
+ if (mod < 3) {
+
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval, srcval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ destval = fetch_data_long(destoffset);
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ test_long(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = not_long(destval);
+ store_data_long(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = neg_long(destval);
+ store_data_long(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_long(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_long(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_long(destval);
+ break;
+ case 7:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_long(destval);
+ break;
+ }
+ } else {
+ u16 destval, srcval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ destval = fetch_data_word(destoffset);
+
+ switch (rh) {
+ case 0: /* test word imm */
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ test_word(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = not_word(destval);
+ store_data_word(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = neg_word(destval);
+ store_data_word(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_word(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_word(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_word(destval);
+ break;
+ case 7:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_word(destval);
+ break;
+ }
+ }
+
+ } else { /* mod=11 */
+
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+
+ switch (rh) {
+ case 0: /* test word imm */
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ test_long(*destreg, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_long(*destreg);
+ break;
+ case 3:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_long(*destreg);
+ break;
+ case 4:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_long(*destreg); /*!!! */
+ break;
+ case 5:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_long(*destreg);
+ break;
+ case 6:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_long(*destreg);
+ break;
+ case 7:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_long(*destreg);
+ break;
+ }
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+
+ switch (rh) {
+ case 0: /* test word imm */
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ test_word(*destreg, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_word(*destreg);
+ break;
+ case 3:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_word(*destreg);
+ break;
+ case 4:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_word(*destreg); /*!!! */
+ break;
+ case 5:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_word(*destreg);
+ break;
+ case 6:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_word(*destreg);
+ break;
+ case 7:
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_word(*destreg);
+ break;
+ }
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf8
+****************************************************************************/
+void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
+{
+ /* clear the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLC\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf9
+****************************************************************************/
+void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
+{
+ /* set the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STC\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfa
+****************************************************************************/
+void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLI\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_IF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfb
+****************************************************************************/
+void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
+{
+ /* enable interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STI\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_IF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfc
+****************************************************************************/
+void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLD\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_DF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfd
+****************************************************************************/
+void x86emuOp_std(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STD\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_DF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfe
+****************************************************************************/
+void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u8 destval;
+ uint destoffset;
+ u8 *destreg;
+
+ /* Yet another special case instruction. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("INC\t");
+ break;
+ case 1:
+ DECODE_PRINTF("DEC\t");
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
+ HALT_SYS();
+ break;
+ }
+ }
+#endif
+ if (mod < 3) {
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ if (rh == 0)
+ destval = inc_byte(destval);
+ else
+ destval = dec_byte(destval);
+ store_data_byte(destoffset, destval);
+ } else {
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ if (rh == 0)
+ *destreg = inc_byte(*destreg);
+ else
+ *destreg = dec_byte(*destreg);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xff
+****************************************************************************/
+void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ uint destoffset = 0;
+ u16 *destreg;
+ u16 destval,destval2;
+
+ /* Yet another special case instruction. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tDWORD PTR ");
+ } else {
+ DECODE_PRINTF("INC\tWORD PTR ");
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tDWORD PTR ");
+ } else {
+ DECODE_PRINTF("DEC\tWORD PTR ");
+ }
+ break;
+ case 2:
+ DECODE_PRINTF("CALL\t ");
+ break;
+ case 3:
+ DECODE_PRINTF("CALL\tFAR ");
+ break;
+ case 4:
+ DECODE_PRINTF("JMP\t");
+ break;
+ case 5:
+ DECODE_PRINTF("JMP\tFAR ");
+ break;
+ case 6:
+ DECODE_PRINTF("PUSH\t");
+ break;
+ case 7:
+ DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
+ HALT_SYS();
+ break;
+ }
+ }
+#endif
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0: /* inc word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1: /* dec word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 3: /* call far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = destval2;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 4: /* jmp word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ break;
+ case 5: /* jmp far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ M.x86.R_CS = destval2;
+ break;
+ case 6: /* push word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ push_long(destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(destval);
+ }
+ break;
+ }
+ } else {
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = inc_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = inc_word(*destreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = dec_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = dec_word(*destreg);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = *destreg;
+ break;
+ case 3: /* jmp far ptr ... */
+ DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ break;
+
+ case 4: /* jmp ... */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ M.x86.R_IP = (u16) (*destreg);
+ break;
+ case 5: /* jmp far ptr ... */
+ DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_word(*destreg);
+ }
+ break;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/***************************************************************************
+ * Single byte operation code table:
+ **************************************************************************/
+void (*x86emu_optab[256])(u8) __attribute__ ((section(".got2"))) =
+{
+/* 0x00 */ x86emuOp_genop_byte_RM_R,
+/* 0x01 */ x86emuOp_genop_word_RM_R,
+/* 0x02 */ x86emuOp_genop_byte_R_RM,
+/* 0x03 */ x86emuOp_genop_word_R_RM,
+/* 0x04 */ x86emuOp_genop_byte_AL_IMM,
+/* 0x05 */ x86emuOp_genop_word_AX_IMM,
+/* 0x06 */ x86emuOp_push_ES,
+/* 0x07 */ x86emuOp_pop_ES,
+
+/* 0x08 */ x86emuOp_genop_byte_RM_R,
+/* 0x09 */ x86emuOp_genop_word_RM_R,
+/* 0x0a */ x86emuOp_genop_byte_R_RM,
+/* 0x0b */ x86emuOp_genop_word_R_RM,
+/* 0x0c */ x86emuOp_genop_byte_AL_IMM,
+/* 0x0d */ x86emuOp_genop_word_AX_IMM,
+/* 0x0e */ x86emuOp_push_CS,
+/* 0x0f */ x86emuOp_two_byte,
+
+/* 0x10 */ x86emuOp_genop_byte_RM_R,
+/* 0x11 */ x86emuOp_genop_word_RM_R,
+/* 0x12 */ x86emuOp_genop_byte_R_RM,
+/* 0x13 */ x86emuOp_genop_word_R_RM,
+/* 0x14 */ x86emuOp_genop_byte_AL_IMM,
+/* 0x15 */ x86emuOp_genop_word_AX_IMM,
+/* 0x16 */ x86emuOp_push_SS,
+/* 0x17 */ x86emuOp_pop_SS,
+
+/* 0x18 */ x86emuOp_genop_byte_RM_R,
+/* 0x19 */ x86emuOp_genop_word_RM_R,
+/* 0x1a */ x86emuOp_genop_byte_R_RM,
+/* 0x1b */ x86emuOp_genop_word_R_RM,
+/* 0x1c */ x86emuOp_genop_byte_AL_IMM,
+/* 0x1d */ x86emuOp_genop_word_AX_IMM,
+/* 0x1e */ x86emuOp_push_DS,
+/* 0x1f */ x86emuOp_pop_DS,
+
+/* 0x20 */ x86emuOp_genop_byte_RM_R,
+/* 0x21 */ x86emuOp_genop_word_RM_R,
+/* 0x22 */ x86emuOp_genop_byte_R_RM,
+/* 0x23 */ x86emuOp_genop_word_R_RM,
+/* 0x24 */ x86emuOp_genop_byte_AL_IMM,
+/* 0x25 */ x86emuOp_genop_word_AX_IMM,
+/* 0x26 */ x86emuOp_segovr_ES,
+/* 0x27 */ x86emuOp_daa,
+
+/* 0x28 */ x86emuOp_genop_byte_RM_R,
+/* 0x29 */ x86emuOp_genop_word_RM_R,
+/* 0x2a */ x86emuOp_genop_byte_R_RM,
+/* 0x2b */ x86emuOp_genop_word_R_RM,
+/* 0x2c */ x86emuOp_genop_byte_AL_IMM,
+/* 0x2d */ x86emuOp_genop_word_AX_IMM,
+/* 0x2e */ x86emuOp_segovr_CS,
+/* 0x2f */ x86emuOp_das,
+
+/* 0x30 */ x86emuOp_genop_byte_RM_R,
+/* 0x31 */ x86emuOp_genop_word_RM_R,
+/* 0x32 */ x86emuOp_genop_byte_R_RM,
+/* 0x33 */ x86emuOp_genop_word_R_RM,
+/* 0x34 */ x86emuOp_genop_byte_AL_IMM,
+/* 0x35 */ x86emuOp_genop_word_AX_IMM,
+/* 0x36 */ x86emuOp_segovr_SS,
+/* 0x37 */ x86emuOp_aaa,
+
+/* 0x38 */ x86emuOp_genop_byte_RM_R,
+/* 0x39 */ x86emuOp_genop_word_RM_R,
+/* 0x3a */ x86emuOp_genop_byte_R_RM,
+/* 0x3b */ x86emuOp_genop_word_R_RM,
+/* 0x3c */ x86emuOp_genop_byte_AL_IMM,
+/* 0x3d */ x86emuOp_genop_word_AX_IMM,
+/* 0x3e */ x86emuOp_segovr_DS,
+/* 0x3f */ x86emuOp_aas,
+
+/* 0x40 */ x86emuOp_inc_register,
+/* 0x41 */ x86emuOp_inc_register,
+/* 0x42 */ x86emuOp_inc_register,
+/* 0x43 */ x86emuOp_inc_register,
+/* 0x44 */ x86emuOp_inc_register,
+/* 0x45 */ x86emuOp_inc_register,
+/* 0x46 */ x86emuOp_inc_register,
+/* 0x47 */ x86emuOp_inc_register,
+
+/* 0x48 */ x86emuOp_dec_register,
+/* 0x49 */ x86emuOp_dec_register,
+/* 0x4a */ x86emuOp_dec_register,
+/* 0x4b */ x86emuOp_dec_register,
+/* 0x4c */ x86emuOp_dec_register,
+/* 0x4d */ x86emuOp_dec_register,
+/* 0x4e */ x86emuOp_dec_register,
+/* 0x4f */ x86emuOp_dec_register,
+
+/* 0x50 */ x86emuOp_push_register,
+/* 0x51 */ x86emuOp_push_register,
+/* 0x52 */ x86emuOp_push_register,
+/* 0x53 */ x86emuOp_push_register,
+/* 0x54 */ x86emuOp_push_register,
+/* 0x55 */ x86emuOp_push_register,
+/* 0x56 */ x86emuOp_push_register,
+/* 0x57 */ x86emuOp_push_register,
+
+/* 0x58 */ x86emuOp_pop_register,
+/* 0x59 */ x86emuOp_pop_register,
+/* 0x5a */ x86emuOp_pop_register,
+/* 0x5b */ x86emuOp_pop_register,
+/* 0x5c */ x86emuOp_pop_register,
+/* 0x5d */ x86emuOp_pop_register,
+/* 0x5e */ x86emuOp_pop_register,
+/* 0x5f */ x86emuOp_pop_register,
+
+/* 0x60 */ x86emuOp_push_all,
+/* 0x61 */ x86emuOp_pop_all,
+/* 0x62 */ x86emuOp_illegal_op, /* bound */
+/* 0x63 */ x86emuOp_illegal_op, /* arpl */
+/* 0x64 */ x86emuOp_segovr_FS,
+/* 0x65 */ x86emuOp_segovr_GS,
+/* 0x66 */ x86emuOp_prefix_data,
+/* 0x67 */ x86emuOp_prefix_addr,
+
+/* 0x68 */ x86emuOp_push_word_IMM,
+/* 0x69 */ x86emuOp_imul_word_IMM,
+/* 0x6a */ x86emuOp_push_byte_IMM,
+/* 0x6b */ x86emuOp_imul_byte_IMM,
+/* 0x6c */ x86emuOp_ins_byte,
+/* 0x6d */ x86emuOp_ins_word,
+/* 0x6e */ x86emuOp_outs_byte,
+/* 0x6f */ x86emuOp_outs_word,
+
+/* 0x70 */ x86emuOp_jump_near_cond,
+/* 0x71 */ x86emuOp_jump_near_cond,
+/* 0x72 */ x86emuOp_jump_near_cond,
+/* 0x73 */ x86emuOp_jump_near_cond,
+/* 0x74 */ x86emuOp_jump_near_cond,
+/* 0x75 */ x86emuOp_jump_near_cond,
+/* 0x76 */ x86emuOp_jump_near_cond,
+/* 0x77 */ x86emuOp_jump_near_cond,
+
+/* 0x78 */ x86emuOp_jump_near_cond,
+/* 0x79 */ x86emuOp_jump_near_cond,
+/* 0x7a */ x86emuOp_jump_near_cond,
+/* 0x7b */ x86emuOp_jump_near_cond,
+/* 0x7c */ x86emuOp_jump_near_cond,
+/* 0x7d */ x86emuOp_jump_near_cond,
+/* 0x7e */ x86emuOp_jump_near_cond,
+/* 0x7f */ x86emuOp_jump_near_cond,
+
+/* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
+/* 0x81 */ x86emuOp_opc81_word_RM_IMM,
+/* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
+/* 0x83 */ x86emuOp_opc83_word_RM_IMM,
+/* 0x84 */ x86emuOp_test_byte_RM_R,
+/* 0x85 */ x86emuOp_test_word_RM_R,
+/* 0x86 */ x86emuOp_xchg_byte_RM_R,
+/* 0x87 */ x86emuOp_xchg_word_RM_R,
+
+/* 0x88 */ x86emuOp_mov_byte_RM_R,
+/* 0x89 */ x86emuOp_mov_word_RM_R,
+/* 0x8a */ x86emuOp_mov_byte_R_RM,
+/* 0x8b */ x86emuOp_mov_word_R_RM,
+/* 0x8c */ x86emuOp_mov_word_RM_SR,
+/* 0x8d */ x86emuOp_lea_word_R_M,
+/* 0x8e */ x86emuOp_mov_word_SR_RM,
+/* 0x8f */ x86emuOp_pop_RM,
+
+/* 0x90 */ x86emuOp_nop,
+/* 0x91 */ x86emuOp_xchg_word_AX_register,
+/* 0x92 */ x86emuOp_xchg_word_AX_register,
+/* 0x93 */ x86emuOp_xchg_word_AX_register,
+/* 0x94 */ x86emuOp_xchg_word_AX_register,
+/* 0x95 */ x86emuOp_xchg_word_AX_register,
+/* 0x96 */ x86emuOp_xchg_word_AX_register,
+/* 0x97 */ x86emuOp_xchg_word_AX_register,
+
+/* 0x98 */ x86emuOp_cbw,
+/* 0x99 */ x86emuOp_cwd,
+/* 0x9a */ x86emuOp_call_far_IMM,
+/* 0x9b */ x86emuOp_wait,
+/* 0x9c */ x86emuOp_pushf_word,
+/* 0x9d */ x86emuOp_popf_word,
+/* 0x9e */ x86emuOp_sahf,
+/* 0x9f */ x86emuOp_lahf,
+
+/* 0xa0 */ x86emuOp_mov_AL_M_IMM,
+/* 0xa1 */ x86emuOp_mov_AX_M_IMM,
+/* 0xa2 */ x86emuOp_mov_M_AL_IMM,
+/* 0xa3 */ x86emuOp_mov_M_AX_IMM,
+/* 0xa4 */ x86emuOp_movs_byte,
+/* 0xa5 */ x86emuOp_movs_word,
+/* 0xa6 */ x86emuOp_cmps_byte,
+/* 0xa7 */ x86emuOp_cmps_word,
+/* 0xa8 */ x86emuOp_test_AL_IMM,
+/* 0xa9 */ x86emuOp_test_AX_IMM,
+/* 0xaa */ x86emuOp_stos_byte,
+/* 0xab */ x86emuOp_stos_word,
+/* 0xac */ x86emuOp_lods_byte,
+/* 0xad */ x86emuOp_lods_word,
+/* 0xac */ x86emuOp_scas_byte,
+/* 0xad */ x86emuOp_scas_word,
+
+/* 0xb0 */ x86emuOp_mov_byte_register_IMM,
+/* 0xb1 */ x86emuOp_mov_byte_register_IMM,
+/* 0xb2 */ x86emuOp_mov_byte_register_IMM,
+/* 0xb3 */ x86emuOp_mov_byte_register_IMM,
+/* 0xb4 */ x86emuOp_mov_byte_register_IMM,
+/* 0xb5 */ x86emuOp_mov_byte_register_IMM,
+/* 0xb6 */ x86emuOp_mov_byte_register_IMM,
+/* 0xb7 */ x86emuOp_mov_byte_register_IMM,
+
+/* 0xb8 */ x86emuOp_mov_word_register_IMM,
+/* 0xb9 */ x86emuOp_mov_word_register_IMM,
+/* 0xba */ x86emuOp_mov_word_register_IMM,
+/* 0xbb */ x86emuOp_mov_word_register_IMM,
+/* 0xbc */ x86emuOp_mov_word_register_IMM,
+/* 0xbd */ x86emuOp_mov_word_register_IMM,
+/* 0xbe */ x86emuOp_mov_word_register_IMM,
+/* 0xbf */ x86emuOp_mov_word_register_IMM,
+
+/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
+/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
+/* 0xc2 */ x86emuOp_ret_near_IMM,
+/* 0xc3 */ x86emuOp_ret_near,
+/* 0xc4 */ x86emuOp_les_R_IMM,
+/* 0xc5 */ x86emuOp_lds_R_IMM,
+/* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
+/* 0xc7 */ x86emuOp_mov_word_RM_IMM,
+/* 0xc8 */ x86emuOp_enter,
+/* 0xc9 */ x86emuOp_leave,
+/* 0xca */ x86emuOp_ret_far_IMM,
+/* 0xcb */ x86emuOp_ret_far,
+/* 0xcc */ x86emuOp_int3,
+/* 0xcd */ x86emuOp_int_IMM,
+/* 0xce */ x86emuOp_into,
+/* 0xcf */ x86emuOp_iret,
+
+/* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
+/* 0xd1 */ x86emuOp_opcD1_word_RM_1,
+/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
+/* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
+/* 0xd4 */ x86emuOp_aam,
+/* 0xd5 */ x86emuOp_aad,
+/* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
+/* 0xd7 */ x86emuOp_xlat,
+/* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
+/* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
+/* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
+/* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
+/* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
+/* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
+/* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
+/* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
+
+/* 0xe0 */ x86emuOp_loopne,
+/* 0xe1 */ x86emuOp_loope,
+/* 0xe2 */ x86emuOp_loop,
+/* 0xe3 */ x86emuOp_jcxz,
+/* 0xe4 */ x86emuOp_in_byte_AL_IMM,
+/* 0xe5 */ x86emuOp_in_word_AX_IMM,
+/* 0xe6 */ x86emuOp_out_byte_IMM_AL,
+/* 0xe7 */ x86emuOp_out_word_IMM_AX,
+
+/* 0xe8 */ x86emuOp_call_near_IMM,
+/* 0xe9 */ x86emuOp_jump_near_IMM,
+/* 0xea */ x86emuOp_jump_far_IMM,
+/* 0xeb */ x86emuOp_jump_byte_IMM,
+/* 0xec */ x86emuOp_in_byte_AL_DX,
+/* 0xed */ x86emuOp_in_word_AX_DX,
+/* 0xee */ x86emuOp_out_byte_DX_AL,
+/* 0xef */ x86emuOp_out_word_DX_AX,
+
+/* 0xf0 */ x86emuOp_lock,
+/* 0xf1 */ x86emuOp_illegal_op,
+/* 0xf2 */ x86emuOp_repne,
+/* 0xf3 */ x86emuOp_repe,
+/* 0xf4 */ x86emuOp_halt,
+/* 0xf5 */ x86emuOp_cmc,
+/* 0xf6 */ x86emuOp_opcF6_byte_RM,
+/* 0xf7 */ x86emuOp_opcF7_word_RM,
+
+/* 0xf8 */ x86emuOp_clc,
+/* 0xf9 */ x86emuOp_stc,
+/* 0xfa */ x86emuOp_cli,
+/* 0xfb */ x86emuOp_sti,
+/* 0xfc */ x86emuOp_cld,
+/* 0xfd */ x86emuOp_std,
+/* 0xfe */ x86emuOp_opcFE_byte_RM,
+/* 0xff */ x86emuOp_opcFF_word_RM,
+};
+
+#endif
diff --git a/drivers/bios_emulator/x86emu/ops2.c b/drivers/bios_emulator/x86emu/ops2.c
new file mode 100644
index 0000000000..d6a210c973
--- /dev/null
+++ b/drivers/bios_emulator/x86emu/ops2.c
@@ -0,0 +1,1776 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+* Jason Jin <Jason.jin@freescale.com>
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines to implement the decoding
+* and emulation of all the x86 extended two-byte processor
+* instructions.
+*
+* Jason port this file to u-boot. Put the function pointer into
+* got2 sector.
+*
+****************************************************************************/
+
+#include <common.h>
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "x86emu/x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+void x86emuOp2_illegal_op(
+ u8 op2)
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
+ TRACE_REGS();
+ printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
+ M.x86.R_CS, M.x86.R_IP-2,op2);
+ HALT_SYS();
+ END_OF_INSTR();
+}
+
+#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0x80-0x8F
+****************************************************************************/
+int x86emu_check_jump_condition(u8 op)
+{
+ switch (op) {
+ case 0x0:
+ DECODE_PRINTF("JO\t");
+ return ACCESS_FLAG(F_OF);
+ case 0x1:
+ DECODE_PRINTF("JNO\t");
+ return !ACCESS_FLAG(F_OF);
+ break;
+ case 0x2:
+ DECODE_PRINTF("JB\t");
+ return ACCESS_FLAG(F_CF);
+ break;
+ case 0x3:
+ DECODE_PRINTF("JNB\t");
+ return !ACCESS_FLAG(F_CF);
+ break;
+ case 0x4:
+ DECODE_PRINTF("JZ\t");
+ return ACCESS_FLAG(F_ZF);
+ break;
+ case 0x5:
+ DECODE_PRINTF("JNZ\t");
+ return !ACCESS_FLAG(F_ZF);
+ break;
+ case 0x6:
+ DECODE_PRINTF("JBE\t");
+ return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
+ break;
+ case 0x7:
+ DECODE_PRINTF("JNBE\t");
+ return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
+ break;
+ case 0x8:
+ DECODE_PRINTF("JS\t");
+ return ACCESS_FLAG(F_SF);
+ break;
+ case 0x9:
+ DECODE_PRINTF("JNS\t");
+ return !ACCESS_FLAG(F_SF);
+ break;
+ case 0xa:
+ DECODE_PRINTF("JP\t");
+ return ACCESS_FLAG(F_PF);
+ break;
+ case 0xb:
+ DECODE_PRINTF("JNP\t");
+ return !ACCESS_FLAG(F_PF);
+ break;
+ case 0xc:
+ DECODE_PRINTF("JL\t");
+ return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+ break;
+ case 0xd:
+ DECODE_PRINTF("JNL\t");
+ return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+ break;
+ case 0xe:
+ DECODE_PRINTF("JLE\t");
+ return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+ ACCESS_FLAG(F_ZF));
+ break;
+ default:
+ DECODE_PRINTF("JNLE\t");
+ return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+ ACCESS_FLAG(F_ZF));
+ }
+}
+
+void x86emuOp2_long_jump(u8 op2)
+{
+ s32 target;
+ int cond;
+
+ /* conditional jump to word offset. */
+ START_OF_INSTR();
+ cond = x86emu_check_jump_condition(op2 & 0xF);
+ target = (s16) fetch_word_imm();
+ target += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", target);
+ TRACE_AND_STEP();
+ if (cond)
+ M.x86.R_IP = (u16)target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0x90-0x9F
+****************************************************************************/
+void x86emuOp2_set_byte(u8 op2)
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 *destreg;
+ char *name = 0;
+ int cond = 0;
+
+ START_OF_INSTR();
+ switch (op2) {
+ case 0x90:
+ name = "SETO\t";
+ cond = ACCESS_FLAG(F_OF);
+ break;
+ case 0x91:
+ name = "SETNO\t";
+ cond = !ACCESS_FLAG(F_OF);
+ break;
+ case 0x92:
+ name = "SETB\t";
+ cond = ACCESS_FLAG(F_CF);
+ break;
+ case 0x93:
+ name = "SETNB\t";
+ cond = !ACCESS_FLAG(F_CF);
+ break;
+ case 0x94:
+ name = "SETZ\t";
+ cond = ACCESS_FLAG(F_ZF);
+ break;
+ case 0x95:
+ name = "SETNZ\t";
+ cond = !ACCESS_FLAG(F_ZF);
+ break;
+ case 0x96:
+ name = "SETBE\t";
+ cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
+ break;
+ case 0x97:
+ name = "SETNBE\t";
+ cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
+ break;
+ case 0x98:
+ name = "SETS\t";
+ cond = ACCESS_FLAG(F_SF);
+ break;
+ case 0x99:
+ name = "SETNS\t";
+ cond = !ACCESS_FLAG(F_SF);
+ break;
+ case 0x9a:
+ name = "SETP\t";
+ cond = ACCESS_FLAG(F_PF);
+ break;
+ case 0x9b:
+ name = "SETNP\t";
+ cond = !ACCESS_FLAG(F_PF);
+ break;
+ case 0x9c:
+ name = "SETL\t";
+ cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+ break;
+ case 0x9d:
+ name = "SETNL\t";
+ cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+ break;
+ case 0x9e:
+ name = "SETLE\t";
+ cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+ ACCESS_FLAG(F_ZF));
+ break;
+ case 0x9f:
+ name = "SETNLE\t";
+ cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+ ACCESS_FLAG(F_ZF));
+ break;
+ }
+ DECODE_PRINTF(name);
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, cond ? 0x01 : 0x00);
+ } else { /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ TRACE_AND_STEP();
+ *destreg = cond ? 0x01 : 0x00;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa0
+****************************************************************************/
+void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tFS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_FS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa1
+****************************************************************************/
+void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tFS\n");
+ TRACE_AND_STEP();
+ M.x86.R_FS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa3
+****************************************************************************/
+void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit,disp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BT\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval;
+ u32 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+ } else {
+ u16 srcval;
+ u16 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg,*shiftreg;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
+ } else {
+ u16 *srcreg,*shiftreg;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa4
+****************************************************************************/
+void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 shift;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SHLD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shld_long(destval,*shiftreg,shift);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shld_word(destval,*shiftreg,shift);
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ *destreg = shld_long(*destreg,*shiftreg,shift);
+ } else {
+ u16 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ *destreg = shld_word(*destreg,*shiftreg,shift);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa5
+****************************************************************************/
+void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SHLD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shld_long(destval,*shiftreg,M.x86.R_CL);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shld_word(destval,*shiftreg,M.x86.R_CL);
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
+ } else {
+ u16 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa8
+****************************************************************************/
+void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tGS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_GS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa9
+****************************************************************************/
+void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tGS\n");
+ TRACE_AND_STEP();
+ M.x86.R_GS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xaa
+****************************************************************************/
+void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit,disp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BTS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval | mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, srcval | mask);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg,*shiftreg;
+ u32 mask;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg |= mask;
+ } else {
+ u16 *srcreg,*shiftreg;
+ u16 mask;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg |= mask;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xac
+****************************************************************************/
+void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 shift;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SHLD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shrd_long(destval,*shiftreg,shift);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shrd_word(destval,*shiftreg,shift);
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ *destreg = shrd_long(*destreg,*shiftreg,shift);
+ } else {
+ u16 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ *destreg = shrd_word(*destreg,*shiftreg,shift);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xad
+****************************************************************************/
+void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SHLD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
+ store_data_word(destoffset, destval);
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
+ } else {
+ u16 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xaf
+****************************************************************************/
+void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IMUL\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_long(srcoffset);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_word(srcoffset);
+ TRACE_AND_STEP();
+ res = (s16)*destreg * (s16)srcval;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg,*srcreg;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ res = (s16)*destreg * (s16)*srcreg;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb2
+****************************************************************************/
+void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LSS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_SS = fetch_data_word(srcoffset + 2);
+ } else { /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb3
+****************************************************************************/
+void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit,disp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BTR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval & ~mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg,*shiftreg;
+ u32 mask;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg &= ~mask;
+ } else {
+ u16 *srcreg,*shiftreg;
+ u16 mask;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg &= ~mask;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb4
+****************************************************************************/
+void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LFS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_FS = fetch_data_word(srcoffset + 2);
+ } else { /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb5
+****************************************************************************/
+void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LGS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_GS = fetch_data_word(srcoffset + 2);
+ } else { /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb6
+****************************************************************************/
+void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVZX\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u8 *srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ } else {
+ u16 *destreg;
+ u8 *srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb7
+****************************************************************************/
+void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ u32 *destreg;
+ u32 srcval;
+ u16 *srcreg;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVZX\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else { /* register to register */
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xba
+****************************************************************************/
+void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ u8 shift;
+ int bit;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (rh) {
+ case 4:
+ DECODE_PRINTF("BT\t");
+ break;
+ case 5:
+ DECODE_PRINTF("BTS\t");
+ break;
+ case 6:
+ DECODE_PRINTF("BTR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("BTC\t");
+ break;
+ default:
+ DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
+ TRACE_REGS();
+ printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
+ M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
+ HALT_SYS();
+ }
+ if (mod < 3) {
+
+ srcoffset = decode_rmXX_address(mod, rl);
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", shift);
+ TRACE_AND_STEP();
+
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, mask;
+
+ bit = shift & 0x1F;
+ srcval = fetch_data_long(srcoffset);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ switch (rh) {
+ case 5:
+ store_data_long(srcoffset, srcval | mask);
+ break;
+ case 6:
+ store_data_long(srcoffset, srcval & ~mask);
+ break;
+ case 7:
+ store_data_long(srcoffset, srcval ^ mask);
+ break;
+ default:
+ break;
+ }
+ } else {
+ u16 srcval, mask;
+
+ bit = shift & 0xF;
+ srcval = fetch_data_word(srcoffset);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ switch (rh) {
+ case 5:
+ store_data_word(srcoffset, srcval | mask);
+ break;
+ case 6:
+ store_data_word(srcoffset, srcval & ~mask);
+ break;
+ case 7:
+ store_data_word(srcoffset, srcval ^ mask);
+ break;
+ default:
+ break;
+ }
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 mask;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", shift);
+ TRACE_AND_STEP();
+ bit = shift & 0x1F;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ switch (rh) {
+ case 5:
+ *srcreg |= mask;
+ break;
+ case 6:
+ *srcreg &= ~mask;
+ break;
+ case 7:
+ *srcreg ^= mask;
+ break;
+ default:
+ break;
+ }
+ } else {
+ u16 *srcreg;
+ u16 mask;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", shift);
+ TRACE_AND_STEP();
+ bit = shift & 0xF;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ switch (rh) {
+ case 5:
+ *srcreg |= mask;
+ break;
+ case 6:
+ *srcreg &= ~mask;
+ break;
+ case 7:
+ *srcreg ^= mask;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbb
+****************************************************************************/
+void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit,disp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BTC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval ^ mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg,*shiftreg;
+ u32 mask;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg ^= mask;
+ } else {
+ u16 *srcreg,*shiftreg;
+ u16 mask;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg ^= mask;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbc
+****************************************************************************/
+void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BSF\n");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, *dstreg;
+
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_long(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
+ if ((srcval >> *dstreg) & 1) break;
+ } else {
+ u16 srcval, *dstreg;
+
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_word(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
+ if ((srcval >> *dstreg) & 1) break;
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg, *dstreg;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
+ if ((*srcreg >> *dstreg) & 1) break;
+ } else {
+ u16 *srcreg, *dstreg;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
+ if ((*srcreg >> *dstreg) & 1) break;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbd
+****************************************************************************/
+void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BSF\n");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ srcoffset = decode_rmXX_address(mod, rl);
+ DECODE_PRINTF(",");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, *dstreg;
+
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_long(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
+ if ((srcval >> *dstreg) & 1) break;
+ } else {
+ u16 srcval, *dstreg;
+
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_word(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
+ if ((srcval >> *dstreg) & 1) break;
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg, *dstreg;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+ for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
+ if ((*srcreg >> *dstreg) & 1) break;
+ } else {
+ u16 *srcreg, *dstreg;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+ for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
+ if ((*srcreg >> *dstreg) & 1) break;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbe
+****************************************************************************/
+void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVSX\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = (s32)((s8)fetch_data_byte(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = (s16)((s8)fetch_data_byte(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ } else { /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u8 *srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = (s32)((s8)*srcreg);
+ } else {
+ u16 *destreg;
+ u8 *srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = (s16)((s8)*srcreg);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbf
+****************************************************************************/
+void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ u32 *destreg;
+ u32 srcval;
+ u16 *srcreg;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVSX\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (mod < 3) {
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rmXX_address(mod, rl);
+ srcval = (s32)((s16)fetch_data_word(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else { /* register to register */
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = (s32)((s16)*srcreg);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/***************************************************************************
+ * Double byte operation code table:
+ **************************************************************************/
+void (*x86emu_optab2[256])(u8) __attribute__((section(".got2"))) =
+{
+/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
+/* 0x01 */ x86emuOp2_illegal_op, /* Group G (ring 0 PM) */
+/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
+/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
+/* 0x04 */ x86emuOp2_illegal_op,
+/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
+/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
+/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
+/* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */
+/* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */
+/* 0x0a */ x86emuOp2_illegal_op,
+/* 0x0b */ x86emuOp2_illegal_op,
+/* 0x0c */ x86emuOp2_illegal_op,
+/* 0x0d */ x86emuOp2_illegal_op,
+/* 0x0e */ x86emuOp2_illegal_op,
+/* 0x0f */ x86emuOp2_illegal_op,
+
+/* 0x10 */ x86emuOp2_illegal_op,
+/* 0x11 */ x86emuOp2_illegal_op,
+/* 0x12 */ x86emuOp2_illegal_op,
+/* 0x13 */ x86emuOp2_illegal_op,
+/* 0x14 */ x86emuOp2_illegal_op,
+/* 0x15 */ x86emuOp2_illegal_op,
+/* 0x16 */ x86emuOp2_illegal_op,
+/* 0x17 */ x86emuOp2_illegal_op,
+/* 0x18 */ x86emuOp2_illegal_op,
+/* 0x19 */ x86emuOp2_illegal_op,
+/* 0x1a */ x86emuOp2_illegal_op,
+/* 0x1b */ x86emuOp2_illegal_op,
+/* 0x1c */ x86emuOp2_illegal_op,
+/* 0x1d */ x86emuOp2_illegal_op,
+/* 0x1e */ x86emuOp2_illegal_op,
+/* 0x1f */ x86emuOp2_illegal_op,
+
+/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
+/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
+/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
+/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
+/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
+/* 0x25 */ x86emuOp2_illegal_op,
+/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
+/* 0x27 */ x86emuOp2_illegal_op,
+/* 0x28 */ x86emuOp2_illegal_op,
+/* 0x29 */ x86emuOp2_illegal_op,
+/* 0x2a */ x86emuOp2_illegal_op,
+/* 0x2b */ x86emuOp2_illegal_op,
+/* 0x2c */ x86emuOp2_illegal_op,
+/* 0x2d */ x86emuOp2_illegal_op,
+/* 0x2e */ x86emuOp2_illegal_op,
+/* 0x2f */ x86emuOp2_illegal_op,
+
+/* 0x30 */ x86emuOp2_illegal_op,
+/* 0x31 */ x86emuOp2_illegal_op,
+/* 0x32 */ x86emuOp2_illegal_op,
+/* 0x33 */ x86emuOp2_illegal_op,
+/* 0x34 */ x86emuOp2_illegal_op,
+/* 0x35 */ x86emuOp2_illegal_op,
+/* 0x36 */ x86emuOp2_illegal_op,
+/* 0x37 */ x86emuOp2_illegal_op,
+/* 0x38 */ x86emuOp2_illegal_op,
+/* 0x39 */ x86emuOp2_illegal_op,
+/* 0x3a */ x86emuOp2_illegal_op,
+/* 0x3b */ x86emuOp2_illegal_op,
+/* 0x3c */ x86emuOp2_illegal_op,
+/* 0x3d */ x86emuOp2_illegal_op,
+/* 0x3e */ x86emuOp2_illegal_op,
+/* 0x3f */ x86emuOp2_illegal_op,
+
+/* 0x40 */ x86emuOp2_illegal_op,
+/* 0x41 */ x86emuOp2_illegal_op,
+/* 0x42 */ x86emuOp2_illegal_op,
+/* 0x43 */ x86emuOp2_illegal_op,
+/* 0x44 */ x86emuOp2_illegal_op,
+/* 0x45 */ x86emuOp2_illegal_op,
+/* 0x46 */ x86emuOp2_illegal_op,
+/* 0x47 */ x86emuOp2_illegal_op,
+/* 0x48 */ x86emuOp2_illegal_op,
+/* 0x49 */ x86emuOp2_illegal_op,
+/* 0x4a */ x86emuOp2_illegal_op,
+/* 0x4b */ x86emuOp2_illegal_op,
+/* 0x4c */ x86emuOp2_illegal_op,
+/* 0x4d */ x86emuOp2_illegal_op,
+/* 0x4e */ x86emuOp2_illegal_op,
+/* 0x4f */ x86emuOp2_illegal_op,
+
+/* 0x50 */ x86emuOp2_illegal_op,
+/* 0x51 */ x86emuOp2_illegal_op,
+/* 0x52 */ x86emuOp2_illegal_op,
+/* 0x53 */ x86emuOp2_illegal_op,
+/* 0x54 */ x86emuOp2_illegal_op,
+/* 0x55 */ x86emuOp2_illegal_op,
+/* 0x56 */ x86emuOp2_illegal_op,
+/* 0x57 */ x86emuOp2_illegal_op,
+/* 0x58 */ x86emuOp2_illegal_op,
+/* 0x59 */ x86emuOp2_illegal_op,
+/* 0x5a */ x86emuOp2_illegal_op,
+/* 0x5b */ x86emuOp2_illegal_op,
+/* 0x5c */ x86emuOp2_illegal_op,
+/* 0x5d */ x86emuOp2_illegal_op,
+/* 0x5e */ x86emuOp2_illegal_op,
+/* 0x5f */ x86emuOp2_illegal_op,
+
+/* 0x60 */ x86emuOp2_illegal_op,
+/* 0x61 */ x86emuOp2_illegal_op,
+/* 0x62 */ x86emuOp2_illegal_op,
+/* 0x63 */ x86emuOp2_illegal_op,
+/* 0x64 */ x86emuOp2_illegal_op,
+/* 0x65 */ x86emuOp2_illegal_op,
+/* 0x66 */ x86emuOp2_illegal_op,
+/* 0x67 */ x86emuOp2_illegal_op,
+/* 0x68 */ x86emuOp2_illegal_op,
+/* 0x69 */ x86emuOp2_illegal_op,
+/* 0x6a */ x86emuOp2_illegal_op,
+/* 0x6b */ x86emuOp2_illegal_op,
+/* 0x6c */ x86emuOp2_illegal_op,
+/* 0x6d */ x86emuOp2_illegal_op,
+/* 0x6e */ x86emuOp2_illegal_op,
+/* 0x6f */ x86emuOp2_illegal_op,
+
+/* 0x70 */ x86emuOp2_illegal_op,
+/* 0x71 */ x86emuOp2_illegal_op,
+/* 0x72 */ x86emuOp2_illegal_op,
+/* 0x73 */ x86emuOp2_illegal_op,
+/* 0x74 */ x86emuOp2_illegal_op,
+/* 0x75 */ x86emuOp2_illegal_op,
+/* 0x76 */ x86emuOp2_illegal_op,
+/* 0x77 */ x86emuOp2_illegal_op,
+/* 0x78 */ x86emuOp2_illegal_op,
+/* 0x79 */ x86emuOp2_illegal_op,
+/* 0x7a */ x86emuOp2_illegal_op,
+/* 0x7b */ x86emuOp2_illegal_op,
+/* 0x7c */ x86emuOp2_illegal_op,
+/* 0x7d */ x86emuOp2_illegal_op,
+/* 0x7e */ x86emuOp2_illegal_op,
+/* 0x7f */ x86emuOp2_illegal_op,
+
+/* 0x80 */ x86emuOp2_long_jump,
+/* 0x81 */ x86emuOp2_long_jump,
+/* 0x82 */ x86emuOp2_long_jump,
+/* 0x83 */ x86emuOp2_long_jump,
+/* 0x84 */ x86emuOp2_long_jump,
+/* 0x85 */ x86emuOp2_long_jump,
+/* 0x86 */ x86emuOp2_long_jump,
+/* 0x87 */ x86emuOp2_long_jump,
+/* 0x88 */ x86emuOp2_long_jump,
+/* 0x89 */ x86emuOp2_long_jump,
+/* 0x8a */ x86emuOp2_long_jump,
+/* 0x8b */ x86emuOp2_long_jump,
+/* 0x8c */ x86emuOp2_long_jump,
+/* 0x8d */ x86emuOp2_long_jump,
+/* 0x8e */ x86emuOp2_long_jump,
+/* 0x8f */ x86emuOp2_long_jump,
+
+/* 0x90 */ x86emuOp2_set_byte,
+/* 0x91 */ x86emuOp2_set_byte,
+/* 0x92 */ x86emuOp2_set_byte,
+/* 0x93 */ x86emuOp2_set_byte,
+/* 0x94 */ x86emuOp2_set_byte,
+/* 0x95 */ x86emuOp2_set_byte,
+/* 0x96 */ x86emuOp2_set_byte,
+/* 0x97 */ x86emuOp2_set_byte,
+/* 0x98 */ x86emuOp2_set_byte,
+/* 0x99 */ x86emuOp2_set_byte,
+/* 0x9a */ x86emuOp2_set_byte,
+/* 0x9b */ x86emuOp2_set_byte,
+/* 0x9c */ x86emuOp2_set_byte,
+/* 0x9d */ x86emuOp2_set_byte,
+/* 0x9e */ x86emuOp2_set_byte,
+/* 0x9f */ x86emuOp2_set_byte,
+
+/* 0xa0 */ x86emuOp2_push_FS,
+/* 0xa1 */ x86emuOp2_pop_FS,
+/* 0xa2 */ x86emuOp2_illegal_op,
+/* 0xa3 */ x86emuOp2_bt_R,
+/* 0xa4 */ x86emuOp2_shld_IMM,
+/* 0xa5 */ x86emuOp2_shld_CL,
+/* 0xa6 */ x86emuOp2_illegal_op,
+/* 0xa7 */ x86emuOp2_illegal_op,
+/* 0xa8 */ x86emuOp2_push_GS,
+/* 0xa9 */ x86emuOp2_pop_GS,
+/* 0xaa */ x86emuOp2_illegal_op,
+/* 0xab */ x86emuOp2_bt_R,
+/* 0xac */ x86emuOp2_shrd_IMM,
+/* 0xad */ x86emuOp2_shrd_CL,
+/* 0xae */ x86emuOp2_illegal_op,
+/* 0xaf */ x86emuOp2_imul_R_RM,
+
+/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
+/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
+/* 0xb2 */ x86emuOp2_lss_R_IMM,
+/* 0xb3 */ x86emuOp2_btr_R,
+/* 0xb4 */ x86emuOp2_lfs_R_IMM,
+/* 0xb5 */ x86emuOp2_lgs_R_IMM,
+/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
+/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
+/* 0xb8 */ x86emuOp2_illegal_op,
+/* 0xb9 */ x86emuOp2_illegal_op,
+/* 0xba */ x86emuOp2_btX_I,
+/* 0xbb */ x86emuOp2_btc_R,
+/* 0xbc */ x86emuOp2_bsf,
+/* 0xbd */ x86emuOp2_bsr,
+/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
+/* 0xbf */ x86emuOp2_movsx_word_R_RM,
+
+/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
+/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
+/* 0xc2 */ x86emuOp2_illegal_op,
+/* 0xc3 */ x86emuOp2_illegal_op,
+/* 0xc4 */ x86emuOp2_illegal_op,
+/* 0xc5 */ x86emuOp2_illegal_op,
+/* 0xc6 */ x86emuOp2_illegal_op,
+/* 0xc7 */ x86emuOp2_illegal_op,
+/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */
+
+/* 0xd0 */ x86emuOp2_illegal_op,
+/* 0xd1 */ x86emuOp2_illegal_op,
+/* 0xd2 */ x86emuOp2_illegal_op,
+/* 0xd3 */ x86emuOp2_illegal_op,
+/* 0xd4 */ x86emuOp2_illegal_op,
+/* 0xd5 */ x86emuOp2_illegal_op,
+/* 0xd6 */ x86emuOp2_illegal_op,
+/* 0xd7 */ x86emuOp2_illegal_op,
+/* 0xd8 */ x86emuOp2_illegal_op,
+/* 0xd9 */ x86emuOp2_illegal_op,
+/* 0xda */ x86emuOp2_illegal_op,
+/* 0xdb */ x86emuOp2_illegal_op,
+/* 0xdc */ x86emuOp2_illegal_op,
+/* 0xdd */ x86emuOp2_illegal_op,
+/* 0xde */ x86emuOp2_illegal_op,
+/* 0xdf */ x86emuOp2_illegal_op,
+
+/* 0xe0 */ x86emuOp2_illegal_op,
+/* 0xe1 */ x86emuOp2_illegal_op,
+/* 0xe2 */ x86emuOp2_illegal_op,
+/* 0xe3 */ x86emuOp2_illegal_op,
+/* 0xe4 */ x86emuOp2_illegal_op,
+/* 0xe5 */ x86emuOp2_illegal_op,
+/* 0xe6 */ x86emuOp2_illegal_op,
+/* 0xe7 */ x86emuOp2_illegal_op,
+/* 0xe8 */ x86emuOp2_illegal_op,
+/* 0xe9 */ x86emuOp2_illegal_op,
+/* 0xea */ x86emuOp2_illegal_op,
+/* 0xeb */ x86emuOp2_illegal_op,
+/* 0xec */ x86emuOp2_illegal_op,
+/* 0xed */ x86emuOp2_illegal_op,
+/* 0xee */ x86emuOp2_illegal_op,
+/* 0xef */ x86emuOp2_illegal_op,
+
+/* 0xf0 */ x86emuOp2_illegal_op,
+/* 0xf1 */ x86emuOp2_illegal_op,
+/* 0xf2 */ x86emuOp2_illegal_op,
+/* 0xf3 */ x86emuOp2_illegal_op,
+/* 0xf4 */ x86emuOp2_illegal_op,
+/* 0xf5 */ x86emuOp2_illegal_op,
+/* 0xf6 */ x86emuOp2_illegal_op,
+/* 0xf7 */ x86emuOp2_illegal_op,
+/* 0xf8 */ x86emuOp2_illegal_op,
+/* 0xf9 */ x86emuOp2_illegal_op,
+/* 0xfa */ x86emuOp2_illegal_op,
+/* 0xfb */ x86emuOp2_illegal_op,
+/* 0xfc */ x86emuOp2_illegal_op,
+/* 0xfd */ x86emuOp2_illegal_op,
+/* 0xfe */ x86emuOp2_illegal_op,
+/* 0xff */ x86emuOp2_illegal_op,
+};
+
+#endif
diff --git a/drivers/bios_emulator/x86emu/prim_ops.c b/drivers/bios_emulator/x86emu/prim_ops.c
new file mode 100644
index 0000000000..2a254a4e67
--- /dev/null
+++ b/drivers/bios_emulator/x86emu/prim_ops.c
@@ -0,0 +1,2452 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file contains the code to implement the primitive
+* machine operations used by the emulation code in ops.c
+*
+* Carry Chain Calculation
+*
+* This represents a somewhat expensive calculation which is
+* apparently required to emulate the setting of the OF343364 and AF flag.
+* The latter is not so important, but the former is. The overflow
+* flag is the XOR of the top two bits of the carry chain for an
+* addition (similar for subtraction). Since we do not want to
+* simulate the addition in a bitwise manner, we try to calculate the
+* carry chain given the two operands and the result.
+*
+* So, given the following table, which represents the addition of two
+* bits, we can derive a formula for the carry chain.
+*
+* a b cin r cout
+* 0 0 0 0 0
+* 0 0 1 1 0
+* 0 1 0 1 0
+* 0 1 1 0 1
+* 1 0 0 1 0
+* 1 0 1 0 1
+* 1 1 0 0 1
+* 1 1 1 1 1
+*
+* Construction of table for cout:
+*
+* ab
+* r \ 00 01 11 10
+* |------------------
+* 0 | 0 1 1 1
+* 1 | 0 0 1 0
+*
+* By inspection, one gets: cc = ab + r'(a + b)
+*
+* That represents alot of operations, but NO CHOICE....
+*
+* Borrow Chain Calculation.
+*
+* The following table represents the subtraction of two bits, from
+* which we can derive a formula for the borrow chain.
+*
+* a b bin r bout
+* 0 0 0 0 0
+* 0 0 1 1 1
+* 0 1 0 1 1
+* 0 1 1 0 1
+* 1 0 0 1 0
+* 1 0 1 0 0
+* 1 1 0 0 0
+* 1 1 1 1 1
+*
+* Construction of table for cout:
+*
+* ab
+* r \ 00 01 11 10
+* |------------------
+* 0 | 0 1 0 0
+* 1 | 1 1 1 0
+*
+* By inspection, one gets: bc = a'b + r(a' + b)
+*
+****************************************************************************/
+
+#include <common.h>
+
+#define PRIM_OPS_NO_REDEFINE_ASM
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "x86emu/x86emui.h"
+
+/*------------------------- Global Variables ------------------------------*/
+
+static u32 x86emu_parity_tab[8] =
+{
+ 0x96696996,
+ 0x69969669,
+ 0x69969669,
+ 0x96696996,
+ 0x69969669,
+ 0x96696996,
+ 0x96696996,
+ 0x69969669,
+};
+
+#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
+#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
+/*----------------------------- Implementation ----------------------------*/
+int abs(int v)
+{
+ return (v>0)?v:-v;
+}
+
+/*----------------------------- Implementation ----------------------------*/
+
+
+/*--------- Side effects helper functions -------*/
+
+/****************************************************************************
+REMARKS:
+implements side efects for byte operations that don't overflow
+****************************************************************************/
+
+static void set_parity_flag(u32 res)
+{
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
+}
+
+static void set_szp_flags_8(u8 res)
+{
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ set_parity_flag(res);
+}
+
+static void set_szp_flags_16(u16 res)
+{
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ set_parity_flag(res);
+}
+
+static void set_szp_flags_32(u32 res)
+{
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ set_parity_flag(res);
+}
+
+static void no_carry_byte_side_eff(u8 res)
+{
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ set_szp_flags_8(res);
+}
+
+static void no_carry_word_side_eff(u16 res)
+{
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ set_szp_flags_16(res);
+}
+
+static void no_carry_long_side_eff(u32 res)
+{
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ set_szp_flags_32(res);
+}
+
+static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
+{
+ u32 cc;
+
+ cc = (s & d) | ((~res) & (s | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ if (set_carry) {
+ CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
+ }
+}
+
+static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
+{
+ u32 bc;
+
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ if (set_carry) {
+ CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAA instruction and side effects.
+****************************************************************************/
+u16 aaa_word(u16 d)
+{
+ u16 res;
+ if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
+ d += 0x6;
+ d += 0x100;
+ SET_FLAG(F_AF);
+ SET_FLAG(F_CF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ }
+ res = (u16)(d & 0xFF0F);
+ set_szp_flags_16(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAA instruction and side effects.
+****************************************************************************/
+u16 aas_word(u16 d)
+{
+ u16 res;
+ if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
+ d -= 0x6;
+ d -= 0x100;
+ SET_FLAG(F_AF);
+ SET_FLAG(F_CF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ }
+ res = (u16)(d & 0xFF0F);
+ set_szp_flags_16(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAD instruction and side effects.
+****************************************************************************/
+u16 aad_word(u16 d)
+{
+ u16 l;
+ u8 hb, lb;
+
+ hb = (u8)((d >> 8) & 0xff);
+ lb = (u8)((d & 0xff));
+ l = (u16)((lb + 10 * hb) & 0xFF);
+
+ no_carry_byte_side_eff(l & 0xFF);
+ return l;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAM instruction and side effects.
+****************************************************************************/
+u16 aam_word(u8 d)
+{
+ u16 h, l;
+
+ h = (u16)(d / 10);
+ l = (u16)(d % 10);
+ l |= (u16)(h << 8);
+
+ no_carry_byte_side_eff(l & 0xFF);
+ return l;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u8 adc_byte(u8 d, u8 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d + s;
+ if (ACCESS_FLAG(F_CF)) res++;
+
+ set_szp_flags_8(res);
+ calc_carry_chain(8,s,d,res,1);
+
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u16 adc_word(u16 d, u16 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d + s;
+ if (ACCESS_FLAG(F_CF))
+ res++;
+
+ set_szp_flags_16((u16)res);
+ calc_carry_chain(16,s,d,res,1);
+
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u32 adc_long(u32 d, u32 s)
+{
+ u32 lo; /* all operands in native machine order */
+ u32 hi;
+ u32 res;
+
+ lo = (d & 0xFFFF) + (s & 0xFFFF);
+ res = d + s;
+
+ if (ACCESS_FLAG(F_CF)) {
+ lo++;
+ res++;
+ }
+
+ hi = (lo >> 16) + (d >> 16) + (s >> 16);
+
+ set_szp_flags_32(res);
+ calc_carry_chain(32,s,d,res,0);
+
+ CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u8 add_byte(u8 d, u8 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d + s;
+ set_szp_flags_8((u8)res);
+ calc_carry_chain(8,s,d,res,1);
+
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u16 add_word(u16 d, u16 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d + s;
+ set_szp_flags_16((u16)res);
+ calc_carry_chain(16,s,d,res,1);
+
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u32 add_long(u32 d, u32 s)
+{
+ u32 res;
+
+ res = d + s;
+ set_szp_flags_32(res);
+ calc_carry_chain(32,s,d,res,0);
+
+ CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u8 and_byte(u8 d, u8 s)
+{
+ u8 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ no_carry_byte_side_eff(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u16 and_word(u16 d, u16 s)
+{
+ u16 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ no_carry_word_side_eff(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u32 and_long(u32 d, u32 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d & s;
+ no_carry_long_side_eff(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u8 cmp_byte(u8 d, u8 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d - s;
+ set_szp_flags_8((u8)res);
+ calc_borrow_chain(8, d, s, res, 1);
+
+ return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u16 cmp_word(u16 d, u16 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d - s;
+ set_szp_flags_16((u16)res);
+ calc_borrow_chain(16, d, s, res, 1);
+
+ return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u32 cmp_long(u32 d, u32 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d - s;
+ set_szp_flags_32(res);
+ calc_borrow_chain(32, d, s, res, 1);
+
+ return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DAA instruction and side effects.
+****************************************************************************/
+u8 daa_byte(u8 d)
+{
+ u32 res = d;
+ if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
+ res += 6;
+ SET_FLAG(F_AF);
+ }
+ if (res > 0x9F || ACCESS_FLAG(F_CF)) {
+ res += 0x60;
+ SET_FLAG(F_CF);
+ }
+ set_szp_flags_8((u8)res);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DAS instruction and side effects.
+****************************************************************************/
+u8 das_byte(u8 d)
+{
+ if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
+ d -= 6;
+ SET_FLAG(F_AF);
+ }
+ if (d > 0x9F || ACCESS_FLAG(F_CF)) {
+ d -= 0x60;
+ SET_FLAG(F_CF);
+ }
+ set_szp_flags_8(d);
+ return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u8 dec_byte(u8 d)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d - 1;
+ set_szp_flags_8((u8)res);
+ calc_borrow_chain(8, d, 1, res, 0);
+
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u16 dec_word(u16 d)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d - 1;
+ set_szp_flags_16((u16)res);
+ calc_borrow_chain(16, d, 1, res, 0);
+
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u32 dec_long(u32 d)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d - 1;
+
+ set_szp_flags_32(res);
+ calc_borrow_chain(32, d, 1, res, 0);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u8 inc_byte(u8 d)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d + 1;
+ set_szp_flags_8((u8)res);
+ calc_carry_chain(8, d, 1, res, 0);
+
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u16 inc_word(u16 d)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d + 1;
+ set_szp_flags_16((u16)res);
+ calc_carry_chain(16, d, 1, res, 0);
+
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u32 inc_long(u32 d)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d + 1;
+ set_szp_flags_32(res);
+ calc_carry_chain(32, d, 1, res, 0);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u8 or_byte(u8 d, u8 s)
+{
+ u8 res; /* all operands in native machine order */
+
+ res = d | s;
+ no_carry_byte_side_eff(res);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u16 or_word(u16 d, u16 s)
+{
+ u16 res; /* all operands in native machine order */
+
+ res = d | s;
+ no_carry_word_side_eff(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u32 or_long(u32 d, u32 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d | s;
+ no_carry_long_side_eff(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u8 neg_byte(u8 s)
+{
+ u8 res;
+
+ CONDITIONAL_SET_FLAG(s != 0, F_CF);
+ res = (u8)-s;
+ set_szp_flags_8(res);
+ calc_borrow_chain(8, 0, s, res, 0);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u16 neg_word(u16 s)
+{
+ u16 res;
+
+ CONDITIONAL_SET_FLAG(s != 0, F_CF);
+ res = (u16)-s;
+ set_szp_flags_16((u16)res);
+ calc_borrow_chain(16, 0, s, res, 0);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u32 neg_long(u32 s)
+{
+ u32 res;
+
+ CONDITIONAL_SET_FLAG(s != 0, F_CF);
+ res = (u32)-s;
+ set_szp_flags_32(res);
+ calc_borrow_chain(32, 0, s, res, 0);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u8 not_byte(u8 s)
+{
+ return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u16 not_word(u16 s)
+{
+ return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u32 not_long(u32 s)
+{
+ return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u8 rcl_byte(u8 d, u8 s)
+{
+ unsigned int res, cnt, mask, cf;
+
+ /* s is the rotate distance. It varies from 0 - 8. */
+ /* have
+
+ CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
+
+ want to rotate through the carry by "s" bits. We could
+ loop, but that's inefficient. So the width is 9,
+ and we split into three parts:
+
+ The new carry flag (was B_n)
+ the stuff in B_n-1 .. B_0
+ the stuff in B_7 .. B_n+1
+
+ The new rotate is done mod 9, and given this,
+ for a rotation of n bits (mod 9) the new carry flag is
+ then located n bits from the MSB. The low part is
+ then shifted up cnt bits, and the high part is or'd
+ in. Using CAPS for new values, and lowercase for the
+ original values, this can be expressed as:
+
+ IF n > 0
+ 1) CF <- b_(8-n)
+ 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
+ 3) B_(n-1) <- cf
+ 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
+ */
+ res = d;
+ if ((cnt = s % 9) != 0) {
+ /* extract the new CARRY FLAG. */
+ /* CF <- b_(8-n) */
+ cf = (d >> (8 - cnt)) & 0x1;
+
+ /* get the low stuff which rotated
+ into the range B_7 .. B_cnt */
+ /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
+ /* note that the right hand side done by the mask */
+ res = (d << cnt) & 0xff;
+
+ /* now the high stuff which rotated around
+ into the positions B_cnt-2 .. B_0 */
+ /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
+ /* shift it downward, 7-(n-2) = 9-n positions.
+ and mask off the result before or'ing in.
+ */
+ mask = (1 << (cnt - 1)) - 1;
+ res |= (d >> (9 - cnt)) & mask;
+
+ /* if the carry flag was set, or it in. */
+ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
+ /* B_(n-1) <- cf */
+ res |= 1 << (cnt - 1);
+ }
+ /* set the new carry flag, based on the variable "cf" */
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ /* OVERFLOW is set *IFF* cnt==1, then it is the
+ xor of CF and the most significant bit. Blecck. */
+ /* parenthesized this expression since it appears to
+ be causing OF to be misset */
+ CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
+ F_OF);
+
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u16 rcl_word(u16 d, u8 s)
+{
+ unsigned int res, cnt, mask, cf;
+
+ res = d;
+ if ((cnt = s % 17) != 0) {
+ cf = (d >> (16 - cnt)) & 0x1;
+ res = (d << cnt) & 0xffff;
+ mask = (1 << (cnt - 1)) - 1;
+ res |= (d >> (17 - cnt)) & mask;
+ if (ACCESS_FLAG(F_CF)) {
+ res |= 1 << (cnt - 1);
+ }
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
+ F_OF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u32 rcl_long(u32 d, u8 s)
+{
+ u32 res, cnt, mask, cf;
+
+ res = d;
+ if ((cnt = s % 33) != 0) {
+ cf = (d >> (32 - cnt)) & 0x1;
+ res = (d << cnt) & 0xffffffff;
+ mask = (1 << (cnt - 1)) - 1;
+ res |= (d >> (33 - cnt)) & mask;
+ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
+ res |= 1 << (cnt - 1);
+ }
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
+ F_OF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u8 rcr_byte(u8 d, u8 s)
+{
+ u32 res, cnt;
+ u32 mask, cf, ocf = 0;
+
+ /* rotate right through carry */
+ /*
+ s is the rotate distance. It varies from 0 - 8.
+ d is the byte object rotated.
+
+ have
+
+ CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
+
+ The new rotate is done mod 9, and given this,
+ for a rotation of n bits (mod 9) the new carry flag is
+ then located n bits from the LSB. The low part is
+ then shifted up cnt bits, and the high part is or'd
+ in. Using CAPS for new values, and lowercase for the
+ original values, this can be expressed as:
+
+ IF n > 0
+ 1) CF <- b_(n-1)
+ 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
+ 3) B_(8-n) <- cf
+ 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
+ */
+ res = d;
+ if ((cnt = s % 9) != 0) {
+ /* extract the new CARRY FLAG. */
+ /* CF <- b_(n-1) */
+ if (cnt == 1) {
+ cf = d & 0x1;
+ /* note hackery here. Access_flag(..) evaluates to either
+ 0 if flag not set
+ non-zero if flag is set.
+ doing access_flag(..) != 0 casts that into either
+ 0..1 in any representation of the flags register
+ (i.e. packed bit array or unpacked.)
+ */
+ ocf = ACCESS_FLAG(F_CF) != 0;
+ } else
+ cf = (d >> (cnt - 1)) & 0x1;
+
+ /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
+ /* note that the right hand side done by the mask
+ This is effectively done by shifting the
+ object to the right. The result must be masked,
+ in case the object came in and was treated
+ as a negative number. Needed??? */
+
+ mask = (1 << (8 - cnt)) - 1;
+ res = (d >> cnt) & mask;
+
+ /* now the high stuff which rotated around
+ into the positions B_cnt-2 .. B_0 */
+ /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
+ /* shift it downward, 7-(n-2) = 9-n positions.
+ and mask off the result before or'ing in.
+ */
+ res |= (d << (9 - cnt));
+
+ /* if the carry flag was set, or it in. */
+ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
+ /* B_(8-n) <- cf */
+ res |= 1 << (8 - cnt);
+ }
+ /* set the new carry flag, based on the variable "cf" */
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ /* OVERFLOW is set *IFF* cnt==1, then it is the
+ xor of CF and the most significant bit. Blecck. */
+ /* parenthesized... */
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
+ F_OF);
+ }
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u16 rcr_word(u16 d, u8 s)
+{
+ u32 res, cnt;
+ u32 mask, cf, ocf = 0;
+
+ /* rotate right through carry */
+ res = d;
+ if ((cnt = s % 17) != 0) {
+ if (cnt == 1) {
+ cf = d & 0x1;
+ ocf = ACCESS_FLAG(F_CF) != 0;
+ } else
+ cf = (d >> (cnt - 1)) & 0x1;
+ mask = (1 << (16 - cnt)) - 1;
+ res = (d >> cnt) & mask;
+ res |= (d << (17 - cnt));
+ if (ACCESS_FLAG(F_CF)) {
+ res |= 1 << (16 - cnt);
+ }
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
+ F_OF);
+ }
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u32 rcr_long(u32 d, u8 s)
+{
+ u32 res, cnt;
+ u32 mask, cf, ocf = 0;
+
+ /* rotate right through carry */
+ res = d;
+ if ((cnt = s % 33) != 0) {
+ if (cnt == 1) {
+ cf = d & 0x1;
+ ocf = ACCESS_FLAG(F_CF) != 0;
+ } else
+ cf = (d >> (cnt - 1)) & 0x1;
+ mask = (1 << (32 - cnt)) - 1;
+ res = (d >> cnt) & mask;
+ if (cnt != 1)
+ res |= (d << (33 - cnt));
+ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
+ res |= 1 << (32 - cnt);
+ }
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
+ F_OF);
+ }
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u8 rol_byte(u8 d, u8 s)
+{
+ unsigned int res, cnt, mask;
+
+ /* rotate left */
+ /*
+ s is the rotate distance. It varies from 0 - 8.
+ d is the byte object rotated.
+
+ have
+
+ CF B_7 ... B_0
+
+ The new rotate is done mod 8.
+ Much simpler than the "rcl" or "rcr" operations.
+
+ IF n > 0
+ 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
+ 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
+ */
+ res = d;
+ if ((cnt = s % 8) != 0) {
+ /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
+ res = (d << cnt);
+
+ /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
+ mask = (1 << cnt) - 1;
+ res |= (d >> (8 - cnt)) & mask;
+
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ /* OVERFLOW is set *IFF* s==1, then it is the
+ xor of CF and the most significant bit. Blecck. */
+ CONDITIONAL_SET_FLAG(s == 1 &&
+ XOR2((res & 0x1) + ((res >> 6) & 0x2)),
+ F_OF);
+ } if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u16 rol_word(u16 d, u8 s)
+{
+ unsigned int res, cnt, mask;
+
+ res = d;
+ if ((cnt = s % 16) != 0) {
+ res = (d << cnt);
+ mask = (1 << cnt) - 1;
+ res |= (d >> (16 - cnt)) & mask;
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ CONDITIONAL_SET_FLAG(s == 1 &&
+ XOR2((res & 0x1) + ((res >> 14) & 0x2)),
+ F_OF);
+ } if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u32 rol_long(u32 d, u8 s)
+{
+ u32 res, cnt, mask;
+
+ res = d;
+ if ((cnt = s % 32) != 0) {
+ res = (d << cnt);
+ mask = (1 << cnt) - 1;
+ res |= (d >> (32 - cnt)) & mask;
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ CONDITIONAL_SET_FLAG(s == 1 &&
+ XOR2((res & 0x1) + ((res >> 30) & 0x2)),
+ F_OF);
+ } if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u8 ror_byte(u8 d, u8 s)
+{
+ unsigned int res, cnt, mask;
+
+ /* rotate right */
+ /*
+ s is the rotate distance. It varies from 0 - 8.
+ d is the byte object rotated.
+
+ have
+
+ B_7 ... B_0
+
+ The rotate is done mod 8.
+
+ IF n > 0
+ 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
+ 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
+ */
+ res = d;
+ if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
+ /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
+ res = (d << (8 - cnt));
+
+ /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
+ mask = (1 << (8 - cnt)) - 1;
+ res |= (d >> (cnt)) & mask;
+
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
+ /* OVERFLOW is set *IFF* s==1, then it is the
+ xor of the two most significant bits. Blecck. */
+ CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
+ } else if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u16 ror_word(u16 d, u8 s)
+{
+ unsigned int res, cnt, mask;
+
+ res = d;
+ if ((cnt = s % 16) != 0) {
+ res = (d << (16 - cnt));
+ mask = (1 << (16 - cnt)) - 1;
+ res |= (d >> (cnt)) & mask;
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
+ CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
+ } else if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u32 ror_long(u32 d, u8 s)
+{
+ u32 res, cnt, mask;
+
+ res = d;
+ if ((cnt = s % 32) != 0) {
+ res = (d << (32 - cnt));
+ mask = (1 << (32 - cnt)) - 1;
+ res |= (d >> (cnt)) & mask;
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
+ CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
+ } else if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u8 shl_byte(u8 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 8) {
+ cnt = s % 8;
+
+ /* last bit shifted out goes into carry flag */
+ if (cnt > 0) {
+ res = d << cnt;
+ cf = d & (1 << (8 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_8((u8)res);
+ } else {
+ res = (u8) d;
+ }
+
+ if (cnt == 1) {
+ /* Needs simplification. */
+ CONDITIONAL_SET_FLAG(
+ (((res & 0x80) == 0x80) ^
+ (ACCESS_FLAG(F_CF) != 0)),
+ /* was (M.x86.R_FLG&F_CF)==F_CF)), */
+ F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u16 shl_word(u16 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 16) {
+ cnt = s % 16;
+ if (cnt > 0) {
+ res = d << cnt;
+ cf = d & (1 << (16 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_16((u16)res);
+ } else {
+ res = (u16) d;
+ }
+
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(
+ (((res & 0x8000) == 0x8000) ^
+ (ACCESS_FLAG(F_CF) != 0)),
+ F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u32 shl_long(u32 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 32) {
+ cnt = s % 32;
+ if (cnt > 0) {
+ res = d << cnt;
+ cf = d & (1 << (32 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_32((u32)res);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
+ (ACCESS_FLAG(F_CF) != 0)), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u8 shr_byte(u8 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 8) {
+ cnt = s % 8;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = d >> cnt;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_8((u8)res);
+ } else {
+ res = (u8) d;
+ }
+
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u16 shr_word(u16 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 16) {
+ cnt = s % 16;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = d >> cnt;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_16((u16)res);
+ } else {
+ res = d;
+ }
+
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u32 shr_long(u32 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 32) {
+ cnt = s % 32;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = d >> cnt;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_32((u32)res);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u8 sar_byte(u8 d, u8 s)
+{
+ unsigned int cnt, res, cf, mask, sf;
+
+ res = d;
+ sf = d & 0x80;
+ cnt = s % 8;
+ if (cnt > 0 && cnt < 8) {
+ mask = (1 << (8 - cnt)) - 1;
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) & mask;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (sf) {
+ res |= ~mask;
+ }
+ set_szp_flags_8((u8)res);
+ } else if (cnt >= 8) {
+ if (sf) {
+ res = 0xff;
+ SET_FLAG(F_CF);
+ CLEAR_FLAG(F_ZF);
+ SET_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u16 sar_word(u16 d, u8 s)
+{
+ unsigned int cnt, res, cf, mask, sf;
+
+ sf = d & 0x8000;
+ cnt = s % 16;
+ res = d;
+ if (cnt > 0 && cnt < 16) {
+ mask = (1 << (16 - cnt)) - 1;
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) & mask;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (sf) {
+ res |= ~mask;
+ }
+ set_szp_flags_16((u16)res);
+ } else if (cnt >= 16) {
+ if (sf) {
+ res = 0xffff;
+ SET_FLAG(F_CF);
+ CLEAR_FLAG(F_ZF);
+ SET_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u32 sar_long(u32 d, u8 s)
+{
+ u32 cnt, res, cf, mask, sf;
+
+ sf = d & 0x80000000;
+ cnt = s % 32;
+ res = d;
+ if (cnt > 0 && cnt < 32) {
+ mask = (1 << (32 - cnt)) - 1;
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) & mask;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (sf) {
+ res |= ~mask;
+ }
+ set_szp_flags_32(res);
+ } else if (cnt >= 32) {
+ if (sf) {
+ res = 0xffffffff;
+ SET_FLAG(F_CF);
+ CLEAR_FLAG(F_ZF);
+ SET_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHLD instruction and side effects.
+****************************************************************************/
+u16 shld_word (u16 d, u16 fill, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 16) {
+ cnt = s % 16;
+ if (cnt > 0) {
+ res = (d << cnt) | (fill >> (16-cnt));
+ cf = d & (1 << (16 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_16((u16)res);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
+ (ACCESS_FLAG(F_CF) != 0)), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHLD instruction and side effects.
+****************************************************************************/
+u32 shld_long (u32 d, u32 fill, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 32) {
+ cnt = s % 32;
+ if (cnt > 0) {
+ res = (d << cnt) | (fill >> (32-cnt));
+ cf = d & (1 << (32 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_32((u32)res);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
+ (ACCESS_FLAG(F_CF) != 0)), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHRD instruction and side effects.
+****************************************************************************/
+u16 shrd_word (u16 d, u16 fill, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 16) {
+ cnt = s % 16;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) | (fill << (16 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_16((u16)res);
+ } else {
+ res = d;
+ }
+
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHRD instruction and side effects.
+****************************************************************************/
+u32 shrd_long (u32 d, u32 fill, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 32) {
+ cnt = s % 32;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) | (fill << (32 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ set_szp_flags_32((u32)res);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u8 sbb_byte(u8 d, u8 s)
+{
+ u32 res; /* all operands in native machine order */
+ u32 bc;
+
+ if (ACCESS_FLAG(F_CF))
+ res = d - s - 1;
+ else
+ res = d - s;
+ set_szp_flags_8((u8)res);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u16 sbb_word(u16 d, u16 s)
+{
+ u32 res; /* all operands in native machine order */
+ u32 bc;
+
+ if (ACCESS_FLAG(F_CF))
+ res = d - s - 1;
+ else
+ res = d - s;
+ set_szp_flags_16((u16)res);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u32 sbb_long(u32 d, u32 s)
+{
+ u32 res; /* all operands in native machine order */
+ u32 bc;
+
+ if (ACCESS_FLAG(F_CF))
+ res = d - s - 1;
+ else
+ res = d - s;
+
+ set_szp_flags_32(res);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u8 sub_byte(u8 d, u8 s)
+{
+ u32 res; /* all operands in native machine order */
+ u32 bc;
+
+ res = d - s;
+ set_szp_flags_8((u8)res);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u16 sub_word(u16 d, u16 s)
+{
+ u32 res; /* all operands in native machine order */
+ u32 bc;
+
+ res = d - s;
+ set_szp_flags_16((u16)res);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u32 sub_long(u32 d, u32 s)
+{
+ u32 res; /* all operands in native machine order */
+ u32 bc;
+
+ res = d - s;
+ set_szp_flags_32(res);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_byte(u8 d, u8 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ CLEAR_FLAG(F_OF);
+ set_szp_flags_8((u8)res);
+ /* AF == dont care */
+ CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_word(u16 d, u16 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ CLEAR_FLAG(F_OF);
+ set_szp_flags_16((u16)res);
+ /* AF == dont care */
+ CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_long(u32 d, u32 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ CLEAR_FLAG(F_OF);
+ set_szp_flags_32(res);
+ /* AF == dont care */
+ CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u8 xor_byte(u8 d, u8 s)
+{
+ u8 res; /* all operands in native machine order */
+
+ res = d ^ s;
+ no_carry_byte_side_eff(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u16 xor_word(u16 d, u16 s)
+{
+ u16 res; /* all operands in native machine order */
+
+ res = d ^ s;
+ no_carry_word_side_eff(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u32 xor_long(u32 d, u32 s)
+{
+ u32 res; /* all operands in native machine order */
+
+ res = d ^ s;
+ no_carry_long_side_eff(res);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_byte(u8 s)
+{
+ s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
+
+ M.x86.R_AX = res;
+ if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
+ ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_word(u16 s)
+{
+ s32 res = (s16)M.x86.R_AX * (s16)s;
+
+ M.x86.R_AX = (u16)res;
+ M.x86.R_DX = (u16)(res >> 16);
+ if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
+ ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+ s64 res = (s32)d * (s32)s;
+
+ *res_lo = (u32)res;
+ *res_hi = (u32)(res >> 32);
+#else
+ u32 d_lo,d_hi,d_sign;
+ u32 s_lo,s_hi,s_sign;
+ u32 rlo_lo,rlo_hi,rhi_lo;
+
+ if ((d_sign = d & 0x80000000) != 0)
+ d = -d;
+ d_lo = d & 0xFFFF;
+ d_hi = d >> 16;
+ if ((s_sign = s & 0x80000000) != 0)
+ s = -s;
+ s_lo = s & 0xFFFF;
+ s_hi = s >> 16;
+ rlo_lo = d_lo * s_lo;
+ rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
+ rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
+ *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
+ *res_hi = rhi_lo;
+ if (d_sign != s_sign) {
+ d = ~*res_lo;
+ s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
+ *res_lo = ~*res_lo+1;
+ *res_hi = ~*res_hi+(s >> 16);
+ }
+#endif
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_long(u32 s)
+{
+ imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
+ if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
+ ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_byte(u8 s)
+{
+ u16 res = (u16)(M.x86.R_AL * s);
+
+ M.x86.R_AX = res;
+ if (M.x86.R_AH == 0) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_word(u16 s)
+{
+ u32 res = M.x86.R_AX * s;
+
+ M.x86.R_AX = (u16)res;
+ M.x86.R_DX = (u16)(res >> 16);
+ if (M.x86.R_DX == 0) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+ u64 res = (u32)M.x86.R_EAX * (u32)s;
+
+ M.x86.R_EAX = (u32)res;
+ M.x86.R_EDX = (u32)(res >> 32);
+#else
+ u32 a,a_lo,a_hi;
+ u32 s_lo,s_hi;
+ u32 rlo_lo,rlo_hi,rhi_lo;
+
+ a = M.x86.R_EAX;
+ a_lo = a & 0xFFFF;
+ a_hi = a >> 16;
+ s_lo = s & 0xFFFF;
+ s_hi = s >> 16;
+ rlo_lo = a_lo * s_lo;
+ rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
+ rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
+ M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
+ M.x86.R_EDX = rhi_lo;
+#endif
+ if (M.x86.R_EDX == 0) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void idiv_byte(u8 s)
+{
+ s32 dvd, div, mod;
+
+ dvd = (s16)M.x86.R_AX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (s8)s;
+ mod = dvd % (s8)s;
+ if (abs(div) > 0x7f) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ M.x86.R_AL = (s8) div;
+ M.x86.R_AH = (s8) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void idiv_word(u16 s)
+{
+ s32 dvd, div, mod;
+
+ dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (s16)s;
+ mod = dvd % (s16)s;
+ if (abs(div) > 0x7fff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_SF);
+ CONDITIONAL_SET_FLAG(div == 0, F_ZF);
+ set_parity_flag(mod);
+
+ M.x86.R_AX = (u16)div;
+ M.x86.R_DX = (u16)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void idiv_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+ s64 dvd, div, mod;
+
+ dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (s32)s;
+ mod = dvd % (s32)s;
+ if (abs(div) > 0x7fffffff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+#else
+ s32 div = 0, mod;
+ s32 h_dvd = M.x86.R_EDX;
+ u32 l_dvd = M.x86.R_EAX;
+ u32 abs_s = s & 0x7FFFFFFF;
+ u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
+ u32 h_s = abs_s >> 1;
+ u32 l_s = abs_s << 31;
+ int counter = 31;
+ int carry;
+
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ do {
+ div <<= 1;
+ carry = (l_dvd >= l_s) ? 0 : 1;
+
+ if (abs_h_dvd < (h_s + carry)) {
+ h_s >>= 1;
+ l_s = abs_s << (--counter);
+ continue;
+ } else {
+ abs_h_dvd -= (h_s + carry);
+ l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
+ : (l_dvd - l_s);
+ h_s >>= 1;
+ l_s = abs_s << (--counter);
+ div |= 1;
+ continue;
+ }
+
+ } while (counter > -1);
+ /* overflow */
+ if (abs_h_dvd || (l_dvd > abs_s)) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ /* sign */
+ div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
+ mod = l_dvd;
+
+#endif
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_ZF);
+ set_parity_flag(mod);
+
+ M.x86.R_EAX = (u32)div;
+ M.x86.R_EDX = (u32)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_byte(u8 s)
+{
+ u32 dvd, div, mod;
+
+ dvd = M.x86.R_AX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (u8)s;
+ mod = dvd % (u8)s;
+ if (abs(div) > 0xff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ M.x86.R_AL = (u8)div;
+ M.x86.R_AH = (u8)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_word(u16 s)
+{
+ u32 dvd, div, mod;
+
+ dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (u16)s;
+ mod = dvd % (u16)s;
+ if (abs(div) > 0xffff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_SF);
+ CONDITIONAL_SET_FLAG(div == 0, F_ZF);
+ set_parity_flag(mod);
+
+ M.x86.R_AX = (u16)div;
+ M.x86.R_DX = (u16)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+ u64 dvd, div, mod;
+
+ dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (u32)s;
+ mod = dvd % (u32)s;
+ if (abs(div) > 0xffffffff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+#else
+ s32 div = 0, mod;
+ s32 h_dvd = M.x86.R_EDX;
+ u32 l_dvd = M.x86.R_EAX;
+
+ u32 h_s = s;
+ u32 l_s = 0;
+ int counter = 32;
+ int carry;
+
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ do {
+ div <<= 1;
+ carry = (l_dvd >= l_s) ? 0 : 1;
+
+ if (h_dvd < (h_s + carry)) {
+ h_s >>= 1;
+ l_s = s << (--counter);
+ continue;
+ } else {
+ h_dvd -= (h_s + carry);
+ l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
+ : (l_dvd - l_s);
+ h_s >>= 1;
+ l_s = s << (--counter);
+ div |= 1;
+ continue;
+ }
+
+ } while (counter > -1);
+ /* overflow */
+ if (h_dvd || (l_dvd > s)) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ mod = l_dvd;
+#endif
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_ZF);
+ set_parity_flag(mod);
+
+ M.x86.R_EAX = (u32)div;
+ M.x86.R_EDX = (u32)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IN string instruction and side effects.
+****************************************************************************/
+
+static void single_in(int size)
+{
+ if(size == 1)
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
+ else if (size == 2)
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
+ else
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
+}
+
+void ins(int size)
+{
+ int inc = size;
+
+ if (ACCESS_FLAG(F_DF)) {
+ inc = -size;
+ }
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* in until CX is ZERO. */
+ u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
+ M.x86.R_ECX : M.x86.R_CX);
+
+ while (count--) {
+ single_in(size);
+ M.x86.R_DI += inc;
+ }
+ M.x86.R_CX = 0;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = 0;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ single_in(size);
+ M.x86.R_DI += inc;
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OUT string instruction and side effects.
+****************************************************************************/
+
+static void single_out(int size)
+{
+ if(size == 1)
+ (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
+ else if (size == 2)
+ (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
+ else
+ (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
+}
+
+void outs(int size)
+{
+ int inc = size;
+
+ if (ACCESS_FLAG(F_DF)) {
+ inc = -size;
+ }
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* out until CX is ZERO. */
+ u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
+ M.x86.R_ECX : M.x86.R_CX);
+ while (count--) {
+ single_out(size);
+ M.x86.R_SI += inc;
+ }
+ M.x86.R_CX = 0;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = 0;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ single_out(size);
+ M.x86.R_SI += inc;
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Address to fetch word from
+
+REMARKS:
+Fetches a word from emulator memory using an absolute address.
+****************************************************************************/
+u16 mem_access_word(int addr)
+{
+DB( if (CHECK_MEM_ACCESS())
+ x86emu_check_mem_access(addr);)
+ return (*sys_rdw)(addr);
+}
+
+/****************************************************************************
+REMARKS:
+Pushes a word onto the stack.
+
+NOTE: Do not inline this, as (*sys_wrX) is already inline!
+****************************************************************************/
+void push_word(u16 w)
+{
+DB( if (CHECK_SP_ACCESS())
+ x86emu_check_sp_access();)
+ M.x86.R_SP -= 2;
+ (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
+}
+
+/****************************************************************************
+REMARKS:
+Pushes a long onto the stack.
+
+NOTE: Do not inline this, as (*sys_wrX) is already inline!
+****************************************************************************/
+void push_long(u32 w)
+{
+DB( if (CHECK_SP_ACCESS())
+ x86emu_check_sp_access();)
+ M.x86.R_SP -= 4;
+ (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
+}
+
+/****************************************************************************
+REMARKS:
+Pops a word from the stack.
+
+NOTE: Do not inline this, as (*sys_rdX) is already inline!
+****************************************************************************/
+u16 pop_word(void)
+{
+ u16 res;
+
+DB( if (CHECK_SP_ACCESS())
+ x86emu_check_sp_access();)
+ res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
+ M.x86.R_SP += 2;
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Pops a long from the stack.
+
+NOTE: Do not inline this, as (*sys_rdX) is already inline!
+****************************************************************************/
+u32 pop_long(void)
+{
+ u32 res;
+
+DB( if (CHECK_SP_ACCESS())
+ x86emu_check_sp_access();)
+ res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
+ M.x86.R_SP += 4;
+ return res;
+}
+
+#endif
diff --git a/drivers/bios_emulator/x86emu/sys.c b/drivers/bios_emulator/x86emu/sys.c
new file mode 100644
index 0000000000..dd44ff1e73
--- /dev/null
+++ b/drivers/bios_emulator/x86emu/sys.c
@@ -0,0 +1,328 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines which are related to
+* programmed I/O and memory access. Included in this module
+* are default functions that do nothing. For real uses these
+* functions will have to be overriden by the user library.
+*
+****************************************************************************/
+
+#include <common.h>
+
+#if defined(CONFIG_BIOSEMU)
+
+#include "x86emu/x86emui.h"
+
+/*------------------------- Global Variables ------------------------------*/
+
+X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
+X86EMU_intrFuncs _X86EMU_intrTab[256];
+
+int debug_intr;
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Byte value read from emulator memory.
+
+REMARKS:
+Reads a byte value from the emulator memory.
+****************************************************************************/
+u8 X86API rdb(u32 addr)
+{
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Word value read from emulator memory.
+
+REMARKS:
+Reads a word value from the emulator memory.
+****************************************************************************/
+u16 X86API rdw(u32 addr)
+{
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Long value read from emulator memory.
+REMARKS:
+Reads a long value from the emulator memory.
+****************************************************************************/
+u32 X86API rdl(u32 addr)
+{
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a byte value to emulator memory.
+****************************************************************************/
+void X86API wrb(u32 addr, u8 val)
+{
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a word value to emulator memory.
+****************************************************************************/
+void X86API wrw(u32 addr, u16 val)
+{
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a long value to emulator memory.
+****************************************************************************/
+void X86API wrl(u32 addr, u32 val)
+{
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO byte read function. Doesn't perform real inb.
+****************************************************************************/
+static u8 X86API p_inb(X86EMU_pioAddr addr)
+{
+ DB(if (DEBUG_IO_TRACE())
+ printk("inb %#04x \n", addr);)
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO word read function. Doesn't perform real inw.
+****************************************************************************/
+static u16 X86API p_inw(X86EMU_pioAddr addr)
+{
+ DB(if (DEBUG_IO_TRACE())
+ printk("inw %#04x \n", addr);)
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO long read function. Doesn't perform real inl.
+****************************************************************************/
+static u32 X86API p_inl(X86EMU_pioAddr addr)
+{
+ DB(if (DEBUG_IO_TRACE())
+ printk("inl %#04x \n", addr);)
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to write
+val - Value to store
+REMARKS:
+Default PIO byte write function. Doesn't perform real outb.
+****************************************************************************/
+static void X86API p_outb(X86EMU_pioAddr addr, u8 val)
+{
+ DB(if (DEBUG_IO_TRACE())
+ printk("outb %#02x -> %#04x \n", val, addr);)
+ return;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to write
+val - Value to store
+REMARKS:
+Default PIO word write function. Doesn't perform real outw.
+****************************************************************************/
+static void X86API p_outw(X86EMU_pioAddr addr, u16 val)
+{
+ DB(if (DEBUG_IO_TRACE())
+ printk("outw %#04x -> %#04x \n", val, addr);)
+ return;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to write
+val - Value to store
+REMARKS:
+Default PIO ;ong write function. Doesn't perform real outl.
+****************************************************************************/
+static void X86API p_outl(X86EMU_pioAddr addr, u32 val)
+{
+ DB(if (DEBUG_IO_TRACE())
+ printk("outl %#08x -> %#04x \n", val, addr);)
+ return;
+}
+
+/*------------------------- Global Variables ------------------------------*/
+
+u8(X86APIP sys_rdb) (u32 addr) = rdb;
+u16(X86APIP sys_rdw) (u32 addr) = rdw;
+u32(X86APIP sys_rdl) (u32 addr) = rdl;
+void (X86APIP sys_wrb) (u32 addr, u8 val) = wrb;
+void (X86APIP sys_wrw) (u32 addr, u16 val) = wrw;
+void (X86APIP sys_wrl) (u32 addr, u32 val) = wrl;
+u8(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb;
+u16(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw;
+u32(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl;
+void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val) = p_outb;
+void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val) = p_outw;
+void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val) = p_outl;
+
+/*----------------------------- Setup -------------------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+funcs - New memory function pointers to make active
+
+REMARKS:
+This function is used to set the pointers to functions which access
+memory space, allowing the user application to override these functions
+and hook them out as necessary for their application.
+****************************************************************************/
+void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs)
+{
+ sys_rdb = funcs->rdb;
+ sys_rdw = funcs->rdw;
+ sys_rdl = funcs->rdl;
+ sys_wrb = funcs->wrb;
+ sys_wrw = funcs->wrw;
+ sys_wrl = funcs->wrl;
+}
+
+/****************************************************************************
+PARAMETERS:
+funcs - New programmed I/O function pointers to make active
+
+REMARKS:
+This function is used to set the pointers to functions which access
+I/O space, allowing the user application to override these functions
+and hook them out as necessary for their application.
+****************************************************************************/
+void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs)
+{
+ sys_inb = funcs->inb;
+ sys_inw = funcs->inw;
+ sys_inl = funcs->inl;
+ sys_outb = funcs->outb;
+ sys_outw = funcs->outw;
+ sys_outl = funcs->outl;
+}
+
+/****************************************************************************
+PARAMETERS:
+funcs - New interrupt vector table to make active
+
+REMARKS:
+This function is used to set the pointers to functions which handle
+interrupt processing in the emulator, allowing the user application to
+hook interrupts as necessary for their application. Any interrupts that
+are not hooked by the user application, and reflected and handled internally
+in the emulator via the interrupt vector table. This allows the application
+to get control when the code being emulated executes specific software
+interrupts.
+****************************************************************************/
+void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[])
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ _X86EMU_intrTab[i] = NULL;
+ if (funcs) {
+ for (i = 0; i < 256; i++)
+ _X86EMU_intrTab[i] = funcs[i];
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+int - New software interrupt to prepare for
+
+REMARKS:
+This function is used to set up the emulator state to exceute a software
+interrupt. This can be used by the user application code to allow an
+interrupt to be hooked, examined and then reflected back to the emulator
+so that the code in the emulator will continue processing the software
+interrupt as per normal. This essentially allows system code to actively
+hook and handle certain software interrupts as necessary.
+****************************************************************************/
+void X86EMU_prepareForInt(int num)
+{
+ push_word((u16) M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(num * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(num * 4);
+ M.x86.intr = 0;
+}
+
+#endif
diff --git a/drivers/cfb_console.c b/drivers/cfb_console.c
index 9727aebbcb..bcf877194e 100644
--- a/drivers/cfb_console.c
+++ b/drivers/cfb_console.c
@@ -63,7 +63,7 @@
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
+ needs CONFIG_CMD_DATE and CONFIG_CONSOLE_CURSOR
CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner
CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo
CONFIG_CONSOLE_EXTRA_INFO - display additional board information strings
@@ -175,15 +175,15 @@ CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability of the
#include <linux/types.h>
#include <devices.h>
#include <video_font.h>
-#ifdef CFG_CMD_DATE
-#include <rtc.h>
+#if defined(CONFIG_CMD_DATE)
+#include <rtc.h>
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
+#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
#include <watchdog.h>
#include <bmp_layout.h>
-#endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) || CONFIG_SPLASH_SCREEN */
+#endif
/*****************************************************************************/
/* Cursor definition: */
@@ -709,7 +709,7 @@ void video_puts (const char *s)
/*****************************************************************************/
-#if (CONFIG_COMMANDS & CFG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
+#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
#define FILL_8BIT_332RGB(r,g,b) { \
*fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \
@@ -1004,7 +1004,7 @@ int video_display_bitmap (ulong bmp_image, int x, int y)
return (0);
}
-#endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) || CONFIG_SPLASH_SCREEN */
+#endif
/*****************************************************************************/
diff --git a/drivers/cs8900.c b/drivers/cs8900.c
index 082434ca28..80c4ba21a6 100644
--- a/drivers/cs8900.c
+++ b/drivers/cs8900.c
@@ -43,7 +43,7 @@
#ifdef CONFIG_DRIVER_CS8900
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
#undef DEBUG
diff --git a/drivers/dataflash.c b/drivers/dataflash.c
index 17eb8597f8..91903c8c8f 100644
--- a/drivers/dataflash.c
+++ b/drivers/dataflash.c
@@ -26,18 +26,67 @@
AT91S_DATAFLASH_INFO dataflash_info[CFG_MAX_DATAFLASH_BANKS];
static AT91S_DataFlash DataFlashInst;
+#ifdef CONFIG_AT91SAM9260EK
+int cs[][CFG_MAX_DATAFLASH_BANKS] = {
+ {CFG_DATAFLASH_LOGIC_ADDR_CS0, 0}, /* Logical adress, CS */
+ {CFG_DATAFLASH_LOGIC_ADDR_CS1, 1}
+};
+#elif defined(CONFIG_AT91SAM9263EK)
+int cs[][CFG_MAX_DATAFLASH_BANKS] = {
+ {CFG_DATAFLASH_LOGIC_ADDR_CS0, 0} /* Logical adress, CS */
+};
+#else
int cs[][CFG_MAX_DATAFLASH_BANKS] = {
{CFG_DATAFLASH_LOGIC_ADDR_CS0, 0}, /* Logical adress, CS */
{CFG_DATAFLASH_LOGIC_ADDR_CS3, 3}
};
+#endif
/*define the area offsets*/
+#if defined(CONFIG_AT91SAM9261EK) || defined(CONFIG_AT91SAM9260EK) || defined(CONFIG_AT91SAM9263EK)
+#if defined(CONFIG_NEW_PARTITION)
+dataflash_protect_t area_list[NB_DATAFLASH_AREA] = {
+ {0x00000000, 0x00003FFF, FLAG_PROTECT_SET, 0, "Bootstrap"}, /* ROM code */
+ {0x00004200, 0x000083FF, FLAG_PROTECT_CLEAR, 0, "Environment"}, /* u-boot environment */
+ {0x00008400, 0x0003DDFF, FLAG_PROTECT_SET, 0, "U-Boot"}, /* u-boot code */
+ {0x0003DE00, 0x00041FFF, FLAG_PROTECT_CLEAR, FLAG_SETENV, "MON"}, /* Room for alternative boot monitor */
+ {0x00042000, 0x0018BFFF, FLAG_PROTECT_CLEAR, FLAG_SETENV, "OS"}, /* data area size to tune */
+ {0x0018C000, 0xFFFFFFFF, FLAG_PROTECT_CLEAR, FLAG_SETENV, "FS"}, /* data area size to tune */
+};
+#else
+dataflash_protect_t area_list[NB_DATAFLASH_AREA] = {
+ {0, 0x3fff, FLAG_PROTECT_SET}, /* ROM code */
+ {0x4000, 0x7fff, FLAG_PROTECT_CLEAR}, /* u-boot environment */
+ {0x8000, 0x37fff, FLAG_PROTECT_SET}, /* u-boot code */
+ {0x38000, 0x1fffff, FLAG_PROTECT_CLEAR}, /* data area size to tune */
+};
+#endif
+#elif defined(CONFIG_NEW_PARTITION)
+/*define the area offsets*/
+/* Invalid partitions should be defined with start > end */
+dataflash_protect_t area_list[NB_DATAFLASH_AREA*CFG_MAX_DATAFLASH_BANKS] = {
+ {0x00000000, 0x000083ff, FLAG_PROTECT_SET, 0, "Bootstrap"}, /* ROM code */
+ {0x00008400, 0x00020fff, FLAG_PROTECT_SET, 0, "U-Boot"}, /* u-boot code */
+ {0x00021000, 0x000293ff, FLAG_PROTECT_CLEAR, 0, "Environment"}, /* u-boot environment 8Kb */
+ {0x00029400, 0x00041fff, FLAG_PROTECT_INVALID, 0, "<Unused>"}, /* Rest of Sector 1 */
+ {0x00042000, 0x0018Bfff, FLAG_PROTECT_CLEAR, FLAG_SETENV, "OS"}, /* data area size to tune */
+ {0x0018C000, 0xffffffff, FLAG_PROTECT_CLEAR, FLAG_SETENV, "FS"}, /* data area size to tune */
+
+ {0x00000000, 0xffffffff, FLAG_PROTECT_CLEAR, FLAG_SETENV, "Data"}, /* data area */
+ {0xffffffff, 0x00000000, FLAG_PROTECT_INVALID, 0, "<Invalid>"}, /* Invalid */
+ {0xffffffff, 0x00000000, FLAG_PROTECT_INVALID, 0, "<Invalid>"}, /* Invalid */
+ {0xffffffff, 0x00000000, FLAG_PROTECT_INVALID, 0, "<Invalid>"}, /* Invalid */
+ {0xffffffff, 0x00000000, FLAG_PROTECT_INVALID, 0, "<Invalid>"}, /* Invalid */
+ {0xffffffff, 0x00000000, FLAG_PROTECT_INVALID, 0, "<Invalid>"}, /* Invalid */
+};
+#else
dataflash_protect_t area_list[NB_DATAFLASH_AREA] = {
{0, 0x7fff, FLAG_PROTECT_SET}, /* ROM code */
{0x8000, 0x1ffff, FLAG_PROTECT_SET}, /* u-boot code */
{0x20000, 0x27fff, FLAG_PROTECT_CLEAR}, /* u-boot environment */
{0x28000, 0x1fffff, FLAG_PROTECT_CLEAR}, /* data area size to tune */
};
+#endif
extern void AT91F_SpiInit (void);
extern int AT91F_DataflashProbe (int i, AT91PS_DataflashDesc pDesc);
@@ -45,22 +94,28 @@ extern int AT91F_DataFlashRead (AT91PS_DataFlash pDataFlash,
unsigned long addr,
unsigned long size, char *buffer);
extern int AT91F_DataFlashWrite( AT91PS_DataFlash pDataFlash,
- unsigned char *src,
- int dest,
- int size );
+ unsigned char *src,
+ int dest,
+ int size );
int AT91F_DataflashInit (void)
{
int i, j;
int dfcode;
+ int part = 0;
+ int last_part;
+ int found[CFG_MAX_DATAFLASH_BANKS];
+ unsigned char protected;
AT91F_SpiInit ();
for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
+ found[i] = 0;
dataflash_info[i].Desc.state = IDLE;
dataflash_info[i].id = 0;
dataflash_info[i].Device.pages_number = 0;
- dfcode = AT91F_DataflashProbe (cs[i][1], &dataflash_info[i].Desc);
+ dfcode = AT91F_DataflashProbe (cs[i][1],
+ &dataflash_info[i].Desc);
switch (dfcode) {
case AT45DB161:
@@ -72,6 +127,7 @@ int AT91F_DataflashInit (void)
dataflash_info[i].Desc.DataFlash_state = IDLE;
dataflash_info[i].logical_address = cs[i][0];
dataflash_info[i].id = dfcode;
+ found[i] += dfcode;;
break;
case AT45DB321:
@@ -83,6 +139,7 @@ int AT91F_DataflashInit (void)
dataflash_info[i].Desc.DataFlash_state = IDLE;
dataflash_info[i].logical_address = cs[i][0];
dataflash_info[i].id = dfcode;
+ found[i] += dfcode;;
break;
case AT45DB642:
@@ -94,7 +151,9 @@ int AT91F_DataflashInit (void)
dataflash_info[i].Desc.DataFlash_state = IDLE;
dataflash_info[i].logical_address = cs[i][0];
dataflash_info[i].id = dfcode;
+ found[i] += dfcode;;
break;
+
case AT45DB128:
dataflash_info[i].Device.pages_number = 16384;
dataflash_info[i].Device.pages_size = 1056;
@@ -104,9 +163,11 @@ int AT91F_DataflashInit (void)
dataflash_info[i].Desc.DataFlash_state = IDLE;
dataflash_info[i].logical_address = cs[i][0];
dataflash_info[i].id = dfcode;
+ found[i] += dfcode;;
break;
default:
+ dfcode = 0;
break;
}
/* set the last area end to the dataflash size*/
@@ -114,16 +175,64 @@ int AT91F_DataflashInit (void)
(dataflash_info[i].Device.pages_number *
dataflash_info[i].Device.pages_size)-1;
+ last_part=0;
/* set the area addresses */
for(j = 0; j<NB_DATAFLASH_AREA; j++) {
- dataflash_info[i].Device.area_list[j].start = area_list[j].start + dataflash_info[i].logical_address;
- dataflash_info[i].Device.area_list[j].end = area_list[j].end + dataflash_info[i].logical_address;
- dataflash_info[i].Device.area_list[j].protected = area_list[j].protected;
+ if(found[i]!=0) {
+ dataflash_info[i].Device.area_list[j].start =
+ area_list[part].start +
+ dataflash_info[i].logical_address;
+ if(area_list[part].end == 0xffffffff) {
+ dataflash_info[i].Device.area_list[j].end =
+ dataflash_info[i].end_address +
+ dataflash_info [i].logical_address;
+ last_part = 1;
+ } else {
+ dataflash_info[i].Device.area_list[j].end =
+ area_list[part].end +
+ dataflash_info[i].logical_address;
+ }
+ protected = area_list[part].protected;
+ /* Set the environment according to the label...*/
+ if(protected == FLAG_PROTECT_INVALID) {
+ dataflash_info[i].Device.area_list[j].protected =
+ FLAG_PROTECT_INVALID;
+ } else {
+ dataflash_info[i].Device.area_list[j].protected =
+ protected;
+ }
+ strcpy((char*)(dataflash_info[i].Device.area_list[j].label),
+ (const char *)area_list[part].label);
+ }
+ part++;
}
}
- return (1);
+ return found[0];
}
+#ifdef CONFIG_NEW_DF_PARTITION
+int AT91F_DataflashSetEnv (void)
+{
+ int i, j;
+ int part;
+ unsigned char env;
+ unsigned char s[32]; /* Will fit a long int in hex */
+ unsigned long start;
+ for (i = 0, part= 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
+ for(j = 0; j<NB_DATAFLASH_AREA; j++) {
+ env = area_list[part].setenv;
+ /* Set the environment according to the label...*/
+ if((env & FLAG_SETENV) == FLAG_SETENV) {
+ start =
+ dataflash_info[i].Device.area_list[j].start;
+ sprintf(s,"%X",start);
+ setenv(area_list[part].label,s);
+ }
+ part++;
+ }
+ }
+}
+#endif
void dataflash_print_info (void)
{
@@ -131,25 +240,25 @@ void dataflash_print_info (void)
for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
if (dataflash_info[i].id != 0) {
- printf ("DataFlash:");
+ printf("DataFlash:");
switch (dataflash_info[i].id) {
case AT45DB161:
- printf ("AT45DB161\n");
+ printf("AT45DB161\n");
break;
case AT45DB321:
- printf ("AT45DB321\n");
+ printf("AT45DB321\n");
break;
case AT45DB642:
- printf ("AT45DB642\n");
+ printf("AT45DB642\n");
break;
case AT45DB128:
- printf ("AT45DB128\n");
+ printf("AT45DB128\n");
break;
}
- printf ("Nb pages: %6d\n"
+ printf("Nb pages: %6d\n"
"Page Size: %6d\n"
"Size=%8d bytes\n"
"Logical address: 0x%08X\n",
@@ -159,28 +268,44 @@ void dataflash_print_info (void)
dataflash_info[i].Device.pages_size,
(unsigned int) dataflash_info[i].logical_address);
for (j=0; j< NB_DATAFLASH_AREA; j++) {
- printf ("Area %i:\t%08lX to %08lX %s\n", j,
- dataflash_info[i].Device.area_list[j].start,
- dataflash_info[i].Device.area_list[j].end,
- (dataflash_info[i].Device.area_list[j].protected ==
- FLAG_PROTECT_SET) ? "(RO)" : "");
+ switch(dataflash_info[i].Device.area_list[j].protected) {
+ case FLAG_PROTECT_SET:
+ case FLAG_PROTECT_CLEAR:
+ printf("Area %i:\t%08lX to %08lX %s", j,
+ dataflash_info[i].Device.area_list[j].start,
+ dataflash_info[i].Device.area_list[j].end,
+ (dataflash_info[i].Device.area_list[j].protected==FLAG_PROTECT_SET) ? "(RO)" : " ");
+#ifdef CONFIG_NEW_DF_PARTITION
+ printf(" %s\n", dataflash_info[i].Device.area_list[j].label);
+#else
+ printf("\n");
+#endif
+ break;
+#ifdef CONFIG_NEW_DF_PARTITION
+ case FLAG_PROTECT_INVALID:
+ break;
+#endif
+ }
}
}
}
}
-/*------------------------------------------------------------------------------*/
-/* Function Name : AT91F_DataflashSelect */
-/* Object : Select the correct device */
-/*------------------------------------------------------------------------------*/
-AT91PS_DataFlash AT91F_DataflashSelect (AT91PS_DataFlash pFlash, unsigned long *addr)
+/*---------------------------------------------------------------------------*/
+/* Function Name : AT91F_DataflashSelect */
+/* Object : Select the correct device */
+/*---------------------------------------------------------------------------*/
+AT91PS_DataFlash AT91F_DataflashSelect (AT91PS_DataFlash pFlash,
+ unsigned long *addr)
{
char addr_valid = 0;
int i;
for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++)
- if ((*addr & 0xFF000000) == dataflash_info[i].logical_address) {
+ if ( dataflash_info[i].id
+ && ((((int) addr) & 0xFF000000) ==
+ dataflash_info[i].logical_address)) {
addr_valid = 1;
break;
}
@@ -194,10 +319,10 @@ AT91PS_DataFlash AT91F_DataflashSelect (AT91PS_DataFlash pFlash, unsigned long *
return (pFlash);
}
-/*------------------------------------------------------------------------------*/
-/* Function Name : addr_dataflash */
-/* Object : Test if address is valid */
-/*------------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Function Name : addr_dataflash */
+/* Object : Test if address is valid */
+/*---------------------------------------------------------------------------*/
int addr_dataflash (unsigned long addr)
{
int addr_valid = 0;
@@ -213,25 +338,27 @@ int addr_dataflash (unsigned long addr)
return addr_valid;
}
-/*-----------------------------------------------------------------------------*/
-/* Function Name : size_dataflash */
-/* Object : Test if address is valid regarding the size */
-/*-----------------------------------------------------------------------------*/
-int size_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr, unsigned long size)
+/*---------------------------------------------------------------------------*/
+/* Function Name : size_dataflash */
+/* Object : Test if address is valid regarding the size */
+/*---------------------------------------------------------------------------*/
+int size_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr,
+ unsigned long size)
{
/* is outside the dataflash */
if (((int)addr & 0x0FFFFFFF) > (pdataFlash->pDevice->pages_size *
pdataFlash->pDevice->pages_number)) return 0;
/* is too large for the dataflash */
if (size > ((pdataFlash->pDevice->pages_size *
- pdataFlash->pDevice->pages_number) - ((int)addr & 0x0FFFFFFF))) return 0;
+ pdataFlash->pDevice->pages_number) -
+ ((int)addr & 0x0FFFFFFF))) return 0;
return 1;
}
-/*-----------------------------------------------------------------------------*/
-/* Function Name : prot_dataflash */
-/* Object : Test if destination area is protected */
-/*-----------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Function Name : prot_dataflash */
+/* Object : Test if destination area is protected */
+/*---------------------------------------------------------------------------*/
int prot_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr)
{
int area;
@@ -241,17 +368,23 @@ int area;
(addr < pdataFlash->pDevice->area_list[area].end))
break;
}
- if (area == NB_DATAFLASH_AREA) return -1;
+ if (area == NB_DATAFLASH_AREA)
+ return -1;
+
/*test protection value*/
- if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_SET) return 0;
+ if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_SET)
+ return 0;
+ if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_INVALID)
+ return 0;
return 1;
}
-/*-----------------------------------------------------------------------------*/
-/* Function Name : dataflash_real_protect */
-/* Object : protect/unprotect area */
-/*-----------------------------------------------------------------------------*/
-int dataflash_real_protect (int flag, unsigned long start_addr, unsigned long end_addr)
+/*--------------------------------------------------------------------------*/
+/* Function Name : dataflash_real_protect */
+/* Object : protect/unprotect area */
+/*--------------------------------------------------------------------------*/
+int dataflash_real_protect (int flag, unsigned long start_addr,
+ unsigned long end_addr)
{
int i,j, area1, area2, addr_valid = 0;
/* find dataflash */
@@ -267,27 +400,38 @@ int i,j, area1, area2, addr_valid = 0;
}
/* find start area */
for (area1=0; area1 < NB_DATAFLASH_AREA; area1++) {
- if (start_addr == dataflash_info[i].Device.area_list[area1].start) break;
+ if (start_addr == dataflash_info[i].Device.area_list[area1].start)
+ break;
}
if (area1 == NB_DATAFLASH_AREA) return -1;
/* find end area */
for (area2=0; area2 < NB_DATAFLASH_AREA; area2++) {
- if (end_addr == dataflash_info[i].Device.area_list[area2].end) break;
+ if (end_addr == dataflash_info[i].Device.area_list[area2].end)
+ break;
}
- if (area2 == NB_DATAFLASH_AREA) return -1;
+ if (area2 == NB_DATAFLASH_AREA)
+ return -1;
/*set protection value*/
for(j = area1; j < area2+1 ; j++)
- if (flag == 0) dataflash_info[i].Device.area_list[j].protected = FLAG_PROTECT_CLEAR;
- else dataflash_info[i].Device.area_list[j].protected = FLAG_PROTECT_SET;
+ if(dataflash_info[i].Device.area_list[j].protected
+ != FLAG_PROTECT_INVALID) {
+ if (flag == 0) {
+ dataflash_info[i].Device.area_list[j].protected
+ = FLAG_PROTECT_CLEAR;
+ } else {
+ dataflash_info[i].Device.area_list[j].protected
+ = FLAG_PROTECT_SET;
+ }
+ }
return (area2-area1+1);
}
-/*------------------------------------------------------------------------------*/
-/* Function Name : read_dataflash */
-/* Object : dataflash memory read */
-/*------------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Function Name : read_dataflash */
+/* Object : dataflash memory read */
+/*---------------------------------------------------------------------------*/
int read_dataflash (unsigned long addr, unsigned long size, char *result)
{
unsigned long AddrToRead = addr;
@@ -305,12 +449,12 @@ int read_dataflash (unsigned long addr, unsigned long size, char *result)
}
-/*-----------------------------------------------------------------------------*/
-/* Function Name : write_dataflash */
-/* Object : write a block in dataflash */
-/*-----------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Function Name : write_dataflash */
+/* Object : write a block in dataflash */
+/*---------------------------------------------------------------------------*/
int write_dataflash (unsigned long addr_dest, unsigned long addr_src,
- unsigned long size)
+ unsigned long size)
{
unsigned long AddrToWrite = addr_dest;
AT91PS_DataFlash pFlash = &DataFlashInst;
@@ -329,7 +473,8 @@ int write_dataflash (unsigned long addr_dest, unsigned long addr_src,
if (AddrToWrite == -1)
return -1;
- return AT91F_DataFlashWrite (pFlash, (uchar *)addr_src, AddrToWrite, size);
+ return AT91F_DataFlashWrite (pFlash, (uchar *)addr_src,
+ AddrToWrite, size);
}
@@ -339,22 +484,22 @@ void dataflash_perror (int err)
case ERR_OK:
break;
case ERR_TIMOUT:
- printf ("Timeout writing to DataFlash\n");
+ printf("Timeout writing to DataFlash\n");
break;
case ERR_PROTECTED:
- printf ("Can't write to protected DataFlash sectors\n");
+ printf("Can't write to protected/invalid DataFlash sectors\n");
break;
case ERR_INVAL:
- printf ("Outside available DataFlash\n");
+ printf("Outside available DataFlash\n");
break;
case ERR_UNKNOWN_FLASH_TYPE:
- printf ("Unknown Type of DataFlash\n");
+ printf("Unknown Type of DataFlash\n");
break;
case ERR_PROG_ERROR:
- printf ("General DataFlash Programming Error\n");
+ printf("General DataFlash Programming Error\n");
break;
default:
- printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
+ printf("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
break;
}
}
diff --git a/drivers/dc2114x.c b/drivers/dc2114x.c
index c43cd5ec2f..d5275dceb0 100644
--- a/drivers/dc2114x.c
+++ b/drivers/dc2114x.c
@@ -20,8 +20,8 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
- && defined(CONFIG_TULIP)
+#if defined(CONFIG_CMD_NET) \
+ && defined(CONFIG_NET_MULTI) && defined(CONFIG_TULIP)
#include <malloc.h>
#include <net.h>
@@ -768,4 +768,4 @@ static void update_srom(struct eth_device *dev, bd_t *bis)
}
#endif /* UPDATE_SROM */
-#endif /* CFG_CMD_NET && CONFIG_NET_MULTI && CONFIG_TULIP */
+#endif
diff --git a/drivers/dm9000x.c b/drivers/dm9000x.c
index 687707627e..6131b5c357 100644
--- a/drivers/dm9000x.c
+++ b/drivers/dm9000x.c
@@ -99,7 +99,7 @@ void eth_halt(void);
static int dm9000_probe(void);
static u16 phy_read(int);
static void phy_write(int, u16);
-static u16 read_srom_word(int);
+u16 read_srom_word(int);
static u8 DM9000_ior(int);
static void DM9000_iow(int reg, u8 value);
@@ -302,6 +302,21 @@ eth_init(bd_t * bd)
/* Set Node address */
for (i = 0; i < 6; i++)
((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
+
+ if (is_zero_ether_addr(bd->bi_enetaddr) ||
+ is_multicast_ether_addr(bd->bi_enetaddr)) {
+ /* try reading from environment */
+ u8 i;
+ char *s, *e;
+ s = getenv ("ethaddr");
+ for (i = 0; i < 6; ++i) {
+ bd->bi_enetaddr[i] = s ?
+ simple_strtoul (s, &e, 16) : 0;
+ if (s)
+ s = (*e) ? e + 1 : e;
+ }
+ }
+
printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
@@ -522,16 +537,28 @@ eth_rx(void)
/*
Read a word data from SROM
*/
-static u16
+u16
read_srom_word(int offset)
{
DM9000_iow(DM9000_EPAR, offset);
DM9000_iow(DM9000_EPCR, 0x4);
- udelay(200);
+ udelay(8000);
DM9000_iow(DM9000_EPCR, 0x0);
return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
}
+void
+write_srom_word(int offset, u16 val)
+{
+ DM9000_iow(DM9000_EPAR, offset);
+ DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
+ DM9000_iow(DM9000_EPDRL, (val & 0xff));
+ DM9000_iow(DM9000_EPCR, 0x12);
+ udelay(8000);
+ DM9000_iow(DM9000_EPCR, 0);
+}
+
+
/*
Read a byte from I/O port
*/
diff --git a/drivers/e1000.c b/drivers/e1000.c
index 927acbb267..f0741da82b 100644
--- a/drivers/e1000.c
+++ b/drivers/e1000.c
@@ -44,8 +44,8 @@ tested on both gig copper and gig fiber boards
#include "e1000.h"
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
- defined(CONFIG_E1000)
+#if defined(CONFIG_CMD_NET) \
+ && defined(CONFIG_NET_MULTI) && defined(CONFIG_E1000)
#define TOUT_LOOP 100000
diff --git a/drivers/eepro100.c b/drivers/eepro100.c
index 04c17f69f6..738146e661 100644
--- a/drivers/eepro100.c
+++ b/drivers/eepro100.c
@@ -30,8 +30,8 @@
#undef DEBUG
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
- defined(CONFIG_EEPRO100)
+#if defined(CONFIG_CMD_NET) \
+ && defined(CONFIG_NET_MULTI) && defined(CONFIG_EEPRO100)
/* Ethernet chip registers.
*/
@@ -272,7 +272,7 @@ static inline void OUTL (struct eth_device *dev, int command, u_long addr)
*(volatile u32 *) ((addr + dev->iobase)) = cpu_to_le32 (command);
}
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
static inline int INL (struct eth_device *dev, u_long addr)
{
return le32_to_cpu (*(volatile u32 *) (addr + dev->iobase));
@@ -386,7 +386,7 @@ static int eepro100_miiphy_write (char *devname, unsigned char addr,
return 0;
}
-#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */
+#endif
/* Wait for the chip get the command.
*/
@@ -462,7 +462,7 @@ int eepro100_initialize (bd_t * bis)
eth_register (dev);
-#if defined (CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined (CONFIG_MII) || defined(CONFIG_CMD_MII)
/* register mii command access routines */
miiphy_register(dev->name,
eepro100_miiphy_read, eepro100_miiphy_write);
diff --git a/drivers/enc28j60.c b/drivers/enc28j60.c
new file mode 100644
index 0000000000..98303aceee
--- /dev/null
+++ b/drivers/enc28j60.c
@@ -0,0 +1,983 @@
+/*
+ * 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>
+#include <common.h>
+#ifdef CONFIG_ENC28J60
+#include <net.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/spi.h>
+
+/*
+ * Control Registers in Bank 0
+ */
+
+#define CTL_REG_ERDPTL 0x00
+#define CTL_REG_ERDPTH 0x01
+#define CTL_REG_EWRPTL 0x02
+#define CTL_REG_EWRPTH 0x03
+#define CTL_REG_ETXSTL 0x04
+#define CTL_REG_ETXSTH 0x05
+#define CTL_REG_ETXNDL 0x06
+#define CTL_REG_ETXNDH 0x07
+#define CTL_REG_ERXSTL 0x08
+#define CTL_REG_ERXSTH 0x09
+#define CTL_REG_ERXNDL 0x0A
+#define CTL_REG_ERXNDH 0x0B
+#define CTL_REG_ERXRDPTL 0x0C
+#define CTL_REG_ERXRDPTH 0x0D
+#define CTL_REG_ERXWRPTL 0x0E
+#define CTL_REG_ERXWRPTH 0x0F
+#define CTL_REG_EDMASTL 0x10
+#define CTL_REG_EDMASTH 0x11
+#define CTL_REG_EDMANDL 0x12
+#define CTL_REG_EDMANDH 0x13
+#define CTL_REG_EDMADSTL 0x14
+#define CTL_REG_EDMADSTH 0x15
+#define CTL_REG_EDMACSL 0x16
+#define CTL_REG_EDMACSH 0x17
+/* these are common in all banks */
+#define CTL_REG_EIE 0x1B
+#define CTL_REG_EIR 0x1C
+#define CTL_REG_ESTAT 0x1D
+#define CTL_REG_ECON2 0x1E
+#define CTL_REG_ECON1 0x1F
+
+/*
+ * Control Registers in Bank 1
+ */
+
+#define CTL_REG_EHT0 0x00
+#define CTL_REG_EHT1 0x01
+#define CTL_REG_EHT2 0x02
+#define CTL_REG_EHT3 0x03
+#define CTL_REG_EHT4 0x04
+#define CTL_REG_EHT5 0x05
+#define CTL_REG_EHT6 0x06
+#define CTL_REG_EHT7 0x07
+#define CTL_REG_EPMM0 0x08
+#define CTL_REG_EPMM1 0x09
+#define CTL_REG_EPMM2 0x0A
+#define CTL_REG_EPMM3 0x0B
+#define CTL_REG_EPMM4 0x0C
+#define CTL_REG_EPMM5 0x0D
+#define CTL_REG_EPMM6 0x0E
+#define CTL_REG_EPMM7 0x0F
+#define CTL_REG_EPMCSL 0x10
+#define CTL_REG_EPMCSH 0x11
+#define CTL_REG_EPMOL 0x14
+#define CTL_REG_EPMOH 0x15
+#define CTL_REG_EWOLIE 0x16
+#define CTL_REG_EWOLIR 0x17
+#define CTL_REG_ERXFCON 0x18
+#define CTL_REG_EPKTCNT 0x19
+
+/*
+ * Control Registers in Bank 2
+ */
+
+#define CTL_REG_MACON1 0x00
+#define CTL_REG_MACON2 0x01
+#define CTL_REG_MACON3 0x02
+#define CTL_REG_MACON4 0x03
+#define CTL_REG_MABBIPG 0x04
+#define CTL_REG_MAIPGL 0x06
+#define CTL_REG_MAIPGH 0x07
+#define CTL_REG_MACLCON1 0x08
+#define CTL_REG_MACLCON2 0x09
+#define CTL_REG_MAMXFLL 0x0A
+#define CTL_REG_MAMXFLH 0x0B
+#define CTL_REG_MAPHSUP 0x0D
+#define CTL_REG_MICON 0x11
+#define CTL_REG_MICMD 0x12
+#define CTL_REG_MIREGADR 0x14
+#define CTL_REG_MIWRL 0x16
+#define CTL_REG_MIWRH 0x17
+#define CTL_REG_MIRDL 0x18
+#define CTL_REG_MIRDH 0x19
+
+/*
+ * Control Registers in Bank 3
+ */
+
+#define CTL_REG_MAADR1 0x00
+#define CTL_REG_MAADR0 0x01
+#define CTL_REG_MAADR3 0x02
+#define CTL_REG_MAADR2 0x03
+#define CTL_REG_MAADR5 0x04
+#define CTL_REG_MAADR4 0x05
+#define CTL_REG_EBSTSD 0x06
+#define CTL_REG_EBSTCON 0x07
+#define CTL_REG_EBSTCSL 0x08
+#define CTL_REG_EBSTCSH 0x09
+#define CTL_REG_MISTAT 0x0A
+#define CTL_REG_EREVID 0x12
+#define CTL_REG_ECOCON 0x15
+#define CTL_REG_EFLOCON 0x17
+#define CTL_REG_EPAUSL 0x18
+#define CTL_REG_EPAUSH 0x19
+
+
+/*
+ * PHY Register
+ */
+
+#define PHY_REG_PHID1 0x02
+#define PHY_REG_PHID2 0x03
+/* taken from the Linux driver */
+#define PHY_REG_PHCON1 0x00
+#define PHY_REG_PHCON2 0x10
+#define PHY_REG_PHLCON 0x14
+
+/*
+ * Receive Filter Register (ERXFCON) bits
+ */
+
+#define ENC_RFR_UCEN 0x80
+#define ENC_RFR_ANDOR 0x40
+#define ENC_RFR_CRCEN 0x20
+#define ENC_RFR_PMEN 0x10
+#define ENC_RFR_MPEN 0x08
+#define ENC_RFR_HTEN 0x04
+#define ENC_RFR_MCEN 0x02
+#define ENC_RFR_BCEN 0x01
+
+/*
+ * ECON1 Register Bits
+ */
+
+#define ENC_ECON1_TXRST 0x80
+#define ENC_ECON1_RXRST 0x40
+#define ENC_ECON1_DMAST 0x20
+#define ENC_ECON1_CSUMEN 0x10
+#define ENC_ECON1_TXRTS 0x08
+#define ENC_ECON1_RXEN 0x04
+#define ENC_ECON1_BSEL1 0x02
+#define ENC_ECON1_BSEL0 0x01
+
+/*
+ * ECON2 Register Bits
+ */
+#define ENC_ECON2_AUTOINC 0x80
+#define ENC_ECON2_PKTDEC 0x40
+#define ENC_ECON2_PWRSV 0x20
+#define ENC_ECON2_VRPS 0x08
+
+/*
+ * EIR Register Bits
+ */
+#define ENC_EIR_PKTIF 0x40
+#define ENC_EIR_DMAIF 0x20
+#define ENC_EIR_LINKIF 0x10
+#define ENC_EIR_TXIF 0x08
+#define ENC_EIR_WOLIF 0x04
+#define ENC_EIR_TXERIF 0x02
+#define ENC_EIR_RXERIF 0x01
+
+/*
+ * ESTAT Register Bits
+ */
+
+#define ENC_ESTAT_INT 0x80
+#define ENC_ESTAT_LATECOL 0x10
+#define ENC_ESTAT_RXBUSY 0x04
+#define ENC_ESTAT_TXABRT 0x02
+#define ENC_ESTAT_CLKRDY 0x01
+
+/*
+ * EIE Register Bits
+ */
+
+#define ENC_EIE_INTIE 0x80
+#define ENC_EIE_PKTIE 0x40
+#define ENC_EIE_DMAIE 0x20
+#define ENC_EIE_LINKIE 0x10
+#define ENC_EIE_TXIE 0x08
+#define ENC_EIE_WOLIE 0x04
+#define ENC_EIE_TXERIE 0x02
+#define ENC_EIE_RXERIE 0x01
+
+/*
+ * MACON1 Register Bits
+ */
+#define ENC_MACON1_LOOPBK 0x10
+#define ENC_MACON1_TXPAUS 0x08
+#define ENC_MACON1_RXPAUS 0x04
+#define ENC_MACON1_PASSALL 0x02
+#define ENC_MACON1_MARXEN 0x01
+
+
+/*
+ * MACON2 Register Bits
+ */
+#define ENC_MACON2_MARST 0x80
+#define ENC_MACON2_RNDRST 0x40
+#define ENC_MACON2_MARXRST 0x08
+#define ENC_MACON2_RFUNRST 0x04
+#define ENC_MACON2_MATXRST 0x02
+#define ENC_MACON2_TFUNRST 0x01
+
+/*
+ * MACON3 Register Bits
+ */
+#define ENC_MACON3_PADCFG2 0x80
+#define ENC_MACON3_PADCFG1 0x40
+#define ENC_MACON3_PADCFG0 0x20
+#define ENC_MACON3_TXCRCEN 0x10
+#define ENC_MACON3_PHDRLEN 0x08
+#define ENC_MACON3_HFRMEN 0x04
+#define ENC_MACON3_FRMLNEN 0x02
+#define ENC_MACON3_FULDPX 0x01
+
+/*
+ * MICMD Register Bits
+ */
+#define ENC_MICMD_MIISCAN 0x02
+#define ENC_MICMD_MIIRD 0x01
+
+/*
+ * MISTAT Register Bits
+ */
+#define ENC_MISTAT_NVALID 0x04
+#define ENC_MISTAT_SCAN 0x02
+#define ENC_MISTAT_BUSY 0x01
+
+/*
+ * PHID1 and PHID2 values
+ */
+#define ENC_PHID1_VALUE 0x0083
+#define ENC_PHID2_VALUE 0x1400
+#define ENC_PHID2_MASK 0xFC00
+
+
+#define ENC_SPI_SLAVE_CS 0x00010000 /* pin P1.16 */
+#define ENC_RESET 0x00020000 /* pin P1.17 */
+
+#define FAILSAFE_VALUE 5000
+
+/*
+ * Controller memory layout:
+ *
+ * 0x0000 - 0x17ff 6k bytes receive buffer
+ * 0x1800 - 0x1fff 2k bytes transmit buffer
+ */
+/* Use the lower memory for receiver buffer. See errata pt. 5 */
+#define ENC_RX_BUF_START 0x0000
+#define ENC_TX_BUF_START 0x1800
+/* taken from the Linux driver */
+#define ENC_RX_BUF_END 0x17ff
+#define ENC_TX_BUF_END 0x1fff
+
+/* maximum frame length */
+#define ENC_MAX_FRM_LEN 1518
+
+#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS)
+#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS)
+#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8);
+
+
+static unsigned char encReadReg (unsigned char regNo);
+static void encWriteReg (unsigned char regNo, unsigned char data);
+static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c);
+static void encReadBuff (unsigned short length, unsigned char *pBuff);
+static void encWriteBuff (unsigned short length, unsigned char *pBuff);
+static void encBitSet (unsigned char regNo, unsigned char data);
+static void encBitClr (unsigned char regNo, unsigned char data);
+static void encReset (void);
+static void encInit (unsigned char *pEthAddr);
+static unsigned short phyRead (unsigned char addr);
+static void phyWrite(unsigned char, unsigned short);
+static void encPoll (void);
+static void encRx (void);
+
+#define m_nic_read(reg) encReadReg(reg)
+#define m_nic_write(reg, data) encWriteReg(reg, data)
+#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count)
+#define m_nic_read_data(len, buf) encReadBuff((len), (buf))
+#define m_nic_write_data(len, buf) encWriteBuff((len), (buf))
+
+/* bit field set */
+#define m_nic_bfs(reg, data) encBitSet(reg, data)
+
+/* bit field clear */
+#define m_nic_bfc(reg, data) encBitClr(reg, data)
+
+static unsigned char bank = 0; /* current bank in enc28j60 */
+static unsigned char next_pointer_lsb;
+static unsigned char next_pointer_msb;
+
+static unsigned char buffer[ENC_MAX_FRM_LEN];
+static int rxResetCounter = 0;
+
+#define RX_RESET_COUNTER 1000;
+
+/*-----------------------------------------------------------------------------
+ * Always returns 0
+ */
+int eth_init (bd_t * bis)
+{
+ unsigned char estatVal;
+
+ /* configure GPIO */
+ (*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS;
+ (*((volatile unsigned long *) IO1DIR)) |= ENC_RESET;
+
+ /* CS and RESET active low */
+ PUT32 (IO1SET, ENC_SPI_SLAVE_CS);
+ PUT32 (IO1SET, ENC_RESET);
+
+ spi_init ();
+
+ /* taken from the Linux driver - dangerous stuff here! */
+ /* Wait for CLKRDY to become set (i.e., check that we can communicate with
+ the ENC) */
+ do
+ {
+ estatVal = m_nic_read(CTL_REG_ESTAT);
+ } while ((estatVal & 0x08) || (~estatVal & ENC_ESTAT_CLKRDY));
+
+ /* initialize controller */
+ encReset ();
+ encInit (bis->bi_enetaddr);
+
+ m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */
+
+ return 0;
+}
+
+int eth_send (volatile void *packet, int length)
+{
+ /* check frame length, etc. */
+ /* TODO: */
+
+ /* switch to bank 0 */
+ m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+ /* set EWRPT */
+ m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff));
+ m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8));
+
+ /* set ETXND */
+ m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF);
+ m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8);
+
+ /* set ETXST */
+ m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF);
+ m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8);
+
+ /* write packet */
+ m_nic_write_data (length, (unsigned char *) packet);
+
+ /* taken from the Linux driver */
+ /* Verify that the internal transmit logic has not been altered by excessive
+ collisions. See Errata B4 12 and 14.
+ */
+ if (m_nic_read(CTL_REG_EIR) & ENC_EIR_TXERIF) {
+ m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRST);
+ m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_TXRST);
+ }
+ m_nic_bfc(CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF));
+
+ /* set ECON1.TXRTS */
+ m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS);
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * This function resets the receiver only. This function may be called from
+ * interrupt-context.
+ */
+static void encReceiverReset (void)
+{
+ unsigned char econ1;
+
+ econ1 = m_nic_read (CTL_REG_ECON1);
+ if ((econ1 & ENC_ECON1_RXRST) == 0) {
+ m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST);
+ rxResetCounter = RX_RESET_COUNTER;
+ }
+}
+
+/*****************************************************************************
+ * receiver reset timer
+ */
+static void encReceiverResetCallback (void)
+{
+ m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST);
+ m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */
+}
+
+/*-----------------------------------------------------------------------------
+ * Check for received packets. Call NetReceive for each packet. The return
+ * value is ignored by the caller.
+ */
+int eth_rx (void)
+{
+ if (rxResetCounter > 0 && --rxResetCounter == 0) {
+ encReceiverResetCallback ();
+ }
+
+ encPoll ();
+
+ return 0;
+}
+
+void eth_halt (void)
+{
+ m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN); /* disable receive */
+}
+
+/*****************************************************************************/
+
+static void encPoll (void)
+{
+ unsigned char eir_reg;
+ volatile unsigned char estat_reg;
+ unsigned char pkt_cnt;
+
+#ifdef CONFIG_USE_IRQ
+ /* clear global interrupt enable bit in enc28j60 */
+ m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+ estat_reg = m_nic_read (CTL_REG_ESTAT);
+
+ eir_reg = m_nic_read (CTL_REG_EIR);
+
+ if (eir_reg & ENC_EIR_TXIF) {
+ /* clear TXIF bit in EIR */
+ m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF);
+ }
+
+ /* We have to use pktcnt and not pktif bit, see errata pt. 6 */
+
+ /* move to bank 1 */
+ m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+ m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+ /* read pktcnt */
+ pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
+
+ if (pkt_cnt > 0) {
+ if ((eir_reg & ENC_EIR_PKTIF) == 0) {
+ /*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */
+ }
+ encRx ();
+ /* clear PKTIF bit in EIR, this should not need to be done but it
+ seems like we get problems if we do not */
+ m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF);
+ }
+
+ if (eir_reg & ENC_EIR_RXERIF) {
+ printf ("encPoll: rx error\n");
+ m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF);
+ }
+ if (eir_reg & ENC_EIR_TXERIF) {
+ printf ("encPoll: tx error\n");
+ m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF);
+ }
+
+#ifdef CONFIG_USE_IRQ
+ /* set global interrupt enable bit in enc28j60 */
+ m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+}
+
+static void encRx (void)
+{
+ unsigned short pkt_len;
+ unsigned short copy_len;
+ unsigned short status;
+ unsigned char eir_reg;
+ unsigned char pkt_cnt = 0;
+ unsigned short rxbuf_rdpt;
+
+ /* switch to bank 0 */
+ m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+ m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
+ m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
+
+ do {
+ m_nic_read_data (6, buffer);
+ next_pointer_lsb = buffer[0];
+ next_pointer_msb = buffer[1];
+ pkt_len = buffer[2];
+ pkt_len |= (unsigned short) buffer[3] << 8;
+ status = buffer[4];
+ status |= (unsigned short) buffer[5] << 8;
+
+ if (pkt_len <= ENC_MAX_FRM_LEN)
+ copy_len = pkt_len;
+ else
+ copy_len = 0;
+
+ if ((status & (1L << 7)) == 0) /* check Received Ok bit */
+ copy_len = 0;
+
+ /* taken from the Linux driver */
+ /* check if next pointer is resonable */
+ if ((((unsigned int)next_pointer_msb << 8) |
+ (unsigned int)next_pointer_lsb) >= ENC_TX_BUF_START)
+ copy_len = 0;
+
+ if (copy_len > 0) {
+ m_nic_read_data (copy_len, buffer);
+ }
+
+ /* advance read pointer to next pointer */
+ m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
+ m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
+
+ /* decrease packet counter */
+ m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC);
+
+ /* taken from the Linux driver */
+ /* Only odd values should be written to ERXRDPTL,
+ * see errata B4 pt.13
+ */
+ rxbuf_rdpt = (next_pointer_msb << 8 | next_pointer_lsb) - 1;
+ if ((rxbuf_rdpt < (m_nic_read(CTL_REG_ERXSTH) << 8 |
+ m_nic_read(CTL_REG_ERXSTL))) || (rxbuf_rdpt >
+ (m_nic_read(CTL_REG_ERXNDH) << 8 |
+ m_nic_read(CTL_REG_ERXNDL)))) {
+ m_nic_write(CTL_REG_ERXRDPTL, m_nic_read(CTL_REG_ERXNDL));
+ m_nic_write(CTL_REG_ERXRDPTH, m_nic_read(CTL_REG_ERXNDH));
+ } else {
+ m_nic_write(CTL_REG_ERXRDPTL, rxbuf_rdpt & 0xFF);
+ m_nic_write(CTL_REG_ERXRDPTH, rxbuf_rdpt >> 8);
+ }
+
+ /* move to bank 1 */
+ m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+ m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+ /* read pktcnt */
+ pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
+
+ /* switch to bank 0 */
+ m_nic_bfc (CTL_REG_ECON1,
+ (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+ if (copy_len == 0) {
+ eir_reg = m_nic_read (CTL_REG_EIR);
+ encReceiverReset ();
+ printf ("eth_rx: copy_len=0\n");
+ continue;
+ }
+
+ NetReceive ((unsigned char *) buffer, pkt_len);
+
+ eir_reg = m_nic_read (CTL_REG_EIR);
+ } while (pkt_cnt); /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
+}
+
+static void encWriteReg (unsigned char regNo, unsigned char data)
+{
+ spi_lock ();
+ enc_cfg_spi ();
+ enc_enable ();
+
+ spi_write (0x40 | regNo); /* write in regNo */
+ spi_write (data);
+
+ enc_disable ();
+ enc_enable ();
+
+ spi_write (0x1f); /* write reg 0x1f */
+
+ enc_disable ();
+ spi_unlock ();
+}
+
+static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c)
+{
+ unsigned char readback;
+ int i;
+
+ spi_lock ();
+
+ for (i = 0; i < c; i++) {
+ enc_cfg_spi ();
+ enc_enable ();
+
+ spi_write (0x40 | regNo); /* write in regNo */
+ spi_write (data);
+
+ enc_disable ();
+ enc_enable ();
+
+ spi_write (0x1f); /* write reg 0x1f */
+
+ enc_disable ();
+
+ spi_unlock (); /* we must unlock spi first */
+
+ readback = encReadReg (regNo);
+
+ spi_lock ();
+
+ if (readback == data)
+ break;
+ }
+ spi_unlock ();
+
+ if (i == c) {
+ printf ("enc28j60: write reg %d failed\n", regNo);
+ }
+}
+
+static unsigned char encReadReg (unsigned char regNo)
+{
+ unsigned char rxByte;
+
+ spi_lock ();
+ enc_cfg_spi ();
+ enc_enable ();
+
+ spi_write (0x1f); /* read reg 0x1f */
+
+ bank = spi_read () & 0x3;
+
+ enc_disable ();
+ enc_enable ();
+
+ spi_write (regNo);
+ rxByte = spi_read ();
+
+ /* check if MAC or MII register */
+ if (((bank == 2) && (regNo <= 0x1a)) ||
+ ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) {
+ /* ignore first byte and read another byte */
+ rxByte = spi_read ();
+ }
+
+ enc_disable ();
+ spi_unlock ();
+
+ return rxByte;
+}
+
+static void encReadBuff (unsigned short length, unsigned char *pBuff)
+{
+ spi_lock ();
+ enc_cfg_spi ();
+ enc_enable ();
+
+ spi_write (0x20 | 0x1a); /* read buffer memory */
+
+ while (length--) {
+ if (pBuff != NULL)
+ *pBuff++ = spi_read ();
+ else
+ spi_write (0);
+ }
+
+ enc_disable ();
+ spi_unlock ();
+}
+
+static void encWriteBuff (unsigned short length, unsigned char *pBuff)
+{
+ spi_lock ();
+ enc_cfg_spi ();
+ enc_enable ();
+
+ spi_write (0x60 | 0x1a); /* write buffer memory */
+
+ spi_write (0x00); /* control byte */
+
+ while (length--)
+ spi_write (*pBuff++);
+
+ enc_disable ();
+ spi_unlock ();
+}
+
+static void encBitSet (unsigned char regNo, unsigned char data)
+{
+ spi_lock ();
+ enc_cfg_spi ();
+ enc_enable ();
+
+ spi_write (0x80 | regNo); /* bit field set */
+ spi_write (data);
+
+ enc_disable ();
+ spi_unlock ();
+}
+
+static void encBitClr (unsigned char regNo, unsigned char data)
+{
+ spi_lock ();
+ enc_cfg_spi ();
+ enc_enable ();
+
+ spi_write (0xA0 | regNo); /* bit field clear */
+ spi_write (data);
+
+ enc_disable ();
+ spi_unlock ();
+}
+
+static void encReset (void)
+{
+ spi_lock ();
+ enc_cfg_spi ();
+ enc_enable ();
+
+ spi_write (0xff); /* soft reset */
+
+ enc_disable ();
+ spi_unlock ();
+
+ /* sleep 1 ms. See errata pt. 2 */
+ udelay (1000);
+}
+
+static void encInit (unsigned char *pEthAddr)
+{
+ unsigned short phid1 = 0;
+ unsigned short phid2 = 0;
+
+ /* switch to bank 0 */
+ m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+ /*
+ * Setup the buffer space. The reset values are valid for the
+ * other pointers.
+ */
+ /* We shall not write to ERXST, see errata pt. 5. Instead we
+ have to make sure that ENC_RX_BUS_START is 0. */
+ m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1);
+ m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1);
+
+ /* taken from the Linux driver */
+ m_nic_write_retry (CTL_REG_ERXNDL, (ENC_RX_BUF_END & 0xFF), 1);
+ m_nic_write_retry (CTL_REG_ERXNDH, (ENC_RX_BUF_END >> 8), 1);
+
+ m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1);
+ m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1);
+
+ next_pointer_lsb = (ENC_RX_BUF_START & 0xFF);
+ next_pointer_msb = (ENC_RX_BUF_START >> 8);
+
+ /* verify identification */
+ phid1 = phyRead (PHY_REG_PHID1);
+ phid2 = phyRead (PHY_REG_PHID2);
+
+ if (phid1 != ENC_PHID1_VALUE
+ || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) {
+ printf ("ERROR: failed to identify controller\n");
+ printf ("phid1 = %x, phid2 = %x\n",
+ phid1, (phid2 & ENC_PHID2_MASK));
+ printf ("should be phid1 = %x, phid2 = %x\n",
+ ENC_PHID1_VALUE, ENC_PHID2_VALUE);
+ }
+
+ /*
+ * --- MAC Initialization ---
+ */
+
+ /* Pull MAC out of Reset */
+
+ /* switch to bank 2 */
+ m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+ m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+ /* enable MAC to receive frames */
+ /* added some bits from the Linux driver */
+ m_nic_write_retry (CTL_REG_MACON1
+ ,(ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS)
+ ,10);
+
+ /* configure pad, tx-crc and duplex */
+ /* added a bit from the Linux driver */
+ m_nic_write_retry (CTL_REG_MACON3
+ ,(ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN | ENC_MACON3_FRMLNEN)
+ ,10);
+
+ /* added 4 new lines from the Linux driver */
+ /* Allow infinite deferals if the medium is continously busy */
+ m_nic_write_retry(CTL_REG_MACON4, (1<<6) /*ENC_MACON4_DEFER*/, 10);
+
+ /* Late collisions occur beyond 63 bytes */
+ m_nic_write_retry(CTL_REG_MACLCON2, 63, 10);
+
+ /* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */
+ m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10);
+
+ /*
+ * Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended
+ * 0x0c for half-duplex. Nothing for full-duplex
+ */
+ m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10);
+
+ /* set maximum frame length */
+ m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10);
+ m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10);
+
+ /*
+ * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex
+ * and 0x15 for full duplex.
+ */
+ m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10);
+
+ /* set MAC address */
+
+ /* switch to bank 3 */
+ m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1));
+
+ m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1);
+ m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1);
+ m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1);
+ m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1);
+ m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1);
+ m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1);
+
+ /*
+ * PHY Initialization taken from the Linux driver
+ */
+
+ /* Prevent automatic loopback of data beeing transmitted by setting
+ ENC_PHCON2_HDLDIS */
+ phyWrite(PHY_REG_PHCON2, (1<<8));
+
+ /* LEDs configuration
+ * LEDA: LACFG = 0100 -> display link status
+ * LEDB: LBCFG = 0111 -> display TX & RX activity
+ * STRCH = 1 -> LED pulses
+ */
+ phyWrite(PHY_REG_PHLCON, 0x0472);
+
+ /* Reset PDPXMD-bit => half duplex */
+ phyWrite(PHY_REG_PHCON1, 0);
+
+ /*
+ * Receive settings
+ */
+
+#ifdef CONFIG_USE_IRQ
+ /* enable interrupts */
+ m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE);
+ m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE);
+ m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE);
+ m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE);
+ m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+}
+
+/*****************************************************************************
+ *
+ * Description:
+ * Read PHY registers.
+ *
+ * NOTE! This function will change to Bank 2.
+ *
+ * Params:
+ * [in] addr address of the register to read
+ *
+ * Returns:
+ * The value in the register
+ */
+static unsigned short phyRead (unsigned char addr)
+{
+ unsigned short ret = 0;
+
+ /* move to bank 2 */
+ m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+ m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+ /* write address to MIREGADR */
+ m_nic_write (CTL_REG_MIREGADR, addr);
+
+ /* set MICMD.MIIRD */
+ m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD);
+
+ /* taken from the Linux driver */
+ /* move to bank 3 */
+ m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+ m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+ /* poll MISTAT.BUSY bit until operation is complete */
+ while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
+ static int cnt = 0;
+
+ if (cnt++ >= 1000) {
+ /* GJ - this seems extremely dangerous! */
+ /* printf("#"); */
+ cnt = 0;
+ }
+ }
+
+ /* taken from the Linux driver */
+ /* move to bank 2 */
+ m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+ m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+ /* clear MICMD.MIIRD */
+ m_nic_write (CTL_REG_MICMD, 0);
+
+ ret = (m_nic_read (CTL_REG_MIRDH) << 8);
+ ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF);
+
+ return ret;
+}
+
+/*****************************************************************************
+ *
+ * Taken from the Linux driver.
+ * Description:
+ * Write PHY registers.
+ *
+ * NOTE! This function will change to Bank 3.
+ *
+ * Params:
+ * [in] addr address of the register to write to
+ * [in] data to be written
+ *
+ * Returns:
+ * None
+ */
+static void phyWrite(unsigned char addr, unsigned short data)
+{
+ /* move to bank 2 */
+ m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+ m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+ /* write address to MIREGADR */
+ m_nic_write(CTL_REG_MIREGADR, addr);
+
+ m_nic_write(CTL_REG_MIWRL, data & 0xff);
+ m_nic_write(CTL_REG_MIWRH, data >> 8);
+
+ /* move to bank 3 */
+ m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+ m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+ /* poll MISTAT.BUSY bit until operation is complete */
+ while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
+ static int cnt = 0;
+
+ if(cnt++ >= 1000) {
+ cnt = 0;
+ }
+ }
+}
+
+#endif /* CONFIG_ENC28J60 */
diff --git a/drivers/fsl_i2c.c b/drivers/fsl_i2c.c
index ebae5af154..22485ea916 100644
--- a/drivers/fsl_i2c.c
+++ b/drivers/fsl_i2c.c
@@ -69,9 +69,10 @@ i2c_init(int speed, int slaveadd)
dev = (struct fsl_i2c *) (CFG_IMMR + CFG_I2C2_OFFSET);
writeb(0, &dev->cr); /* stop I2C controller */
+ udelay(5); /* let it shutdown in peace */
writeb(0x3F, &dev->fdr); /* set bus speed */
writeb(0x3F, &dev->dfsrr); /* set default filter */
- writeb(slaveadd, &dev->adr); /* write slave address */
+ writeb(slaveadd << 1, &dev->adr); /* write slave address */
writeb(0x0, &dev->sr); /* clear status register */
writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */
#endif /* CFG_I2C2_OFFSET */
diff --git a/drivers/fsl_pci_init.c b/drivers/fsl_pci_init.c
new file mode 100644
index 0000000000..3a13eea1f2
--- /dev/null
+++ b/drivers/fsl_pci_init.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * 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>
+
+#ifdef CONFIG_FSL_PCI_INIT
+
+/*
+ * PCI/PCIE Controller initialization for mpc85xx/mpc86xx soc's
+ *
+ * Initialize controller and call the common driver/pci pci_hose_scan to
+ * scan for bridges and devices.
+ *
+ * Hose fields which need to be pre-initialized by board specific code:
+ * regions[]
+ * first_busno
+ *
+ * Fields updated:
+ * last_busno
+ */
+
+#include <pci.h>
+#include <asm/immap_fsl_pci.h>
+
+void pciauto_prescan_setup_bridge(struct pci_controller *hose,
+ pci_dev_t dev, int sub_bus);
+void pciauto_postscan_setup_bridge(struct pci_controller *hose,
+ pci_dev_t dev, int sub_bus);
+
+void pciauto_config_init(struct pci_controller *hose);
+void
+fsl_pci_init(struct pci_controller *hose)
+{
+ u16 temp16;
+ u32 temp32;
+ int busno = hose->first_busno;
+ int enabled;
+ u16 ltssm;
+ u8 temp8;
+ int r;
+ int bridge;
+ volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) hose->cfg_addr;
+ pci_dev_t dev = PCI_BDF(busno,0,0);
+
+ /* Initialize ATMU registers based on hose regions and flags */
+ volatile pot_t *po=&pci->pot[1]; /* skip 0 */
+ volatile pit_t *pi=&pci->pit[0]; /* ranges from: 3 to 1 */
+
+#ifdef DEBUG
+ int neg_link_w;
+#endif
+
+ for (r=0; r<hose->region_count; r++) {
+ if (hose->regions[r].flags & PCI_REGION_MEMORY) { /* inbound */
+ pi->pitar = (hose->regions[r].bus_start >> 12) & 0x000fffff;
+ pi->piwbar = (hose->regions[r].phys_start >> 12) & 0x000fffff;
+ pi->piwbear = 0;
+ pi->piwar = PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP |
+ (__ilog2(hose->regions[r].size) - 1);
+ pi++;
+ } else { /* Outbound */
+ po->powbar = (hose->regions[r].phys_start >> 12) & 0x000fffff;
+ po->potar = (hose->regions[r].bus_start >> 12) & 0x000fffff;
+ po->potear = 0;
+ if (hose->regions[r].flags & PCI_REGION_IO)
+ po->powar = POWAR_EN | POWAR_IO_READ | POWAR_IO_WRITE |
+ (__ilog2(hose->regions[r].size) - 1);
+ else
+ po->powar = POWAR_EN | POWAR_MEM_READ | POWAR_MEM_WRITE |
+ (__ilog2(hose->regions[r].size) - 1);
+ po++;
+ }
+ }
+
+ pci_register_hose(hose);
+ pciauto_config_init(hose); /* grab pci_{mem,prefetch,io} */
+ hose->current_busno = hose->first_busno;
+
+ pci->pedr = 0xffffffff; /* Clear any errors */
+ pci->peer = ~0x20140; /* Enable All Error Interupts except
+ * - Master abort (pci)
+ * - Master PERR (pci)
+ * - ICCA (PCIe)
+ */
+ pci_hose_read_config_dword (hose, dev, PCI_DCR, &temp32);
+ temp32 |= 0xf000e; /* set URR, FER, NFER (but not CER) */
+ pci_hose_write_config_dword(hose, dev, PCI_DCR, temp32);
+
+ pci_hose_read_config_byte (hose, dev, PCI_HEADER_TYPE, &temp8);
+ bridge = temp8 & PCI_HEADER_TYPE_BRIDGE; /* Bridge, such as pcie */
+
+ if ( bridge ) {
+
+ pci_hose_read_config_word(hose, dev, PCI_LTSSM, &ltssm);
+ enabled = ltssm >= PCI_LTSSM_L0;
+
+ if (!enabled) {
+ debug("....PCIE link error. Skipping scan."
+ "LTSSM=0x%02x\n", ltssm);
+ hose->last_busno = hose->first_busno;
+ return;
+ }
+
+ pci->pme_msg_det = 0xffffffff;
+ pci->pme_msg_int_en = 0xffffffff;
+#ifdef DEBUG
+ pci_hose_read_config_word(hose, dev, PCI_LSR, &temp16);
+ neg_link_w = (temp16 & 0x3f0 ) >> 4;
+ printf("...PCIE LTSSM=0x%x, Negotiated link width=%d\n",
+ ltssm, neg_link_w);
+#endif
+ hose->current_busno++; /* Start scan with secondary */
+ pciauto_prescan_setup_bridge(hose, dev, hose->current_busno);
+
+ }
+
+ /* Use generic setup_device to initialize standard pci regs,
+ * but do not allocate any windows since any BAR found (such
+ * as PCSRBAR) is not in this cpu's memory space.
+ */
+
+ pciauto_setup_device(hose, dev, 0, hose->pci_mem,
+ hose->pci_prefetch, hose->pci_io);
+
+#ifndef CONFIG_PCI_NOSCAN
+ printf (" Scanning PCI bus %02x\n", hose->current_busno);
+ hose->last_busno = pci_hose_scan_bus(hose,hose->current_busno);
+
+ if ( bridge ) { /* update limit regs and subordinate busno */
+ pciauto_postscan_setup_bridge(hose, dev, hose->last_busno);
+ }
+#else
+ hose->last_busno = hose->current_busno;
+#endif
+
+ /* Clear all error indications */
+
+ pci->pme_msg_det = 0xffffffff;
+ pci->pedr = 0xffffffff;
+
+ pci_hose_read_config_word (hose, dev, PCI_DSR, &temp16);
+ if (temp16) {
+ pci_hose_write_config_word(hose, dev,
+ PCI_DSR, 0xffff);
+ }
+
+ pci_hose_read_config_word (hose, dev, PCI_SEC_STATUS, &temp16);
+ if (temp16) {
+ pci_hose_write_config_word(hose, dev, PCI_SEC_STATUS, 0xffff);
+ }
+}
+
+#endif /* CONFIG_FSL_PCI */
diff --git a/drivers/inca-ip_sw.c b/drivers/inca-ip_sw.c
index ab22b4d538..e4aaed6afb 100644
--- a/drivers/inca-ip_sw.c
+++ b/drivers/inca-ip_sw.c
@@ -26,8 +26,8 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
- && defined(CONFIG_INCA_IP_SWITCH)
+#if defined(CONFIG_CMD_NET) \
+ && defined(CONFIG_NET_MULTI) && defined(CONFIG_INCA_IP_SWITCH)
#include <malloc.h>
#include <net.h>
diff --git a/drivers/isp116x-hcd.c b/drivers/isp116x-hcd.c
new file mode 100644
index 0000000000..8e2bc7adcc
--- /dev/null
+++ b/drivers/isp116x-hcd.c
@@ -0,0 +1,1413 @@
+/*
+ * ISP116x HCD (Host Controller Driver) for u-boot.
+ *
+ * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * 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
+ *
+ *
+ * Derived in part from the SL811 HCD driver "u-boot/drivers/sl811_usb.c"
+ * (original copyright message follows):
+ *
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This code is based on linux driver for sl811hs chip, source at
+ * drivers/usb/host/sl811.c:
+ *
+ * SL811 Host Controller Interface driver for USB.
+ *
+ * Copyright (c) 2003/06, Courage Co., Ltd.
+ *
+ * Based on:
+ * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
+ * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
+ * Adam Richter, Gregory P. Smith;
+ * 2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
+ * 3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
+ *
+ * [[GNU/GPL disclaimer]]
+ *
+ * and in part from AU1x00 OHCI HCD driver "u-boot/cpu/mips/au1x00_usb_ohci.c"
+ * (original copyright message follows):
+ *
+ * URB OHCI HCD (Host Controller Driver) for USB on the AU1x00.
+ *
+ * (C) Copyright 2003
+ * Gary Jennejohn, DENX Software Engineering <gj@denx.de>
+ *
+ * [[GNU/GPL disclaimer]]
+ *
+ * Note: Part of this code has been derived from linux
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_USB_ISP116X_HCD
+#include <asm/io.h>
+#include <usb.h>
+#include <malloc.h>
+#include <linux/list.h>
+
+/*
+ * ISP116x chips require certain delays between accesses to its
+ * registers. The following timing options exist.
+ *
+ * 1. Configure your memory controller (the best)
+ * 2. Use ndelay (easiest, poorest). For that, enable the following macro.
+ *
+ * Value is in microseconds.
+ */
+#ifdef ISP116X_HCD_USE_UDELAY
+#define UDELAY 1
+#endif
+
+/*
+ * On some (slowly?) machines an extra delay after data packing into
+ * controller's FIFOs is required, * otherwise you may get the following
+ * error:
+ *
+ * uboot> usb start
+ * (Re)start USB...
+ * USB: scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT
+ * isp116x: isp116x_submit_job: ****** FIFO not ready! ******
+ *
+ * USB device not responding, giving up (status=4)
+ * isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ * isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ * isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ * 3 USB Device(s) found
+ * scanning bus for storage devices... 0 Storage Device(s) found
+ *
+ * Value is in milliseconds.
+ */
+#ifdef ISP116X_HCD_USE_EXTRA_DELAY
+#define EXTRA_DELAY 2
+#endif
+
+/*
+ * Enable the following defines if you wish enable debugging messages.
+ */
+#undef DEBUG /* enable debugging messages */
+#undef TRACE /* enable tracing code */
+#undef VERBOSE /* verbose debugging messages */
+
+#include "isp116x.h"
+
+#define DRIVER_VERSION "08 Jan 2007"
+static const char hcd_name[] = "isp116x-hcd";
+
+struct isp116x isp116x_dev;
+struct isp116x_platform_data isp116x_board;
+int got_rhsc = 0; /* root hub status change */
+struct usb_device *devgone; /* device which was disconnected */
+int rh_devnum = 0; /* address of Root Hub endpoint */
+
+/* ------------------------------------------------------------------------- */
+
+#define ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL))
+#define min_t(type,x,y) \
+ ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
+
+/* ------------------------------------------------------------------------- */
+
+static int isp116x_reset(struct isp116x *isp116x);
+
+/* --- Debugging functions ------------------------------------------------- */
+
+#define isp116x_show_reg(d, r) { \
+ if ((r) < 0x20) { \
+ DBG("%-12s[%02x]: %08x", #r, \
+ r, isp116x_read_reg32(d, r)); \
+ } else { \
+ DBG("%-12s[%02x]: %04x", #r, \
+ r, isp116x_read_reg16(d, r)); \
+ } \
+}
+
+#define isp116x_show_regs(d) { \
+ isp116x_show_reg(d, HCREVISION); \
+ isp116x_show_reg(d, HCCONTROL); \
+ isp116x_show_reg(d, HCCMDSTAT); \
+ isp116x_show_reg(d, HCINTSTAT); \
+ isp116x_show_reg(d, HCINTENB); \
+ isp116x_show_reg(d, HCFMINTVL); \
+ isp116x_show_reg(d, HCFMREM); \
+ isp116x_show_reg(d, HCFMNUM); \
+ isp116x_show_reg(d, HCLSTHRESH); \
+ isp116x_show_reg(d, HCRHDESCA); \
+ isp116x_show_reg(d, HCRHDESCB); \
+ isp116x_show_reg(d, HCRHSTATUS); \
+ isp116x_show_reg(d, HCRHPORT1); \
+ isp116x_show_reg(d, HCRHPORT2); \
+ isp116x_show_reg(d, HCHWCFG); \
+ isp116x_show_reg(d, HCDMACFG); \
+ isp116x_show_reg(d, HCXFERCTR); \
+ isp116x_show_reg(d, HCuPINT); \
+ isp116x_show_reg(d, HCuPINTENB); \
+ isp116x_show_reg(d, HCCHIPID); \
+ isp116x_show_reg(d, HCSCRATCH); \
+ isp116x_show_reg(d, HCITLBUFLEN); \
+ isp116x_show_reg(d, HCATLBUFLEN); \
+ isp116x_show_reg(d, HCBUFSTAT); \
+ isp116x_show_reg(d, HCRDITL0LEN); \
+ isp116x_show_reg(d, HCRDITL1LEN); \
+}
+
+#if defined(TRACE)
+
+static int isp116x_get_current_frame_number(struct usb_device *usb_dev)
+{
+ struct isp116x *isp116x = &isp116x_dev;
+
+ return isp116x_read_reg32(isp116x, HCFMNUM);
+}
+
+static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, char *str)
+{
+#if defined(VERBOSE)
+ int i;
+#endif
+
+ DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx",
+ str,
+ isp116x_get_current_frame_number(dev),
+ usb_pipedevice(pipe),
+ usb_pipeendpoint(pipe),
+ usb_pipeout(pipe) ? 'O' : 'I',
+ usb_pipetype(pipe) < 2 ?
+ (usb_pipeint(pipe) ?
+ "INTR" : "ISOC") :
+ (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status);
+#if defined(VERBOSE)
+ if (len > 0 && buffer) {
+ printf(__FILE__ ": data(%d):", len);
+ for (i = 0; i < 16 && i < len; i++)
+ printf(" %02x", ((__u8 *) buffer)[i]);
+ printf("%s\n", i < len ? "..." : "");
+ }
+#endif
+}
+
+#define PTD_DIR_STR(ptd) ({char __c; \
+ switch(PTD_GET_DIR(ptd)){ \
+ case 0: __c = 's'; break; \
+ case 1: __c = 'o'; break; \
+ default: __c = 'i'; break; \
+ }; __c;})
+
+/*
+ Dump PTD info. The code documents the format
+ perfectly, right :)
+*/
+static inline void dump_ptd(struct ptd *ptd)
+{
+#if defined(VERBOSE)
+ int k;
+#endif
+
+ DBG("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x",
+ PTD_GET_CC(ptd),
+ PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd),
+ PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd),
+ PTD_GET_TOGGLE(ptd),
+ PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd));
+#if defined(VERBOSE)
+ printf("isp116x: %s: PTD(byte): ", __FUNCTION__);
+ for (k = 0; k < sizeof(struct ptd); ++k)
+ printf("%02x ", ((u8 *) ptd)[k]);
+ printf("\n");
+#endif
+}
+
+static inline void dump_ptd_data(struct ptd *ptd, u8 * buf, int type)
+{
+#if defined(VERBOSE)
+ int k;
+
+ if (type == 0 /* 0ut data */ ) {
+ printf("isp116x: %s: out data: ", __FUNCTION__);
+ for (k = 0; k < PTD_GET_LEN(ptd); ++k)
+ printf("%02x ", ((u8 *) buf)[k]);
+ printf("\n");
+ }
+ if (type == 1 /* 1n data */ ) {
+ printf("isp116x: %s: in data: ", __FUNCTION__);
+ for (k = 0; k < PTD_GET_COUNT(ptd); ++k)
+ printf("%02x ", ((u8 *) buf)[k]);
+ printf("\n");
+ }
+
+ if (PTD_GET_LAST(ptd))
+ DBG("--- last PTD ---");
+#endif
+}
+
+#else
+
+#define dump_msg(dev, pipe, buffer, len, str) do { } while (0)
+#define dump_pkt(dev, pipe, buffer, len, setup, str, small) do {} while (0)
+
+#define dump_ptd(ptd) do {} while (0)
+#define dump_ptd_data(ptd, buf, type) do {} while (0)
+
+#endif
+
+/* --- Virtual Root Hub ---------------------------------------------------- */
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] = {
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x01, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] = {
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x00, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x02,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] = {
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] = {
+ 0x22, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'I', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'S', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'P', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '1', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '1', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '6', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'x', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+/*
+ * Hub class-specific descriptor is constructed dynamically
+ */
+
+/* --- Virtual root hub management functions ------------------------------- */
+
+static int rh_check_port_status(struct isp116x *isp116x)
+{
+ u32 temp, ndp, i;
+ int res;
+
+ res = -1;
+ temp = isp116x_read_reg32(isp116x, HCRHSTATUS);
+ ndp = (temp & RH_A_NDP);
+ for (i = 0; i < ndp; i++) {
+ temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i);
+ /* check for a device disconnect */
+ if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+ (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) {
+ res = i;
+ break;
+ }
+ }
+ return res;
+}
+
+/* --- HC management functions --------------------------------------------- */
+
+/* Write len bytes to fifo, pad till 32-bit boundary
+ */
+static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
+{
+ u8 *dp = (u8 *) buf;
+ u16 *dp2 = (u16 *) buf;
+ u16 w;
+ int quot = len % 4;
+
+ if ((unsigned long)dp2 & 1) {
+ /* not aligned */
+ for (; len > 1; len -= 2) {
+ w = *dp++;
+ w |= *dp++ << 8;
+ isp116x_raw_write_data16(isp116x, w);
+ }
+ if (len)
+ isp116x_write_data16(isp116x, (u16) * dp);
+ } else {
+ /* aligned */
+ for (; len > 1; len -= 2)
+ isp116x_raw_write_data16(isp116x, *dp2++);
+ if (len)
+ isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2));
+ }
+ if (quot == 1 || quot == 2)
+ isp116x_raw_write_data16(isp116x, 0);
+}
+
+/* Read len bytes from fifo and then read till 32-bit boundary
+ */
+static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
+{
+ u8 *dp = (u8 *) buf;
+ u16 *dp2 = (u16 *) buf;
+ u16 w;
+ int quot = len % 4;
+
+ if ((unsigned long)dp2 & 1) {
+ /* not aligned */
+ for (; len > 1; len -= 2) {
+ w = isp116x_raw_read_data16(isp116x);
+ *dp++ = w & 0xff;
+ *dp++ = (w >> 8) & 0xff;
+ }
+ if (len)
+ *dp = 0xff & isp116x_read_data16(isp116x);
+ } else {
+ /* aligned */
+ for (; len > 1; len -= 2)
+ *dp2++ = isp116x_raw_read_data16(isp116x);
+ if (len)
+ *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x);
+ }
+ if (quot == 1 || quot == 2)
+ isp116x_raw_read_data16(isp116x);
+}
+
+/* Write PTD's and data for scheduled transfers into the fifo ram.
+ * Fifo must be empty and ready */
+static void pack_fifo(struct isp116x *isp116x, struct usb_device *dev,
+ unsigned long pipe, struct ptd *ptd, int n, void *data,
+ int len)
+{
+ int buflen = n * sizeof(struct ptd) + len;
+ int i, done;
+
+ DBG("--- pack buffer %p - %d bytes (fifo %d) ---", data, len, buflen);
+
+ isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
+ isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
+ isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
+
+ done = 0;
+ for (i = 0; i < n; i++) {
+ DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i]));
+
+ dump_ptd(&ptd[i]);
+ isp116x_write_data16(isp116x, ptd[i].count);
+ isp116x_write_data16(isp116x, ptd[i].mps);
+ isp116x_write_data16(isp116x, ptd[i].len);
+ isp116x_write_data16(isp116x, ptd[i].faddr);
+
+ dump_ptd_data(&ptd[i], (__u8 *) data + done, 0);
+ write_ptddata_to_fifo(isp116x,
+ (__u8 *) data + done,
+ PTD_GET_LEN(&ptd[i]));
+
+ done += PTD_GET_LEN(&ptd[i]);
+ }
+}
+
+/* Read the processed PTD's and data from fifo ram back to URBs' buffers.
+ * Fifo must be full and done */
+static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev,
+ unsigned long pipe, struct ptd *ptd, int n, void *data,
+ int len)
+{
+ int buflen = n * sizeof(struct ptd) + len;
+ int i, done, cc, ret;
+
+ isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
+ isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
+ isp116x_write_addr(isp116x, HCATLPORT);
+
+ ret = TD_CC_NOERROR;
+ done = 0;
+ for (i = 0; i < n; i++) {
+ DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i]));
+
+ ptd[i].count = isp116x_read_data16(isp116x);
+ ptd[i].mps = isp116x_read_data16(isp116x);
+ ptd[i].len = isp116x_read_data16(isp116x);
+ ptd[i].faddr = isp116x_read_data16(isp116x);
+ dump_ptd(&ptd[i]);
+
+ read_ptddata_from_fifo(isp116x,
+ (__u8 *) data + done,
+ PTD_GET_LEN(&ptd[i]));
+ dump_ptd_data(&ptd[i], (__u8 *) data + done, 1);
+
+ done += PTD_GET_LEN(&ptd[i]);
+
+ cc = PTD_GET_CC(&ptd[i]);
+ if (cc == TD_DATAUNDERRUN) { /* underrun is no error... */
+ DBG("allowed data underrun");
+ cc = TD_CC_NOERROR;
+ }
+ if (cc != TD_CC_NOERROR && ret == TD_CC_NOERROR)
+ ret = cc;
+ }
+
+ DBG("--- unpack buffer %p - %d bytes (fifo %d) ---", data, len, buflen);
+
+ return ret;
+}
+
+/* Interrupt handling
+ */
+static int isp116x_interrupt(struct isp116x *isp116x)
+{
+ u16 irqstat;
+ u32 intstat;
+ int ret = 0;
+
+ isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+ irqstat = isp116x_read_reg16(isp116x, HCuPINT);
+ isp116x_write_reg16(isp116x, HCuPINT, irqstat);
+ DBG(">>>>>> irqstat %x <<<<<<", irqstat);
+
+ if (irqstat & HCuPINT_ATL) {
+ DBG(">>>>>> HCuPINT_ATL <<<<<<");
+ udelay(500);
+ ret = 1;
+ }
+
+ if (irqstat & HCuPINT_OPR) {
+ intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
+ isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
+ DBG(">>>>>> HCuPINT_OPR %x <<<<<<", intstat);
+
+ if (intstat & HCINT_UE) {
+ ERR("unrecoverable error, controller disabled");
+
+ /* FIXME: be optimistic, hope that bug won't repeat
+ * often. Make some non-interrupt context restart the
+ * controller. Count and limit the retries though;
+ * either hardware or software errors can go forever...
+ */
+ isp116x_reset(isp116x);
+ ret = -1;
+ return -1;
+ }
+
+ if (intstat & HCINT_RHSC) {
+ got_rhsc = 1;
+ ret = 1;
+ /* When root hub or any of its ports is going
+ to come out of suspend, it may take more
+ than 10ms for status bits to stabilize. */
+ wait_ms(20);
+ }
+
+ if (intstat & HCINT_SO) {
+ ERR("schedule overrun");
+ ret = -1;
+ }
+
+ irqstat &= ~HCuPINT_OPR;
+ }
+
+ return ret;
+}
+
+#define PTD_NUM 64 /* it should be enougth... */
+struct ptd ptd[PTD_NUM];
+static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe)
+{
+ return min(PTD_NUM * usb_maxpacket(dev, pipe), PTD_NUM * 16);
+}
+
+/* Do an USB transfer
+ */
+static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
+ int dir, void *buffer, int len)
+{
+ struct isp116x *isp116x = &isp116x_dev;
+ int type = usb_pipetype(pipe);
+ int epnum = usb_pipeendpoint(pipe);
+ int max = usb_maxpacket(dev, pipe);
+ int dir_out = usb_pipeout(pipe);
+ int speed_low = usb_pipeslow(pipe);
+ int i, done, stat, timeout, cc;
+ int retries = 10;
+
+ DBG("------------------------------------------------");
+ dump_msg(dev, pipe, buffer, len, "SUBMIT");
+ DBG("------------------------------------------------");
+
+ if (isp116x->disabled) {
+ ERR("EPIPE");
+ dev->status = USB_ST_CRC_ERR;
+ return -1;
+ }
+
+ /* device pulled? Shortcut the action. */
+ if (devgone == dev) {
+ ERR("ENODEV");
+ dev->status = USB_ST_CRC_ERR;
+ return USB_ST_CRC_ERR;
+ }
+
+ if (!max) {
+ ERR("pipesize for pipe %lx is zero", pipe);
+ dev->status = USB_ST_CRC_ERR;
+ return -1;
+ }
+
+ if (type == PIPE_ISOCHRONOUS) {
+ ERR("isochronous transfers not supported");
+ dev->status = USB_ST_CRC_ERR;
+ return -1;
+ }
+
+ /* FIFO not empty? */
+ if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) {
+ ERR("****** FIFO not empty! ******");
+ dev->status = USB_ST_BUF_ERR;
+ return -1;
+ }
+
+ retry:
+ isp116x_write_reg32(isp116x, HCINTSTAT, 0xff);
+
+ /* Prepare the PTD data */
+ done = 0;
+ i = 0;
+ do {
+ ptd[i].count = PTD_CC_MSK | PTD_ACTIVE_MSK |
+ PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out));
+ ptd[i].mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum);
+ ptd[i].len = PTD_LEN(max > len - done ? len - done : max) |
+ PTD_DIR(dir);
+ ptd[i].faddr = PTD_FA(usb_pipedevice(pipe));
+
+ usb_dotoggle(dev, epnum, dir_out);
+ done += PTD_GET_LEN(&ptd[i]);
+ i++;
+ if (i >= PTD_NUM) {
+ ERR("****** Cannot pack buffer! ******");
+ dev->status = USB_ST_BUF_ERR;
+ return -1;
+ }
+ } while (done < len);
+ ptd[i - 1].mps |= PTD_LAST_MSK;
+
+ /* Pack data into FIFO ram */
+ pack_fifo(isp116x, dev, pipe, ptd, i, buffer, len);
+#ifdef EXTRA_DELAY
+ wait_ms(EXTRA_DELAY);
+#endif
+
+ /* Start the data transfer */
+
+ /* Allow more time for a BULK device to react - some are slow */
+ if (usb_pipetype(pipe) == PIPE_BULK)
+ timeout = 5000;
+ else
+ timeout = 100;
+
+ /* Wait for it to complete */
+ for (;;) {
+ /* Check whether the controller is done */
+ stat = isp116x_interrupt(isp116x);
+
+ if (stat < 0) {
+ dev->status = USB_ST_CRC_ERR;
+ break;
+ }
+ if (stat > 0)
+ break;
+
+ /* Check the timeout */
+ if (--timeout)
+ udelay(1);
+ else {
+ ERR("CTL:TIMEOUT ");
+ stat = USB_ST_CRC_ERR;
+ break;
+ }
+ }
+
+ /* We got an Root Hub Status Change interrupt */
+ if (got_rhsc) {
+ isp116x_show_regs(isp116x);
+
+ got_rhsc = 0;
+
+ /* Abuse timeout */
+ timeout = rh_check_port_status(isp116x);
+ if (timeout >= 0) {
+ /*
+ * FIXME! NOTE! AAAARGH!
+ * This is potentially dangerous because it assumes
+ * that only one device is ever plugged in!
+ */
+ devgone = dev;
+ }
+ }
+
+ /* Ok, now we can read transfer status */
+
+ /* FIFO not ready? */
+ if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) {
+ ERR("****** FIFO not ready! ******");
+ dev->status = USB_ST_BUF_ERR;
+ return -1;
+ }
+
+ /* Unpack data from FIFO ram */
+ cc = unpack_fifo(isp116x, dev, pipe, ptd, i, buffer, len);
+
+ /* Mmm... sometime we get 0x0f as cc which is a non sense!
+ * Just retry the transfer...
+ */
+ if (cc == 0x0f && retries-- > 0) {
+ usb_dotoggle(dev, epnum, dir_out);
+ goto retry;
+ }
+
+ if (cc != TD_CC_NOERROR) {
+ DBG("****** completition code error %x ******", cc);
+ switch (cc) {
+ case TD_CC_BITSTUFFING:
+ dev->status = USB_ST_BIT_ERR;
+ break;
+ case TD_CC_STALL:
+ dev->status = USB_ST_STALLED;
+ break;
+ case TD_BUFFEROVERRUN:
+ case TD_BUFFERUNDERRUN:
+ dev->status = USB_ST_BUF_ERR;
+ break;
+ default:
+ dev->status = USB_ST_CRC_ERR;
+ }
+ return -cc;
+ }
+
+ dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)");
+
+ dev->status = 0;
+ return done;
+}
+
+/* Adapted from au1x00_usb_ohci.c
+ */
+static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len,
+ struct devrequest *cmd)
+{
+ struct isp116x *isp116x = &isp116x_dev;
+ u32 tmp = 0;
+
+ int leni = transfer_len;
+ int len = 0;
+ int stat = 0;
+ u32 datab[4];
+ u8 *data_buf = (u8 *) datab;
+ u16 bmRType_bReq;
+ u16 wValue;
+ u16 wIndex;
+ u16 wLength;
+
+ if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
+ INFO("Root-Hub submit IRQ: NOT implemented");
+ return 0;
+ }
+
+ bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+ wValue = swap_16(cmd->value);
+ wIndex = swap_16(cmd->index);
+ wLength = swap_16(cmd->length);
+
+ DBG("--- HUB ----------------------------------------");
+ DBG("submit rh urb, req=%x val=%#x index=%#x len=%d",
+ bmRType_bReq, wValue, wIndex, wLength);
+ dump_msg(dev, pipe, buffer, transfer_len, "RH");
+ DBG("------------------------------------------------");
+
+ switch (bmRType_bReq) {
+ case RH_GET_STATUS:
+ DBG("RH_GET_STATUS");
+
+ *(__u16 *) data_buf = swap_16(1);
+ len = 2;
+ break;
+
+ case RH_GET_STATUS | RH_INTERFACE:
+ DBG("RH_GET_STATUS | RH_INTERFACE");
+
+ *(__u16 *) data_buf = swap_16(0);
+ len = 2;
+ break;
+
+ case RH_GET_STATUS | RH_ENDPOINT:
+ DBG("RH_GET_STATUS | RH_ENDPOINT");
+
+ *(__u16 *) data_buf = swap_16(0);
+ len = 2;
+ break;
+
+ case RH_GET_STATUS | RH_CLASS:
+ DBG("RH_GET_STATUS | RH_CLASS");
+
+ tmp = isp116x_read_reg32(isp116x, HCRHSTATUS);
+
+ *(__u32 *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE));
+ len = 4;
+ break;
+
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ DBG("RH_GET_STATUS | RH_OTHER | RH_CLASS");
+
+ tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1);
+ *(__u32 *) data_buf = swap_32(tmp);
+ isp116x_show_regs(isp116x);
+ len = 4;
+ break;
+
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ DBG("RH_CLEAR_FEATURE | RH_ENDPOINT");
+
+ switch (wValue) {
+ case RH_ENDPOINT_STALL:
+ DBG("C_HUB_ENDPOINT_STALL");
+ len = 0;
+ break;
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ DBG("RH_CLEAR_FEATURE | RH_CLASS");
+
+ switch (wValue) {
+ case RH_C_HUB_LOCAL_POWER:
+ DBG("C_HUB_LOCAL_POWER");
+ len = 0;
+ break;
+
+ case RH_C_HUB_OVER_CURRENT:
+ DBG("C_HUB_OVER_CURRENT");
+ isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC);
+ len = 0;
+ break;
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ DBG("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS");
+
+ switch (wValue) {
+ case RH_PORT_ENABLE:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_CCS);
+ len = 0;
+ break;
+
+ case RH_PORT_SUSPEND:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_POCI);
+ len = 0;
+ break;
+
+ case RH_PORT_POWER:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_LSDA);
+ len = 0;
+ break;
+
+ case RH_C_PORT_CONNECTION:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_CSC);
+ len = 0;
+ break;
+
+ case RH_C_PORT_ENABLE:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_PESC);
+ len = 0;
+ break;
+
+ case RH_C_PORT_SUSPEND:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_PSSC);
+ len = 0;
+ break;
+
+ case RH_C_PORT_OVER_CURRENT:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_POCI);
+ len = 0;
+ break;
+
+ case RH_C_PORT_RESET:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_PRSC);
+ len = 0;
+ break;
+
+ default:
+ ERR("invalid wValue");
+ stat = USB_ST_STALLED;
+ }
+
+ isp116x_show_regs(isp116x);
+
+ break;
+
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ DBG("RH_SET_FEATURE | RH_OTHER | RH_CLASS");
+
+ switch (wValue) {
+ case RH_PORT_SUSPEND:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_PSS);
+ len = 0;
+ break;
+
+ case RH_PORT_RESET:
+ /* Spin until any current reset finishes */
+ while (1) {
+ tmp =
+ isp116x_read_reg32(isp116x,
+ HCRHPORT1 + wIndex - 1);
+ if (!(tmp & RH_PS_PRS))
+ break;
+ wait_ms(1);
+ }
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_PRS);
+ wait_ms(10);
+
+ len = 0;
+ break;
+
+ case RH_PORT_POWER:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_PPS);
+ len = 0;
+ break;
+
+ case RH_PORT_ENABLE:
+ isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+ RH_PS_PES);
+ len = 0;
+ break;
+
+ default:
+ ERR("invalid wValue");
+ stat = USB_ST_STALLED;
+ }
+
+ isp116x_show_regs(isp116x);
+
+ break;
+
+ case RH_SET_ADDRESS:
+ DBG("RH_SET_ADDRESS");
+
+ rh_devnum = wValue;
+ len = 0;
+ break;
+
+ case RH_GET_DESCRIPTOR:
+ DBG("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength);
+
+ switch (wValue) {
+ case (USB_DT_DEVICE << 8): /* device descriptor */
+ len = min_t(unsigned int,
+ leni, min_t(unsigned int,
+ sizeof(root_hub_dev_des),
+ wLength));
+ data_buf = root_hub_dev_des;
+ break;
+
+ case (USB_DT_CONFIG << 8): /* configuration descriptor */
+ len = min_t(unsigned int,
+ leni, min_t(unsigned int,
+ sizeof(root_hub_config_des),
+ wLength));
+ data_buf = root_hub_config_des;
+ break;
+
+ case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */
+ len = min_t(unsigned int,
+ leni, min_t(unsigned int,
+ sizeof(root_hub_str_index0),
+ wLength));
+ data_buf = root_hub_str_index0;
+ break;
+
+ case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */
+ len = min_t(unsigned int,
+ leni, min_t(unsigned int,
+ sizeof(root_hub_str_index1),
+ wLength));
+ data_buf = root_hub_str_index1;
+ break;
+
+ default:
+ ERR("invalid wValue");
+ stat = USB_ST_STALLED;
+ }
+
+ break;
+
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ DBG("RH_GET_DESCRIPTOR | RH_CLASS");
+
+ tmp = isp116x_read_reg32(isp116x, HCRHDESCA);
+
+ data_buf[0] = 0x09; /* min length; */
+ data_buf[1] = 0x29;
+ data_buf[2] = tmp & RH_A_NDP;
+ data_buf[3] = 0;
+ if (tmp & RH_A_PSM) /* per-port power switching? */
+ data_buf[3] |= 0x01;
+ if (tmp & RH_A_NOCP) /* no overcurrent reporting? */
+ data_buf[3] |= 0x10;
+ else if (tmp & RH_A_OCPM) /* per-port overcurrent rep? */
+ data_buf[3] |= 0x08;
+
+ /* Corresponds to data_buf[4-7] */
+ datab[1] = 0;
+ data_buf[5] = (tmp & RH_A_POTPGT) >> 24;
+
+ tmp = isp116x_read_reg32(isp116x, HCRHDESCB);
+
+ data_buf[7] = tmp & RH_B_DR;
+ if (data_buf[2] < 7)
+ data_buf[8] = 0xff;
+ else {
+ data_buf[0] += 2;
+ data_buf[8] = (tmp & RH_B_DR) >> 8;
+ data_buf[10] = data_buf[9] = 0xff;
+ }
+
+ len = min_t(unsigned int, leni,
+ min_t(unsigned int, data_buf[0], wLength));
+ break;
+
+ case RH_GET_CONFIGURATION:
+ DBG("RH_GET_CONFIGURATION");
+
+ *(__u8 *) data_buf = 0x01;
+ len = 1;
+ break;
+
+ case RH_SET_CONFIGURATION:
+ DBG("RH_SET_CONFIGURATION");
+
+ isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC);
+ len = 0;
+ break;
+
+ default:
+ ERR("*** *** *** unsupported root hub command *** *** ***");
+ stat = USB_ST_STALLED;
+ }
+
+ len = min_t(int, len, leni);
+ if (buffer != data_buf)
+ memcpy(buffer, data_buf, len);
+
+ dev->act_len = len;
+ dev->status = stat;
+ DBG("dev act_len %d, status %d", dev->act_len, dev->status);
+
+ dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)");
+
+ return stat;
+}
+
+/* --- Transfer functions -------------------------------------------------- */
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, int interval)
+{
+ DBG("dev=%p pipe=%#lx buf=%p size=%d int=%d",
+ dev, pipe, buffer, len, interval);
+
+ return -1;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, struct devrequest *setup)
+{
+ int devnum = usb_pipedevice(pipe);
+ int epnum = usb_pipeendpoint(pipe);
+ int max = max_transfer_len(dev, pipe);
+ int dir_in = usb_pipein(pipe);
+ int done, ret;
+
+ /* Control message is for the HUB? */
+ if (devnum == rh_devnum)
+ return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup);
+
+ /* Ok, no HUB message so send the message to the device */
+
+ /* Setup phase */
+ DBG("--- SETUP PHASE --------------------------------");
+ usb_settoggle(dev, epnum, 1, 0);
+ ret = isp116x_submit_job(dev, pipe,
+ PTD_DIR_SETUP,
+ setup, sizeof(struct devrequest));
+ if (ret < 0) {
+ DBG("control setup phase error (ret = %d", ret);
+ return -1;
+ }
+
+ /* Data phase */
+ DBG("--- DATA PHASE ---------------------------------");
+ done = 0;
+ usb_settoggle(dev, epnum, !dir_in, 1);
+ while (done < len) {
+ ret = isp116x_submit_job(dev, pipe,
+ dir_in ? PTD_DIR_IN : PTD_DIR_OUT,
+ (__u8 *) buffer + done,
+ max > len - done ? len - done : max);
+ if (ret < 0) {
+ DBG("control data phase error (ret = %d)", ret);
+ return -1;
+ }
+ done += ret;
+
+ if (dir_in && ret < max) /* short packet */
+ break;
+ }
+
+ /* Status phase */
+ DBG("--- STATUS PHASE -------------------------------");
+ usb_settoggle(dev, epnum, !dir_in, 1);
+ ret = isp116x_submit_job(dev, pipe,
+ !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0);
+ if (ret < 0) {
+ DBG("control status phase error (ret = %d", ret);
+ return -1;
+ }
+
+ dev->act_len = done;
+
+ dump_msg(dev, pipe, buffer, len, "DEV(ret)");
+
+ return done;
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len)
+{
+ int dir_out = usb_pipeout(pipe);
+ int max = max_transfer_len(dev, pipe);
+ int done, ret;
+
+ DBG("--- BULK ---------------------------------------");
+ DBG("dev=%ld pipe=%ld buf=%p size=%d dir_out=%d",
+ usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out);
+
+ done = 0;
+ while (done < len) {
+ ret = isp116x_submit_job(dev, pipe,
+ !dir_out ? PTD_DIR_IN : PTD_DIR_OUT,
+ (__u8 *) buffer + done,
+ max > len - done ? len - done : max);
+ if (ret < 0) {
+ DBG("error on bulk message (ret = %d)", ret);
+ return -1;
+ }
+
+ done += ret;
+
+ if (!dir_out && ret < max) /* short packet */
+ break;
+ }
+
+ dev->act_len = done;
+
+ return 0;
+}
+
+/* --- Basic functions ----------------------------------------------------- */
+
+static int isp116x_sw_reset(struct isp116x *isp116x)
+{
+ int retries = 15;
+ int ret = 0;
+
+ DBG("");
+
+ isp116x->disabled = 1;
+
+ isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC);
+ isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR);
+ while (--retries) {
+ /* It usually resets within 1 ms */
+ wait_ms(1);
+ if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR))
+ break;
+ }
+ if (!retries) {
+ ERR("software reset timeout");
+ ret = -1;
+ }
+ return ret;
+}
+
+static int isp116x_reset(struct isp116x *isp116x)
+{
+ unsigned long t;
+ u16 clkrdy = 0;
+ int ret, timeout = 15 /* ms */ ;
+
+ DBG("");
+
+ ret = isp116x_sw_reset(isp116x);
+ if (ret)
+ return ret;
+
+ for (t = 0; t < timeout; t++) {
+ clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY;
+ if (clkrdy)
+ break;
+ wait_ms(1);
+ }
+ if (!clkrdy) {
+ ERR("clock not ready after %dms", timeout);
+ /* After sw_reset the clock won't report to be ready, if
+ H_WAKEUP pin is high. */
+ ERR("please make sure that the H_WAKEUP pin is pulled low!");
+ ret = -1;
+ }
+ return ret;
+}
+
+static void isp116x_stop(struct isp116x *isp116x)
+{
+ u32 val;
+
+ DBG("");
+
+ isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+
+ /* Switch off ports' power, some devices don't come up
+ after next 'start' without this */
+ val = isp116x_read_reg32(isp116x, HCRHDESCA);
+ val &= ~(RH_A_NPS | RH_A_PSM);
+ isp116x_write_reg32(isp116x, HCRHDESCA, val);
+ isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);
+
+ isp116x_sw_reset(isp116x);
+}
+
+/*
+ * Configure the chip. The chip must be successfully reset by now.
+ */
+static int isp116x_start(struct isp116x *isp116x)
+{
+ struct isp116x_platform_data *board = isp116x->board;
+ u32 val;
+
+ DBG("");
+
+ /* Clear interrupt status and disable all interrupt sources */
+ isp116x_write_reg16(isp116x, HCuPINT, 0xff);
+ isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+
+ isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
+ isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
+
+ /* Hardware configuration */
+ val = HCHWCFG_DBWIDTH(1);
+ if (board->sel15Kres)
+ val |= HCHWCFG_15KRSEL;
+ /* Remote wakeup won't work without working clock */
+ if (board->remote_wakeup_enable)
+ val |= HCHWCFG_CLKNOTSTOP;
+ if (board->oc_enable)
+ val |= HCHWCFG_ANALOG_OC;
+ isp116x_write_reg16(isp116x, HCHWCFG, val);
+
+ /* --- Root hub configuration */
+ val = (25 << 24) & RH_A_POTPGT;
+ /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to
+ be always set. Yet, instead, we request individual port
+ power switching. */
+ val |= RH_A_PSM;
+ /* Report overcurrent per port */
+ val |= RH_A_OCPM;
+ isp116x_write_reg32(isp116x, HCRHDESCA, val);
+ isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);
+
+ val = RH_B_PPCM;
+ isp116x_write_reg32(isp116x, HCRHDESCB, val);
+ isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB);
+
+ val = 0;
+ if (board->remote_wakeup_enable)
+ val |= RH_HS_DRWE;
+ isp116x_write_reg32(isp116x, HCRHSTATUS, val);
+ isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
+
+ isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);
+
+ /* Go operational */
+ val = HCCONTROL_USB_OPER;
+ if (board->remote_wakeup_enable)
+ val |= HCCONTROL_RWE;
+ isp116x_write_reg32(isp116x, HCCONTROL, val);
+
+ /* Disable ports to avoid race in device enumeration */
+ isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
+ isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
+
+ isp116x_show_regs(isp116x);
+
+ isp116x->disabled = 0;
+
+ return 0;
+}
+
+/* --- Init functions ------------------------------------------------------ */
+
+int isp116x_check_id(struct isp116x *isp116x)
+{
+ int val;
+
+ val = isp116x_read_reg16(isp116x, HCCHIPID);
+ if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) {
+ ERR("invalid chip ID %04x", val);
+ return -1;
+ }
+
+ return 0;
+}
+
+int usb_lowlevel_init(void)
+{
+ struct isp116x *isp116x = &isp116x_dev;
+
+ DBG("");
+
+ /* Init device registers addr */
+ isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR;
+ isp116x->data_reg = (u16 *) ISP116X_HCD_DATA;
+
+ /* Setup specific board settings */
+#ifdef ISP116X_HCD_SEL15kRES
+ isp116x_board.sel15Kres = 1;
+#endif
+#ifdef ISP116X_HCD_OC_ENABLE
+ isp116x_board.oc_enable = 1;
+#endif
+#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE
+ isp116x_board.remote_wakeup_enable = 1;
+#endif
+ isp116x->board = &isp116x_board;
+
+ /* Try to get ISP116x silicon chip ID */
+ if (isp116x_check_id(isp116x) < 0)
+ return -1;
+
+ isp116x->disabled = 1;
+ isp116x->sleeping = 0;
+
+ isp116x_reset(isp116x);
+ isp116x_start(isp116x);
+
+ return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+ struct isp116x *isp116x = &isp116x_dev;
+
+ DBG("");
+
+ if (!isp116x->disabled)
+ isp116x_stop(isp116x);
+
+ return 0;
+}
+
+#endif /* CONFIG_USB_ISP116X_HCD */
diff --git a/drivers/isp116x.h b/drivers/isp116x.h
new file mode 100644
index 0000000000..a3ce3b582c
--- /dev/null
+++ b/drivers/isp116x.h
@@ -0,0 +1,489 @@
+/*
+ * ISP116x register declarations and HCD data structures
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>
+ * Portions:
+ * Copyright (C) 2004 Lothar Wassmann
+ * Copyright (C) 2004 Psion Teklogix
+ * Copyright (C) 2004 David Brownell
+ *
+ * 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
+ */
+
+#ifdef DEBUG
+#define DBG(fmt, args...) \
+ printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
+#else
+#define DBG(fmt, args...) do {} while (0)
+#endif
+
+#ifdef VERBOSE
+# define VDBG DBG
+#else
+# define VDBG(fmt, args...) do {} while (0)
+#endif
+
+#define ERR(fmt, args...) \
+ printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
+#define WARN(fmt, args...) \
+ printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
+#define INFO(fmt, args...) \
+ printf("isp116x: " fmt "\n" , ## args)
+
+/* ------------------------------------------------------------------------- */
+
+/* us of 1ms frame */
+#define MAX_LOAD_LIMIT 850
+
+/* Full speed: max # of bytes to transfer for a single urb
+ at a time must be < 1024 && must be multiple of 64.
+ 832 allows transfering 4kiB within 5 frames. */
+#define MAX_TRANSFER_SIZE_FULLSPEED 832
+
+/* Low speed: there is no reason to schedule in very big
+ chunks; often the requested long transfers are for
+ string descriptors containing short strings. */
+#define MAX_TRANSFER_SIZE_LOWSPEED 64
+
+/* Bytetime (us), a rough indication of how much time it
+ would take to transfer a byte of useful data over USB */
+#define BYTE_TIME_FULLSPEED 1
+#define BYTE_TIME_LOWSPEED 20
+
+/* Buffer sizes */
+#define ISP116x_BUF_SIZE 4096
+#define ISP116x_ITL_BUFSIZE 0
+#define ISP116x_ATL_BUFSIZE ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE))
+
+#define ISP116x_WRITE_OFFSET 0x80
+
+/* --- ISP116x registers/bits ---------------------------------------------- */
+
+#define HCREVISION 0x00
+#define HCCONTROL 0x01
+#define HCCONTROL_HCFS (3 << 6) /* host controller
+ functional state */
+#define HCCONTROL_USB_RESET (0 << 6)
+#define HCCONTROL_USB_RESUME (1 << 6)
+#define HCCONTROL_USB_OPER (2 << 6)
+#define HCCONTROL_USB_SUSPEND (3 << 6)
+#define HCCONTROL_RWC (1 << 9) /* remote wakeup connected */
+#define HCCONTROL_RWE (1 << 10) /* remote wakeup enable */
+#define HCCMDSTAT 0x02
+#define HCCMDSTAT_HCR (1 << 0) /* host controller reset */
+#define HCCMDSTAT_SOC (3 << 16) /* scheduling overrun count */
+#define HCINTSTAT 0x03
+#define HCINT_SO (1 << 0) /* scheduling overrun */
+#define HCINT_WDH (1 << 1) /* writeback of done_head */
+#define HCINT_SF (1 << 2) /* start frame */
+#define HCINT_RD (1 << 3) /* resume detect */
+#define HCINT_UE (1 << 4) /* unrecoverable error */
+#define HCINT_FNO (1 << 5) /* frame number overflow */
+#define HCINT_RHSC (1 << 6) /* root hub status change */
+#define HCINT_OC (1 << 30) /* ownership change */
+#define HCINT_MIE (1 << 31) /* master interrupt enable */
+#define HCINTENB 0x04
+#define HCINTDIS 0x05
+#define HCFMINTVL 0x0d
+#define HCFMREM 0x0e
+#define HCFMNUM 0x0f
+#define HCLSTHRESH 0x11
+#define HCRHDESCA 0x12
+#define RH_A_NDP (0x3 << 0) /* # downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* overcurrent protection
+ mode */
+#define RH_A_NOCP (1 << 12) /* no overcurrent protection */
+#define RH_A_POTPGT (0xff << 24) /* power on -> power good
+ time */
+#define HCRHDESCB 0x13
+#define RH_B_DR (0xffff << 0) /* device removable flags */
+#define RH_B_PPCM (0xffff << 16) /* port power control mask */
+#define HCRHSTATUS 0x14
+#define RH_HS_LPS (1 << 0) /* local power status */
+#define RH_HS_OCI (1 << 1) /* over current indicator */
+#define RH_HS_DRWE (1 << 15) /* device remote wakeup
+ enable */
+#define RH_HS_LPSC (1 << 16) /* local power status change */
+#define RH_HS_OCIC (1 << 17) /* over current indicator
+ change */
+#define RH_HS_CRWE (1 << 31) /* clear remote wakeup
+ enable */
+#define HCRHPORT1 0x15
+#define RH_PS_CCS (1 << 0) /* current connect status */
+#define RH_PS_PES (1 << 1) /* port enable status */
+#define RH_PS_PSS (1 << 2) /* port suspend status */
+#define RH_PS_POCI (1 << 3) /* port over current
+ indicator */
+#define RH_PS_PRS (1 << 4) /* port reset status */
+#define RH_PS_PPS (1 << 8) /* port power status */
+#define RH_PS_LSDA (1 << 9) /* low speed device attached */
+#define RH_PS_CSC (1 << 16) /* connect status change */
+#define RH_PS_PESC (1 << 17) /* port enable status change */
+#define RH_PS_PSSC (1 << 18) /* port suspend status
+ change */
+#define RH_PS_OCIC (1 << 19) /* over current indicator
+ change */
+#define RH_PS_PRSC (1 << 20) /* port reset status change */
+#define HCRHPORT_CLRMASK (0x1f << 16)
+#define HCRHPORT2 0x16
+#define HCHWCFG 0x20
+#define HCHWCFG_15KRSEL (1 << 12)
+#define HCHWCFG_CLKNOTSTOP (1 << 11)
+#define HCHWCFG_ANALOG_OC (1 << 10)
+#define HCHWCFG_DACK_MODE (1 << 8)
+#define HCHWCFG_EOT_POL (1 << 7)
+#define HCHWCFG_DACK_POL (1 << 6)
+#define HCHWCFG_DREQ_POL (1 << 5)
+#define HCHWCFG_DBWIDTH_MASK (0x03 << 3)
+#define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK)
+#define HCHWCFG_INT_POL (1 << 2)
+#define HCHWCFG_INT_TRIGGER (1 << 1)
+#define HCHWCFG_INT_ENABLE (1 << 0)
+#define HCDMACFG 0x21
+#define HCDMACFG_BURST_LEN_MASK (0x03 << 5)
+#define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK)
+#define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0)
+#define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1)
+#define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2)
+#define HCDMACFG_DMA_ENABLE (1 << 4)
+#define HCDMACFG_BUF_TYPE_MASK (0x07 << 1)
+#define HCDMACFG_CTR_SEL (1 << 2)
+#define HCDMACFG_ITLATL_SEL (1 << 1)
+#define HCDMACFG_DMA_RW_SELECT (1 << 0)
+#define HCXFERCTR 0x22
+#define HCuPINT 0x24
+#define HCuPINT_SOF (1 << 0)
+#define HCuPINT_ATL (1 << 1)
+#define HCuPINT_AIIEOT (1 << 2)
+#define HCuPINT_OPR (1 << 4)
+#define HCuPINT_SUSP (1 << 5)
+#define HCuPINT_CLKRDY (1 << 6)
+#define HCuPINTENB 0x25
+#define HCCHIPID 0x27
+#define HCCHIPID_MASK 0xff00
+#define HCCHIPID_MAGIC 0x6100
+#define HCSCRATCH 0x28
+#define HCSWRES 0x29
+#define HCSWRES_MAGIC 0x00f6
+#define HCITLBUFLEN 0x2a
+#define HCATLBUFLEN 0x2b
+#define HCBUFSTAT 0x2c
+#define HCBUFSTAT_ITL0_FULL (1 << 0)
+#define HCBUFSTAT_ITL1_FULL (1 << 1)
+#define HCBUFSTAT_ATL_FULL (1 << 2)
+#define HCBUFSTAT_ITL0_DONE (1 << 3)
+#define HCBUFSTAT_ITL1_DONE (1 << 4)
+#define HCBUFSTAT_ATL_DONE (1 << 5)
+#define HCRDITL0LEN 0x2d
+#define HCRDITL1LEN 0x2e
+#define HCITLPORT 0x40
+#define HCATLPORT 0x41
+
+/* PTD accessor macros. */
+#define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0)
+#define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK)
+#define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10)
+#define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK)
+#define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11)
+#define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK)
+#define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12)
+#define PTD_CC(v) (((v) << 12) & PTD_CC_MSK)
+#define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0)
+#define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK)
+#define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10)
+#define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK)
+#define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11)
+#define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK)
+#define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12)
+#define PTD_EP(v) (((v) << 12) & PTD_EP_MSK)
+#define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0)
+#define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK)
+#define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10)
+#define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK)
+#define PTD_GET_B5_5(p) (((p)->len & PTD_B5_5_MSK) >> 13)
+#define PTD_B5_5(v) (((v) << 13) & PTD_B5_5_MSK)
+#define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0)
+#define PTD_FA(v) (((v) << 0) & PTD_FA_MSK)
+#define PTD_GET_FMT(p) (((p)->faddr & PTD_FMT_MSK) >> 7)
+#define PTD_FMT(v) (((v) << 7) & PTD_FMT_MSK)
+
+/* Hardware transfer status codes -- CC from ptd->count */
+#define TD_CC_NOERROR 0x00
+#define TD_CC_CRC 0x01
+#define TD_CC_BITSTUFFING 0x02
+#define TD_CC_DATATOGGLEM 0x03
+#define TD_CC_STALL 0x04
+#define TD_DEVNOTRESP 0x05
+#define TD_PIDCHECKFAIL 0x06
+#define TD_UNEXPECTEDPID 0x07
+#define TD_DATAOVERRUN 0x08
+#define TD_DATAUNDERRUN 0x09
+ /* 0x0A, 0x0B reserved for hardware */
+#define TD_BUFFEROVERRUN 0x0C
+#define TD_BUFFERUNDERRUN 0x0D
+ /* 0x0E, 0x0F reserved for HCD */
+#define TD_NOTACCESSED 0x0F
+
+/* ------------------------------------------------------------------------- */
+
+#define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */
+#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE)
+
+/* Philips transfer descriptor */
+struct ptd {
+ u16 count;
+#define PTD_COUNT_MSK (0x3ff << 0)
+#define PTD_TOGGLE_MSK (1 << 10)
+#define PTD_ACTIVE_MSK (1 << 11)
+#define PTD_CC_MSK (0xf << 12)
+ u16 mps;
+#define PTD_MPS_MSK (0x3ff << 0)
+#define PTD_SPD_MSK (1 << 10)
+#define PTD_LAST_MSK (1 << 11)
+#define PTD_EP_MSK (0xf << 12)
+ u16 len;
+#define PTD_LEN_MSK (0x3ff << 0)
+#define PTD_DIR_MSK (3 << 10)
+#define PTD_DIR_SETUP (0)
+#define PTD_DIR_OUT (1)
+#define PTD_DIR_IN (2)
+#define PTD_B5_5_MSK (1 << 13)
+ u16 faddr;
+#define PTD_FA_MSK (0x7f << 0)
+#define PTD_FMT_MSK (1 << 7)
+} __attribute__ ((packed, aligned(2)));
+
+struct isp116x_ep {
+ struct usb_device *udev;
+ struct ptd ptd;
+
+ u8 maxpacket;
+ u8 epnum;
+ u8 nextpid;
+
+ u16 length; /* of current packet */
+ unsigned char *data; /* to databuf */
+
+ u16 error_count;
+};
+
+/* URB struct */
+#define N_URB_TD 48
+#define URB_DEL 1
+typedef struct {
+ struct isp116x_ep *ed;
+ void *transfer_buffer; /* (in) associated data buffer */
+ int actual_length; /* (return) actual transfer length */
+ unsigned long pipe; /* (in) pipe information */
+#if 0
+ int state;
+#endif
+} urb_priv_t;
+
+struct isp116x_platform_data {
+ /* Enable internal resistors on downstream ports */
+ unsigned sel15Kres:1;
+ /* On-chip overcurrent detection */
+ unsigned oc_enable:1;
+ /* Enable wakeup by devices on usb bus (e.g. wakeup
+ by attachment/detachment or by device activity
+ such as moving a mouse). When chosen, this option
+ prevents stopping internal clock, increasing
+ thereby power consumption in suspended state. */
+ unsigned remote_wakeup_enable:1;
+};
+
+struct isp116x {
+ u16 *addr_reg;
+ u16 *data_reg;
+
+ struct isp116x_platform_data *board;
+
+ struct dentry *dentry;
+ unsigned long stat1, stat2, stat4, stat8, stat16;
+
+ /* Status flags */
+ unsigned disabled:1;
+ unsigned sleeping:1;
+
+ /* Root hub registers */
+ u32 rhdesca;
+ u32 rhdescb;
+ u32 rhstatus;
+ u32 rhport[2];
+
+ /* Schedule for the current frame */
+ struct isp116x_ep *atl_active;
+ int atl_buflen;
+ int atl_bufshrt;
+ int atl_last_dir;
+ int atl_finishing;
+};
+
+/* ------------------------------------------------- */
+
+/* Inter-io delay (ns). The chip is picky about access timings; it
+ * expects at least:
+ * 150ns delay between consecutive accesses to DATA_REG,
+ * 300ns delay between access to ADDR_REG and DATA_REG
+ * OE, WE MUST NOT be changed during these intervals
+ */
+#if defined(UDELAY)
+#define isp116x_delay(h,d) udelay(d)
+#else
+#define isp116x_delay(h,d) do {} while (0)
+#endif
+
+static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
+{
+ writew(reg & 0xff, isp116x->addr_reg);
+ isp116x_delay(isp116x, UDELAY);
+}
+
+static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val)
+{
+ writew(val, isp116x->data_reg);
+ isp116x_delay(isp116x, UDELAY);
+}
+
+static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val)
+{
+ __raw_writew(val, isp116x->data_reg);
+ isp116x_delay(isp116x, UDELAY);
+}
+
+static inline u16 isp116x_read_data16(struct isp116x *isp116x)
+{
+ u16 val;
+
+ val = readw(isp116x->data_reg);
+ isp116x_delay(isp116x, UDELAY);
+ return val;
+}
+
+static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x)
+{
+ u16 val;
+
+ val = __raw_readw(isp116x->data_reg);
+ isp116x_delay(isp116x, UDELAY);
+ return val;
+}
+
+static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val)
+{
+ writew(val & 0xffff, isp116x->data_reg);
+ isp116x_delay(isp116x, UDELAY);
+ writew(val >> 16, isp116x->data_reg);
+ isp116x_delay(isp116x, UDELAY);
+}
+
+static inline u32 isp116x_read_data32(struct isp116x *isp116x)
+{
+ u32 val;
+
+ val = (u32) readw(isp116x->data_reg);
+ isp116x_delay(isp116x, UDELAY);
+ val |= ((u32) readw(isp116x->data_reg)) << 16;
+ isp116x_delay(isp116x, UDELAY);
+ return val;
+}
+
+/* Let's keep register access functions out of line. Hint:
+ we wait at least 150 ns at every access.
+*/
+static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg)
+{
+ isp116x_write_addr(isp116x, reg);
+ return isp116x_read_data16(isp116x);
+}
+
+static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg)
+{
+ isp116x_write_addr(isp116x, reg);
+ return isp116x_read_data32(isp116x);
+}
+
+static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg,
+ unsigned val)
+{
+ isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
+ isp116x_write_data16(isp116x, (u16) (val & 0xffff));
+}
+
+static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
+ unsigned val)
+{
+ isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
+ isp116x_write_data32(isp116x, (u32) val);
+}
+
+/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */
+
+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
diff --git a/drivers/lan91c96.c b/drivers/lan91c96.c
index a50c5f0abe..ecdcbd9b32 100644
--- a/drivers/lan91c96.c
+++ b/drivers/lan91c96.c
@@ -65,7 +65,7 @@
#ifdef CONFIG_DRIVER_LAN91C96
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
/*------------------------------------------------------------------------
*
diff --git a/drivers/macb.c b/drivers/macb.c
index 186ab19d35..95cdc496cb 100644
--- a/drivers/macb.c
+++ b/drivers/macb.c
@@ -17,7 +17,8 @@
*/
#include <common.h>
-#if defined(CONFIG_MACB) && (CONFIG_COMMANDS & (CFG_CMD_NET | CFG_CMD_MII))
+#if defined(CONFIG_MACB) \
+ && (defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_MII))
/*
* The u-boot networking stack is a little weird. It seems like the
@@ -51,6 +52,8 @@
#include "macb.h"
+#define barrier() asm volatile("" ::: "memory")
+
#define CFG_MACB_RX_BUFFER_SIZE 4096
#define CFG_MACB_RX_RING_SIZE (CFG_MACB_RX_BUFFER_SIZE / 128)
#define CFG_MACB_TX_RING_SIZE 16
@@ -163,7 +166,7 @@ static u16 macb_mdio_read(struct macb_device *macb, u8 reg)
return MACB_BFEXT(DATA, frame);
}
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
static int macb_send(struct eth_device *netdev, volatile void *packet,
int length)
@@ -185,31 +188,31 @@ static int macb_send(struct eth_device *netdev, volatile void *packet,
macb->tx_ring[tx_head].ctrl = ctrl;
macb->tx_ring[tx_head].addr = paddr;
+ barrier();
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
/*
* I guess this is necessary because the networking core may
* re-use the transmit buffer as soon as we return...
*/
- i = 0;
- while (!(macb->tx_ring[tx_head].ctrl & TXBUF_USED)) {
- if (i > CFG_MACB_TX_TIMEOUT) {
- printf("%s: TX timeout\n", netdev->name);
+ for (i = 0; i <= CFG_MACB_TX_TIMEOUT; i++) {
+ barrier();
+ ctrl = macb->tx_ring[tx_head].ctrl;
+ if (ctrl & TXBUF_USED)
break;
- }
udelay(1);
- i++;
}
dma_unmap_single(packet, length, paddr);
if (i <= CFG_MACB_TX_TIMEOUT) {
- ctrl = macb->tx_ring[tx_head].ctrl;
if (ctrl & TXBUF_UNDERRUN)
printf("%s: TX underrun\n", netdev->name);
if (ctrl & TXBUF_EXHAUSTED)
printf("%s: TX buffers exhausted in mid frame\n",
netdev->name);
+ } else {
+ printf("%s: TX timeout\n", netdev->name);
}
/* No one cares anyway */
@@ -234,6 +237,7 @@ static void reclaim_rx_buffers(struct macb_device *macb,
i++;
}
+ barrier();
macb->rx_tail = new_tail;
}
@@ -283,25 +287,17 @@ static int macb_recv(struct eth_device *netdev)
rx_tail = 0;
}
}
+ barrier();
}
return 0;
}
-static int macb_phy_init(struct macb_device *macb)
+static void macb_phy_reset(struct macb_device *macb)
{
struct eth_device *netdev = &macb->netdev;
- u32 ncfgr;
- u16 phy_id, status, adv, lpa;
- int media, speed, duplex;
int i;
-
- /* Check if the PHY is up to snuff... */
- phy_id = macb_mdio_read(macb, MII_PHYSID1);
- if (phy_id == 0xffff) {
- printf("%s: No PHY present\n", netdev->name);
- return 0;
- }
+ u16 status, adv;
adv = ADVERTISE_CSMA | ADVERTISE_ALL;
macb_mdio_write(macb, MII_ADVERTISE, adv);
@@ -309,11 +305,6 @@ static int macb_phy_init(struct macb_device *macb)
macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE
| BMCR_ANRESTART));
-#if 0
- for (i = 0; i < 9; i++)
- printf("mii%d: 0x%04x\n", i, macb_mdio_read(macb, i));
-#endif
-
for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) {
status = macb_mdio_read(macb, MII_BMSR);
if (status & BMSR_ANEGCOMPLETE)
@@ -326,13 +317,33 @@ static int macb_phy_init(struct macb_device *macb)
else
printf("%s: Autonegotiation timed out (status=0x%04x)\n",
netdev->name, status);
+}
+static int macb_phy_init(struct macb_device *macb)
+{
+ struct eth_device *netdev = &macb->netdev;
+ u32 ncfgr;
+ u16 phy_id, status, adv, lpa;
+ int media, speed, duplex;
+ int i;
+
+ /* Check if the PHY is up to snuff... */
+ phy_id = macb_mdio_read(macb, MII_PHYSID1);
+ if (phy_id == 0xffff) {
+ printf("%s: No PHY present\n", netdev->name);
+ return 0;
+ }
+
+ status = macb_mdio_read(macb, MII_BMSR);
if (!(status & BMSR_LSTATUS)) {
+ /* Try to re-negotiate if we don't have link already. */
+ macb_phy_reset(macb);
+
for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) {
- udelay(100);
status = macb_mdio_read(macb, MII_BMSR);
if (status & BMSR_LSTATUS)
break;
+ udelay(100);
}
}
@@ -341,6 +352,7 @@ static int macb_phy_init(struct macb_device *macb)
netdev->name, status);
return 0;
} else {
+ adv = macb_mdio_read(macb, MII_ADVERTISE);
lpa = macb_mdio_read(macb, MII_LPA);
media = mii_nway_result(lpa & adv);
speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
@@ -492,9 +504,9 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
return 0;
}
-#endif /* (CONFIG_COMMANDS & CFG_CMD_NET) */
+#endif
-#if (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_CMD_MII)
int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
{
@@ -570,6 +582,6 @@ int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
return 0;
}
-#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) */
+#endif
#endif /* CONFIG_MACB */
diff --git a/drivers/mpc8xx_pcmcia.c b/drivers/mpc8xx_pcmcia.c
index 399a719e56..8a34cd3054 100644
--- a/drivers/mpc8xx_pcmcia.c
+++ b/drivers/mpc8xx_pcmcia.c
@@ -6,11 +6,11 @@
#undef CONFIG_PCMCIA
-#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+#if defined(CONFIG_CMD_PCMCIA)
#define CONFIG_PCMCIA
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
+#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
#define CONFIG_PCMCIA
#endif
@@ -23,7 +23,7 @@ extern int check_ide_device (int slot);
extern int pcmcia_hardware_enable (int slot);
extern int pcmcia_voltage_set(int slot, int vcc, int vpp);
-#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+#if defined(CONFIG_CMD_PCMCIA)
extern int pcmcia_hardware_disable(int slot);
#endif
@@ -189,7 +189,7 @@ int pcmcia_on (void)
return rc;
}
-#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+#if defined(CONFIG_CMD_PCMCIA)
int pcmcia_off (void)
{
int i;
@@ -221,7 +221,7 @@ int pcmcia_off (void)
pcmcia_hardware_disable(_slot_);
return 0;
}
-#endif /* CFG_CMD_PCMCIA */
+#endif
static u_int m8xx_get_graycode(u_int size)
diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c
index 9fef71d629..27b5792bcc 100644
--- a/drivers/nand/nand.c
+++ b/drivers/nand/nand.c
@@ -23,7 +23,7 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <nand.h>
diff --git a/drivers/nand/nand_base.c b/drivers/nand/nand_base.c
index c6fee18222..151f535c58 100644
--- a/drivers/nand/nand_base.c
+++ b/drivers/nand/nand_base.c
@@ -72,7 +72,7 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <malloc.h>
#include <watchdog.h>
diff --git a/drivers/nand/nand_bbt.c b/drivers/nand/nand_bbt.c
index aaa9400e54..19a9bc2a5b 100644
--- a/drivers/nand/nand_bbt.c
+++ b/drivers/nand/nand_bbt.c
@@ -54,7 +54,7 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <malloc.h>
#include <linux/mtd/compat.h>
diff --git a/drivers/nand/nand_ecc.c b/drivers/nand/nand_ecc.c
index f33be9655d..4c532b0794 100644
--- a/drivers/nand/nand_ecc.c
+++ b/drivers/nand/nand_ecc.c
@@ -37,9 +37,16 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include<linux/mtd/mtd.h>
+
+/*
+ * NAND-SPL has no sofware ECC for now, so don't include nand_calculate_ecc(),
+ * only nand_correct_data() is needed
+ */
+
+#ifndef CONFIG_NAND_SPL
/*
* Pre-calculated 256-way 1 byte column parity
*/
@@ -62,90 +69,75 @@ static const u_char nand_ecc_precalc_table[] = {
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
};
-
-/**
- * nand_trans_result - [GENERIC] create non-inverted ECC
- * @reg2: line parity reg 2
- * @reg3: line parity reg 3
- * @ecc_code: ecc
- *
- * Creates non-inverted ECC code from line parity
- */
-static void nand_trans_result(u_char reg2, u_char reg3,
- u_char *ecc_code)
-{
- u_char a, b, i, tmp1, tmp2;
-
- /* Initialize variables */
- a = b = 0x80;
- tmp1 = tmp2 = 0;
-
- /* Calculate first ECC byte */
- for (i = 0; i < 4; i++) {
- if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */
- tmp1 |= b;
- b >>= 1;
- if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */
- tmp1 |= b;
- b >>= 1;
- a >>= 1;
- }
-
- /* Calculate second ECC byte */
- b = 0x80;
- for (i = 0; i < 4; i++) {
- if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */
- tmp2 |= b;
- b >>= 1;
- if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */
- tmp2 |= b;
- b >>= 1;
- a >>= 1;
- }
-
- /* Store two of the ECC bytes */
- ecc_code[0] = tmp1;
- ecc_code[1] = tmp2;
-}
-
/**
- * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block
+ * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block
* @mtd: MTD block structure
* @dat: raw data
* @ecc_code: buffer for ECC
*/
-int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+ u_char *ecc_code)
{
- u_char idx, reg1, reg2, reg3;
- int j;
+ uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
+ int i;
/* Initialize variables */
reg1 = reg2 = reg3 = 0;
- ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
/* Build up column parity */
- for(j = 0; j < 256; j++) {
-
+ for(i = 0; i < 256; i++) {
/* Get CP0 - CP5 from table */
- idx = nand_ecc_precalc_table[dat[j]];
+ idx = nand_ecc_precalc_table[*dat++];
reg1 ^= (idx & 0x3f);
/* All bit XOR = 1 ? */
if (idx & 0x40) {
- reg3 ^= (u_char) j;
- reg2 ^= ~((u_char) j);
+ reg3 ^= (uint8_t) i;
+ reg2 ^= ~((uint8_t) i);
}
}
/* Create non-inverted ECC code from line parity */
- nand_trans_result(reg2, reg3, ecc_code);
+ tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */
+ tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
+ tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
+ tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
+ tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
+ tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
+ tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
+ tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
+
+ tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */
+ tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
+ tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
+ tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
+ tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
+ tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
+ tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
+ tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
/* Calculate final ECC code */
- ecc_code[0] = ~ecc_code[0];
- ecc_code[1] = ~ecc_code[1];
+#ifdef CONFIG_MTD_NAND_ECC_SMC
+ ecc_code[0] = ~tmp2;
+ ecc_code[1] = ~tmp1;
+#else
+ ecc_code[0] = ~tmp1;
+ ecc_code[1] = ~tmp2;
+#endif
ecc_code[2] = ((~reg1) << 2) | 0x03;
+
return 0;
}
+#endif /* CONFIG_NAND_SPL */
+
+static inline int countbits(uint32_t byte)
+{
+ int res = 0;
+
+ for (;byte; byte >>= 1)
+ res += byte & 0x01;
+ return res;
+}
/**
* nand_correct_data - [NAND Interface] Detect and correct bit error(s)
@@ -156,89 +148,53 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code
*
* Detect and correct a 1 bit error for 256 byte block
*/
-int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+int nand_correct_data(struct mtd_info *mtd, u_char *dat,
+ u_char *read_ecc, u_char *calc_ecc)
{
- u_char a, b, c, d1, d2, d3, add, bit, i;
+ uint8_t s0, s1, s2;
+
+#ifdef CONFIG_MTD_NAND_ECC_SMC
+ s0 = calc_ecc[0] ^ read_ecc[0];
+ s1 = calc_ecc[1] ^ read_ecc[1];
+ s2 = calc_ecc[2] ^ read_ecc[2];
+#else
+ s1 = calc_ecc[0] ^ read_ecc[0];
+ s0 = calc_ecc[1] ^ read_ecc[1];
+ s2 = calc_ecc[2] ^ read_ecc[2];
+#endif
+ if ((s0 | s1 | s2) == 0)
+ return 0;
- /* Do error detection */
- d1 = calc_ecc[0] ^ read_ecc[0];
- d2 = calc_ecc[1] ^ read_ecc[1];
- d3 = calc_ecc[2] ^ read_ecc[2];
+ /* Check for a single bit error */
+ if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
+ ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
+ ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
- if ((d1 | d2 | d3) == 0) {
- /* No errors */
- return 0;
- }
- else {
- a = (d1 ^ (d1 >> 1)) & 0x55;
- b = (d2 ^ (d2 >> 1)) & 0x55;
- c = (d3 ^ (d3 >> 1)) & 0x54;
-
- /* Found and will correct single bit error in the data */
- if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
- c = 0x80;
- add = 0;
- a = 0x80;
- for (i=0; i<4; i++) {
- if (d1 & c)
- add |= a;
- c >>= 2;
- a >>= 1;
- }
- c = 0x80;
- for (i=0; i<4; i++) {
- if (d2 & c)
- add |= a;
- c >>= 2;
- a >>= 1;
- }
- bit = 0;
- b = 0x04;
- c = 0x80;
- for (i=0; i<3; i++) {
- if (d3 & c)
- bit |= b;
- c >>= 2;
- b >>= 1;
- }
- b = 0x01;
- a = dat[add];
- a ^= (b << bit);
- dat[add] = a;
- return 1;
- } else {
- i = 0;
- while (d1) {
- if (d1 & 0x01)
- ++i;
- d1 >>= 1;
- }
- while (d2) {
- if (d2 & 0x01)
- ++i;
- d2 >>= 1;
- }
- while (d3) {
- if (d3 & 0x01)
- ++i;
- d3 >>= 1;
- }
- if (i == 1) {
- /* ECC Code Error Correction */
- read_ecc[0] = calc_ecc[0];
- read_ecc[1] = calc_ecc[1];
- read_ecc[2] = calc_ecc[2];
- return 2;
- }
- else {
- /* Uncorrectable Error */
- return -1;
- }
- }
+ uint32_t byteoffs, bitnum;
+
+ byteoffs = (s1 << 0) & 0x80;
+ byteoffs |= (s1 << 1) & 0x40;
+ byteoffs |= (s1 << 2) & 0x20;
+ byteoffs |= (s1 << 3) & 0x10;
+
+ byteoffs |= (s0 >> 4) & 0x08;
+ byteoffs |= (s0 >> 3) & 0x04;
+ byteoffs |= (s0 >> 2) & 0x02;
+ byteoffs |= (s0 >> 1) & 0x01;
+
+ bitnum = (s2 >> 5) & 0x04;
+ bitnum |= (s2 >> 4) & 0x02;
+ bitnum |= (s2 >> 3) & 0x01;
+
+ dat[byteoffs] ^= (1 << bitnum);
+
+ return 1;
}
- /* Should never happen */
+ if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
+ return 1;
+
return -1;
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */
+#endif
diff --git a/drivers/nand/nand_ids.c b/drivers/nand/nand_ids.c
index 8b58736bc1..6d7e347fba 100644
--- a/drivers/nand/nand_ids.c
+++ b/drivers/nand/nand_ids.c
@@ -13,7 +13,7 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <linux/mtd/nand.h>
@@ -123,6 +123,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_NATIONAL, "National"},
{NAND_MFR_RENESAS, "Renesas"},
{NAND_MFR_STMICRO, "ST Micro"},
+ {NAND_MFR_MICRON, "Micron"},
{0x0, "Unknown"}
};
#endif
diff --git a/drivers/nand/nand_util.c b/drivers/nand/nand_util.c
index 10bf03659e..4fd4e166e6 100644
--- a/drivers/nand/nand_util.c
+++ b/drivers/nand/nand_util.c
@@ -32,11 +32,12 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <command.h>
#include <watchdog.h>
#include <malloc.h>
+#include <div64.h>
#include <nand.h>
#include <jffs2/jffs2.h>
@@ -208,10 +209,13 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
}
if (!opts->quiet) {
- int percent = (int)
- ((unsigned long long)
- (erase.addr+meminfo->erasesize-opts->offset)
- * 100 / erase_length);
+ unsigned long long n =(unsigned long long)
+ (erase.addr + meminfo->erasesize - opts->offset)
+ * 100;
+ int percent;
+
+ do_div(n, erase_length);
+ percent = (int)n;
/* output progress message only at whole percent
* steps to reduce the number of messages printed
@@ -475,10 +479,13 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
imglen -= readlen;
if (!opts->quiet) {
- int percent = (int)
- ((unsigned long long)
- (opts->length-imglen) * 100
- / opts->length);
+ unsigned long long n = (unsigned long long)
+ (opts->length-imglen) * 100;
+ int percent;
+
+ do_div(n, opts->length);
+ percent = (int)n;
+
/* output progress message only at whole percent
* steps to reduce the number of messages printed
* on (slow) serial consoles
@@ -651,10 +658,13 @@ int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)
}
if (!opts->quiet) {
- int percent = (int)
- ((unsigned long long)
- (opts->length-imglen) * 100
- / opts->length);
+ unsigned long long n = (unsigned long long)
+ (opts->length-imglen) * 100;
+ int percent;
+
+ do_div(n, opts->length);
+ percent = (int)n;
+
/* output progress message only at whole percent
* steps to reduce the number of messages printed
* on (slow) serial consoles
@@ -859,4 +869,4 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length)
return ret;
}
-#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) */
+#endif
diff --git a/drivers/nand_legacy/nand_legacy.c b/drivers/nand_legacy/nand_legacy.c
index 458046d41c..49d2ebb67d 100644
--- a/drivers/nand_legacy/nand_legacy.c
+++ b/drivers/nand_legacy/nand_legacy.c
@@ -15,14 +15,7 @@
#include <asm/io.h>
#include <watchdog.h>
-#ifdef CONFIG_SHOW_BOOT_PROGRESS
-# include <status_led.h>
-# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
-#else
-# define SHOW_BOOT_PROGRESS(arg)
-#endif
-
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)
#include <linux/mtd/nand_legacy.h>
#include <linux/mtd/nand_ids.h>
@@ -1616,4 +1609,4 @@ int read_jffs2_nand(size_t start, size_t len,
}
#endif /* CONFIG_JFFS2_NAND */
-#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) && defined(CFG_NAND_LEGACY) */
+#endif
diff --git a/drivers/natsemi.c b/drivers/natsemi.c
index b009db63eb..075d6c52c4 100644
--- a/drivers/natsemi.c
+++ b/drivers/natsemi.c
@@ -56,8 +56,8 @@
#include <asm/io.h>
#include <pci.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
- defined(CONFIG_NATSEMI)
+#if defined(CONFIG_CMD_NET) \
+ && defined(CONFIG_NET_MULTI) && defined(CONFIG_NATSEMI)
/* defines */
#define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
new file mode 100644
index 0000000000..37d69b9949
--- /dev/null
+++ b/drivers/net/Makefile
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2006
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libnet.a
+
+COBJS := mcffec.o
+
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/net/mcffec.c b/drivers/net/mcffec.c
new file mode 100644
index 0000000000..3b812585b7
--- /dev/null
+++ b/drivers/net/mcffec.c
@@ -0,0 +1,597 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2007 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew@freescale.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 <common.h>
+#include <malloc.h>
+
+#ifdef CONFIG_MCFFEC
+
+#include <asm/fec.h>
+#include <asm/immap.h>
+
+#include <command.h>
+#include <net.h>
+#include <miiphy.h>
+
+#undef ET_DEBUG
+#undef MII_DEBUG
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH 1520
+#define TX_BUF_CNT 2
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+#define PKT_MAXBLR_SIZE 1520
+#define LAST_PKTBUFSRX PKTBUFSRX - 1
+#define BD_ENET_RX_W_E (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY)
+#define BD_ENET_TX_RDY_LST (BD_ENET_TX_READY | BD_ENET_TX_LAST)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI)
+
+struct fec_info_s fec_info[] = {
+#ifdef CFG_FEC0_IOBASE
+ {
+ 0, /* index */
+ CFG_FEC0_IOBASE, /* io base */
+ CFG_FEC0_PINMUX, /* gpio pin muxing */
+ CFG_FEC0_MIIBASE, /* mii base */
+ -1, /* phy_addr */
+ 0, /* duplex and speed */
+ 0, /* phy name */
+ 0, /* phyname init */
+ 0, /* RX BD */
+ 0, /* TX BD */
+ 0, /* rx Index */
+ 0, /* tx Index */
+ 0, /* tx buffer */
+ 0, /* initialized flag */
+ },
+#endif
+#ifdef CFG_FEC1_IOBASE
+ {
+ 1, /* index */
+ CFG_FEC1_IOBASE, /* io base */
+ CFG_FEC1_PINMUX, /* gpio pin muxing */
+ CFG_FEC1_MIIBASE, /* mii base */
+ -1, /* phy_addr */
+ 0, /* duplex and speed */
+ 0, /* phy name */
+ 0, /* phy name init */
+ 0, /* RX BD */
+ 0, /* TX BD */
+ 0, /* rx Index */
+ 0, /* tx Index */
+ 0, /* tx buffer */
+ 0, /* initialized flag */
+ }
+#endif
+};
+
+int fec_send(struct eth_device *dev, volatile void *packet, int length);
+int fec_recv(struct eth_device *dev);
+int fec_init(struct eth_device *dev, bd_t * bd);
+void fec_halt(struct eth_device *dev);
+void fec_reset(struct eth_device *dev);
+
+extern int fecpin_setclear(struct eth_device *dev, int setclear);
+
+#ifdef CFG_DISCOVER_PHY
+extern void __mii_init(void);
+extern uint mii_send(uint mii_cmd);
+extern int mii_discover_phy(struct eth_device *dev);
+extern int mcffec_miiphy_read(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value);
+extern int mcffec_miiphy_write(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value);
+#endif
+
+void setFecDuplexSpeed(volatile fec_t * fecp, bd_t * bd, int dup_spd)
+{
+ if ((dup_spd >> 16) == FULL) {
+ /* Set maximum frame length */
+ fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE |
+ FEC_RCR_PROM | 0x100;
+ fecp->tcr = FEC_TCR_FDEN;
+ } else {
+ /* Half duplex mode */
+ fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) |
+ FEC_RCR_MII_MODE | FEC_RCR_DRT;
+ fecp->tcr &= ~FEC_TCR_FDEN;
+ }
+
+ if ((dup_spd & 0xFFFF) == _100BASET) {
+#ifdef MII_DEBUG
+ printf("100Mbps\n");
+#endif
+ bd->bi_ethspeed = 100;
+ } else {
+#ifdef MII_DEBUG
+ printf("10Mbps\n");
+#endif
+ bd->bi_ethspeed = 10;
+ }
+}
+
+int fec_send(struct eth_device *dev, volatile void *packet, int length)
+{
+ struct fec_info_s *info = dev->priv;
+ volatile fec_t *fecp = (fec_t *) (info->iobase);
+ int j, rc;
+ u16 phyStatus;
+
+ miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &phyStatus);
+
+ /* section 16.9.23.3
+ * Wait for ready
+ */
+ j = 0;
+ while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) &&
+ (j < MCFFEC_TOUT_LOOP)) {
+ udelay(1);
+ j++;
+ }
+ if (j >= MCFFEC_TOUT_LOOP) {
+ printf("TX not ready\n");
+ }
+
+ info->txbd[info->txIdx].cbd_bufaddr = (uint) packet;
+ info->txbd[info->txIdx].cbd_datlen = length;
+ info->txbd[info->txIdx].cbd_sc |= BD_ENET_TX_RDY_LST;
+
+ /* Activate transmit Buffer Descriptor polling */
+ fecp->tdar = 0x01000000; /* Descriptor polling active */
+
+#ifdef CFG_UNIFY_CACHE
+ icache_invalid();
+#endif
+ j = 0;
+ while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) &&
+ (j < MCFFEC_TOUT_LOOP)) {
+ udelay(1);
+ j++;
+ }
+ if (j >= MCFFEC_TOUT_LOOP) {
+ printf("TX timeout\n");
+ }
+
+#ifdef ET_DEBUG
+ printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n",
+ __FILE__, __LINE__, __FUNCTION__, j,
+ info->txbd[info->txIdx].cbd_sc,
+ (info->txbd[info->txIdx].cbd_sc & 0x003C) >> 2);
+#endif
+
+ /* return only status bits */
+ rc = (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_STATS);
+ info->txIdx = (info->txIdx + 1) % TX_BUF_CNT;
+
+ return rc;
+}
+
+int fec_recv(struct eth_device *dev)
+{
+ struct fec_info_s *info = dev->priv;
+ volatile fec_t *fecp = (fec_t *) (info->iobase);
+ int length;
+
+ for (;;) {
+#ifdef CFG_UNIFY_CACHE
+ icache_invalid();
+#endif
+ /* section 16.9.23.2 */
+ if (info->rxbd[info->rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+
+ length = info->rxbd[info->rxIdx].cbd_datlen;
+
+ if (info->rxbd[info->rxIdx].cbd_sc & 0x003f) {
+ printf("%s[%d] err: %x\n",
+ __FUNCTION__, __LINE__,
+ info->rxbd[info->rxIdx].cbd_sc);
+#ifdef ET_DEBUG
+ printf("%s[%d] err: %x\n",
+ __FUNCTION__, __LINE__,
+ info->rxbd[info->rxIdx].cbd_sc);
+#endif
+ } else {
+
+ length -= 4;
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[info->rxIdx], length);
+
+ fecp->eir |= FEC_EIR_RXF;
+ }
+
+ /* Give the buffer back to the FEC. */
+ info->rxbd[info->rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if (info->rxIdx == LAST_PKTBUFSRX) {
+ info->rxbd[PKTBUFSRX - 1].cbd_sc = BD_ENET_RX_W_E;
+ info->rxIdx = 0;
+ } else {
+ info->rxbd[info->rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ info->rxIdx++;
+ }
+
+ /* Try to fill Buffer Descriptors */
+ fecp->rdar = 0x01000000; /* Descriptor polling active */
+ }
+
+ return length;
+}
+
+#ifdef ET_DEBUG
+void dbgFecRegs(struct eth_device *dev)
+{
+ struct fec_info_s *info = dev->priv;
+ volatile fec_t *fecp = (fec_t *) (info->iobase);
+
+ printf("=====\n");
+ printf("ievent %x - %x\n", (int)&fecp->eir, fecp->eir);
+ printf("imask %x - %x\n", (int)&fecp->eimr, fecp->eimr);
+ printf("r_des_active %x - %x\n", (int)&fecp->rdar, fecp->rdar);
+ printf("x_des_active %x - %x\n", (int)&fecp->tdar, fecp->tdar);
+ printf("ecntrl %x - %x\n", (int)&fecp->ecr, fecp->ecr);
+ printf("mii_mframe %x - %x\n", (int)&fecp->mmfr, fecp->mmfr);
+ printf("mii_speed %x - %x\n", (int)&fecp->mscr, fecp->mscr);
+ printf("mii_ctrlstat %x - %x\n", (int)&fecp->mibc, fecp->mibc);
+ printf("r_cntrl %x - %x\n", (int)&fecp->rcr, fecp->rcr);
+ printf("x_cntrl %x - %x\n", (int)&fecp->tcr, fecp->tcr);
+ printf("padr_l %x - %x\n", (int)&fecp->palr, fecp->palr);
+ printf("padr_u %x - %x\n", (int)&fecp->paur, fecp->paur);
+ printf("op_pause %x - %x\n", (int)&fecp->opd, fecp->opd);
+ printf("iadr_u %x - %x\n", (int)&fecp->iaur, fecp->iaur);
+ printf("iadr_l %x - %x\n", (int)&fecp->ialr, fecp->ialr);
+ printf("gadr_u %x - %x\n", (int)&fecp->gaur, fecp->gaur);
+ printf("gadr_l %x - %x\n", (int)&fecp->galr, fecp->galr);
+ printf("x_wmrk %x - %x\n", (int)&fecp->tfwr, fecp->tfwr);
+ printf("r_bound %x - %x\n", (int)&fecp->frbr, fecp->frbr);
+ printf("r_fstart %x - %x\n", (int)&fecp->frsr, fecp->frsr);
+ printf("r_drng %x - %x\n", (int)&fecp->erdsr, fecp->erdsr);
+ printf("x_drng %x - %x\n", (int)&fecp->etdsr, fecp->etdsr);
+ printf("r_bufsz %x - %x\n", (int)&fecp->emrbr, fecp->emrbr);
+
+ printf("\n");
+ printf("rmon_t_drop %x - %x\n", (int)&fecp->rmon_t_drop,
+ fecp->rmon_t_drop);
+ printf("rmon_t_packets %x - %x\n", (int)&fecp->rmon_t_packets,
+ fecp->rmon_t_packets);
+ printf("rmon_t_bc_pkt %x - %x\n", (int)&fecp->rmon_t_bc_pkt,
+ fecp->rmon_t_bc_pkt);
+ printf("rmon_t_mc_pkt %x - %x\n", (int)&fecp->rmon_t_mc_pkt,
+ fecp->rmon_t_mc_pkt);
+ printf("rmon_t_crc_align %x - %x\n", (int)&fecp->rmon_t_crc_align,
+ fecp->rmon_t_crc_align);
+ printf("rmon_t_undersize %x - %x\n", (int)&fecp->rmon_t_undersize,
+ fecp->rmon_t_undersize);
+ printf("rmon_t_oversize %x - %x\n", (int)&fecp->rmon_t_oversize,
+ fecp->rmon_t_oversize);
+ printf("rmon_t_frag %x - %x\n", (int)&fecp->rmon_t_frag,
+ fecp->rmon_t_frag);
+ printf("rmon_t_jab %x - %x\n", (int)&fecp->rmon_t_jab,
+ fecp->rmon_t_jab);
+ printf("rmon_t_col %x - %x\n", (int)&fecp->rmon_t_col,
+ fecp->rmon_t_col);
+ printf("rmon_t_p64 %x - %x\n", (int)&fecp->rmon_t_p64,
+ fecp->rmon_t_p64);
+ printf("rmon_t_p65to127 %x - %x\n", (int)&fecp->rmon_t_p65to127,
+ fecp->rmon_t_p65to127);
+ printf("rmon_t_p128to255 %x - %x\n", (int)&fecp->rmon_t_p128to255,
+ fecp->rmon_t_p128to255);
+ printf("rmon_t_p256to511 %x - %x\n", (int)&fecp->rmon_t_p256to511,
+ fecp->rmon_t_p256to511);
+ printf("rmon_t_p512to1023 %x - %x\n", (int)&fecp->rmon_t_p512to1023,
+ fecp->rmon_t_p512to1023);
+ printf("rmon_t_p1024to2047 %x - %x\n", (int)&fecp->rmon_t_p1024to2047,
+ fecp->rmon_t_p1024to2047);
+ printf("rmon_t_p_gte2048 %x - %x\n", (int)&fecp->rmon_t_p_gte2048,
+ fecp->rmon_t_p_gte2048);
+ printf("rmon_t_octets %x - %x\n", (int)&fecp->rmon_t_octets,
+ fecp->rmon_t_octets);
+
+ printf("\n");
+ printf("ieee_t_drop %x - %x\n", (int)&fecp->ieee_t_drop,
+ fecp->ieee_t_drop);
+ printf("ieee_t_frame_ok %x - %x\n", (int)&fecp->ieee_t_frame_ok,
+ fecp->ieee_t_frame_ok);
+ printf("ieee_t_1col %x - %x\n", (int)&fecp->ieee_t_1col,
+ fecp->ieee_t_1col);
+ printf("ieee_t_mcol %x - %x\n", (int)&fecp->ieee_t_mcol,
+ fecp->ieee_t_mcol);
+ printf("ieee_t_def %x - %x\n", (int)&fecp->ieee_t_def,
+ fecp->ieee_t_def);
+ printf("ieee_t_lcol %x - %x\n", (int)&fecp->ieee_t_lcol,
+ fecp->ieee_t_lcol);
+ printf("ieee_t_excol %x - %x\n", (int)&fecp->ieee_t_excol,
+ fecp->ieee_t_excol);
+ printf("ieee_t_macerr %x - %x\n", (int)&fecp->ieee_t_macerr,
+ fecp->ieee_t_macerr);
+ printf("ieee_t_cserr %x - %x\n", (int)&fecp->ieee_t_cserr,
+ fecp->ieee_t_cserr);
+ printf("ieee_t_sqe %x - %x\n", (int)&fecp->ieee_t_sqe,
+ fecp->ieee_t_sqe);
+ printf("ieee_t_fdxfc %x - %x\n", (int)&fecp->ieee_t_fdxfc,
+ fecp->ieee_t_fdxfc);
+ printf("ieee_t_octets_ok %x - %x\n", (int)&fecp->ieee_t_octets_ok,
+ fecp->ieee_t_octets_ok);
+
+ printf("\n");
+ printf("rmon_r_drop %x - %x\n", (int)&fecp->rmon_r_drop,
+ fecp->rmon_r_drop);
+ printf("rmon_r_packets %x - %x\n", (int)&fecp->rmon_r_packets,
+ fecp->rmon_r_packets);
+ printf("rmon_r_bc_pkt %x - %x\n", (int)&fecp->rmon_r_bc_pkt,
+ fecp->rmon_r_bc_pkt);
+ printf("rmon_r_mc_pkt %x - %x\n", (int)&fecp->rmon_r_mc_pkt,
+ fecp->rmon_r_mc_pkt);
+ printf("rmon_r_crc_align %x - %x\n", (int)&fecp->rmon_r_crc_align,
+ fecp->rmon_r_crc_align);
+ printf("rmon_r_undersize %x - %x\n", (int)&fecp->rmon_r_undersize,
+ fecp->rmon_r_undersize);
+ printf("rmon_r_oversize %x - %x\n", (int)&fecp->rmon_r_oversize,
+ fecp->rmon_r_oversize);
+ printf("rmon_r_frag %x - %x\n", (int)&fecp->rmon_r_frag,
+ fecp->rmon_r_frag);
+ printf("rmon_r_jab %x - %x\n", (int)&fecp->rmon_r_jab,
+ fecp->rmon_r_jab);
+ printf("rmon_r_p64 %x - %x\n", (int)&fecp->rmon_r_p64,
+ fecp->rmon_r_p64);
+ printf("rmon_r_p65to127 %x - %x\n", (int)&fecp->rmon_r_p65to127,
+ fecp->rmon_r_p65to127);
+ printf("rmon_r_p128to255 %x - %x\n", (int)&fecp->rmon_r_p128to255,
+ fecp->rmon_r_p128to255);
+ printf("rmon_r_p256to511 %x - %x\n", (int)&fecp->rmon_r_p256to511,
+ fecp->rmon_r_p256to511);
+ printf("rmon_r_p512to1023 %x - %x\n", (int)&fecp->rmon_r_p512to1023,
+ fecp->rmon_r_p512to1023);
+ printf("rmon_r_p1024to2047 %x - %x\n", (int)&fecp->rmon_r_p1024to2047,
+ fecp->rmon_r_p1024to2047);
+ printf("rmon_r_p_gte2048 %x - %x\n", (int)&fecp->rmon_r_p_gte2048,
+ fecp->rmon_r_p_gte2048);
+ printf("rmon_r_octets %x - %x\n", (int)&fecp->rmon_r_octets,
+ fecp->rmon_r_octets);
+
+ printf("\n");
+ printf("ieee_r_drop %x - %x\n", (int)&fecp->ieee_r_drop,
+ fecp->ieee_r_drop);
+ printf("ieee_r_frame_ok %x - %x\n", (int)&fecp->ieee_r_frame_ok,
+ fecp->ieee_r_frame_ok);
+ printf("ieee_r_crc %x - %x\n", (int)&fecp->ieee_r_crc,
+ fecp->ieee_r_crc);
+ printf("ieee_r_align %x - %x\n", (int)&fecp->ieee_r_align,
+ fecp->ieee_r_align);
+ printf("ieee_r_macerr %x - %x\n", (int)&fecp->ieee_r_macerr,
+ fecp->ieee_r_macerr);
+ printf("ieee_r_fdxfc %x - %x\n", (int)&fecp->ieee_r_fdxfc,
+ fecp->ieee_r_fdxfc);
+ printf("ieee_r_octets_ok %x - %x\n", (int)&fecp->ieee_r_octets_ok,
+ fecp->ieee_r_octets_ok);
+
+ printf("\n\n\n");
+}
+#endif
+
+int fec_init(struct eth_device *dev, bd_t * bd)
+{
+ struct fec_info_s *info = dev->priv;
+ volatile fec_t *fecp = (fec_t *) (info->iobase);
+ int i;
+ u8 *ea = NULL;
+
+ fecpin_setclear(dev, 1);
+
+ fec_reset(dev);
+
+#if defined(CONFIG_CMD_MII) || defined (CONFIG_MII) || \
+ defined (CFG_DISCOVER_PHY)
+
+ mii_init();
+
+ setFecDuplexSpeed(fecp, bd, info->dup_spd);
+#else
+#ifndef CFG_DISCOVER_PHY
+ setFecDuplexSpeed(fecp, bd, (FECDUPLEX << 16) | FECSPEED);
+#endif /* ifndef CFG_DISCOVER_PHY */
+#endif /* CONFIG_CMD_MII || CONFIG_MII */
+
+ /* We use strictly polling mode only */
+ fecp->eimr = 0;
+
+ /* Clear any pending interrupt */
+ fecp->eir = 0xffffffff;
+
+ /* Set station address */
+ if ((u32) fecp == CFG_FEC0_IOBASE) {
+#ifdef CFG_FEC1_IOBASE
+ volatile fec_t *fecp1 = (fec_t *) (CFG_FEC1_IOBASE);
+ ea = &bd->bi_enet1addr[0];
+ fecp1->palr =
+ (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
+ fecp1->paur = (ea[4] << 24) | (ea[5] << 16);
+#endif
+ ea = &bd->bi_enetaddr[0];
+ fecp->palr =
+ (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
+ fecp->paur = (ea[4] << 24) | (ea[5] << 16);
+ } else {
+#ifdef CFG_FEC0_IOBASE
+ volatile fec_t *fecp0 = (fec_t *) (CFG_FEC0_IOBASE);
+ ea = &bd->bi_enetaddr[0];
+ fecp0->palr =
+ (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
+ fecp0->paur = (ea[4] << 24) | (ea[5] << 16);
+#endif
+#ifdef CFG_FEC1_IOBASE
+ ea = &bd->bi_enet1addr[0];
+ fecp->palr =
+ (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
+ fecp->paur = (ea[4] << 24) | (ea[5] << 16);
+#endif
+ }
+
+ /* Clear unicast address hash table */
+ fecp->iaur = 0;
+ fecp->ialr = 0;
+
+ /* Clear multicast address hash table */
+ fecp->gaur = 0;
+ fecp->galr = 0;
+
+ /* Set maximum receive buffer size. */
+ fecp->emrbr = PKT_MAXBLR_SIZE;
+
+ /*
+ * Setup Buffers and Buffer Desriptors
+ */
+ info->rxIdx = 0;
+ info->txIdx = 0;
+
+ /*
+ * Setup Receiver Buffer Descriptors (13.14.24.18)
+ * Settings:
+ * Empty, Wrap
+ */
+ for (i = 0; i < PKTBUFSRX; i++) {
+ info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+ info->rxbd[i].cbd_datlen = 0; /* Reset */
+ info->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+ }
+ info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /*
+ * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+ * Settings:
+ * Last, Tx CRC
+ */
+ for (i = 0; i < TX_BUF_CNT; i++) {
+ info->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
+ info->txbd[i].cbd_datlen = 0; /* Reset */
+ info->txbd[i].cbd_bufaddr = (uint) (&info->txbuf[0]);
+ }
+ info->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /* Set receive and transmit descriptor base */
+ fecp->erdsr = (unsigned int)(&info->rxbd[0]);
+ fecp->etdsr = (unsigned int)(&info->txbd[0]);
+
+ /* Now enable the transmit and receive processing */
+ fecp->ecr |= FEC_ECR_ETHER_EN;
+
+ /* And last, try to fill Rx Buffer Descriptors */
+ fecp->rdar = 0x01000000; /* Descriptor polling active */
+
+ return 1;
+}
+
+void fec_reset(struct eth_device *dev)
+{
+ struct fec_info_s *info = dev->priv;
+ volatile fec_t *fecp = (fec_t *) (info->iobase);
+ int i;
+
+ fecp->ecr = FEC_ECR_RESET;
+ for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) {
+ udelay(1);
+ }
+ if (i == FEC_RESET_DELAY) {
+ printf("FEC_RESET_DELAY timeout\n");
+ }
+}
+
+void fec_halt(struct eth_device *dev)
+{
+ struct fec_info_s *info = dev->priv;
+
+ fec_reset(dev);
+
+ fecpin_setclear(dev, 0);
+
+ info->rxIdx = info->txIdx = 0;
+ memset(info->rxbd, 0, PKTBUFSRX * sizeof(cbd_t));
+ memset(info->txbd, 0, TX_BUF_CNT * sizeof(cbd_t));
+ memset(info->txbuf, 0, DBUF_LENGTH);
+}
+
+int mcffec_initialize(bd_t * bis)
+{
+ struct eth_device *dev;
+ int i;
+
+ for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) {
+
+ dev =
+ (struct eth_device *)memalign(CFG_CACHELINE_SIZE,
+ sizeof *dev);
+ if (dev == NULL)
+ hang();
+
+ memset(dev, 0, sizeof(*dev));
+
+ sprintf(dev->name, "FEC%d", fec_info[i].index);
+
+ dev->priv = &fec_info[i];
+ dev->init = fec_init;
+ dev->halt = fec_halt;
+ dev->send = fec_send;
+ dev->recv = fec_recv;
+
+ /* setup Receive and Transmit buffer descriptor */
+ fec_info[i].rxbd =
+ (cbd_t *) memalign(CFG_CACHELINE_SIZE,
+ (PKTBUFSRX * sizeof(cbd_t)));
+ fec_info[i].txbd =
+ (cbd_t *) memalign(CFG_CACHELINE_SIZE,
+ (TX_BUF_CNT * sizeof(cbd_t)));
+ fec_info[i].txbuf =
+ (char *)memalign(CFG_CACHELINE_SIZE, DBUF_LENGTH);
+#ifdef ET_DEBUG
+ printf("rxbd %x txbd %x\n",
+ (int)fec_info[i].rxbd, (int)fec_info[i].txbd);
+#endif
+
+ fec_info[i].phy_name = (char *)memalign(CFG_CACHELINE_SIZE, 32);
+
+ eth_register(dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+ miiphy_register(dev->name,
+ mcffec_miiphy_read, mcffec_miiphy_write);
+#endif
+ }
+
+ /* default speed */
+ bis->bi_ethspeed = 10;
+
+ return 1;
+}
+
+#endif /* CONFIG_CMD_NET, FEC_ENET & NET_MULTI */
+#endif /* CONFIG_MCFFEC */
diff --git a/drivers/netarm_eth.c b/drivers/netarm_eth.c
index 89b3a8394e..a99ee5da2e 100644
--- a/drivers/netarm_eth.c
+++ b/drivers/netarm_eth.c
@@ -30,7 +30,7 @@
#include <asm/arch/netarm_registers.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
static int na_mii_poll_busy (void);
diff --git a/drivers/ns8382x.c b/drivers/ns8382x.c
index 976f86aaff..f8b143a01a 100644
--- a/drivers/ns8382x.c
+++ b/drivers/ns8382x.c
@@ -56,8 +56,8 @@
#include <asm/io.h>
#include <pci.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
- defined(CONFIG_NS8382X)
+#if defined(CONFIG_CMD_NET) \
+ && defined(CONFIG_NET_MULTI) && defined(CONFIG_NS8382X)
/* defines */
#define DSIZE 0x00000FFF
diff --git a/drivers/pci.c b/drivers/pci.c
index 050582f782..50ca6b0bad 100644
--- a/drivers/pci.c
+++ b/drivers/pci.c
@@ -82,8 +82,10 @@ int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose,\
{ \
u32 val32; \
\
- if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0)\
+ if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0) { \
+ *val = -1; \
return -1; \
+ } \
\
*val = (val32 >> ((offset & (int)off_mask) * 8)); \
\
@@ -490,10 +492,16 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus)
int pci_hose_scan(struct pci_controller *hose)
{
+ /* Start scan at current_busno.
+ * PCIe will start scan at first_busno+1.
+ */
+ /* For legacy support, ensure current>=first */
+ if (hose->first_busno > hose->current_busno)
+ hose->current_busno = hose->first_busno;
#ifdef CONFIG_PCI_PNP
pciauto_config_init(hose);
#endif
- return pci_hose_scan_bus(hose, hose->first_busno);
+ return pci_hose_scan_bus(hose, hose->current_busno);
}
void pci_init(void)
diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c
index f170c2db89..acfda83ba5 100644
--- a/drivers/pci_auto.c
+++ b/drivers/pci_auto.c
@@ -28,6 +28,11 @@
#define PCIAUTO_IDE_MODE_MASK 0x05
+/* the user can define CFG_PCI_CACHE_LINE_SIZE to avoid problems */
+#ifndef CFG_PCI_CACHE_LINE_SIZE
+#define CFG_PCI_CACHE_LINE_SIZE 8
+#endif
+
/*
*
*/
@@ -65,7 +70,7 @@ int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned
res->bus_lower = addr + size;
- DEBUGF("address=0x%lx", addr);
+ DEBUGF("address=0x%lx bus_lower=%x", addr, res->bus_lower);
*bar = addr;
return 0;
@@ -94,7 +99,7 @@ void pciauto_setup_device(struct pci_controller *hose,
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) {
+ 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);
@@ -150,11 +155,12 @@ void pciauto_setup_device(struct pci_controller *hose,
}
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_CACHE_LINE_SIZE,
+ CFG_PCI_CACHE_LINE_SIZE);
pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
}
-static void pciauto_prescan_setup_bridge(struct pci_controller *hose,
+void pciauto_prescan_setup_bridge(struct pci_controller *hose,
pci_dev_t dev, int sub_bus)
{
struct pci_region *pci_mem = hose->pci_mem;
@@ -165,8 +171,10 @@ static void pciauto_prescan_setup_bridge(struct pci_controller *hose,
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);
+ pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS,
+ PCI_BUS(dev) - hose->first_busno);
+ pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS,
+ sub_bus - hose->first_busno);
pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff);
if (pci_mem) {
@@ -211,7 +219,7 @@ static void pciauto_prescan_setup_bridge(struct pci_controller *hose,
pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat | PCI_COMMAND_MASTER);
}
-static void pciauto_postscan_setup_bridge(struct pci_controller *hose,
+void pciauto_postscan_setup_bridge(struct pci_controller *hose,
pci_dev_t dev, int sub_bus)
{
struct pci_region *pci_mem = hose->pci_mem;
@@ -219,7 +227,8 @@ static void pciauto_postscan_setup_bridge(struct pci_controller *hose,
struct pci_region *pci_io = hose->pci_io;
/* Configure bus number registers */
- pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus);
+ pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS,
+ sub_bus - hose->first_busno);
if (pci_mem) {
/* Round memory allocator to 1MB boundary */
@@ -282,25 +291,36 @@ void pciauto_config_init(struct pci_controller *hose)
if (hose->pci_mem) {
pciauto_region_init(hose->pci_mem);
- DEBUGF("PCI Autoconfig: Memory region: [%lx-%lx]\n",
+ DEBUGF("PCI Autoconfig: Bus Memory region: [%lx-%lx],\n"
+ "\t\tPhysical Memory [%x-%x]\n",
hose->pci_mem->bus_start,
- hose->pci_mem->bus_start + hose->pci_mem->size - 1);
+ hose->pci_mem->bus_start + hose->pci_mem->size - 1,
+ hose->pci_mem->phys_start,
+ hose->pci_mem->phys_start + hose->pci_mem->size - 1);
}
if (hose->pci_prefetch) {
pciauto_region_init(hose->pci_prefetch);
- DEBUGF("PCI Autoconfig: Prefetchable Memory region: [%lx-%lx]\n",
+ DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [%lx-%lx],\n"
+ "\t\tPhysical Memory [%x-%x]\n",
hose->pci_prefetch->bus_start,
- hose->pci_prefetch->bus_start + hose->pci_prefetch->size - 1);
+ hose->pci_prefetch->bus_start + hose->pci_prefetch->size - 1,
+ hose->pci_prefetch->phys_start,
+ hose->pci_prefetch->phys_start +
+ hose->pci_prefetch->size - 1);
}
if (hose->pci_io) {
pciauto_region_init(hose->pci_io);
- DEBUGF("PCI Autoconfig: I/O region: [%lx-%lx]\n",
+ DEBUGF("PCI Autoconfig: Bus I/O region: [%lx-%lx],\n"
+ "\t\tPhysical Memory: [%x-%x]\n",
hose->pci_io->bus_start,
- hose->pci_io->bus_start + hose->pci_io->size - 1);
+ hose->pci_io->bus_start + hose->pci_io->size - 1,
+ hose->pci_io->phys_start,
+ hose->pci_io->phys_start + hose->pci_io->size - 1);
+
}
}
@@ -317,6 +337,12 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
switch(class) {
+ case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */
+ DEBUGF("PCI AutoConfig: Found PowerPC device\n");
+ pciauto_setup_device(hose, dev, 6, hose->pci_mem,
+ hose->pci_prefetch, hose->pci_io);
+ break;
+
case PCI_CLASS_BRIDGE_PCI:
hose->current_busno++;
pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_prefetch, hose->pci_io);
diff --git a/drivers/pci_indirect.c b/drivers/pci_indirect.c
index d7be0810f5..a8220fb411 100644
--- a/drivers/pci_indirect.c
+++ b/drivers/pci_indirect.c
@@ -45,7 +45,7 @@ indirect_##rw##_config_##size(struct pci_controller *hose, \
cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
return 0; \
}
-#elif defined(CONFIG_E500)
+#elif defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
#define INDIRECT_PCI_OP(rw, size, type, op, mask) \
static int \
indirect_##rw##_config_##size(struct pci_controller *hose, \
@@ -55,7 +55,7 @@ indirect_##rw##_config_##size(struct pci_controller *hose, \
b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev); \
b = b - hose->first_busno; \
dev = PCI_BDF(b, d, f); \
- *(hose->cfg_addr) = dev | (offset & 0xfc) | 0x80000000; \
+ *(hose->cfg_addr) = dev | (offset & 0xfc) | ((offset & 0xf00) << 16) | 0x80000000; \
sync(); \
cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
return 0; \
diff --git a/drivers/pcnet.c b/drivers/pcnet.c
index da9ac7f99a..2af0e8f244 100644
--- a/drivers/pcnet.c
+++ b/drivers/pcnet.c
@@ -45,8 +45,8 @@
#define PCNET_DEBUG2(fmt,args...)
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
- && defined(CONFIG_PCNET)
+#if defined(CONFIG_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!"
diff --git a/drivers/plb2800_eth.c b/drivers/plb2800_eth.c
index 4c683d7a5c..0ae5d808a6 100644
--- a/drivers/plb2800_eth.c
+++ b/drivers/plb2800_eth.c
@@ -25,8 +25,8 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
- && defined(CONFIG_PLB2800_ETHER)
+#if defined(CONFIG_CMD_NET) \
+ && defined(CONFIG_NET_MULTI) && defined(CONFIG_PLB2800_ETHER)
#include <malloc.h>
#include <net.h>
diff --git a/drivers/pxa_pcmcia.c b/drivers/pxa_pcmcia.c
index d9d38bbfcd..6020e46283 100644
--- a/drivers/pxa_pcmcia.c
+++ b/drivers/pxa_pcmcia.c
@@ -85,7 +85,7 @@ int pcmcia_on (void)
return rc;
}
-#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+#if defined(CONFIG_CMD_PCMCIA)
int pcmcia_off (void)
{
return 0;
diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c
index 5f209629f4..7559e92227 100644
--- a/drivers/qe/qe.c
+++ b/drivers/qe/qe.c
@@ -30,6 +30,8 @@
qe_map_t *qe_immr = NULL;
static qe_snum_t snums[QE_NUM_OF_SNUM];
+DECLARE_GLOBAL_DATA_PTR;
+
void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
{
u32 cecr;
@@ -51,8 +53,6 @@ void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
uint qe_muram_alloc(uint size, uint align)
{
- DECLARE_GLOBAL_DATA_PTR;
-
uint retloc;
uint align_mask, off;
uint savebase;
@@ -98,7 +98,7 @@ static void qe_sdma_init(void)
out_be32(&p->sdaqmr, 0);
/* Allocate 2KB temporary buffer for sdma */
- sdma_buffer_base = qe_muram_alloc(2048, 64);
+ sdma_buffer_base = qe_muram_alloc(2048, 4096);
out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);
/* Clear sdma status */
@@ -158,8 +158,6 @@ void qe_put_snum(u8 snum)
void qe_init(uint qe_base)
{
- DECLARE_GLOBAL_DATA_PTR;
-
/* Init the QE IMMR base */
qe_immr = (qe_map_t *)qe_base;
@@ -204,7 +202,6 @@ void qe_assign_page(uint snum, uint para_ram_base)
int qe_set_brg(uint brg, uint rate)
{
- DECLARE_GLOBAL_DATA_PTR;
volatile uint *bp;
u32 divisor;
int div16 = 0;
diff --git a/drivers/qe/qe.h b/drivers/qe/qe.h
index 0bcd0a9573..400b1a6f60 100644
--- a/drivers/qe/qe.h
+++ b/drivers/qe/qe.h
@@ -29,7 +29,7 @@
#define QE_NUM_OF_BRGS 16
#define UCC_MAX_NUM 8
-#define QE_DATAONLY_BASE (uint)(128)
+#define QE_DATAONLY_BASE 0
#define QE_DATAONLY_SIZE (QE_MURAM_SIZE - QE_DATAONLY_BASE)
/* QE threads SNUM
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c
index c416a67c83..dc2765bb09 100644
--- a/drivers/qe/uec.c
+++ b/drivers/qe/uec.c
@@ -391,17 +391,17 @@ static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode)
return 0;
}
-static int init_mii_management_configuration(uec_t *uec_regs)
+static int init_mii_management_configuration(uec_mii_t *uec_mii_regs)
{
uint timeout = 0x1000;
u32 miimcfg = 0;
- miimcfg = in_be32(&uec_regs->miimcfg);
+ miimcfg = in_be32(&uec_mii_regs->miimcfg);
miimcfg |= MIIMCFG_MNGMNT_CLC_DIV_INIT_VALUE;
- out_be32(&uec_regs->miimcfg, miimcfg);
+ out_be32(&uec_mii_regs->miimcfg, miimcfg);
/* Wait until the bus is free */
- while ((in_be32(&uec_regs->miimcfg) & MIIMIND_BUSY) && timeout--);
+ while ((in_be32(&uec_mii_regs->miimcfg) & MIIMIND_BUSY) && timeout--);
if (timeout <= 0) {
printf("%s: The MII Bus is stuck!", __FUNCTION__);
return -ETIMEDOUT;
@@ -413,13 +413,13 @@ static int init_mii_management_configuration(uec_t *uec_regs)
static int init_phy(struct eth_device *dev)
{
uec_private_t *uec;
- uec_t *uec_regs;
+ uec_mii_t *umii_regs;
struct uec_mii_info *mii_info;
struct phy_info *curphy;
int err;
uec = (uec_private_t *)dev->priv;
- uec_regs = uec->uec_regs;
+ umii_regs = uec->uec_mii_regs;
uec->oldlink = 0;
uec->oldspeed = 0;
@@ -451,19 +451,19 @@ static int init_phy(struct eth_device *dev)
mii_info->mii_id = uec->uec_info->phy_address;
mii_info->dev = dev;
- mii_info->mdio_read = &read_phy_reg;
- mii_info->mdio_write = &write_phy_reg;
+ mii_info->mdio_read = &uec_read_phy_reg;
+ mii_info->mdio_write = &uec_write_phy_reg;
uec->mii_info = mii_info;
- if (init_mii_management_configuration(uec_regs)) {
+ if (init_mii_management_configuration(umii_regs)) {
printf("%s: The MII Bus is stuck!", dev->name);
err = -1;
goto bus_fail;
}
/* get info for this PHY */
- curphy = get_phy_info(uec->mii_info);
+ curphy = uec_get_phy_info(uec->mii_info);
if (!curphy) {
printf("%s: No PHY found", dev->name);
err = -1;
@@ -989,6 +989,13 @@ static int uec_startup(uec_private_t *uec)
/* Setup MAC interface mode */
uec_set_mac_if_mode(uec, uec_info->enet_interface);
+ /* Setup MII management base */
+#ifndef CONFIG_eTSEC_MDIO_BUS
+ uec->uec_mii_regs = (uec_mii_t *)(&uec_regs->miimcfg);
+#else
+ uec->uec_mii_regs = (uec_mii_t *) CONFIG_MIIM_ADDRESS;
+#endif
+
/* Setup MII master clock source */
qe_set_mii_clk_src(uec_info->uf_info.ucc_num);
@@ -1103,7 +1110,7 @@ static int uec_init(struct eth_device* dev, bd_t *bd)
if (dev->enetaddr[0] & 0x01) {
printf("%s: MacAddress is multcast address\n",
__FUNCTION__);
- return -EINVAL;
+ return 0;
}
uec_set_mac_address(uec, dev->enetaddr);
uec->the_first_run = 1;
@@ -1112,10 +1119,10 @@ static int uec_init(struct eth_device* dev, bd_t *bd)
err = uec_open(uec, COMM_DIR_RX_AND_TX);
if (err) {
printf("%s: cannot enable UEC device\n", dev->name);
- return err;
+ return 0;
}
- return 0;
+ return uec->mii_info->link;
}
static void uec_halt(struct eth_device* dev)
diff --git a/drivers/qe/uec.h b/drivers/qe/uec.h
index 04950264b8..c384055ceb 100644
--- a/drivers/qe/uec.h
+++ b/drivers/qe/uec.h
@@ -675,6 +675,7 @@ typedef struct uec_private {
ucc_fast_private_t *uccf;
struct eth_device *dev;
uec_t *uec_regs;
+ uec_mii_t *uec_mii_regs;
/* enet init command parameter */
uec_init_cmd_pram_t *p_init_enet_param;
u32 init_enet_param_offset;
diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c
index 76fd38896a..ca6faa6ef4 100644
--- a/drivers/qe/uec_phy.c
+++ b/drivers/qe/uec_phy.c
@@ -60,14 +60,14 @@ void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
/* Write value to the PHY for this device to the register at regnum, */
/* waiting until the write is done before it returns. All PHY */
/* configuration has to be done through the TSEC1 MIIM regs */
-void write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int value)
+void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int value)
{
uec_private_t *ugeth = (uec_private_t *) dev->priv;
- uec_t *ug_regs;
+ uec_mii_t *ug_regs;
enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
u32 tmp_reg;
- ug_regs = ugeth->uec_regs;
+ ug_regs = ugeth->uec_mii_regs;
/* Stop the MII management read cycle */
out_be32 (&ug_regs->miimcom, 0);
@@ -87,15 +87,15 @@ void write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int value)
/* Reads from register regnum in the PHY for device dev, */
/* returning the value. Clears miimcom first. All PHY */
/* configuration has to be done through the TSEC1 MIIM regs */
-int read_phy_reg (struct eth_device *dev, int mii_id, int regnum)
+int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum)
{
uec_private_t *ugeth = (uec_private_t *) dev->priv;
- uec_t *ug_regs;
+ uec_mii_t *ug_regs;
enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
u32 tmp_reg;
u16 value;
- ug_regs = ugeth->uec_regs;
+ ug_regs = ugeth->uec_mii_regs;
/* Setting up the MII Mangement Address Register */
tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
@@ -521,7 +521,7 @@ void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val)
/* Use the PHY ID registers to determine what type of PHY is attached
* to device dev. return a struct phy_info structure describing that PHY
*/
-struct phy_info *get_phy_info (struct uec_mii_info *mii_info)
+struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
{
u16 phy_reg;
u32 phy_ID;
diff --git a/drivers/qe/uec_phy.h b/drivers/qe/uec_phy.h
index 9bd926ddd5..e59a940e0d 100644
--- a/drivers/qe/uec_phy.h
+++ b/drivers/qe/uec_phy.h
@@ -249,10 +249,10 @@ struct phy_info {
void (*close) (struct uec_mii_info * mii_info);
};
-struct phy_info *get_phy_info (struct uec_mii_info *mii_info);
-void write_phy_reg (struct eth_device *dev, int mii_id, int regnum,
+struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info);
+void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum,
int value);
-int read_phy_reg (struct eth_device *dev, int mii_id, int regnum);
+int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum);
void mii_clear_phy_interrupt (struct uec_mii_info *mii_info);
void mii_configure_phy_interrupt (struct uec_mii_info *mii_info,
u32 interrupts);
diff --git a/drivers/rpx_pcmcia.c b/drivers/rpx_pcmcia.c
index 2a0a9e05a2..c7c425b93c 100644
--- a/drivers/rpx_pcmcia.c
+++ b/drivers/rpx_pcmcia.c
@@ -9,11 +9,11 @@
#undef CONFIG_PCMCIA
-#if CONFIG_COMMANDS & CFG_CMD_PCMCIA
+#if defined(CONFIG_CMD_PCMCIA)
#define CONFIG_PCMCIA
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
+#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
#define CONFIG_PCMCIA
#endif
@@ -62,12 +62,12 @@ int pcmcia_hardware_enable (int slot)
return 0; /* No hardware to enable */
}
-#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+#if defined(CONFIG_CMD_PCMCIA)
static int pcmcia_hardware_disable(int slot)
{
return 0; /* No hardware to disable */
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_PCMCIA */
+#endif
#endif /* CONFIG_PCMCIA && (CONFIG_RPXCLASSIC || CONFIG_RPXLITE) */
diff --git a/drivers/rtl8019.c b/drivers/rtl8019.c
index 62b9245517..409a69f021 100644
--- a/drivers/rtl8019.c
+++ b/drivers/rtl8019.c
@@ -34,7 +34,7 @@
#ifdef CONFIG_DRIVER_RTL8019
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
/* packet page register access functions */
diff --git a/drivers/rtl8139.c b/drivers/rtl8139.c
index afe1a4fdaf..2367180057 100644
--- a/drivers/rtl8139.c
+++ b/drivers/rtl8139.c
@@ -77,7 +77,7 @@
#include <asm/io.h>
#include <pci.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_RTL8139)
#define TICKS_PER_SEC CFG_HZ
@@ -193,6 +193,12 @@ static void rtl_reset(struct eth_device *dev);
static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length);
static int rtl_poll(struct eth_device *dev);
static void rtl_disable(struct eth_device *dev);
+#ifdef CONFIG_MCAST_TFTP/* This driver already accepts all b/mcast */
+static int rtl_bcast_addr (struct eth_device *dev, u8 bcast_mac, u8 set)
+{
+ return (0);
+}
+#endif
static struct pci_device_id supported[] = {
{PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139},
@@ -228,6 +234,9 @@ int rtl8139_initialize(bd_t *bis)
dev->halt = rtl_disable;
dev->send = rtl_transmit;
dev->recv = rtl_poll;
+#ifdef CONFIG_MCAST_TFTP
+ dev->mcast = rtl_bcast_addr;
+#endif
eth_register (dev);
@@ -535,4 +544,4 @@ static void rtl_disable(struct eth_device *dev)
udelay (100); /* wait 100us */
}
}
-#endif /* CFG_CMD_NET && CONFIG_NET_MULTI && CONFIG_RTL8139 */
+#endif
diff --git a/drivers/rtl8169.c b/drivers/rtl8169.c
index 3393ba890a..63ea2cca9b 100644
--- a/drivers/rtl8169.c
+++ b/drivers/rtl8169.c
@@ -55,7 +55,7 @@
#include <asm/io.h>
#include <pci.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_RTL8169)
#undef DEBUG_RTL8169
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
new file mode 100644
index 0000000000..93c68dd2e0
--- /dev/null
+++ b/drivers/serial/Makefile
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2006
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libserial.a
+
+COBJS := mcfuart.o
+
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c
new file mode 100644
index 0000000000..88f3eb10ab
--- /dev/null
+++ b/drivers/serial/mcfuart.c
@@ -0,0 +1,133 @@
+/*
+ * (C) Copyright 2004-2007 Freescale Semiconductor, Inc.
+ * TsiChung Liew, Tsi-Chung.Liew@freescale.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
+ *
+ */
+
+/*
+ * Minimal serial functions needed to use one of the uart ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_MCFUART
+
+#include <asm/immap.h>
+#include <asm/uart.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void uart_port_conf(void);
+
+int serial_init(void)
+{
+ volatile uart_t *uart;
+ u32 counter;
+
+ uart = (volatile uart_t *)(CFG_UART_BASE);
+
+ uart_port_conf();
+
+ /* write to SICR: SIM2 = uart mode,dcd does not affect rx */
+ uart->ucr = UART_UCR_RESET_RX;
+ uart->ucr = UART_UCR_RESET_TX;
+ uart->ucr = UART_UCR_RESET_ERROR;
+ uart->ucr = UART_UCR_RESET_MR;
+ __asm__("nop");
+
+ uart->uimr = 0;
+
+ /* write to CSR: RX/TX baud rate from timers */
+ uart->ucsr = (UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK);
+
+ uart->umr = (UART_UMR_BC_8 | UART_UMR_PM_NONE);
+ uart->umr = UART_UMR_SB_STOP_BITS_1;
+
+ /* Setting up BaudRate */
+ counter = (u32) (gd->bus_clk / (gd->baudrate));
+ counter >>= 5;
+
+ /* write to CTUR: divide counter upper byte */
+ uart->ubg1 = (u8) ((counter & 0xff00) >> 8);
+ /* write to CTLR: divide counter lower byte */
+ uart->ubg2 = (u8) (counter & 0x00ff);
+
+ uart->ucr = (UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED);
+
+ return (0);
+}
+
+void serial_putc(const char c)
+{
+ volatile uart_t *uart = (volatile uart_t *)(CFG_UART_BASE);
+
+ if (c == '\n')
+ serial_putc('\r');
+
+ /* Wait for last character to go. */
+ while (!(uart->usr & UART_USR_TXRDY)) ;
+
+ uart->utb = c;
+}
+
+void serial_puts(const char *s)
+{
+ while (*s) {
+ serial_putc(*s++);
+ }
+}
+
+int serial_getc(void)
+{
+ volatile uart_t *uart = (volatile uart_t *)(CFG_UART_BASE);
+
+ /* Wait for a character to arrive. */
+ while (!(uart->usr & UART_USR_RXRDY)) ;
+ return uart->urb;
+}
+
+int serial_tstc(void)
+{
+ volatile uart_t *uart = (volatile uart_t *)(CFG_UART_BASE);
+
+ return (uart->usr & UART_USR_RXRDY);
+}
+
+void serial_setbrg(void)
+{
+ volatile uart_t *uart = (volatile uart_t *)(CFG_UART_BASE);
+ u32 counter;
+
+ counter = ((gd->bus_clk / gd->baudrate)) >> 5;
+ counter++;
+
+ /* write to CTUR: divide counter upper byte */
+ uart->ubg1 = ((counter & 0xff00) >> 8);
+ /* write to CTLR: divide counter lower byte */
+ uart->ubg2 = (counter & 0x00ff);
+
+ uart->ucr = UART_UCR_RESET_RX;
+ uart->ucr = UART_UCR_RESET_TX;
+
+ uart->ucr = UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED;
+}
+#endif /* CONFIG_MCFUART */
diff --git a/drivers/sil680.c b/drivers/sil680.c
new file mode 100644
index 0000000000..a6143df4c0
--- /dev/null
+++ b/drivers/sil680.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2007
+ * Gary Jennejohn, DENX Software Engineering, garyj@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
+ *
+ */
+/* sil680.c - ide support functions for the Sil0680A controller */
+
+/*
+ * The following parameters must be defined in the configuration file
+ * of the target board:
+ *
+ * #define CFG_IDE_SIL680
+ *
+ * #define CONFIG_PCI_PNP
+ * NOTE it may also be necessary to define this if the default of 8 is
+ * incorrect for the target board (e.g. the sequoia board requires 0).
+ * #define CFG_PCI_CACHE_LINE_SIZE 0
+ *
+ * #define CONFIG_CMD_IDE
+ * #undef CONFIG_IDE_8xx_DIRECT
+ * #undef CONFIG_IDE_LED
+ * #undef CONFIG_IDE_RESET
+ * #define CONFIG_IDE_PREINIT
+ * #define CFG_IDE_MAXBUS 2 - modify to suit
+ * #define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*2) - modify to suit
+ * #define CFG_ATA_BASE_ADDR 0
+ * #define CFG_ATA_IDE0_OFFSET 0
+ * #define CFG_ATA_IDE1_OFFSET 0
+ * #define CFG_ATA_DATA_OFFSET 0
+ * #define CFG_ATA_REG_OFFSET 0
+ * #define CFG_ATA_ALT_OFFSET 0x0004
+ *
+ * The mapping for PCI IO-space.
+ * NOTE this is the value for the sequoia board. Modify to suit.
+ * #define CFG_PCI0_IO_SPACE 0xE8000000
+ */
+
+#include <common.h>
+#if defined(CFG_IDE_SIL680)
+#include <ata.h>
+#include <ide.h>
+#include <pci.h>
+
+extern ulong ide_bus_offset[CFG_IDE_MAXBUS];
+
+int ide_preinit (void)
+{
+ int status;
+ pci_dev_t devbusfn;
+ int l;
+
+ status = 1;
+ for (l = 0; l < CFG_IDE_MAXBUS; l++) {
+ ide_bus_offset[l] = -ATA_STATUS;
+ }
+ devbusfn = pci_find_device (0x1095, 0x0680, 0);
+ if (devbusfn != -1) {
+ status = 0;
+
+ pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0,
+ (u32 *) &ide_bus_offset[0]);
+ ide_bus_offset[0] &= 0xfffffff8;
+ ide_bus_offset[0] += CFG_PCI0_IO_SPACE;
+ pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_2,
+ (u32 *) &ide_bus_offset[1]);
+ ide_bus_offset[1] &= 0xfffffff8;
+ ide_bus_offset[1] += CFG_PCI0_IO_SPACE;
+ /* init various things - taken from the Linux driver */
+ /* set PIO mode */
+ pci_write_config_byte(devbusfn, 0x80, 0x00);
+ pci_write_config_byte(devbusfn, 0x84, 0x00);
+ /* IDE0 */
+ pci_write_config_byte(devbusfn, 0xA1, 0x02);
+ pci_write_config_word(devbusfn, 0xA2, 0x328A);
+ pci_write_config_dword(devbusfn, 0xA4, 0x62DD62DD);
+ pci_write_config_dword(devbusfn, 0xA8, 0x43924392);
+ pci_write_config_dword(devbusfn, 0xAC, 0x40094009);
+ /* IDE1 */
+ pci_write_config_byte(devbusfn, 0xB1, 0x02);
+ pci_write_config_word(devbusfn, 0xB2, 0x328A);
+ pci_write_config_dword(devbusfn, 0xB4, 0x62DD62DD);
+ pci_write_config_dword(devbusfn, 0xB8, 0x43924392);
+ pci_write_config_dword(devbusfn, 0xBC, 0x40094009);
+ }
+ return (status);
+}
+
+void ide_set_reset (int flag) {
+ return;
+}
+
+#endif /* CFG_IDE_SIL680 */
diff --git a/drivers/sk98lin/uboot_drv.c b/drivers/sk98lin/uboot_drv.c
index 263dac8106..d02cd1be24 100644
--- a/drivers/sk98lin/uboot_drv.c
+++ b/drivers/sk98lin/uboot_drv.c
@@ -25,7 +25,7 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_SK98)
#include "h/skdrv1st.h"
diff --git a/drivers/sym53c8xx.c b/drivers/sym53c8xx.c
index ae10f80ecf..29eeccd9a8 100644
--- a/drivers/sym53c8xx.c
+++ b/drivers/sym53c8xx.c
@@ -51,7 +51,7 @@
#define PRINTF(fmt,args...)
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
+#if defined(CONFIG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
#undef SCSI_SINGLE_STEP
/*
@@ -787,7 +787,7 @@ void scsi_chip_init(void)
scsi_write_byte(DMODE,0x00);
#endif
}
-#endif /* (CONFIG_COMMANDS & CFG_CMD_SCSI) */
+#endif
#endif /* CONFIG_SCSI_SYM53C8XX */
diff --git a/drivers/systemace.c b/drivers/systemace.c
index 3848d9c59c..7d82c27c6e 100644
--- a/drivers/systemace.c
+++ b/drivers/systemace.c
@@ -211,10 +211,16 @@ static unsigned long systemace_read(int dev, unsigned long start,
/* Write sector count | ReadMemCardData. */
ace_writew((trans & 0xff) | 0x0300, 0x14);
+/*
+ * For FPGA configuration via SystemACE is reset unacceptable
+ * CFGDONE bit in STATUSREG is not set to 1.
+ */
+#ifndef SYSTEMACE_CONFIG_FPGA
/* Reset the configruation controller */
val = ace_readw(0x18);
val |= 0x0080;
ace_writew(val, 0x18);
+#endif
retry = trans * 16;
while (retry > 0) {
diff --git a/drivers/ti_pci1410a.c b/drivers/ti_pci1410a.c
index d5297b5721..208ca50a74 100644
--- a/drivers/ti_pci1410a.c
+++ b/drivers/ti_pci1410a.c
@@ -64,7 +64,7 @@
#include <pcmcia.h>
-#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) && defined(CONFIG_IDE_TI_CARDBUS)
+#if defined(CONFIG_CMD_PCMCIA) && defined(CONFIG_IDE_TI_CARDBUS)
int pcmcia_on(int ide_base_bus);
diff --git a/drivers/tigon3.c b/drivers/tigon3.c
index ec2cd2ac36..5f6a4ecd0a 100644
--- a/drivers/tigon3.c
+++ b/drivers/tigon3.c
@@ -12,7 +12,7 @@
/******************************************************************************/
#include <common.h>
#include <asm/types.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \
defined(CONFIG_TIGON3)
#ifdef CONFIG_BMW
#include <mpc824x.h>
@@ -26,69 +26,70 @@
/* 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);
+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);
+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);
+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);
-
+LM_STATUS LM_LoadRlsFirmware (PLM_DEVICE_BLOCK pDevice);
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-LM_UINT32
-LM_RegRdInd(
-PLM_DEVICE_BLOCK pDevice,
-LM_UINT32 Register) {
- LM_UINT32 Value32;
+LM_UINT32 LM_RegRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register)
+{
+ LM_UINT32 Value32;
#if PCIX_TARGET_WORKAROUND
- MM_ACQUIRE_UNDI_LOCK(pDevice);
+ MM_ACQUIRE_UNDI_LOCK (pDevice);
#endif
- MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
- MM_ReadConfig32(pDevice, T3_PCI_REG_DATA_REG, &Value32);
+ 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);
+ MM_RELEASE_UNDI_LOCK (pDevice);
#endif
- return Value32;
-} /* LM_RegRdInd */
-
+ return Value32;
+} /* LM_RegRdInd */
/******************************************************************************/
/* Description: */
@@ -96,47 +97,41 @@ LM_UINT32 Register) {
/* Return: */
/******************************************************************************/
LM_VOID
-LM_RegWrInd(
-PLM_DEVICE_BLOCK pDevice,
-LM_UINT32 Register,
-LM_UINT32 Value32) {
+LM_RegWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, LM_UINT32 Value32)
+{
#if PCIX_TARGET_WORKAROUND
- MM_ACQUIRE_UNDI_LOCK(pDevice);
+ MM_ACQUIRE_UNDI_LOCK (pDevice);
#endif
- MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
- MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, Value32);
+ 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);
+ MM_RELEASE_UNDI_LOCK (pDevice);
#endif
-} /* LM_RegWrInd */
-
+} /* LM_RegWrInd */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-LM_UINT32
-LM_MemRdInd(
-PLM_DEVICE_BLOCK pDevice,
-LM_UINT32 MemAddr) {
- LM_UINT32 Value32;
+LM_UINT32 LM_MemRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr)
+{
+ LM_UINT32 Value32;
- MM_ACQUIRE_UNDI_LOCK(pDevice);
+ 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]); */
+ 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);
+ 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 */
+ MM_RELEASE_UNDI_LOCK (pDevice);
+ return Value32;
+} /* LM_MemRdInd */
/******************************************************************************/
/* Description: */
@@ -144,168 +139,161 @@ LM_UINT32 MemAddr) {
/* Return: */
/******************************************************************************/
LM_VOID
-LM_MemWrInd(
-PLM_DEVICE_BLOCK pDevice,
-LM_UINT32 MemAddr,
-LM_UINT32 Value32) {
- MM_ACQUIRE_UNDI_LOCK(pDevice);
+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);
+ 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);
+ 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 */
-
+ 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;
+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 */
+ LM_UINT32 JumboBdAdded = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
- Lmstatus = LM_STATUS_SUCCESS;
+ Lmstatus = LM_STATUS_SUCCESS;
- pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
- while(pPacket) {
- switch(pPacket->u.Rx.RcvProdRing) {
+ 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;
+ 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);
+ 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));
+ /* 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;
+ /* 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;
+ 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);
+ 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));
+ /* 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;
+ /* Update the producer index. */
+ pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) &
+ T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
- StdBdAdded++;
- break;
+ StdBdAdded++;
+ break;
- case T3_UNKNOWN_RCV_PROD_RING:
- default:
- Lmstatus = LM_STATUS_FAILURE;
- break;
- } /* switch */
+ 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;
- }
+ /* Bail out if there is any error. */
+ if (Lmstatus != LM_STATUS_SUCCESS) {
+ break;
+ }
- pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
- } /* while */
+ 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);
- }
+ 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 */
+ 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)
+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;
+ 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);
- REG_WR(pDevice, Nvram.Config1, Value32);
+ for (j = 0; j < 100; j++) {
+ MM_Wait (10);
}
- }
-} /* LM_NvRamInit */
+ /* 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: */
@@ -313,51 +301,44 @@ LM_NvramInit(
/* Return: */
/******************************************************************************/
STATIC LM_STATUS
-LM_EepromRead(
- PLM_DEVICE_BLOCK pDevice,
- LM_UINT32 Offset,
- LM_UINT32 *pData)
+LM_EepromRead (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 * pData)
{
- LM_UINT32 Value32;
- LM_UINT32 Addr;
- LM_UINT32 Dev;
- LM_UINT32 j;
+ LM_UINT32 Value32;
+ LM_UINT32 Addr;
+ LM_UINT32 Dev;
+ LM_UINT32 j;
- if(Offset > SEEPROM_CHIP_SIZE)
- {
- return LM_STATUS_FAILURE;
- }
+ if (Offset > SEEPROM_CHIP_SIZE) {
+ return LM_STATUS_FAILURE;
+ }
- Dev = Offset / SEEPROM_CHIP_SIZE;
- Addr = Offset % SEEPROM_CHIP_SIZE;
+ 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);
+ 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;
+ for (j = 0; j < 1000; j++) {
+ Value32 = REG_RD (pDevice, Grc.EepromAddr);
+ if (Value32 & SEEPROM_ADDR_COMPLETE) {
+ break;
+ }
+ MM_Wait (10);
}
- MM_Wait(10);
- }
- if(Value32 & SEEPROM_ADDR_COMPLETE)
- {
- Value32 = REG_RD(pDevice, Grc.EepromData);
- *pData = Value32;
+ if (Value32 & SEEPROM_ADDR_COMPLETE) {
+ Value32 = REG_RD (pDevice, Grc.EepromData);
+ *pData = Value32;
- return LM_STATUS_SUCCESS;
- }
-
- return LM_STATUS_FAILURE;
-} /* LM_EepromRead */
+ return LM_STATUS_SUCCESS;
+ }
+ return LM_STATUS_FAILURE;
+} /* LM_EepromRead */
/******************************************************************************/
/* Description: */
@@ -365,291 +346,248 @@ LM_EepromRead(
/* Return: */
/******************************************************************************/
STATIC LM_STATUS
-LM_NvramRead(
- PLM_DEVICE_BLOCK pDevice,
- LM_UINT32 Offset,
- LM_UINT32 *pData)
+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);
- }
- }
+ 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;
- }
+ 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);
+ /* 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);
+ 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);
+ /* 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;
- }
- }
+ 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);
+ /* 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);
+ Value32 = REG_RD (pDevice, Nvram.Cmd);
+ if (Value32 & NVRAM_CMD_DONE) {
+ MM_Wait (10);
- *pData = REG_RD(pDevice, Nvram.ReadData);
+ *pData =
+ REG_RD (pDevice, Nvram.ReadData);
- /* Change the endianess. */
- *pData = ((*pData & 0xff) << 24)| ((*pData & 0xff00) << 8)|
- ((*pData & 0xff0000) >> 8) | ((*pData >> 24) & 0xff);
+ /* Change the endianess. */
+ *pData =
+ ((*pData & 0xff) << 24) |
+ ((*pData & 0xff00) << 8) |
+ ((*pData & 0xff0000) >> 8) |
+ ((*pData >> 24) & 0xff);
- break;
+ break;
+ }
+ }
}
- }
- }
- REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1);
- if(Value32 & NVRAM_CMD_DONE)
- {
- Status = LM_STATUS_SUCCESS;
- }
- else
- {
- Status = LM_STATUS_FAILURE;
+ 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 */
+ return Status;
+} /* LM_NvramRead */
-STATIC void
-LM_ReadVPD(PLM_DEVICE_BLOCK pDevice)
+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;
+ 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;
}
- else
- {
- if (Vpd[j + 2] == 0)
- {
+ *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;
- }
- j = j + Vpd[j + 2];
}
- }
- break;
}
- else {
- break;
- }
- }
}
-STATIC void
-LM_ReadBootCodeVersion(PLM_DEVICE_BLOCK pDevice)
+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)
- {
+ 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;
- }
- *((LM_UINT32 *) &pDevice->BootCodeVer[i]) = cpu_to_le32(Value32);
- }
- }
- else {
- char c;
- if (LM_NvramRead(pDevice, 0x94, &Value32) != 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;
- i = 0;
- c = ((Value32 & 0xff0000) >> 16);
+ if (LM_NvramRead (pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS)
+ return;
- 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';
+ 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;
}
- pDevice->BootCodeVer[i] = 0;
- }
}
-STATIC void
-LM_GetBusSpeed(PLM_DEVICE_BLOCK pDevice)
+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;
- }
+ 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);
+ strcat (pDevice->BusSpeedStr, SpeedStr);
}
/******************************************************************************/
@@ -660,977 +598,890 @@ LM_GetBusSpeed(PLM_DEVICE_BLOCK pDevice)
/* Return: */
/* LM_STATUS_SUCCESS */
/******************************************************************************/
-LM_STATUS
-LM_GetAdapterInfo(
-PLM_DEVICE_BLOCK pDevice)
+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;
- }
+ 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;
+ 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 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 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 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 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 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;
+ /* 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 (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;
+ 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;
+ /* 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;
}
- /* 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;
+ /* 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;
}
- }
- 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;
+ /* 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;
- }
-
+ /* 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;
- }
+ if (pDevice->EnableMWI) {
+ Value32 |= PCI_MEMORY_WRITE_INVALIDATE;
+ } else {
+ Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE);
+ }
- /* save the value we are going to write into the PCI command word */
- pDevice->PciCommandStatusWords = Value32;
+ /* Error out if mem-mapping is NOT enabled for PCI systems */
+ if (!(Value32 | PCI_MEM_SPACE_ENABLE)) {
+ return LM_STATUS_FAILURE;
+ }
- Status = MM_WriteConfig32(pDevice, PCI_COMMAND_REG, Value32);
- if(Status != LM_STATUS_SUCCESS)
- {
- return Status;
- }
+ /* 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);
+ /* 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 |
+ 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 */
+ 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);
+ /* 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);
+ REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl);
#ifdef BIG_ENDIAN_PCI
- Value32 = GRC_MODE_WORD_SWAP_DATA|
- GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+ 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;
+ 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;
+ 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);
+#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;
- }
+ 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);
+ /*
+ * 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);
+ /* 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)
- {
+ /* 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;
+ 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;
- 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;
+ 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;
-#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;
+ 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
- case T3_NIC_CFG_PHY_TYPE_FIBER:
- EePhyTypeSerdes = TRUE;
+ 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:
- EePhyTypeSerdes = FALSE;
+ default:
+ pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+ pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96;
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;
+ pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+ pDevice->QueueRxPackets = TRUE;
- case T3_NIC_CFG_LED_MODE_LINK_SPEED:
- EePhyLedMode = LED_MODE_LINK10;
- break;
+ pDevice->EnableWireSpeed = TRUE;
- 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;
+#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_LED_MODE_OUTPUT:
- EePhyLedMode = LED_MODE_OUTPUT;
- break;
+ case T3_NIC_CFG_PHY_TYPE_FIBER:
+ EePhyTypeSerdes = TRUE;
+ 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;
- }
- }
+ EePhyTypeSerdes = FALSE;
+ break;
+ }
- /* 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;
+ /* 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;
+ }
+ }
- Value32 = Value32 & T3_NIC_PHY_ID2_MASK;
+ /* 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;
- EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
- (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
- }
- else
- {
- EePhyId = 0;
+ 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;
}
- }
- else
- {
- EeSigFound = FALSE;
- }
- /* Set the PHY address. */
- pDevice->PhyAddr = PHY_DEVICE_ID;
+ /* 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);
+ /* 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;
+ /* 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);
+ 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)
- {
+ /* 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;
+ pDevice->EnableTbi = FALSE;
+ break;
case PHY_BCM5401_PHY_ID:
- pDevice->EnableTbi = FALSE;
- break;
+ pDevice->EnableTbi = FALSE;
+ break;
case PHY_BCM5411_PHY_ID:
- pDevice->EnableTbi = FALSE;
- break;
+ pDevice->EnableTbi = FALSE;
+ break;
case PHY_BCM5701_PHY_ID:
- pDevice->EnableTbi = FALSE;
- break;
+ pDevice->EnableTbi = FALSE;
+ break;
case PHY_BCM5703_PHY_ID:
- pDevice->EnableTbi = FALSE;
- break;
+ pDevice->EnableTbi = FALSE;
+ break;
case PHY_BCM5704_PHY_ID:
- pDevice->EnableTbi = FALSE;
- break;
+ pDevice->EnableTbi = FALSE;
+ break;
case PHY_BCM8002_PHY_ID:
- pDevice->EnableTbi = TRUE;
- break;
+ 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 (pAdapterInfo) {
+ pDevice->PhyId = pAdapterInfo->PhyId;
+ pDevice->EnableTbi = pAdapterInfo->Serdes;
+ } else if (EeSigFound) {
+ pDevice->PhyId = EePhyId;
+ pDevice->EnableTbi = EePhyTypeSerdes;
+ }
+ break;
+ }
- 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;
- }
+ /* 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;
- }
+ 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);
+ /* 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);
+ /* If we don't have link reset the PHY. */
+ if (!(Value32 & PHY_STATUS_LINK_PASS)
+ || pDevice->ResetPhyOnInit) {
- for(j = 0; j < 100; j++)
- {
- MM_Wait(10);
+ LM_WritePhy (pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
- LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
- if(Value32 && !(Value32 & PHY_CTRL_PHY_RESET))
- {
- MM_Wait(40);
- break;
- }
- }
+ 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);
- }
+ /* 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 (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);
+ }
+ }
+ }
-#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;
+ /* 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);
- 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;
+ MM_Wait (40);
}
-
- if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
- {
- pDevice->TxCoalescingTicksDuringInt =
- DEFAULT_TX_COALESCING_TICKS_DURING_INT;
+#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 */
- if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
- {
- pDevice->RxMaxCoalescedFramesDuringInt =
- DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT;
- }
+ /* UseTaggedStatus is only valid for 5701 and later. */
+ if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) {
+ pDevice->UseTaggedStatus = FALSE;
- 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;
+ pDevice->CoalesceMode = 0;
+ } else {
+ pDevice->CoalesceMode =
+ HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT |
+ HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT;
}
- if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
- {
- pDevice->TxCoalescingTicksDuringInt = 0;
+ /* 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;
}
- if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
- {
- pDevice->RxMaxCoalescedFramesDuringInt = 0;
- }
+ /* 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->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
- {
- pDevice->TxMaxCoalescedFramesDuringInt = 0;
+ 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->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;
- 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->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
- pDevice->RxPacketDescCnt =
+ pDevice->RxPacketDescCnt =
#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
- pDevice->RxJumboDescCnt +
-#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
- pDevice->RxStdDescCnt;
+ 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;
+ if (pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC) {
+ pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
}
- else
- {
- pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+
+ if (pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE) {
+ pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE;
}
- }
- 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;
+
+ /* 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;
+ /* 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;
+ }
}
- 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;
}
- }
- 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;
- /* 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 (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 &&
+ 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;
- }
+ 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;
- }
+ 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;
+ }
+ }
}
- 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)
+
+ /* 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];
+ 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;
+ return NULL;
}
-
/******************************************************************************/
/* Description: */
/* This routine sets up receive/transmit buffer descriptions queues. */
@@ -1638,237 +1489,226 @@ LM_GetAdapterInfoBySsid(
/* Return: */
/* LM_STATUS_SUCCESS */
/******************************************************************************/
-LM_STATUS
-LM_InitializeAdapter(
-PLM_DEVICE_BLOCK pDevice)
+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) +
+ 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;
+ 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;
+ }
}
- else
- {
- pDevice->DmaReadWriteCtrl = 0x761b000f;
+ if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5703) {
+ pDevice->DmaReadWriteCtrl &= 0xfffffff0;
}
- 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);
+ 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;
+ }
- /* 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));
+ /* 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);
- /* Receive standard BD buffer. */
- pDevice->pRxStdBdVirt = (PT3_RCV_BD) pMemVirt;
- pDevice->RxStdBdPhy = MemPhy;
+ /* 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));
- 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));
+ /* 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 */
+ /* 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 */
+ /* Create the Jumbo packet descriptors. */
+ for (j = 0; j < pDevice->RxJumboDescCnt; j++) {
+ /* Receive producer ring. */
+ pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING;
- /* Default receive mask. */
- pDevice->ReceiveMask = LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST |
- LM_ACCEPT_UNICAST;
+ /* Receive buffer size. */
+ pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize;
- /* Make sure we are in the first 32k memory window or NicSendBd. */
- REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+ /* Add the descriptor to RxPacketFreeQ. */
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
- /* Initialize the hardware. */
- Status = LM_ResetAdapter(pDevice);
- if(Status != LM_STATUS_SUCCESS)
- {
- return Status;
- }
+ /* 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 */
- /* We are done with initialization. */
- pDevice->InitDone = TRUE;
+ /* 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;
- return LM_STATUS_SUCCESS;
-} /* LM_InitializeAdapter */
+ /* 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: */
@@ -1878,414 +1718,408 @@ PLM_DEVICE_BLOCK pDevice)
/* LM_STATUS_SUCCESS */
/******************************************************************************/
LM_STATUS
-LM_CntrlBlock(
-PLM_DEVICE_BLOCK pDevice,
-LM_UINT32 mask,LM_UINT32 cntrl)
+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;
+ 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_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_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_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_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_DMA_WR:
- data = REG_RD(pDevice, DmaWrite.Mode);
- if (cntrl == LM_DISABLE)
- {
- data &= ~DMA_WRITE_MODE_ENABLE;
- REG_WR(pDevice, DmaWrite.Mode,data);
+ 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;
- 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_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_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_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_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_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_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_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;
+ 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);
}
- MM_Wait(10);
- }
- }
- else
- {
- pDevice->RxMode |= RX_MODE_ENABLE;
- REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
- }
- break;
+ 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_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_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_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_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_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_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_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_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_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;
+ 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 */
+ default:
+ return LM_STATUS_FAILURE;
+ } /* switch */
- if(j >= MaxWaitCnt)
- {
- return LM_STATUS_FAILURE;
+ if (j >= MaxWaitCnt) {
+ return LM_STATUS_FAILURE;
+ }
}
- }
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
/******************************************************************************/
@@ -2295,682 +2129,631 @@ LM_UINT32 mask,LM_UINT32 cntrl)
/* Return: */
/* LM_STATUS_SUCCESS */
/******************************************************************************/
-LM_STATUS
-LM_ResetAdapter(
-PLM_DEVICE_BLOCK pDevice)
+LM_STATUS LM_ResetAdapter (PLM_DEVICE_BLOCK pDevice)
{
- LM_UINT32 Value32;
- LM_UINT16 Value16;
- LM_UINT32 j, k;
+ LM_UINT32 Value32;
+ LM_UINT16 Value16;
+ LM_UINT32 j, k;
- /* Disable interrupt. */
- LM_DisableInterrupt(pDevice);
+ /* Disable interrupt. */
+ LM_DisableInterrupt (pDevice);
- /* May get a spurious interrupt */
- pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED;
+ /* 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);
- }
+ /* Disable transmit and receive DMA engines. Abort all pending requests. */
+ if (pDevice->InitDone) {
+ LM_Abort (pDevice);
+ }
- pDevice->ShuttingDown = FALSE;
+ pDevice->ShuttingDown = FALSE;
- LM_ResetChip(pDevice);
+ 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);
- }
+ /* 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 (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;
- }
+ /* 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);
+ 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;
+ /* 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 =
+ /* 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 |
+ 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 |
+ 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);
+ 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;
}
- 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);
+
+ /* Configure pseudo checksum mode. */
+ if (pDevice->NoTxPseudoHdrChksum) {
+ Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM;
}
- 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);
+
+ if (pDevice->NoRxPseudoHdrChksum) {
+ Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM;
}
- else
- {
- REG_WR(pDevice, BufMgr.MbufHighWaterMark,
- T3_DEF_MBUF_HIGH_WMARK_JUMBO);
+
+ 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);
+ }
}
- }
- REG_WR(pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK);
- REG_WR(pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK);
+ /* 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);
+ }
+ }
- /* Enable buffer manager. */
- REG_WR(pDevice, BufMgr.Mode, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
+ /* 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);
+ }
+ }
- for(j = 0 ;j < 2000; j++)
- {
- if(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE)
- break;
- MM_Wait(10);
- }
+ REG_WR (pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK);
+ REG_WR (pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK);
- 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);
+ /* 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);
+ }
- REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, 0);
+ if (j >= 2000) {
+ return LM_STATUS_FAILURE;
+ }
-#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+ /* Enable the FTQs. */
+ REG_WR (pDevice, Ftq.Reset, 0xffffffff);
+ REG_WR (pDevice, Ftq.Reset, 0);
- /* Initialize the Mini Receive RCB. */
- REG_WR(pDevice, RcvDataBdIn.MiniRcvRcb.u.MaxLen_Flags,
- T3_RCB_FLAG_RING_DISABLED);
+ /* 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;
+ }
- {
- 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);
- }
+ /* 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);
- /* Receive BD Ring replenish threshold. */
- REG_WR(pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt/8);
+ /* 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, RcvBdIn.JumboRcvThreshold, pDevice->RxJumboDescCnt/8);
-#endif /* 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);
- /* 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 */
+ 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);
- /* Initialize the indices. */
- pDevice->SendProdIdx = 0;
- pDevice->SendConIdx = 0;
+ /* 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);
+ }
- MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, 0);
- MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, 0);
+ pDevice->RcvRetConIdx = 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);
+ 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. */
- MEM_WR(pDevice, SendRcb[0].NicRingAddr,T3_NIC_SND_BUFFER_DESC_ADDR);
+ /* 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, SendRcb[0].u.MaxLen_Flags,
- T3_SEND_RCB_ENTRY_COUNT << 16);
+ MEM_WR (pDevice, RcvRetRcb[0].u.MaxLen_Flags,
+ T3_RCV_RETURN_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);
+ /* 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;
+ pDevice->RxJumboProdIdx = 0;
+ pDevice->RxJumboQueuedCnt = 0;
#endif
- /* Reinitialize our copy of the indices. */
- pDevice->RxStdProdIdx = 0;
- pDevice->RxStdQueuedCnt = 0;
+ /* 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);
+ 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);
- }
+ /* 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;
+ /* 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;
}
- }
- REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
- /* Activate Link to enable MAC state machine */
- REG_WR(pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN);
+ /* Disable auto polling. */
+ pDevice->MiMode = 0xc0000;
+ REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode);
- 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);
+ 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;
+ }
}
- }
- /* Setup the phy chip. */
- LM_SetupPhy(pDevice);
+ REG_WR (pDevice, MacCtrl.LedCtrl, Value32);
- if (!pDevice->EnableTbi) {
- /* Clear CRC stats */
- LM_ReadPhy(pDevice, 0x1e, &Value32);
- LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000);
- LM_ReadPhy(pDevice, 0x14, &Value32);
- }
+ /* Activate Link to enable MAC state machine */
+ REG_WR (pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN);
- /* Set up the receive mask. */
- LM_SetReceiveMask(pDevice, pDevice->ReceiveMask);
+ 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);
- /* Queue Rx packet buffers. */
- if(pDevice->QueueRxPackets)
- {
- LM_QueueRxPackets(pDevice);
- }
+ if (!pDevice->EnableTbi) {
+ /* Clear CRC stats */
+ LM_ReadPhy (pDevice, 0x1e, &Value32);
+ LM_WritePhy (pDevice, 0x1e, Value32 | 0x8000);
+ LM_ReadPhy (pDevice, 0x14, &Value32);
+ }
- /* Enable interrupt to the host. */
- if(pDevice->InitDone)
- {
- LM_EnableInterrupt(pDevice);
- }
+ /* Set up the receive mask. */
+ LM_SetReceiveMask (pDevice, pDevice->ReceiveMask);
- return LM_STATUS_SUCCESS;
-} /* LM_ResetAdapter */
+ /* 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: */
@@ -2979,18 +2762,15 @@ PLM_DEVICE_BLOCK pDevice)
/* Return: */
/* LM_STATUS_SUCCESS */
/******************************************************************************/
-LM_STATUS
-LM_DisableInterrupt(
- PLM_DEVICE_BLOCK pDevice)
+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);
+ 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;
+ return LM_STATUS_SUCCESS;
}
-
/******************************************************************************/
/* Description: */
/* This routine enables the adapter to generate interrupts. */
@@ -2998,24 +2778,20 @@ LM_DisableInterrupt(
/* Return: */
/* LM_STATUS_SUCCESS */
/******************************************************************************/
-LM_STATUS
-LM_EnableInterrupt(
- PLM_DEVICE_BLOCK pDevice)
+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);
+ 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);
- }
+ if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
+ REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+ GRC_MISC_LOCAL_CTRL_SET_INT);
+ }
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-
/******************************************************************************/
/* Description: */
/* This routine puts a packet on the wire if there is a transmit DMA */
@@ -3027,306 +2803,279 @@ LM_EnableInterrupt(
/* LM_STATUS_SUCCESS */
/******************************************************************************/
#if 0
-LM_STATUS
-LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+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;
+ 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);
- }
+ 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);
+ /* Update the SendBdLeft count. */
+ atomic_sub (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
- /* Initalize the send buffer descriptors. */
- Idx = pDevice->SendProdIdx;
+ /* Initalize the send buffer descriptors. */
+ Idx = pDevice->SendProdIdx;
- pSendBd = &pDevice->pSendBdVirt[Idx];
+ pSendBd = &pDevice->pSendBdVirt[Idx];
- /* Next producer index. */
- if (pDevice->NicSendBd == TRUE)
- {
- T3_64BIT_HOST_ADDR paddr;
+ /* 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));
+ }
+ }
- 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 */
+ 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);
+ /* Put the packet descriptor in the ActiveQ. */
+ QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket);
- wmb();
- MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+ 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);
+ } 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;
+ pSendBd->u2.VlanTag = pPacket->VlanTag;
- /* Setup the control flags and send buffer size. */
- Value32 = (Len << 16) | pPacket->Flags;
+ /* Setup the control flags and send buffer size. */
+ Value32 = (Len << 16) | pPacket->Flags;
- Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+ 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 */
+ 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);
+ /* Put the packet descriptor in the ActiveQ. */
+ QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket);
- wmb();
- MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+ wmb ();
+ MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
- }
+ }
- /* Update the producer index. */
- pDevice->SendProdIdx = Idx;
+ /* Update the producer index. */
+ pDevice->SendProdIdx = Idx;
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
#endif
-LM_STATUS
-LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+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;
+ 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];
+ }
- while (1)
- {
- /* Initalize the send buffer descriptors. */
- StartIdx = Idx = pDevice->SendProdIdx;
+ /* Next producer index. */
+ for (FragCount = 0;;) {
+ LM_UINT32 Value32, Len;
- if (pDevice->NicSendBd)
- {
- pTmpSendBd = pSendBd = &NicSendBdArr[0];
- }
- else
- {
- pTmpSendBd = pSendBd = &pDevice->pSendBdVirt[Idx];
+ /* 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);
- /* Next producer index. */
- for(FragCount = 0; ; )
- {
- LM_UINT32 Value32, Len;
+ if (pDevice->NicSendBd) {
+ pSendBd = &pDevice->pSendBdVirt[StartIdx];
+ pShadowSendBd = &pDevice->ShadowSendBd[StartIdx];
- /* Initialize the pointer to the send buffer fragment. */
- MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount);
+ while (StartIdx != Idx) {
+ LM_UINT32 Value32;
- pSendBd->u2.VlanTag = pPacket->VlanTag;
+ if ((Value32 = pTmpSendBd->HostAddr.High) !=
+ pShadowSendBd->HostAddr.High) {
+ __raw_writel (Value32,
+ &(pSendBd->HostAddr.High));
+ pShadowSendBd->HostAddr.High = Value32;
+ }
- /* Setup the control flags and send buffer size. */
- Value32 = (Len << 16) | pPacket->Flags;
+ __raw_writel (pTmpSendBd->HostAddr.Low,
+ &(pSendBd->HostAddr.Low));
- Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+ if ((Value32 = pTmpSendBd->u1.Len_Flags) !=
+ pShadowSendBd->u1.Len_Flags) {
+ __raw_writel (Value32,
+ &(pSendBd->u1.Len_Flags));
+ pShadowSendBd->u1.Len_Flags = Value32;
+ }
- 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 (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
+ __raw_writel (pTmpSendBd->u2.VlanTag,
+ &(pSendBd->u2.VlanTag));
+ }
- 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);
+ 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.SendHostProdIdx[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 SendBdLeft count. */
+ atomic_sub (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
- /* Update the producer index. */
- pDevice->SendProdIdx = Idx;
+ /* Update the producer index. */
+ pDevice->SendProdIdx = Idx;
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
STATIC LM_STATUS
-LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
- PT3_SND_BD pSendBd)
+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;
+ 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];
+ }
+ }
}
- pSendBd++;
- if (!pDevice->NicSendBd)
- {
- Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
- if (Idx == 0)
- {
- pSendBd = &pDevice->pSendBdVirt[0];
- }
- }
- }
- return LM_STATUS_FAILURE;
+ return LM_STATUS_FAILURE;
}
/******************************************************************************/
@@ -3335,35 +3084,30 @@ LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
/* Return: */
/******************************************************************************/
__inline static unsigned long
-ComputeCrc32(
-unsigned char *pBuffer,
-unsigned long BufferSize) {
- unsigned long Reg;
- unsigned long Tmp;
- unsigned long j, k;
+ComputeCrc32 (unsigned char *pBuffer, unsigned long BufferSize)
+{
+ unsigned long Reg;
+ unsigned long Tmp;
+ unsigned long j, k;
- Reg = 0xffffffff;
+ Reg = 0xffffffff;
- for(j = 0; j < BufferSize; j++)
- {
- Reg ^= pBuffer[j];
+ for (j = 0; j < BufferSize; j++) {
+ Reg ^= pBuffer[j];
- for(k = 0; k < 8; k++)
- {
- Tmp = Reg & 0x01;
+ for (k = 0; k < 8; k++) {
+ Tmp = Reg & 0x01;
- Reg >>= 1;
+ Reg >>= 1;
- if(Tmp)
- {
- Reg ^= 0xedb88320;
- }
+ if (Tmp) {
+ Reg ^= 0xedb88320;
+ }
+ }
}
- }
-
- return ~Reg;
-} /* ComputeCrc32 */
+ return ~Reg;
+} /* ComputeCrc32 */
/******************************************************************************/
/* Description: */
@@ -3372,149 +3116,139 @@ unsigned long BufferSize) {
/* 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;
- }
+LM_STATUS LM_SetReceiveMask (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask)
+{
+ LM_UINT32 ReceiveMask;
+ LM_UINT32 RxMode;
+ LM_UINT32 j, k;
- /* Commit the new filter. */
- pDevice->RxMode = RxMode;
- REG_WR(pDevice, MacCtrl.RxMode, RxMode);
+ ReceiveMask = Mask;
- pDevice->ReceiveMask = ReceiveMask;
+ RxMode = pDevice->RxMode;
- /* 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);
+ if (Mask & LM_ACCEPT_UNICAST) {
+ Mask &= ~LM_ACCEPT_UNICAST;
}
- }
- 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;
+ 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;
+ }
- Crc32 = ComputeCrc32(pDevice->McTable[j], ETHERNET_ADDRESS_SIZE);
+ 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;
+ }
- /* 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;
+ /* Commit the new filter. */
+ pDevice->RxMode = RxMode;
+ REG_WR (pDevice, MacCtrl.RxMode, RxMode);
- /* Hash register index. */
- RegIndex = (Bitpos & 0x60) >> 5;
+ pDevice->ReceiveMask = ReceiveMask;
- /* Bit to turn on within a hash register. */
- Bitpos &= 0x1f;
+ /* 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);
+ }
- /* 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);
+ }
}
- /* 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]);
+ /* 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);
}
- }
- 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 */
+ return LM_STATUS_SUCCESS;
+} /* LM_SetReceiveMask */
/******************************************************************************/
/* Description: */
@@ -3525,138 +3259,135 @@ LM_UINT32 Mask) {
/* Return: */
/* LM_STATUS_SUCCESS */
/******************************************************************************/
-LM_STATUS
-LM_Abort(
-PLM_DEVICE_BLOCK pDevice)
+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);
+ 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;
+ /* 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));
+ 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);
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
- Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
- } /* while */
+ Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+ } /* while */
- /* Reinitialize our copy of the indices. */
- pDevice->RxStdProdIdx = 0;
+ /* 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;
+ /* 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));
+ 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);
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
- Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
- } /* while */
+ 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 */
+ /* Reinitialize our copy of the indices. */
+ pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
- MM_RELEASE_INT_LOCK(pDevice);
+ 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 */
+ /* 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: */
@@ -3667,140 +3398,130 @@ PLM_DEVICE_BLOCK pDevice)
/* Return: */
/* LM_STATUS_SUCCESS */
/******************************************************************************/
-LM_STATUS
-LM_Halt(
-PLM_DEVICE_BLOCK pDevice) {
- PLM_PACKET pPacket;
- LM_UINT32 EntryCnt;
-
- LM_Abort(pDevice);
+LM_STATUS LM_Halt (PLM_DEVICE_BLOCK pDevice)
+{
+ PLM_PACKET pPacket;
+ LM_UINT32 EntryCnt;
- /* Get the number of entries in the queue. */
- EntryCnt = QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container);
+ LM_Abort (pDevice);
- /* 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;
+ /* Get the number of entries in the queue. */
+ EntryCnt = QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container);
- MM_FreeRxBuffer(pDevice, pPacket);
+ /* 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;
- QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
- }
+ MM_FreeRxBuffer (pDevice, pPacket);
- LM_ResetChip(pDevice);
+ QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
+ }
- /* 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);
+ LM_ResetChip (pDevice);
- /* Reprogram the MAC address. */
- LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+ /* 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);
- return LM_STATUS_SUCCESS;
-} /* LM_Halt */
+ /* Reprogram the MAC address. */
+ LM_SetMacAddress (pDevice, pDevice->NodeAddress);
+ return LM_STATUS_SUCCESS;
+} /* LM_Halt */
-STATIC LM_STATUS
-LM_ResetChip(PLM_DEVICE_BLOCK pDevice)
+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);
+ 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);
+ /* 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);
+ /* 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;
+ /* 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);
+ MM_WriteConfig32 (pDevice, T3_PCI_STATE_REG, Value32);
- /* Restore PCI command register. */
- MM_WriteConfig32(pDevice, PCI_COMMAND_REG,
- pDevice->PciCommandStatusWords);
+ /* 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);
+ /* 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);
+ /* 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;
+#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;
+ /* 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;
+ /* 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;
+ 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;
+ return LM_STATUS_SUCCESS;
}
/******************************************************************************/
@@ -3808,161 +3529,143 @@ LM_ResetChip(PLM_DEVICE_BLOCK pDevice)
/* */
/* 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. */
+__inline static void LM_ServiceTxInterrupt (PLM_DEVICE_BLOCK pDevice)
+{
+ PLM_PACKET pPacket;
+ LM_UINT32 HwConIdx;
+ LM_UINT32 SwConIdx;
+
HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
- } /* while */
- /* Save the new SwConIdx. */
- pDevice->SendConIdx = SwConIdx;
+ /* 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;
-} /* LM_ServiceTxInterrupt */
+ /* 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;
+__inline static void LM_ServiceRxInterrupt (PLM_DEVICE_BLOCK pDevice)
+{
+ PLM_PACKET pPacket;
+ PT3_RCV_BD pRcvBd;
+ LM_UINT32 HwRcvRetProdIdx;
+ LM_UINT32 SwRcvRetConIdx;
- pPacket->Flags = pRcvBd->Flags;
- if(pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG)
- {
- pPacket->VlanTag = pRcvBd->VlanTag;
- }
+ /* Loop thru the receive return rings for received packets. */
+ HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
- pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum;
- }
+ SwRcvRetConIdx = pDevice->RcvRetConIdx;
+ while (SwRcvRetConIdx != HwRcvRetProdIdx) {
+ pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx];
- /* Put the packet descriptor containing the received packet */
- /* buffer in the RxPacketReceivedQ for indication later. */
- QQ_PushTail(&pDevice->RxPacketReceivedQ.Container, pPacket);
+ /* Get the received packet descriptor. */
+ pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) +
+ MM_UINT_PTR (pRcvBd->Opaque));
- /* Go to the next buffer descriptor. */
- SwRcvRetConIdx = (SwRcvRetConIdx + 1) &
- T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK;
+ /* Check the error flag. */
+ if (pRcvBd->ErrorFlag &&
+ pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) {
+ pPacket->PacketStatus = LM_STATUS_FAILURE;
- /* Get the updated HwRcvRetProdIdx. */
- HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
- } /* while */
+ 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++;
+ }
- pDevice->RcvRetConIdx = SwRcvRetConIdx;
+ 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;
- /* Update the receive return ring consumer index. */
- MB_REG_WR(pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx);
-} /* LM_ServiceRxInterrupt */
+ 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: */
@@ -3972,206 +3675,179 @@ PLM_DEVICE_BLOCK pDevice) {
/* Return: */
/* LM_STATUS_SUCCESS */
/******************************************************************************/
-LM_STATUS
-LM_ServiceInterrupts(
- PLM_DEVICE_BLOCK pDevice)
+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;
+ 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;
- }
+ if (pDevice->IgnoreTbiLinkChange == TRUE) {
+ ServicePhyInt = FALSE;
+ }
#endif
- if (ServicePhyInt == TRUE)
- {
- LM_SetupPhy(pDevice);
- }
-
- /* Service receive and transmit interrupts. */
- LM_ServiceRxInterrupt(pDevice);
- LM_ServiceTxInterrupt(pDevice);
+ if (ServicePhyInt == TRUE) {
+ LM_SetupPhy (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); */
- }
+ /* 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->TxPacketXmittedQ.Container))
- {
- MM_IndicateTxPackets(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); */
+ }
- return LM_STATUS_SUCCESS;
-} /* LM_ServiceInterrupts */
+ /* 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;
+LM_STATUS LM_MulticastAdd (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress)
+{
+ PLM_UINT8 pEntry;
+ LM_UINT32 j;
- return LM_STATUS_SUCCESS;
- }
+ 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;
- pEntry += LM_MC_ENTRY_SIZE;
- }
+ return LM_STATUS_SUCCESS;
+ }
- if(pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE)
- {
- return LM_STATUS_FAILURE;
- }
+ pEntry += LM_MC_ENTRY_SIZE;
+ }
- pEntry = pDevice->McTable[pDevice->McEntryCount];
+ if (pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE) {
+ return LM_STATUS_FAILURE;
+ }
- COPY_ETH_ADDRESS(pMcAddress, pEntry);
- pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1;
+ pEntry = pDevice->McTable[pDevice->McEntryCount];
- pDevice->McEntryCount++;
+ COPY_ETH_ADDRESS (pMcAddress, pEntry);
+ pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1;
- LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST);
+ pDevice->McEntryCount++;
- return LM_STATUS_SUCCESS;
-} /* LM_MulticastAdd */
+ 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--;
+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);
+ }
- /* 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;
+ }
- return LM_STATUS_SUCCESS;
+ pEntry += LM_MC_ENTRY_SIZE;
}
- pEntry += LM_MC_ENTRY_SIZE;
- }
-
- return LM_STATUS_FAILURE;
-} /* LM_MulticastDel */
-
+ 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);
+LM_STATUS LM_MulticastClear (PLM_DEVICE_BLOCK pDevice)
+{
+ pDevice->McEntryCount = 0;
- return LM_STATUS_SUCCESS;
-} /* LM_MulticastClear */
+ 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_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;
-}
+ 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: */
@@ -4182,93 +3858,93 @@ LM_SetMacAddress(
/* 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) {
+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;
+ *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;
+ *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;
+ *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;
+ *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;
+ *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;
+ *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;
+ *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;
+ *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;
+ *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;
+ *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;
+ *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;
+ *pMediaType = LM_MEDIA_TYPE_FIBER;
+ *pLineSpeed = LM_LINE_SPEED_1000MBPS;
+ *pDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
default:
- break;
- } /* switch */
+ break;
+ } /* switch */
- return LM_STATUS_SUCCESS;
-} /* LM_TranslateRequestedMediaType */
+ return LM_STATUS_SUCCESS;
+} /* LM_TranslateRequestedMediaType */
/******************************************************************************/
/* Description: */
@@ -4277,285 +3953,284 @@ PLM_DUPLEX_MODE pDuplexMode) {
/* LM_STATUS_LINK_ACTIVE */
/* LM_STATUS_LINK_DOWN */
/******************************************************************************/
-static LM_STATUS
-LM_InitBcm540xPhy(
-PLM_DEVICE_BLOCK pDevice)
+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);
+ 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);
+ if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) {
+ LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32);
+ LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32);
- LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
- LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+ if (!pDevice->InitDone) {
+ Value32 = 0;
+ }
- LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
- LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+ if (!(Value32 & PHY_STATUS_LINK_PASS)) {
+ LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x0c20);
- LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
- LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+ LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+ LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1804);
- LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
- LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+ LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+ LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1204);
- LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
- LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+ LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+ LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0132);
- LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
- for(j = 0; j < 1000; j++)
- {
- MM_Wait(10);
+ LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+ LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0232);
- LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
- if(Value32 & PHY_STATUS_LINK_PASS)
- {
- MM_Wait(40);
- break;
- }
- }
+ LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+ LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
- 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_STATUS_REG, &Value32);
+ for (j = 0; j < 1000; j++) {
+ MM_Wait (10);
- LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
- if(!(Value32 & PHY_CTRL_PHY_RESET))
- {
- MM_Wait(40);
- break;
+ LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32);
+ if (Value32 & PHY_STATUS_LINK_PASS) {
+ 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);
+ 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);
}
- }
- }
- }
- 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;
+ 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);
+ /* 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;
+ if (Value32 & PHY_STATUS_LINK_PASS) {
+ break;
+ }
+ MM_Wait (40);
}
- 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;
- }
- }
+ if (Value32 & PHY_STATUS_LINK_PASS) {
- switch(Value32 & BCM540X_AUX_SPEED_MASK)
- {
- case BCM540X_AUX_10BASET_HD:
- CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
- CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
- break;
+ /* Determine the current line and duplex settings. */
+ LM_ReadPhy (pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+ for (j = 0; j < 2000; j++) {
+ MM_Wait (10);
- case BCM540X_AUX_10BASET_FD:
- CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
- CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
- break;
+ LM_ReadPhy (pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+ if (Value32) {
+ break;
+ }
+ }
- case BCM540X_AUX_100BASETX_HD:
- CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
- CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
- 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_100BASETX_FD:
- CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
- CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
- break;
+ case BCM540X_AUX_10BASET_FD:
+ CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+ 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_100BASETX_HD:
+ CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
- case BCM540X_AUX_100BASET_FD:
- CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
- CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
- break;
+ case BCM540X_AUX_100BASETX_FD:
+ CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+ break;
- default:
+ case BCM540X_AUX_100BASET_HD:
+ CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+ break;
- CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN;
- CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
- break;
- }
+ case BCM540X_AUX_100BASET_FD:
+ CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+ CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+ 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;
- }
+ default:
- if(Value32 == 0 && pDevice->RequestedMediaType ==
- LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS)
- {
- break;
- }
+ CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN;
+ CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+ break;
+ }
- MM_Wait(10);
- }
+ /* 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;
+ }
- /* 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;
+ if (Value32 == 0 && pDevice->RequestedMediaType ==
+ LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS) {
+ break;
+ }
- /* 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;
+ MM_Wait (10);
}
- else
- {
- CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+
+ /* 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;
+ }
}
- }
- else
- {
- CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
- }
- }
- /* Save line settings. */
- pDevice->LineSpeed = CurrentLineSpeed;
- pDevice->DuplexMode = CurrentDuplexMode;
- pDevice->MediaType = LM_MEDIA_TYPE_UTP;
- }
+ /* Save line settings. */
+ pDevice->LineSpeed = CurrentLineSpeed;
+ pDevice->DuplexMode = CurrentDuplexMode;
+ pDevice->MediaType = LM_MEDIA_TYPE_UTP;
+ }
- return CurrentLinkStatus;
-} /* LM_InitBcm540xPhy */
+ return CurrentLinkStatus;
+} /* LM_InitBcm540xPhy */
/******************************************************************************/
/* Description: */
@@ -4563,83 +4238,69 @@ PLM_DEVICE_BLOCK pDevice)
/* Return: */
/******************************************************************************/
LM_STATUS
-LM_SetFlowControl(
- PLM_DEVICE_BLOCK pDevice,
- LM_UINT32 LocalPhyAd,
- LM_UINT32 RemotePhyAd)
+LM_SetFlowControl (PLM_DEVICE_BLOCK pDevice,
+ LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd)
{
- LM_FLOW_CONTROL FlowCap;
+ LM_FLOW_CONTROL FlowCap;
- /* Resolve flow control. */
- FlowCap = LM_FLOW_CONTROL_NONE;
+ /* 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;
-}
+ /* 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
/******************************************************************************/
@@ -4647,583 +4308,520 @@ LM_SetFlowControl(
/* */
/* Return: */
/******************************************************************************/
-STATIC LM_STATUS
-LM_InitBcm800xPhy(
- PLM_DEVICE_BLOCK pDevice)
+STATIC LM_STATUS LM_InitBcm800xPhy (PLM_DEVICE_BLOCK pDevice)
{
- LM_UINT32 Value32;
- LM_UINT32 j;
+ LM_UINT32 Value32;
+ LM_UINT32 j;
- Value32 = REG_RD(pDevice, MacCtrl.Status);
+ 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);
+ /* 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);
+ /* Software reset. */
+ LM_WritePhy (pDevice, 0x00, 0x8000);
- /* Wait for reset to complete. */
- for(j = 0; j < 500; j++)
- {
- MM_Wait(10);
- }
+ /* 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);
+ /* 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);
+ /* Enable auto-lock and comdet, select txclk for tx. */
+ LM_WritePhy (pDevice, 0x11, 0x0a10);
- LM_WritePhy(pDevice, 0x18, 0x00a0);
- LM_WritePhy(pDevice, 0x16, 0x41ff);
+ 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);
+ /* 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);
+ 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);
- }
+ /* 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);
- }
+ /* Deselect the channel register so we can read the PHY id later. */
+ LM_WritePhy (pDevice, 0x10, 0x8011);
+ }
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-STATIC LM_STATUS
-LM_SetupFiberPhy(
- PLM_DEVICE_BLOCK pDevice)
+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;
+ 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);
+ pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK);
- /* Initialize the send_config register. */
- REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+ /* 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);
+ /* 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)
- {
+ /* Initialize the BCM8002 SERDES PHY. */
+ switch (pDevice->PhyId & PHY_ID_MASK) {
case PHY_BCM8002_PHY_ID:
- LM_InitBcm800xPhy(pDevice);
- break;
+ 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;
+ break;
+ }
- /* 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;
- }
+ /* Enable link change interrupt. */
+ REG_WR (pDevice, MacCtrl.MacEvent,
+ MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
- pDevice->AnInfo.CurrentTime_us = REG_RD(pDevice, Grc.Timer);
+ /* Default to link down. */
+ CurrentLinkStatus = LM_STATUS_LINK_DOWN;
- }
- if((AnStatus == AUTONEG_STATUS_DONE) ||
- (AnStatus == AUTONEG_STATUS_FAILED))
- {
- break;
- }
- if (j >= 1)
- {
- if (!(REG_RD(pDevice, MacCtrl.Status) &
- MAC_STATUS_PCS_SYNCED)) {
- break;
- }
- }
- }
+ /* 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;
+ }
- /* Stop sending configs. */
- MM_AnTxIdle(&pDevice->AnInfo);
+ if (Value32 & PHY_AN_AD_ASYM_PAUSE) {
+ pDevice->AnInfo.mr_adv_asym_pause = 1;
+ } else {
+ pDevice->AnInfo.mr_adv_asym_pause = 0;
+ }
- /* 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;
+ /* 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;
+ }
+ }
+ }
- LocalPhyAd = 0;
- if(pDevice->AnInfo.mr_adv_sym_pause)
- {
- LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE;
+ /* 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);
- if(pDevice->AnInfo.mr_adv_asym_pause)
- {
- LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE;
- }
+ pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+ (pDevice->pStatusBlkVirt->
+ Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
- RemotePhyAd = 0;
- if(pDevice->AnInfo.mr_lp_adv_sym_pause)
- {
- RemotePhyAd |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
- }
+ 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;
+ }
- if(pDevice->AnInfo.mr_lp_adv_asym_pause)
- {
- RemotePhyAd |= PHY_LINK_PARTNER_ASYM_PAUSE;
+ 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);
}
+ }
- LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+ /* 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);
+ }
- 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;
- }
+ /* Indicate link status. */
+ if (pDevice->LinkStatus != CurrentLinkStatus) {
+ pDevice->LinkStatus = CurrentLinkStatus;
+ MM_IndicateStatus (pDevice, CurrentLinkStatus);
}
- 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 */
+ return LM_STATUS_SUCCESS;
+}
+#endif /* INCLUDE_TBI_SUPPORT */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-LM_STATUS
-LM_SetupCopperPhy(
- PLM_DEVICE_BLOCK pDevice)
+LM_STATUS LM_SetupCopperPhy (PLM_DEVICE_BLOCK pDevice)
{
- LM_STATUS CurrentLinkStatus;
- LM_UINT32 Value32;
+ LM_STATUS CurrentLinkStatus;
+ LM_UINT32 Value32;
- /* Assume there is not link first. */
- CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+ /* Assume there is not link first. */
+ CurrentLinkStatus = LM_STATUS_LINK_DOWN;
- /* Disable phy link change attention. */
- REG_WR(pDevice, MacCtrl.MacEvent, 0);
+ /* 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);
+ /* 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);
+ /* 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);
+ /* 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)
- {
+ /* 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;
+ CurrentLinkStatus = LM_InitBcm540xPhy (pDevice);
+ break;
default:
- break;
- }
-
- if(CurrentLinkStatus == LM_STATUS_LINK_SETTING_MISMATCH)
- {
- CurrentLinkStatus = LM_STATUS_LINK_DOWN;
- }
+ break;
+ }
- /* Setup flow control. */
- pDevice->FlowControl = LM_FLOW_CONTROL_NONE;
- if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
- {
- LM_FLOW_CONTROL FlowCap; /* Flow control capability. */
+ 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);
+ }
+ }
+ }
- FlowCap = LM_FLOW_CONTROL_NONE;
+ if (CurrentLinkStatus == LM_STATUS_LINK_DOWN) {
+ LM_ForceAutoNeg (pDevice, pDevice->RequestedMediaType);
- 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;
+ /* 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;
+ }
+ }
- LM_ReadPhy(pDevice, PHY_AN_AD_REG, &LocalPhyAd);
- pDevice->advertising = LocalPhyAd;
- LocalPhyAd &= (PHY_AN_AD_ASYM_PAUSE | PHY_AN_AD_PAUSE_CAPABLE);
+ /* 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;
+ }
- ExpectedPhyAd = GetPhyAdFlowCntrlSettings(pDevice);
+ /* 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;
+ }
- if(LocalPhyAd != ExpectedPhyAd)
- {
- CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+ /* 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;
}
- else
- {
- LM_ReadPhy(pDevice, PHY_LINK_PARTNER_ABILITY_REG,
- &RemotePhyAd);
- LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+ /* 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;
+ }
}
- }
- else
- {
- pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
- LM_SetFlowControl(pDevice, 0, 0);
- }
+ REG_WR (pDevice, MacCtrl.LedCtrl, Value32);
}
- }
- if(CurrentLinkStatus == LM_STATUS_LINK_DOWN)
- {
- LM_ForceAutoNeg(pDevice, pDevice->RequestedMediaType);
+ REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode);
- /* 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;
+ /* 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);
}
- }
- /* 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;
+ /* 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);
}
- 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;
+ 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);
}
- /* 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;
+ /* Indicate link status. */
+ if (pDevice->LinkStatus != CurrentLinkStatus) {
+ pDevice->LinkStatus = CurrentLinkStatus;
+ MM_IndicateStatus (pDevice, CurrentLinkStatus);
}
- 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 */
+
+ return LM_STATUS_SUCCESS;
+} /* LM_SetupCopperPhy */
/******************************************************************************/
/* Description: */
/* */
/* Return: */
/******************************************************************************/
-LM_STATUS
-LM_SetupPhy(
- PLM_DEVICE_BLOCK pDevice)
+LM_STATUS LM_SetupPhy (PLM_DEVICE_BLOCK pDevice)
{
- LM_STATUS LmStatus;
- LM_UINT32 Value32;
+ 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;
+ 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;
}
/******************************************************************************/
@@ -5232,55 +4830,47 @@ LM_SetupPhy(
/* Return: */
/******************************************************************************/
LM_VOID
-LM_ReadPhy(
-PLM_DEVICE_BLOCK pDevice,
-LM_UINT32 PhyReg,
-PLM_UINT32 pData32) {
- LM_UINT32 Value32;
- LM_UINT32 j;
+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);
- }
+ 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;
+ 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);
+ REG_WR (pDevice, MacCtrl.MiCom, Value32);
- for(j = 0; j < 20; j++)
- {
- MM_Wait(25);
+ for (j = 0; j < 20; j++) {
+ MM_Wait (25);
- Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+ 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)) {
+ 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 (Value32 & MI_COM_BUSY) {
+ Value32 = 0;
+ }
- if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
- {
- REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
- MM_Wait(40);
- }
-} /* LM_ReadPhy */
+ *pData32 = Value32;
+ if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) {
+ REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode);
+ MM_Wait (40);
+ }
+} /* LM_ReadPhy */
/******************************************************************************/
/* Description: */
@@ -5288,341 +4878,296 @@ PLM_UINT32 pData32) {
/* Return: */
/******************************************************************************/
LM_VOID
-LM_WritePhy(
-PLM_DEVICE_BLOCK pDevice,
-LM_UINT32 PhyReg,
-LM_UINT32 Data32) {
- LM_UINT32 Value32;
- LM_UINT32 j;
+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);
- }
+ 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;
+ 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);
+ REG_WR (pDevice, MacCtrl.MiCom, Value32);
- for(j = 0; j < 20; j++)
- {
- MM_Wait(25);
+ for (j = 0; j < 20; j++) {
+ MM_Wait (25);
- Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+ Value32 = REG_RD (pDevice, MacCtrl.MiCom);
- if(!(Value32 & MI_COM_BUSY))
- {
- MM_Wait(5);
- break;
+ 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 */
+ 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;
+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);
+ /* 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);
+ /* 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;
+ PmCtrl |= T3_PM_PME_ASSERTED;
+ PmCtrl &= ~T3_PM_POWER_STATE_MASK;
- /* Set the appropriate power state. */
- if(PowerLevel == LM_POWER_STATE_D0)
- {
+ /* 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);
+ /* 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);
+ 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;
- }
+ 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;
- 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);
+ /* 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);
- /* 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;
+ if (!pDevice->RestoreOnWakeUp) {
+ pDevice->RestoreOnWakeUp = TRUE;
+ pDevice->WakeUpDisableAutoNeg = pDevice->DisableAutoNeg;
+ pDevice->WakeUpRequestedMediaType = pDevice->RequestedMediaType;
}
- REG_WR(pDevice, MacCtrl.Mode, Value32);
+ /* Force auto-negotiation to 10 line speed. */
+ pDevice->DisableAutoNeg = FALSE;
+ pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
+ LM_SetupPhy (pDevice);
- /* 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);
+ /* Put the driver in the initial state, and go through the power down */
+ /* sequence. */
+ LM_Halt (pDevice);
- MM_Wait(40);
+ MM_ReadConfig32 (pDevice, T3_PCI_PM_CAP_REG, &PmeSupport);
- 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;
- }
+ if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE) {
- REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
+ /* Enable WOL. */
+ LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x5a);
+ MM_Wait (40);
- 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;
+ }
+ }
- 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;
- }
+ 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, 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, MacCtrl.Mode, Value32);
+
+ /* Enable the receiver. */
+ REG_WR (pDevice, MacCtrl.RxMode, RX_MODE_ENABLE);
}
- REG_WR(pDevice, PciCfg.ClockCtrl, Value32);
- }
+ /* 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;
+ }
- MM_Wait(40);
+ REG_WR (pDevice, PciCfg.ClockCtrl, Value32);
- 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);
+ 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);
}
- 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 */
+ 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)
+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;
+ 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;
+ return Value32;
}
-
/******************************************************************************/
/* Description: */
/* */
@@ -5632,195 +5177,169 @@ GetPhyAdFlowCntrlSettings(
/* */
/******************************************************************************/
static LM_STATUS
-LM_ForceAutoNegBcm540xPhy(
-PLM_DEVICE_BLOCK pDevice,
-LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
+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;
+ 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;
- }
+ /* 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, 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, PHY_AN_AD_REG, Value32);
- pDevice->advertising = Value32;
+ 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;
+ }
- if(DuplexMode != LM_DUPLEX_MODE_FULL)
- {
- Value32 = BCM540X_AN_AD_1000BASET_HALF;
- }
- else
- {
- Value32 = BCM540X_AN_AD_1000BASET_FULL;
- }
+ Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+ Value32 |= GetPhyAdFlowCntrlSettings (pDevice);
- 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;
+ 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_100BASETX_HALF;
- }
- else
- {
- Value32 = PHY_AN_AD_100BASETX_FULL;
- }
+ 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);
+ 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;
+ LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32);
+ pDevice->advertising = Value32;
+ }
}
- if(DuplexMode == LM_DUPLEX_MODE_FULL)
- {
- NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE;
- }
+ /* 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;
- /* 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);
+ /* 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;
+ }
- /* Wait for link to go down. */
- for(Cnt = 0; Cnt < 15000; Cnt++)
- {
- MM_Wait(10);
+ if (DuplexMode == LM_DUPLEX_MODE_FULL) {
+ NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE;
+ }
- LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
- LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+ /* 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);
- if(!(Value32 & PHY_STATUS_LINK_PASS))
- {
- MM_Wait(40);
- break;
- }
- }
+ /* Wait for link to go down. */
+ for (Cnt = 0; Cnt < 15000; Cnt++) {
+ MM_Wait (10);
- 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);
- }
+ LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32);
+ LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32);
+
+ if (!(Value32 & PHY_STATUS_LINK_PASS)) {
+ MM_Wait (40);
+ break;
+ }
+ }
- return LM_STATUS_SUCCESS;
-} /* LM_ForceAutoNegBcm540xPhy */
+ 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: */
@@ -5828,218 +5347,199 @@ LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
/* Return: */
/******************************************************************************/
static LM_STATUS
-LM_ForceAutoNeg(
-PLM_DEVICE_BLOCK pDevice,
-LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
+LM_ForceAutoNeg (PLM_DEVICE_BLOCK pDevice,
+ LM_REQUESTED_MEDIA_TYPE RequestedMediaType)
{
- LM_STATUS LmStatus;
+ LM_STATUS LmStatus;
- /* Initialize the phy chip. */
- switch(pDevice->PhyId & PHY_ID_MASK)
- {
+ /* 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;
+ LmStatus =
+ LM_ForceAutoNegBcm540xPhy (pDevice, RequestedMediaType);
+ break;
default:
- LmStatus = LM_STATUS_FAILURE;
- break;
- }
+ LmStatus = LM_STATUS_FAILURE;
+ break;
+ }
- return LmStatus;
-} /* LM_ForceAutoNeg */
+ 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_STATUS LM_LoadFirmware (PLM_DEVICE_BLOCK pDevice,
+ PT3_FWIMG_INFO pFwImg,
+ LM_UINT32 LoadCpu, LM_UINT32 StartCpu)
{
- LM_UINT32 i;
- LM_UINT32 address;
+ 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;
- }
+ 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);
- }
+ /* 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]);
- }
+ /* 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->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]);
+ 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;
- }
+ 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);
- }
+ /* 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]);
- }
+ /* 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->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]);
+ 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;
+ 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, 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);
}
- 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;
- 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,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);
}
- REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
- REG_WR(pDevice,txCpu.reg.mode, 0);
- }
-
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
-STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number)
+STATIC LM_STATUS LM_HaltCpu (PLM_DEVICE_BLOCK pDevice, LM_UINT32 cpu_number)
{
- LM_UINT32 i;
+ 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 (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;
- }
+ 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);
+ 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;
+ if (REG_RD (pDevice, txCpu.reg.mode) & CPU_MODE_HALT)
+ break;
+ }
}
- }
- return (( i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS);
+ return ((i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS);
}
-
-int
-LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec)
+int LM_BlinkLED (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec)
{
LM_UINT32 Oldcfg;
int j;
int ret = 0;
- if(BlinkDurationSec == 0)
- {
+ if (BlinkDurationSec == 0) {
return 0;
}
- if(BlinkDurationSec > 120)
- {
+ if (BlinkDurationSec > 120) {
BlinkDurationSec = 120;
}
- Oldcfg = REG_RD(pDevice, MacCtrl.LedCtrl);
- for(j = 0; j < BlinkDurationSec * 2; j++)
- {
- if(j % 2)
- {
+ 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,
+ REG_WR (pDevice, MacCtrl.LedCtrl,
LED_CTRL_OVERRIDE_LINK_LED |
LED_CTRL_1000MBPS_LED_ON |
LED_CTRL_100MBPS_LED_ON |
@@ -6047,154 +5547,153 @@ LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec)
LED_CTRL_OVERRIDE_TRAFFIC_LED |
LED_CTRL_BLINK_TRAFFIC_LED |
LED_CTRL_TRAFFIC_LED);
- }
- else
- {
+ } else {
/* Turn off the LEDs. */
- REG_WR(pDevice, MacCtrl.LedCtrl,
+ 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) {
+ if (schedule_timeout (HZ / 2) != 0) {
ret = -EINTR;
break;
}
#else
- udelay(100000); /* 1s sleep */
+ udelay (100000); /* 1s sleep */
#endif
}
- REG_WR(pDevice, MacCtrl.LedCtrl, Oldcfg);
+ 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)
+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++)
- {
+ 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)
- value32 = REG_RD(pDevice, Ftq.RcvBdCompFtqFifoEnqueueDequeue);
+ REG_WR (pDevice, Ftq.DmaHighReadFtqFifoEnqueueDequeue,
+ dma_desc_addr);
else
- value32 = REG_RD(pDevice, Ftq.RcvDataCompFtqFifoEnqueueDequeue);
+ 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;
+ if ((value32 & 0xffff) == dma_desc_addr)
+ break;
- MM_Wait(10);
- }
+ MM_Wait (10);
+ }
- return LM_STATUS_SUCCESS;
+ return LM_STATUS_SUCCESS;
}
STATIC LM_STATUS
-LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt,
- LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize)
+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;
+ 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;
+ }
- 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;
- 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;
+ }
- 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;
}
-
- 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;
+ return LM_STATUS_SUCCESS;
}
-#endif /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_TIGON3 */
+
+#endif
diff --git a/drivers/tigon3.h b/drivers/tigon3.h
index ea4367d61d..c03347fdc9 100644
--- a/drivers/tigon3.h
+++ b/drivers/tigon3.h
@@ -21,7 +21,6 @@
#include "bcm570x_autoneg.h"
#endif
-
/* io defines */
#if !defined(BIG_ENDIAN_HOST)
#define readl(addr) \
@@ -29,7 +28,7 @@
#define writel(b,addr) \
((*(volatile unsigned int *)(addr)) = (LONGSWAP(b)))
#else
-#if 0 /* !defined(PPC603) */
+#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
@@ -37,25 +36,28 @@
#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;
+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);
+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 /* PPC603 */
#endif
-
/******************************************************************************/
/* Constants. */
/******************************************************************************/
@@ -90,7 +92,7 @@ static __inline void writel(unsigned int b, unsigned int addr){
/* 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 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)
@@ -161,32 +163,32 @@ static __inline void writel(unsigned int b, unsigned int addr){
/* 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 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 */
+#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. */
+#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 */
+#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_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 */
+#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
@@ -195,10 +197,9 @@ static __inline void writel(unsigned int b, unsigned int addr){
/* or 2048. */
#ifndef T3_RCV_RETURN_RCB_ENTRY_COUNT
#define T3_RCV_RETURN_RCB_ENTRY_COUNT 1024
-#endif /* T3_RCV_RETURN_RCB_ENTRY_COUNT */
+#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
@@ -227,7 +228,6 @@ static __inline void writel(unsigned int b, unsigned int addr){
#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
@@ -240,12 +240,10 @@ static __inline void writel(unsigned int b, unsigned int addr){
/* 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
@@ -265,19 +263,17 @@ static __inline void writel(unsigned int b, unsigned int addr){
#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_NIC_DMA_DESC_POOL_SIZE 0x2000 /* 8KB. */
#define T3_DEF_DMA_MBUF_LOW_WMARK 0x40
#define T3_DEF_RX_MAC_MBUF_LOW_WMARK 0x20
@@ -301,24 +297,21 @@ static __inline void writel(unsigned int b, unsigned int addr){
#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;
+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. */
/******************************************************************************/
@@ -362,7 +355,6 @@ typedef struct T3_FWIMG_INFO
#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
@@ -386,7 +378,6 @@ typedef struct T3_FWIMG_INFO
#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
@@ -409,7 +400,6 @@ typedef struct T3_FWIMG_INFO
#define T3_PM_PME_ENABLE BIT_8
#define T3_PM_PME_ASSERTED BIT_15
-
/* PCI state register. */
#define T3_PCI_STATE_REG 0x70
@@ -419,17 +409,16 @@ typedef struct T3_FWIMG_INFO
#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_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_BCM95701A7 0x0007 /* Agilent */
#define T3_SSID_BROADCOM_BCM95701A10 0x0008
#define T3_SSID_BROADCOM_BCM95701A12 0x8008
#define T3_SSID_BROADCOM_BCM95703Ax1 0x0009
@@ -449,7 +438,6 @@ typedef struct T3_FWIMG_INFO
#define T3_SSID_3COM_3C996SX 0x1004
#define T3_SSID_3COM_3C997SX 0x1005
-
/* Dell subsystem/subvendor IDs. */
#define T3_SVID_DELL 0x1028
@@ -469,7 +457,6 @@ typedef struct T3_FWIMG_INFO
#define T3_SSID_COMPAQ_NC7780 0x0085
#define T3_SSID_COMPAQ_NC7780_2 0x0099
-
/******************************************************************************/
/* MII registers. */
/******************************************************************************/
@@ -490,14 +477,12 @@ typedef struct T3_FWIMG_INFO
#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
@@ -507,7 +492,6 @@ typedef struct T3_FWIMG_INFO
#define PHY_ID2_MODEL_MASK 0x03f0
#define PHY_ID2_OUI_MASK 0xfc00
-
/* Auto-negotiation advertisement register. */
#define PHY_AN_AD_REG 0x04
@@ -519,18 +503,15 @@ typedef struct T3_FWIMG_INFO
#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. */
/******************************************************************************/
@@ -557,7 +538,6 @@ typedef struct T3_FWIMG_INFO
#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) && \
@@ -566,7 +546,6 @@ typedef struct T3_FWIMG_INFO
(((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
@@ -575,7 +554,6 @@ typedef struct T3_FWIMG_INFO
#define BCM540X_CONFIG_AS_MASTER BIT_11
#define BCM540X_ENABLE_CONFIG_AS_MASTER BIT_12
-
/* Extended control register. */
#define BCM540X_EXT_CTRL_REG 0x10
@@ -587,11 +565,9 @@ typedef struct T3_FWIMG_INFO
#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
@@ -631,7 +607,6 @@ typedef struct T3_FWIMG_INFO
#define BCM540X_CONTROL_ALL_CHANNELS BIT_15
-
/* Auxilliary Control Register (Shadow Register) */
#define BCM5401_AUX_CTRL 0x18
@@ -644,7 +619,6 @@ typedef struct T3_FWIMG_INFO
#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
@@ -664,7 +638,6 @@ typedef struct T3_FWIMG_INFO
#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
@@ -678,7 +651,6 @@ typedef struct T3_FWIMG_INFO
#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
@@ -687,11 +659,9 @@ typedef struct T3_FWIMG_INFO
#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. */
/******************************************************************************/
@@ -701,9 +671,9 @@ 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;
+ /* 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;
@@ -711,47 +681,44 @@ 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;
-
+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;
+ T3_64BIT_REGISTER HostRingAddr;
- union {
- struct {
+ 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;
+ T3_16BIT_REGISTER MaxLen;
+ T3_16BIT_REGISTER Flags;
+#else /* BIG_ENDIAN_HOST */
+ T3_16BIT_REGISTER Flags;
+ T3_16BIT_REGISTER MaxLen;
#endif
- } s;
+ } s;
- T3_32BIT_REGISTER MaxLen_Flags;
- } u;
+ T3_32BIT_REGISTER MaxLen_Flags;
+ } u;
- T3_32BIT_REGISTER NicRingAddr;
+ 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. */
/******************************************************************************/
@@ -763,98 +730,95 @@ typedef struct {
#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 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;
+ 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];
+ 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;
+ T3_64BIT_HOST_ADDR HostAddr;
#ifdef BIG_ENDIAN_HOST
- volatile LM_UINT16 Index;
- volatile LM_UINT16 Len;
+ volatile LM_UINT16 Index;
+ volatile LM_UINT16 Len;
- volatile LM_UINT16 Type;
- volatile LM_UINT16 Flags;
+ volatile LM_UINT16 Type;
+ volatile LM_UINT16 Flags;
- volatile LM_UINT16 IpCksum;
- volatile LM_UINT16 TcpUdpCksum;
+ 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 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 Flags;
+ volatile LM_UINT16 Type;
- volatile LM_UINT16 TcpUdpCksum;
- volatile LM_UINT16 IpCksum;
+ volatile LM_UINT16 TcpUdpCksum;
+ volatile LM_UINT16 IpCksum;
- volatile LM_UINT16 VlanTag;
- volatile LM_UINT16 ErrorFlag;
+ volatile LM_UINT16 VlanTag;
+ volatile LM_UINT16 ErrorFlag;
#endif
- volatile LM_UINT32 Reserved;
- volatile LM_UINT32 Opaque;
+ volatile LM_UINT32 Reserved;
+ volatile LM_UINT32 Opaque;
} T3_RCV_BD, *PT3_RCV_BD;
-
typedef struct {
- T3_64BIT_HOST_ADDR HostAddr[3];
+ T3_64BIT_HOST_ADDR HostAddr[3];
#ifdef BIG_ENDIAN_HOST
- LM_UINT16 Len1;
- LM_UINT16 Len2;
+ LM_UINT16 Len1;
+ LM_UINT16 Len2;
- LM_UINT16 Len3;
- LM_UINT16 Reserved1;
-#else /* BIG_ENDIAN_HOST */
- LM_UINT16 Len2;
- LM_UINT16 Len1;
+ LM_UINT16 Len3;
+ LM_UINT16 Reserved1;
+#else /* BIG_ENDIAN_HOST */
+ LM_UINT16 Len2;
+ LM_UINT16 Len1;
- LM_UINT16 Reserved1;
- LM_UINT16 Len3;
+ LM_UINT16 Reserved1;
+ LM_UINT16 Len3;
#endif
- T3_RCV_BD StdRcvBd;
+ 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
@@ -866,7 +830,6 @@ typedef struct {
#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
@@ -877,44 +840,42 @@ typedef struct {
#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;
+ T3_64BIT_HOST_ADDR HostAddr;
- union {
- struct {
+ union {
+ struct {
#ifdef BIG_ENDIAN_HOST
- LM_UINT16 Len;
- LM_UINT16 Flags;
-#else /* BIG_ENDIAN_HOST */
- LM_UINT16 Flags;
- LM_UINT16 Len;
+ LM_UINT16 Len;
+ LM_UINT16 Flags;
+#else /* BIG_ENDIAN_HOST */
+ LM_UINT16 Flags;
+ LM_UINT16 Len;
#endif
- } s1;
+ } s1;
- LM_UINT32 Len_Flags;
- } u1;
+ LM_UINT32 Len_Flags;
+ } u1;
- union {
- struct {
+ union {
+ struct {
#ifdef BIG_ENDIAN_HOST
- LM_UINT16 Reserved;
- LM_UINT16 VlanTag;
-#else /* BIG_ENDIAN_HOST */
- LM_UINT16 VlanTag;
- LM_UINT16 Reserved;
+ LM_UINT16 Reserved;
+ LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+ LM_UINT16 VlanTag;
+ LM_UINT16 Reserved;
#endif
- } s2;
+ } s2;
- LM_UINT32 VlanTag;
- } u2;
+ 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
@@ -932,435 +893,426 @@ typedef struct {
/* 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;
+ 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;
+ 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;
+} 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;
+ 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];
+ 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;
+ 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 */
+ /* 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 ModeCtrl;
- T3_32BIT_REGISTER MiscCfg;
+ T3_32BIT_REGISTER MiscCfg;
- T3_32BIT_REGISTER MiscLocalCtrl;
+ T3_32BIT_REGISTER MiscLocalCtrl;
- T3_32BIT_REGISTER Unused4;
+ 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;
+ /* 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];
+ LM_UINT8 Unused5[80];
} T3_PCI_CONFIGURATION, *PT3_PCI_CONFIGURATION;
#define PCIX_CMD_MAX_SPLIT_MASK 0x0070
@@ -1374,1382 +1326,1347 @@ typedef struct {
/******************************************************************************/
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
+ /* 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
+#define RCV_LAST_RULE_IDX 0x04
#else
- #define RCV_LAST_RULE_IDX 0x02
+#define RCV_LAST_RULE_IDX 0x02
#endif
- T3_32BIT_REGISTER RcvRuleCfg;
- #define RX_RULE_DEFAULT_CLASS (1 << 3)
+ T3_32BIT_REGISTER RcvRuleCfg;
+#define RX_RULE_DEFAULT_CLASS (1 << 3)
- LM_UINT8 Reserved1[140];
+ LM_UINT8 Reserved1[140];
- T3_32BIT_REGISTER SerdesCfg;
- T3_32BIT_REGISTER SerdesStatus;
+ T3_32BIT_REGISTER SerdesCfg;
+ T3_32BIT_REGISTER SerdesStatus;
- LM_UINT8 Reserved2[104];
+ LM_UINT8 Reserved2[104];
- volatile LM_UINT8 TxMacState[16];
- volatile LM_UINT8 RxMacState[20];
+ volatile LM_UINT8 TxMacState[16];
+ volatile LM_UINT8 RxMacState[20];
- LM_UINT8 Reserved3[476];
+ LM_UINT8 Reserved3[476];
- T3_32BIT_REGISTER RxStats[26];
+ T3_32BIT_REGISTER RxStats[26];
- LM_UINT8 Reserved4[24];
+ LM_UINT8 Reserved4[24];
- T3_32BIT_REGISTER TxStats[28];
+ T3_32BIT_REGISTER TxStats[28];
- LM_UINT8 Reserved5[784];
+ 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;
+ 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
+ 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];
+ /* 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 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 Status;
+#define SND_BD_SEL_STATUS_ERROR_ATTN BIT_2
- T3_32BIT_REGISTER HwDiag;
+ T3_32BIT_REGISTER HwDiag;
- /* Unused space. */
- LM_UINT8 Unused1[52];
+ /* Unused space. */
+ LM_UINT8 Unused1[52];
- /* Send BD Ring Selector Local NIC Send BD Consumer Index. */
- T3_32BIT_REGISTER NicSendBdSelConIdx[16];
+ /* Send BD Ring Selector Local NIC Send BD Consumer Index. */
+ T3_32BIT_REGISTER NicSendBdSelConIdx[16];
- /* Unused space. */
- LM_UINT8 Unused2[896];
+ /* 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 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
+ 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];
+ /* Send BD initiator local NIC send BD producer index. */
+ T3_32BIT_REGISTER NicSendBdInProdIdx[16];
- /* Unused space. */
- LM_UINT8 Unused2[952];
+ /* 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
+ 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];
+ /* 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;
+ /* 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];
+ /* Receive List Placement statistics Enable Mask. */
+ T3_32BIT_REGISTER StatsEnableMask;
- struct {
- T3_32BIT_REGISTER Head;
- T3_32BIT_REGISTER Tail;
- T3_32BIT_REGISTER Count;
+ /* Receive List Placement statistics Increment Mask. */
+ T3_32BIT_REGISTER StatsIncMask;
/* 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;
+ 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;
+ /* 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
+ 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];
+ /* 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 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 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 NicJumboRcvProdIdx;
+ T3_32BIT_REGISTER NicStdRcvProdIdx;
+ T3_32BIT_REGISTER NicMiniRcvProdIdx;
- T3_32BIT_REGISTER MiniRcvThreshold;
- T3_32BIT_REGISTER StdRcvThreshold;
- T3_32BIT_REGISTER JumboRcvThreshold;
+ T3_32BIT_REGISTER MiniRcvThreshold;
+ T3_32BIT_REGISTER StdRcvThreshold;
+ T3_32BIT_REGISTER JumboRcvThreshold;
- /* Unused space. */
- LM_UINT8 Unused[992];
+ /* 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 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 Status;
+#define RCV_BD_COMP_STATUS_ERROR_ATTN BIT_2
- T3_32BIT_REGISTER NicJumboRcvBdProdIdx;
- T3_32BIT_REGISTER NicStdRcvBdProdIdx;
- T3_32BIT_REGISTER NicMiniRcvBdProdIdx;
+ T3_32BIT_REGISTER NicJumboRcvBdProdIdx;
+ T3_32BIT_REGISTER NicStdRcvBdProdIdx;
+ T3_32BIT_REGISTER NicMiniRcvBdProdIdx;
- /* Unused space. */
- LM_UINT8 Unused[1004];
+ /* 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 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
+ T3_32BIT_REGISTER Status;
+#define RCV_LIST_SEL_STATUS_ERROR_ATTN BIT_2
- /* Unused space. */
- LM_UINT8 Unused[1016];
+ /* Unused space. */
+ LM_UINT8 Unused[1016];
} T3_RCV_LIST_SELECTOR, *PT3_RCV_LIST_SELECTOR;
-
/******************************************************************************/
/* Mbuf cluster free registers. */
/******************************************************************************/
typedef struct {
- T3_32BIT_REGISTER Mode;
+ T3_32BIT_REGISTER Mode;
#define MBUF_CLUSTER_FREE_MODE_RESET BIT_0
#define MBUF_CLUSTER_FREE_MODE_ENABLE BIT_1
- T3_32BIT_REGISTER Status;
+ T3_32BIT_REGISTER Status;
- /* Unused space. */
- LM_UINT8 Unused[1016];
+ /* 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
+ /* 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
+ /* Status. */
+ T3_32BIT_REGISTER Status;
+#define HOST_COALESCE_ERROR_ATTN BIT_2
- /* Receive coalescing ticks. */
- T3_32BIT_REGISTER RxCoalescingTicks;
+ /* Receive coalescing ticks. */
+ T3_32BIT_REGISTER RxCoalescingTicks;
- /* Send coalescing ticks. */
- T3_32BIT_REGISTER TxCoalescingTicks;
+ /* Send coalescing ticks. */
+ T3_32BIT_REGISTER TxCoalescingTicks;
- /* Receive max coalesced frames. */
- T3_32BIT_REGISTER RxMaxCoalescedFrames;
+ /* Receive max coalesced frames. */
+ T3_32BIT_REGISTER RxMaxCoalescedFrames;
- /* Send max coalesced frames. */
- T3_32BIT_REGISTER TxMaxCoalescedFrames;
+ /* Send max coalesced frames. */
+ T3_32BIT_REGISTER TxMaxCoalescedFrames;
- /* Receive coalescing ticks during interrupt. */
- T3_32BIT_REGISTER RxCoalescedTickDuringInt;
+ /* Receive coalescing ticks during interrupt. */
+ T3_32BIT_REGISTER RxCoalescedTickDuringInt;
- /* Send coalescing ticks during interrupt. */
- T3_32BIT_REGISTER TxCoalescedTickDuringInt;
+ /* Send coalescing ticks during interrupt. */
+ T3_32BIT_REGISTER TxCoalescedTickDuringInt;
- /* Receive max coalesced frames during interrupt. */
- T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt;
+ /* Receive max coalesced frames during interrupt. */
+ T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt;
- /* Send max coalesced frames during interrupt. */
- T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt;
+ /* Send max coalesced frames during interrupt. */
+ T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt;
- /* Statistics tick. */
- T3_32BIT_REGISTER StatsCoalescingTicks;
+ /* Statistics tick. */
+ T3_32BIT_REGISTER StatsCoalescingTicks;
- /* Unused space. */
- LM_UINT8 Unused2[4];
+ /* Unused space. */
+ LM_UINT8 Unused2[4];
- /* Statistics host address. */
- T3_64BIT_REGISTER StatsBlkHostAddr;
+ /* Statistics host address. */
+ T3_64BIT_REGISTER StatsBlkHostAddr;
- /* Status block host address.*/
- T3_64BIT_REGISTER StatusBlkHostAddr;
+ /* Status block host address. */
+ T3_64BIT_REGISTER StatusBlkHostAddr;
- /* Statistics NIC address. */
- T3_32BIT_REGISTER StatsBlkNicAddr;
+ /* Statistics NIC address. */
+ T3_32BIT_REGISTER StatsBlkNicAddr;
- /* Statust block NIC address. */
- T3_32BIT_REGISTER StatusBlkNicAddr;
+ /* Statust block NIC address. */
+ T3_32BIT_REGISTER StatusBlkNicAddr;
- /* Flow attention registers. */
- T3_32BIT_REGISTER FlowAttn;
+ /* Flow attention registers. */
+ T3_32BIT_REGISTER FlowAttn;
- /* Unused space. */
- LM_UINT8 Unused3[4];
+ /* Unused space. */
+ LM_UINT8 Unused3[4];
- T3_32BIT_REGISTER NicJumboRcvBdConIdx;
- T3_32BIT_REGISTER NicStdRcvBdConIdx;
- T3_32BIT_REGISTER NicMiniRcvBdConIdx;
+ T3_32BIT_REGISTER NicJumboRcvBdConIdx;
+ T3_32BIT_REGISTER NicStdRcvBdConIdx;
+ T3_32BIT_REGISTER NicMiniRcvBdConIdx;
- /* Unused space. */
- LM_UINT8 Unused4[36];
+ /* Unused space. */
+ LM_UINT8 Unused4[36];
- T3_32BIT_REGISTER NicRetProdIdx[16];
- T3_32BIT_REGISTER NicSndBdConIdx[16];
+ T3_32BIT_REGISTER NicRetProdIdx[16];
+ T3_32BIT_REGISTER NicSndBdConIdx[16];
- /* Unused space. */
- LM_UINT8 Unused5[768];
+ /* Unused space. */
+ LM_UINT8 Unused5[768];
} T3_HOST_COALESCING, *PT3_HOST_COALESCING;
-
/******************************************************************************/
/* Memory arbiter registers. */
/******************************************************************************/
typedef struct {
- T3_32BIT_REGISTER Mode;
+ 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 Status;
- T3_32BIT_REGISTER ArbTrapAddrLow;
- T3_32BIT_REGISTER ArbTrapAddrHigh;
+ T3_32BIT_REGISTER ArbTrapAddrLow;
+ T3_32BIT_REGISTER ArbTrapAddrHigh;
- /* Unused space. */
- LM_UINT8 Unused[1008];
+ /* 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;
+ 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_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;
+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;
+ 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];
+ /* Interrupt mailbox registers. */
+ T3_64BIT_REGISTER Interrupt[4];
- /* General mailbox registers. */
- T3_64BIT_REGISTER General[8];
+ /* General mailbox registers. */
+ T3_64BIT_REGISTER General[8];
- /* Reload statistics mailbox. */
- T3_64BIT_REGISTER ReloadStat;
+ /* 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 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];
+ /* 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 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;
+ /* Send BD ring nic producer index registers. */
+ T3_64BIT_REGISTER SendNicProdIdx[16];
+} T3_MAILBOX, *PT3_MAILBOX;
typedef struct {
- T3_MAILBOX Mailbox;
+ T3_MAILBOX Mailbox;
- /* Priority mailbox registers. */
- T3_32BIT_REGISTER HighPriorityEventVector;
- T3_32BIT_REGISTER HighPriorityEventMask;
- T3_32BIT_REGISTER LowPriorityEventVector;
- T3_32BIT_REGISTER LowPriorityEventMask;
+ /* 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];
+ /* 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;
+ 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;
+ T3_32BIT_REGISTER Mode;
#define MSI_MODE_RESET BIT_0
#define MSI_MODE_ENABLE BIT_1
- T3_32BIT_REGISTER Status;
+ T3_32BIT_REGISTER Status;
- T3_32BIT_REGISTER MsiFifoAccess;
+ T3_32BIT_REGISTER MsiFifoAccess;
- /* Unused space. */
- LM_UINT8 Unused[1012];
+ /* 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
+ T3_32BIT_REGISTER Mode;
+#define DMA_COMP_MODE_RESET BIT_0
+#define DMA_COMP_MODE_ENABLE BIT_1
- /* Unused space. */
- LM_UINT8 Unused[1020];
+ /* 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;
+ /* 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;
+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 */
+ /* Page zero for the internal CPUs. */
+ LM_UINT8 PageZero[0x100]; /* 0x0000 */
- /* Send RCBs. */
- T3_RCB SendRcb[16]; /* 0x0100 */
+ /* Send RCBs. */
+ T3_RCB SendRcb[16]; /* 0x0100 */
- /* Receive Return RCBs. */
- T3_RCB RcvRetRcb[16]; /* 0x0200 */
+ /* Receive Return RCBs. */
+ T3_RCB RcvRetRcb[16]; /* 0x0200 */
- /* Statistics block. */
- T3_STATS_BLOCK StatsBlk; /* 0x0300 */
+ /* Statistics block. */
+ T3_STATS_BLOCK StatsBlk; /* 0x0300 */
- /* Status block. */
- T3_STATUS_BLOCK StatusBlk; /* 0x0b00 */
+ /* Status block. */
+ T3_STATUS_BLOCK StatusBlk; /* 0x0b00 */
- /* Reserved for software. */
- LM_UINT8 Reserved[1200]; /* 0x0b50 */
+ /* Reserved for software. */
+ LM_UINT8 Reserved[1200]; /* 0x0b50 */
- /* Unmapped region. */
- LM_UINT8 Unmapped[4096]; /* 0x1000 */
+ /* Unmapped region. */
+ LM_UINT8 Unmapped[4096]; /* 0x1000 */
- /* DMA descriptors. */
- LM_UINT8 DmaDesc[8192]; /* 0x2000 */
+ /* DMA descriptors. */
+ LM_UINT8 DmaDesc[8192]; /* 0x2000 */
- /* Buffer descriptors. */
- LM_UINT8 BufferDesc[16384]; /* 0x4000 */
+ /* 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 */
+ /* PCI configuration registers. */
+ T3_PCI_CONFIGURATION PciCfg;
- /* Mailbox . */
- T3_MAILBOX Mailbox; /* 0x0200 */
+ /* Unused. */
+ LM_UINT8 Unused1[0x100]; /* 0x0100 */
- /* MAC control registers. */
- T3_MAC_CONTROL MacCtrl; /* 0x0400 */
+ /* Mailbox . */
+ T3_MAILBOX Mailbox; /* 0x0200 */
- /* Send data initiator control registers. */
- T3_SEND_DATA_INITIATOR SndDataIn; /* 0x0c00 */
+ /* MAC control registers. */
+ T3_MAC_CONTROL MacCtrl; /* 0x0400 */
- /* Send data completion Control registers. */
- T3_SEND_DATA_COMPLETION SndDataComp; /* 0x1000 */
+ /* Send data initiator control registers. */
+ T3_SEND_DATA_INITIATOR SndDataIn; /* 0x0c00 */
- /* Send BD ring selector. */
- T3_SEND_BD_SELECTOR SndBdSel; /* 0x1400 */
+ /* Send data completion Control registers. */
+ T3_SEND_DATA_COMPLETION SndDataComp; /* 0x1000 */
- /* Send BD initiator control registers. */
- T3_SEND_BD_INITIATOR SndBdIn; /* 0x1800 */
+ /* Send BD ring selector. */
+ T3_SEND_BD_SELECTOR SndBdSel; /* 0x1400 */
- /* Send BD completion control registers. */
- T3_SEND_BD_COMPLETION SndBdComp; /* 0x1c00 */
+ /* Send BD initiator control registers. */
+ T3_SEND_BD_INITIATOR SndBdIn; /* 0x1800 */
- /* Receive list placement control registers. */
- T3_RCV_LIST_PLACEMENT RcvListPlmt; /* 0x2000 */
+ /* Send BD completion control registers. */
+ T3_SEND_BD_COMPLETION SndBdComp; /* 0x1c00 */
- /* Receive Data and Receive BD Initiator Control. */
- T3_RCV_DATA_BD_INITIATOR RcvDataBdIn; /* 0x2400 */
+ /* Receive list placement control registers. */
+ T3_RCV_LIST_PLACEMENT RcvListPlmt; /* 0x2000 */
- /* Receive Data Completion Control */
- T3_RCV_DATA_COMPLETION RcvDataComp; /* 0x2800 */
+ /* Receive Data and Receive BD Initiator Control. */
+ T3_RCV_DATA_BD_INITIATOR RcvDataBdIn; /* 0x2400 */
- /* Receive BD Initiator Control Registers. */
- T3_RCV_BD_INITIATOR RcvBdIn; /* 0x2c00 */
+ /* Receive Data Completion Control */
+ T3_RCV_DATA_COMPLETION RcvDataComp; /* 0x2800 */
- /* Receive BD Completion Control Registers. */
- T3_RCV_BD_COMPLETION RcvBdComp; /* 0x3000 */
+ /* Receive BD Initiator Control Registers. */
+ T3_RCV_BD_INITIATOR RcvBdIn; /* 0x2c00 */
- /* Receive list selector control registers. */
- T3_RCV_LIST_SELECTOR RcvListSel; /* 0x3400 */
+ /* Receive BD Completion Control Registers. */
+ T3_RCV_BD_COMPLETION RcvBdComp; /* 0x3000 */
- /* Mbuf cluster free registers. */
- T3_MBUF_CLUSTER_FREE MbufClusterFree; /* 0x3800 */
+ /* Receive list selector control registers. */
+ T3_RCV_LIST_SELECTOR RcvListSel; /* 0x3400 */
- /* Host coalescing control registers. */
- T3_HOST_COALESCING HostCoalesce; /* 0x3c00 */
+ /* Mbuf cluster free registers. */
+ T3_MBUF_CLUSTER_FREE MbufClusterFree; /* 0x3800 */
- /* Memory arbiter control registers. */
- T3_MEM_ARBITER MemArbiter; /* 0x4000 */
+ /* Host coalescing control registers. */
+ T3_HOST_COALESCING HostCoalesce; /* 0x3c00 */
- /* Buffer manger control registers. */
- T3_BUFFER_MANAGER BufMgr; /* 0x4400 */
+ /* Memory arbiter control registers. */
+ T3_MEM_ARBITER MemArbiter; /* 0x4000 */
- /* Read DMA control registers. */
- T3_DMA_READ DmaRead; /* 0x4800 */
+ /* Buffer manger control registers. */
+ T3_BUFFER_MANAGER BufMgr; /* 0x4400 */
- /* Write DMA control registers. */
- T3_DMA_WRITE DmaWrite; /* 0x4c00 */
+ /* Read DMA control registers. */
+ T3_DMA_READ DmaRead; /* 0x4800 */
- T3_CPU rxCpu; /* 0x5000 */
- T3_CPU txCpu; /* 0x5400 */
+ /* Write DMA control registers. */
+ T3_DMA_WRITE DmaWrite; /* 0x4c00 */
- /* Mailboxes. */
- T3_GRC_MAILBOX GrcMailbox; /* 0x5800 */
+ T3_CPU rxCpu; /* 0x5000 */
+ T3_CPU txCpu; /* 0x5400 */
- /* Flow Through queues. */
- T3_FTQ Ftq; /* 0x5c00 */
+ /* Mailboxes. */
+ T3_GRC_MAILBOX GrcMailbox; /* 0x5800 */
- /* Message signaled interrupt registes. */
- T3_MSG_SIGNALED_INT Msi; /* 0x6000 */
+ /* Flow Through queues. */
+ T3_FTQ Ftq; /* 0x5c00 */
- /* DMA completion registers. */
- T3_DMA_COMPLETION DmaComp; /* 0x6400 */
+ /* Message signaled interrupt registes. */
+ T3_MSG_SIGNALED_INT Msi; /* 0x6000 */
- /* GRC registers. */
- T3_GRC Grc; /* 0x6800 */
+ /* DMA completion registers. */
+ T3_DMA_COMPLETION DmaComp; /* 0x6400 */
- /* Unused space. */
- LM_UINT8 Unused2[1024]; /* 0x6c00 */
+ /* GRC registers. */
+ T3_GRC Grc; /* 0x6800 */
- /* NVRAM registers. */
- T3_NVRAM Nvram; /* 0x7000 */
-
- /* Unused space. */
- LM_UINT8 Unused3[3072]; /* 0x7400 */
+ /* Unused space. */
+ LM_UINT8 Unused2[1024]; /* 0x6c00 */
- /* 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;
+ /* NVRAM registers. */
+ T3_NVRAM Nvram; /* 0x7000 */
- /* Use the memory window base address register to determine the */
- /* MBUF segment. */
- LM_UINT32 Mbuf[32768/4];
- LM_UINT32 MemBlock32K[32768/4];
- } uIntMem;
+ /* 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 */
+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);
-
+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_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_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_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. */
/******************************************************************************/
@@ -2758,331 +2675,328 @@ typedef enum {
#define LM_PACKET_SIGNATURE_RX 0x6b766168
typedef struct _LM_PACKET {
- /* Set in LM. */
- LM_STATUS PacketStatus;
+ /* Set in LM. */
+ LM_STATUS PacketStatus;
- /* Set in LM for Rx, in UM for Tx. */
- LM_UINT32 PacketSize;
+ /* Set in LM for Rx, in UM for Tx. */
+ LM_UINT32 PacketSize;
- LM_UINT16 Flags;
+ LM_UINT16 Flags;
- LM_UINT16 VlanTag;
+ LM_UINT16 VlanTag;
- union {
- /* Send info. */
- struct {
- /* Set up by UM. */
- LM_UINT32 FragCount;
+ union {
+ /* Send info. */
+ struct {
+ /* Set up by UM. */
+ LM_UINT32 FragCount;
- } Tx;
+ } Tx;
- /* Receive info. */
- struct {
- /* This descriptor belongs to either Std, Mini, or Jumbo ring. */
- T3_RCV_PROD_RING RcvProdRing;
+ /* Receive info. */
+ struct {
+ /* This descriptor belongs to either Std, Mini, or Jumbo ring. */
+ T3_RCV_PROD_RING RcvProdRing;
- /* Receive buffer size */
- LM_UINT32 RxBufferSize;
+ /* Receive buffer size */
+ LM_UINT32 RxBufferSize;
- /* Checksum information. */
- LM_UINT16 IpChecksum;
- LM_UINT16 TcpUdpChecksum;
+ /* Checksum information. */
+ LM_UINT16 IpChecksum;
+ LM_UINT16 TcpUdpChecksum;
- } Rx;
- } u;
+ } Rx;
+ } u;
} LM_PACKET;
-
/******************************************************************************/
/* Tigon3 device block. */
/******************************************************************************/
typedef struct _LM_DEVICE_BLOCK {
- int index; /* Device ID */
- /* Memory view. */
- PT3_STD_MEM_MAP pMemView;
+ 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;
+ /* 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;
+ LM_UINT32 MiscHostCtrl;
+ LM_UINT32 GrcLocalCtrl;
+ LM_UINT32 DmaReadWriteCtrl;
+ LM_UINT32 PciState;
- /* Rx info */
- LM_UINT32 RxStdDescCnt;
- LM_UINT32 RxStdQueuedCnt;
- LM_UINT32 RxStdProdIdx;
+ /* Rx info */
+ LM_UINT32 RxStdDescCnt;
+ LM_UINT32 RxStdQueuedCnt;
+ LM_UINT32 RxStdProdIdx;
- PT3_RCV_BD pRxStdBdVirt;
- LM_PHYSICAL_ADDRESS RxStdBdPhy;
+ PT3_RCV_BD pRxStdBdVirt;
+ LM_PHYSICAL_ADDRESS RxStdBdPhy;
- LM_UINT32 RxPacketDescCnt;
- LM_RX_PACKET_Q RxPacketFreeQ;
- LM_RX_PACKET_Q RxPacketReceivedQ;
+ 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;
+ /* 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 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 */
- LM_UINT32 RxJumboProdIdx;
+ /* 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. */
- PT3_RCV_BD pRxJumboBdVirt;
- LM_PHYSICAL_ADDRESS RxJumboBdPhy;
-#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+ /* 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;
- /* 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. */
+ /* MiMode register. */
+ LM_UINT32 MiMode;
- /* 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;
+ /* Host coalesce mode register. */
+ LM_UINT32 CoalesceMode;
- /* 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;
+ /* 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;
+ 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;
+ PLM_UINT8 pMappedMemBase;
- /* Phy info. */
- LM_UINT32 PhyAddr;
- LM_UINT32 PhyId;
+ /* Saved PCI configuration registers for restoring after a reset. */
+ LM_UINT32 SavedCacheLineReg;
- /* Requested phy settings. */
- LM_REQUESTED_MEDIA_TYPE RequestedMediaType;
+ /* Phy info. */
+ LM_UINT32 PhyAddr;
+ LM_UINT32 PhyId;
- /* Disable auto-negotiation. */
- LM_UINT32 DisableAutoNeg;
+ /* Requested phy settings. */
+ LM_REQUESTED_MEDIA_TYPE RequestedMediaType;
- /* 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
+ /* Disable auto-negotiation. */
+ LM_UINT32 DisableAutoNeg;
- /* 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
+ /* 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;
+ /* LED mode. */
+ LM_UINT32 LedMode;
- #define LED_MODE_AUTO 0
+#define LED_MODE_AUTO 0
- /* 5700/01 LED mode. */
- #define LED_MODE_THREE_LINK 1
- #define LED_MODE_LINK10 2
+ /* 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
+ /* 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
+ /* WOL Speed */
+ LM_UINT32 WolSpeed;
+#define WOL_SPEED_10MB 1
+#define WOL_SPEED_100MB 2
- /* Reset the PHY on initialization. */
- LM_UINT32 ResetPhyOnInit;
+ /* Reset the PHY on initialization. */
+ LM_UINT32 ResetPhyOnInit;
- LM_UINT32 RestoreOnWakeUp;
- LM_REQUESTED_MEDIA_TYPE WakeUpRequestedMediaType;
- LM_UINT32 WakeUpDisableAutoNeg;
+ 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! */
+ /* 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];
+ /* 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;
+ /* Use NIC or Host based send BD. */
+ LM_UINT32 NicSendBd;
- /* Athlon fix. */
- LM_UINT32 DelayPciGrant;
+ /* Athlon fix. */
+ LM_UINT32 DelayPciGrant;
- /* Enable OneDmaAtOnce */
- LM_UINT32 OneDmaAtOnce;
+ /* Enable OneDmaAtOnce */
+ LM_UINT32 OneDmaAtOnce;
- /* Split Mode flags, Jimmy new */
- LM_UINT32 SplitModeEnable;
- LM_UINT32 SplitModeMaxReq;
+ /* Split Mode flags, Jimmy new */
+ LM_UINT32 SplitModeEnable;
+ LM_UINT32 SplitModeMaxReq;
- /* Init flag. */
- LM_BOOL InitDone;
+ /* Init flag. */
+ LM_BOOL InitDone;
- /* Shutdown flag. Set by the upper module. */
- LM_BOOL ShuttingDown;
+ /* 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;
+ /* Flag to determine whether to call LM_QueueRxPackets or not in */
+ /* LM_ResetAdapter routine. */
+ LM_BOOL QueueRxPackets;
- LM_UINT32 MbufBase;
- LM_UINT32 MbufSize;
+ LM_UINT32 MbufBase;
+ LM_UINT32 MbufSize;
- /* TRUE if we have a SERDES PHY. */
- LM_UINT32 EnableTbi;
+ /* TRUE if we have a SERDES PHY. */
+ LM_UINT32 EnableTbi;
- /* Ethernet@WireSpeed. */
- LM_UINT32 EnableWireSpeed;
+ /* Ethernet@WireSpeed. */
+ LM_UINT32 EnableWireSpeed;
- LM_UINT32 EepromWp;
+ LM_UINT32 EepromWp;
#if INCLUDE_TBI_SUPPORT
- /* Autoneg state info. */
- AN_STATE_INFO AnInfo;
- LM_UINT32 PollTbiLink;
- LM_UINT32 IgnoreTbiLinkChange;
+ /* 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;
+ 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)
@@ -3216,7 +3130,6 @@ typedef struct _LM_DEVICE_BLOCK {
#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)
@@ -3251,12 +3164,10 @@ typedef struct _LM_DEVICE_BLOCK {
#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)
@@ -3283,25 +3194,24 @@ typedef struct _LM_DEVICE_BLOCK {
#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);
+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 */
+#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);
+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);
+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
@@ -3342,7 +3252,7 @@ LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
#define MEM_WR_OFFSET(pDevice, Offset, Value32) \
LM_MemWrInd(pDevice, Offset, Value32)
-#else /* normal target access path below */
+#else /* normal target access path below */
/* Register access. */
#define REG_RD(pDevice, OffsetName) \
@@ -3355,7 +3265,6 @@ LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
#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) \
@@ -3368,9 +3277,9 @@ LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
#define MEM_WR_OFFSET(pDevice, Offset, Value32) \
LM_MemWrInd(pDevice, Offset, Value32)
-#endif /* PCIX_TARGET_WORKAROUND */
+#endif /* PCIX_TARGET_WORKAROUND */
-#endif /* Jimmy, merging */
+#endif /* Jimmy, merging */
/* Jimmy...rest of file is new stuff! */
/******************************************************************************/
@@ -3378,14 +3287,14 @@ LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
/******************************************************************************/
/* 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);
+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);
+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) ? \
@@ -3427,4 +3336,4 @@ LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
#define MEM_WR_OFFSET(pDevice, Offset, Value32) \
LM_MemWrInd(pDevice, Offset, Value32)
-#endif /* TIGON3_H */
+#endif /* TIGON3_H */
diff --git a/drivers/tqm8xx_pcmcia.c b/drivers/tqm8xx_pcmcia.c
index a0f53cd684..132c7a5169 100644
--- a/drivers/tqm8xx_pcmcia.c
+++ b/drivers/tqm8xx_pcmcia.c
@@ -10,11 +10,11 @@
#undef CONFIG_PCMCIA
-#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+#if defined(CONFIG_CMD_PCMCIA)
#define CONFIG_PCMCIA
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
+#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
#define CONFIG_PCMCIA
#endif
@@ -241,7 +241,7 @@ int pcmcia_hardware_enable(int slot)
}
-#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+#if defined(CONFIG_CMD_PCMCIA)
int pcmcia_hardware_disable(int slot)
{
u_long reg;
@@ -263,7 +263,7 @@ int pcmcia_hardware_disable(int slot)
return (0);
}
-#endif /* CFG_CMD_PCMCIA */
+#endif
int pcmcia_voltage_set(int slot, int vcc, int vpp)
{
diff --git a/drivers/tsec.c b/drivers/tsec.c
index b4187739cb..4ff3339c7d 100644
--- a/drivers/tsec.c
+++ b/drivers/tsec.c
@@ -65,38 +65,30 @@ struct tsec_info_struct {
* FEC_PHYIDX
*/
static struct tsec_info_struct tsec_info[] = {
-#if defined(CONFIG_MPC85XX_TSEC1) || defined(CONFIG_MPC83XX_TSEC1)
-#if defined(CONFIG_MPC8544DS)
- {TSEC1_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC1_PHYIDX},
-#else
- {TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX},
-#endif
-#elif defined(CONFIG_MPC86XX_TSEC1)
- {TSEC1_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC1_PHYIDX},
+#ifdef CONFIG_TSEC1
+ {TSEC1_PHY_ADDR, TSEC1_FLAGS, TSEC1_PHYIDX},
#else
{0, 0, 0},
#endif
-#if defined(CONFIG_MPC85XX_TSEC2) || defined(CONFIG_MPC83XX_TSEC2)
- {TSEC2_PHY_ADDR, TSEC_GIGABIT, TSEC2_PHYIDX},
-#elif defined(CONFIG_MPC86XX_TSEC2)
- {TSEC2_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC2_PHYIDX},
+#ifdef CONFIG_TSEC2
+ {TSEC2_PHY_ADDR, TSEC2_FLAGS, TSEC2_PHYIDX},
#else
{0, 0, 0},
#endif
#ifdef CONFIG_MPC85XX_FEC
- {FEC_PHY_ADDR, 0, FEC_PHYIDX},
+ {FEC_PHY_ADDR, FEC_FLAGS, FEC_PHYIDX},
#else
-#if defined(CONFIG_MPC85XX_TSEC3) || defined(CONFIG_MPC83XX_TSEC3) || defined(CONFIG_MPC86XX_TSEC3)
- {TSEC3_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC3_PHYIDX},
+#ifdef CONFIG_TSEC3
+ {TSEC3_PHY_ADDR, TSEC3_FLAGS, TSEC3_PHYIDX},
#else
{0, 0, 0},
#endif
-#if defined(CONFIG_MPC85XX_TSEC4) || defined(CONFIG_MPC83XX_TSEC4) || defined(CONFIG_MPC86XX_TSEC4)
- {TSEC4_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC4_PHYIDX},
+#ifdef CONFIG_TSEC4
+ {TSEC4_PHY_ADDR, TSEC4_FLAGS, TSEC4_PHYIDX},
#else
{0, 0, 0},
-#endif
-#endif
+#endif /* CONFIG_TSEC4 */
+#endif /* CONFIG_MPC85XX_FEC */
};
#define MAXCONTROLLERS (4)
@@ -129,6 +121,9 @@ static int tsec_miiphy_write(char *devname, unsigned char addr,
unsigned char reg, unsigned short value);
static int tsec_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short *value);
+#ifdef CONFIG_MCAST_TFTP
+static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set);
+#endif
/* Initialize device structure. Returns success if PHY
* initialization succeeded (i.e. if it recognizes the PHY)
@@ -167,6 +162,9 @@ int tsec_initialize(bd_t * bis, int index, char *devname)
dev->halt = tsec_halt;
dev->send = tsec_send;
dev->recv = tsec_recv;
+#ifdef CONFIG_MCAST_TFTP
+ dev->mcast = tsec_mcast_addr;
+#endif
/* Tell u-boot to get the addr from the env */
for (i = 0; i < 6; i++)
@@ -178,7 +176,7 @@ int tsec_initialize(bd_t * bis, int index, char *devname)
priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
&& !defined(BITBANGMII)
miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
#endif
@@ -298,9 +296,9 @@ static int init_phy(struct eth_device *dev)
volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
/* Assign a Physical address to the TBI */
- regs->tbipa = TBIPA_VALUE;
+ regs->tbipa = CFG_TBIPA_VALUE;
regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
- regs->tbipa = TBIPA_VALUE;
+ regs->tbipa = CFG_TBIPA_VALUE;
asm("sync");
/* Reset MII (due to new addresses) */
@@ -349,17 +347,16 @@ uint mii_cr_init(uint mii_reg, struct tsec_private * priv)
uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
{
/*
- * Wait if PHY is capable of autonegotiation and autonegotiation
- * is not complete.
+ * Wait if the link is up, and autonegotiation is in progress
+ * (ie - we're capable and it's not done)
*/
mii_reg = read_phy_reg(priv, MIIM_STATUS);
- if ((mii_reg & PHY_BMSR_AUTN_ABLE)
+ if ((mii_reg & MIIM_STATUS_LINK) && (mii_reg & PHY_BMSR_AUTN_ABLE)
&& !(mii_reg & PHY_BMSR_AUTN_COMP)) {
int i = 0;
puts("Waiting for PHY auto negotiation to complete");
- while (!((mii_reg & PHY_BMSR_AUTN_COMP)
- && (mii_reg & MIIM_STATUS_LINK))) {
+ while (!(mii_reg & PHY_BMSR_AUTN_COMP)) {
/*
* Timeout reached ?
*/
@@ -379,7 +376,10 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
priv->link = 1;
udelay(500000); /* another 500 ms (results in faster booting) */
} else {
- priv->link = 1;
+ if (mii_reg & MIIM_STATUS_LINK)
+ priv->link = 1;
+ else
+ priv->link = 0;
}
return 0;
@@ -519,16 +519,13 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv)
mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
- if (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
- (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
+ if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) &&
+ !(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
int i = 0;
puts("Waiting for PHY realtime link");
- while (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
- (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
- /*
- * Timeout reached ?
- */
+ while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
+ /* Timeout reached ? */
if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
puts(" TIMEOUT !\n");
priv->link = 0;
@@ -543,6 +540,11 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv)
}
puts(" done\n");
udelay(500000); /* another 500 ms (results in faster booting) */
+ } else {
+ if (mii_reg & MIIM_88E1011_PHYSTAT_LINK)
+ priv->link = 1;
+ else
+ priv->link = 0;
}
if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
@@ -900,6 +902,39 @@ static void tsec_halt(struct eth_device *dev)
phy_run_commands(priv, priv->phyinfo->shutdown);
}
+struct phy_info phy_info_M88E1149S = {
+ 0x1410ca,
+ "Marvell 88E1149S",
+ 4,
+ (struct phy_cmd[]){ /* config */
+ /* Reset and configure the PHY */
+ {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+ {0x1d, 0x1f, NULL},
+ {0x1e, 0x200c, NULL},
+ {0x1d, 0x5, NULL},
+ {0x1e, 0x0, NULL},
+ {0x1e, 0x100, NULL},
+ {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
+ {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
+ {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+ {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
+ {miim_end,}
+ },
+ (struct phy_cmd[]){ /* startup */
+ /* Status is read once to clear old link state */
+ {MIIM_STATUS, miim_read, NULL},
+ /* Auto-negotiate */
+ {MIIM_STATUS, miim_read, &mii_parse_sr},
+ /* Read the status */
+ {MIIM_88E1011_PHY_STATUS, miim_read,
+ &mii_parse_88E1011_psr},
+ {miim_end,}
+ },
+ (struct phy_cmd[]){ /* shutdown */
+ {miim_end,}
+ },
+};
+
/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */
struct phy_info phy_info_BCM5461S = {
0x02060c1, /* 5461 ID */
@@ -928,6 +963,33 @@ struct phy_info phy_info_BCM5461S = {
},
};
+struct phy_info phy_info_BCM5464S = {
+ 0x02060b1, /* 5464 ID */
+ "Broadcom BCM5464S",
+ 0, /* not clear to me what minor revisions we can shift away */
+ (struct phy_cmd[]) { /* config */
+ /* Reset and configure the PHY */
+ {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+ {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
+ {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
+ {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+ {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
+ {miim_end,}
+ },
+ (struct phy_cmd[]) { /* startup */
+ /* Status is read once to clear old link state */
+ {MIIM_STATUS, miim_read, NULL},
+ /* Auto-negotiate */
+ {MIIM_STATUS, miim_read, &mii_parse_sr},
+ /* Read the status */
+ {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
+ {miim_end,}
+ },
+ (struct phy_cmd[]) { /* shutdown */
+ {miim_end,}
+ },
+};
+
struct phy_info phy_info_M88E1011S = {
0x01410c6,
"Marvell 88E1011S",
@@ -968,11 +1030,6 @@ struct phy_info phy_info_M88E1111S = {
(struct phy_cmd[]){ /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
- {0x1d, 0x1f, NULL},
- {0x1e, 0x200c, NULL},
- {0x1d, 0x5, NULL},
- {0x1e, 0x0, NULL},
- {0x1e, 0x100, NULL},
{0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
@@ -1012,14 +1069,16 @@ static struct phy_info phy_info_M88E1145 = {
"Marvell 88E1145",
4,
(struct phy_cmd[]){ /* config */
+ /* Reset the PHY */
+ {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+
/* Errata E0, E1 */
{29, 0x001b, NULL},
{30, 0x418f, NULL},
{29, 0x0016, NULL},
{30, 0xa2da, NULL},
- /* Reset and configure the PHY */
- {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+ /* Configure the PHY */
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
{MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO,
@@ -1203,10 +1262,10 @@ uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
case MIIM_LXT971_SR2_100HDX:
priv->speed = 100;
priv->duplexity = 0;
+ break;
default:
priv->speed = 100;
priv->duplexity = 1;
- break;
}
} else {
priv->speed = 0;
@@ -1292,9 +1351,11 @@ struct phy_info *phy_info[] = {
&phy_info_cis8204,
&phy_info_cis8201,
&phy_info_BCM5461S,
+ &phy_info_BCM5464S,
&phy_info_M88E1011S,
&phy_info_M88E1111S,
&phy_info_M88E1145,
+ &phy_info_M88E1149S,
&phy_info_dm9161,
&phy_info_lxt971,
&phy_info_VSC8244,
@@ -1325,8 +1386,10 @@ struct phy_info *get_phy_info(struct eth_device *dev)
/* loop through all the known PHY types, and find one that */
/* matches the ID we read from the PHY. */
for (i = 0; phy_info[i]; i++) {
- if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
+ if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) {
theInfo = phy_info[i];
+ break;
+ }
}
if (theInfo == NULL) {
@@ -1417,7 +1480,7 @@ static void relocate_cmds(void)
relocated = 1;
}
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
&& !defined(BITBANGMII)
struct tsec_private *get_priv_for_phy(unsigned char phyaddr)
@@ -1476,7 +1539,48 @@ static int tsec_miiphy_write(char *devname, unsigned char addr,
return 0;
}
-#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
- && !defined(BITBANGMII) */
+#endif
+
+#ifdef CONFIG_MCAST_TFTP
+
+/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
+
+/* Set the appropriate hash bit for the given addr */
+
+/* The algorithm works like so:
+ * 1) Take the Destination Address (ie the multicast address), and
+ * do a CRC on it (little endian), and reverse the bits of the
+ * result.
+ * 2) Use the 8 most significant bits as a hash into a 256-entry
+ * table. The table is controlled through 8 32-bit registers:
+ * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is
+ * gaddr7. This means that the 3 most significant bits in the
+ * hash index which gaddr register to use, and the 5 other bits
+ * indicate which bit (assuming an IBM numbering scheme, which
+ * for PowerPC (tm) is usually the case) in the tregister holds
+ * the entry. */
+static int
+tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
+{
+ struct tsec_private *priv = privlist[1];
+ volatile tsec_t *regs = priv->regs;
+ volatile u32 *reg_array, value;
+ u8 result, whichbit, whichreg;
+
+ result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff);
+ whichbit = result & 0x1f; /* the 5 LSB = which bit to set */
+ whichreg = result >> 5; /* the 3 MSB = which reg to set it in */
+ value = (1 << (31-whichbit));
+
+ reg_array = &(regs->hash.gaddr0);
+
+ if (set) {
+ reg_array[whichreg] |= value;
+ } else {
+ reg_array[whichreg] &= ~value;
+ }
+ return 0;
+}
+#endif /* Multicast TFTP ? */
#endif /* CONFIG_TSEC_ENET */
diff --git a/drivers/tsec.h b/drivers/tsec.h
index 7bf3dee2b6..2f0092ad59 100644
--- a/drivers/tsec.h
+++ b/drivers/tsec.h
@@ -70,7 +70,9 @@
#define miim_end -2
#define miim_read -1
-#define TBIPA_VALUE 0x1f
+#ifndef CFG_TBIPA_VALUE
+ #define CFG_TBIPA_VALUE 0x1f
+#endif
#define MIIMCFG_INIT_VALUE 0x00000003
#define MIIMCFG_RESET 0x80000000
diff --git a/drivers/tsi108_eth.c b/drivers/tsi108_eth.c
index 47341bee7f..524e9daa4c 100644
--- a/drivers/tsi108_eth.c
+++ b/drivers/tsi108_eth.c
@@ -27,7 +27,7 @@
#include <config.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) \
&& defined(CONFIG_TSI108_ETH)
#if !defined(CONFIG_TSI108_ETH_NUM_PORTS) || (CONFIG_TSI108_ETH_NUM_PORTS > 2)
diff --git a/drivers/tsi108_i2c.c b/drivers/tsi108_i2c.c
index eb52cb66c9..3a3b75c39b 100644
--- a/drivers/tsi108_i2c.c
+++ b/drivers/tsi108_i2c.c
@@ -28,7 +28,7 @@
#ifdef CONFIG_TSI108_I2C
#include <tsi108.h>
-#if (CONFIG_COMMANDS & CFG_CMD_I2C)
+#if defined(CONFIG_CMD_I2C)
#define I2C_DELAY 100000
#undef DEBUG_I2C
@@ -279,5 +279,5 @@ int i2c_probe (uchar chip)
return i2c_read (chip, 0, 1, (char *)&tmp, 1);
}
-#endif /* (CONFIG_COMMANDS & CFG_CMD_I2C) */
+#endif
#endif /* CONFIG_TSI108_I2C */
diff --git a/drivers/usb_ohci.c b/drivers/usb_ohci.c
new file mode 100644
index 0000000000..14984a5f39
--- /dev/null
+++ b/drivers/usb_ohci.c
@@ -0,0 +1,1918 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus.
+ *
+ * Interrupt support is added. Now, it has been tested
+ * on ULI1575 chip and works well with USB keyboard.
+ *
+ * (C) Copyright 2007
+ * Zhang Wei, Freescale Semiconductor, Inc. <wei.zhang@freescale.com>
+ *
+ * (C) Copyright 2003
+ * Gary Jennejohn, DENX Software Engineering <gj@denx.de>
+ *
+ * Note: Much of this code has been derived from Linux 2.4
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell
+ *
+ * Modified for the MP2USB by (C) Copyright 2005 Eric Benard
+ * ebenard@eukrea.com - based on s3c24x0's driver
+ *
+ * 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
+ *
+ */
+/*
+ * IMPORTANT NOTES
+ * 1 - Read doc/README.generic_usb_ohci
+ * 2 - this driver is intended for use with USB Mass Storage Devices
+ * (BBB) and USB keyboard. There is NO support for Isochronous pipes!
+ * 2 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG
+ * to activate workaround for bug #41 or this driver will NOT work!
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_USB_OHCI_NEW
+
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCI_OHCI)
+# include <pci.h>
+#endif
+
+#include <malloc.h>
+#include <usb.h>
+#include "usb_ohci.h"
+
+#if defined(CONFIG_ARM920T) || \
+ defined(CONFIG_S3C2400) || \
+ defined(CONFIG_S3C2410) || \
+ defined(CONFIG_440EP) || \
+ defined(CONFIG_PCI_OHCI) || \
+ defined(CONFIG_MPC5200)
+# define OHCI_USE_NPS /* force NoPowerSwitching mode */
+#endif
+
+#undef OHCI_VERBOSE_DEBUG /* not always helpful */
+#undef DEBUG
+#undef SHOW_INFO
+#undef OHCI_FILL_TRACE
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+/*
+ * e.g. PCI controllers need this
+ */
+#ifdef CFG_OHCI_SWAP_REG_ACCESS
+# define readl(a) __swap_32(*((vu_long *)(a)))
+# define writel(a, b) (*((vu_long *)(b)) = __swap_32((vu_long)a))
+#else
+# define readl(a) (*((vu_long *)(a)))
+# define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a))
+#endif /* CFG_OHCI_SWAP_REG_ACCESS */
+
+#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+
+#ifdef CONFIG_PCI_OHCI
+static struct pci_device_id ohci_pci_ids[] = {
+ {0x10b9, 0x5237}, /* ULI1575 PCI OHCI module ids */
+ /* Please add supported PCI OHCI controller ids here */
+ {0, 0}
+};
+#endif
+
+#ifdef DEBUG
+#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while(0)
+#endif /* DEBUG */
+#define err(format, arg...) printf("ERROR: " format "\n", ## arg)
+#undef SHOW_INFO
+#ifdef SHOW_INFO
+#define info(format, arg...) printf("INFO: " format "\n", ## arg)
+#else
+#define info(format, arg...) do {} while(0)
+#endif
+
+#ifdef CFG_OHCI_BE_CONTROLLER
+# define m16_swap(x) cpu_to_be16(x)
+# define m32_swap(x) cpu_to_be32(x)
+#else
+# define m16_swap(x) cpu_to_le16(x)
+# define m32_swap(x) cpu_to_le32(x)
+#endif /* CFG_OHCI_BE_CONTROLLER */
+
+/* global ohci_t */
+static ohci_t gohci;
+/* this must be aligned to a 256 byte boundary */
+struct ohci_hcca ghcca[1];
+/* a pointer to the aligned storage */
+struct ohci_hcca *phcca;
+/* this allocates EDs for all possible endpoints */
+struct ohci_device ohci_dev;
+/* RHSC flag */
+int got_rhsc;
+/* device which was disconnected */
+struct usb_device *devgone;
+
+/*-------------------------------------------------------------------------*/
+
+/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
+ * The erratum (#4) description is incorrect. AMD's workaround waits
+ * till some bits (mostly reserved) are clear; ok for all revs.
+ */
+#define OHCI_QUIRK_AMD756 0xabcd
+#define read_roothub(hc, register, mask) ({ \
+ u32 temp = readl (&hc->regs->roothub.register); \
+ if (hc->flags & OHCI_QUIRK_AMD756) \
+ while (temp & mask) \
+ temp = readl (&hc->regs->roothub.register); \
+ temp; })
+
+static u32 roothub_a (struct ohci *hc)
+ { return read_roothub (hc, a, 0xfc0fe000); }
+static inline u32 roothub_b (struct ohci *hc)
+ { return readl (&hc->regs->roothub.b); }
+static inline u32 roothub_status (struct ohci *hc)
+ { return readl (&hc->regs->roothub.status); }
+static u32 roothub_portstatus (struct ohci *hc, int i)
+ { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+/* forward declaration */
+static int hc_interrupt (void);
+static void
+td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer,
+ int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval);
+
+/*-------------------------------------------------------------------------*
+ * URB support functions
+ *-------------------------------------------------------------------------*/
+
+/* free HCD-private data associated with this URB */
+
+static void urb_free_priv (urb_priv_t * urb)
+{
+ int i;
+ int last;
+ struct td * td;
+
+ last = urb->length - 1;
+ if (last >= 0) {
+ for (i = 0; i <= last; i++) {
+ td = urb->td[i];
+ if (td) {
+ td->usb_dev = NULL;
+ urb->td[i] = NULL;
+ }
+ }
+ }
+ free(urb);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+static int sohci_get_current_frame_number (struct usb_device * dev);
+
+/* debug| print the main components of an URB
+ * small: 0) header + data packets 1) just header */
+
+static void pkt_print (urb_priv_t *purb, struct usb_device * dev,
+ unsigned long pipe, void * buffer,
+ int transfer_len, struct devrequest * setup, char * str, int small)
+{
+ dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx",
+ str,
+ sohci_get_current_frame_number (dev),
+ usb_pipedevice (pipe),
+ usb_pipeendpoint (pipe),
+ usb_pipeout (pipe)? 'O': 'I',
+ usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
+ (usb_pipecontrol (pipe)? "CTRL": "BULK"),
+ (purb ? purb->actual_length : 0),
+ transfer_len, dev->status);
+#ifdef OHCI_VERBOSE_DEBUG
+ if (!small) {
+ int i, len;
+
+ if (usb_pipecontrol (pipe)) {
+ printf (__FILE__ ": cmd(8):");
+ for (i = 0; i < 8 ; i++)
+ printf (" %02x", ((__u8 *) setup) [i]);
+ printf ("\n");
+ }
+ if (transfer_len > 0 && buffer) {
+ printf (__FILE__ ": data(%d/%d):",
+ (purb ? purb->actual_length : 0),
+ transfer_len);
+ len = usb_pipeout (pipe)?
+ transfer_len:
+ (purb ? purb->actual_length : 0);
+ for (i = 0; i < 16 && i < len; i++)
+ printf (" %02x", ((__u8 *) buffer) [i]);
+ printf ("%s\n", i < len? "...": "");
+ }
+ }
+#endif
+}
+
+/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/
+void ep_print_int_eds (ohci_t *ohci, char * str) {
+ int i, j;
+ __u32 * ed_p;
+ for (i= 0; i < 32; i++) {
+ j = 5;
+ ed_p = &(ohci->hcca->int_table [i]);
+ if (*ed_p == 0)
+ continue;
+ printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i);
+ while (*ed_p != 0 && j--) {
+ ed_t *ed = (ed_t *)m32_swap(ed_p);
+ printf (" ed: %4x;", ed->hwINFO);
+ ed_p = &ed->hwNextED;
+ }
+ printf ("\n");
+ }
+}
+
+static void ohci_dump_intr_mask (char *label, __u32 mask)
+{
+ dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+ label,
+ mask,
+ (mask & OHCI_INTR_MIE) ? " MIE" : "",
+ (mask & OHCI_INTR_OC) ? " OC" : "",
+ (mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+ (mask & OHCI_INTR_FNO) ? " FNO" : "",
+ (mask & OHCI_INTR_UE) ? " UE" : "",
+ (mask & OHCI_INTR_RD) ? " RD" : "",
+ (mask & OHCI_INTR_SF) ? " SF" : "",
+ (mask & OHCI_INTR_WDH) ? " WDH" : "",
+ (mask & OHCI_INTR_SO) ? " SO" : ""
+ );
+}
+
+static void maybe_print_eds (char *label, __u32 value)
+{
+ ed_t *edp = (ed_t *)value;
+
+ if (value) {
+ dbg ("%s %08x", label, value);
+ dbg ("%08x", edp->hwINFO);
+ dbg ("%08x", edp->hwTailP);
+ dbg ("%08x", edp->hwHeadP);
+ dbg ("%08x", edp->hwNextED);
+ }
+}
+
+static char * hcfs2string (int state)
+{
+ switch (state) {
+ case OHCI_USB_RESET: return "reset";
+ case OHCI_USB_RESUME: return "resume";
+ case OHCI_USB_OPER: return "operational";
+ case OHCI_USB_SUSPEND: return "suspend";
+ }
+ return "?";
+}
+
+/* dump control and status registers */
+static void ohci_dump_status (ohci_t *controller)
+{
+ struct ohci_regs *regs = controller->regs;
+ __u32 temp;
+
+ temp = readl (&regs->revision) & 0xff;
+ if (temp != 0x10)
+ dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+ temp = readl (&regs->control);
+ dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+ (temp & OHCI_CTRL_RWE) ? " RWE" : "",
+ (temp & OHCI_CTRL_RWC) ? " RWC" : "",
+ (temp & OHCI_CTRL_IR) ? " IR" : "",
+ hcfs2string (temp & OHCI_CTRL_HCFS),
+ (temp & OHCI_CTRL_BLE) ? " BLE" : "",
+ (temp & OHCI_CTRL_CLE) ? " CLE" : "",
+ (temp & OHCI_CTRL_IE) ? " IE" : "",
+ (temp & OHCI_CTRL_PLE) ? " PLE" : "",
+ temp & OHCI_CTRL_CBSR
+ );
+
+ temp = readl (&regs->cmdstatus);
+ dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+ (temp & OHCI_SOC) >> 16,
+ (temp & OHCI_OCR) ? " OCR" : "",
+ (temp & OHCI_BLF) ? " BLF" : "",
+ (temp & OHCI_CLF) ? " CLF" : "",
+ (temp & OHCI_HCR) ? " HCR" : ""
+ );
+
+ ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
+ ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+
+ maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+ maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+ maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+ maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+ maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+ maybe_print_eds ("donehead", readl (&regs->donehead));
+}
+
+static void ohci_dump_roothub (ohci_t *controller, int verbose)
+{
+ __u32 temp, ndp, i;
+
+ temp = roothub_a (controller);
+ ndp = (temp & RH_A_NDP);
+#ifdef CONFIG_AT91C_PQFP_UHPBUG
+ ndp = (ndp == 2) ? 1:0;
+#endif
+ if (verbose) {
+ dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+ ((temp & RH_A_POTPGT) >> 24) & 0xff,
+ (temp & RH_A_NOCP) ? " NOCP" : "",
+ (temp & RH_A_OCPM) ? " OCPM" : "",
+ (temp & RH_A_DT) ? " DT" : "",
+ (temp & RH_A_NPS) ? " NPS" : "",
+ (temp & RH_A_PSM) ? " PSM" : "",
+ ndp
+ );
+ temp = roothub_b (controller);
+ dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
+ temp,
+ (temp & RH_B_PPCM) >> 16,
+ (temp & RH_B_DR)
+ );
+ temp = roothub_status (controller);
+ dbg ("roothub.status: %08x%s%s%s%s%s%s",
+ temp,
+ (temp & RH_HS_CRWE) ? " CRWE" : "",
+ (temp & RH_HS_OCIC) ? " OCIC" : "",
+ (temp & RH_HS_LPSC) ? " LPSC" : "",
+ (temp & RH_HS_DRWE) ? " DRWE" : "",
+ (temp & RH_HS_OCI) ? " OCI" : "",
+ (temp & RH_HS_LPS) ? " LPS" : ""
+ );
+ }
+
+ for (i = 0; i < ndp; i++) {
+ temp = roothub_portstatus (controller, i);
+ dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
+ i,
+ temp,
+ (temp & RH_PS_PRSC) ? " PRSC" : "",
+ (temp & RH_PS_OCIC) ? " OCIC" : "",
+ (temp & RH_PS_PSSC) ? " PSSC" : "",
+ (temp & RH_PS_PESC) ? " PESC" : "",
+ (temp & RH_PS_CSC) ? " CSC" : "",
+
+ (temp & RH_PS_LSDA) ? " LSDA" : "",
+ (temp & RH_PS_PPS) ? " PPS" : "",
+ (temp & RH_PS_PRS) ? " PRS" : "",
+ (temp & RH_PS_POCI) ? " POCI" : "",
+ (temp & RH_PS_PSS) ? " PSS" : "",
+
+ (temp & RH_PS_PES) ? " PES" : "",
+ (temp & RH_PS_CCS) ? " CCS" : ""
+ );
+ }
+}
+
+static void ohci_dump (ohci_t *controller, int verbose)
+{
+ dbg ("OHCI controller usb-%s state", controller->slot_name);
+
+ /* dumps some of the state we know about */
+ ohci_dump_status (controller);
+ if (verbose)
+ ep_print_int_eds (controller, "hcca");
+ dbg ("hcca frame #%04x", controller->hcca->frame_no);
+ ohci_dump_roothub (controller, 1);
+
+#endif /* DEBUG */
+
+/*-------------------------------------------------------------------------*
+ * Interface functions (URB)
+ *-------------------------------------------------------------------------*/
+
+/* get a transfer request */
+
+int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup)
+{
+ ohci_t *ohci;
+ ed_t * ed;
+ urb_priv_t *purb_priv = urb;
+ int i, size = 0;
+ struct usb_device *dev = urb->dev;
+ unsigned long pipe = urb->pipe;
+ void *buffer = urb->transfer_buffer;
+ int transfer_len = urb->transfer_buffer_length;
+ int interval = urb->interval;
+
+ ohci = &gohci;
+
+ /* when controller's hung, permit only roothub cleanup attempts
+ * such as powering down ports */
+ if (ohci->disabled) {
+ err("sohci_submit_job: EPIPE");
+ return -1;
+ }
+
+ /* we're about to begin a new transaction here so mark the URB unfinished */
+ urb->finished = 0;
+
+ /* every endpoint has a ed, locate and fill it */
+ if (!(ed = ep_add_ed (dev, pipe, interval, 1))) {
+ err("sohci_submit_job: ENOMEM");
+ return -1;
+ }
+
+ /* for the private part of the URB we need the number of TDs (size) */
+ switch (usb_pipetype (pipe)) {
+ case PIPE_BULK: /* one TD for every 4096 Byte */
+ size = (transfer_len - 1) / 4096 + 1;
+ break;
+ case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
+ size = (transfer_len == 0)? 2:
+ (transfer_len - 1) / 4096 + 3;
+ break;
+ case PIPE_INTERRUPT: /* 1 TD */
+ size = 1;
+ break;
+ }
+
+ ed->purb = urb;
+
+ if (size >= (N_URB_TD - 1)) {
+ err("need %d TDs, only have %d", size, N_URB_TD);
+ return -1;
+ }
+ purb_priv->pipe = pipe;
+
+ /* fill the private part of the URB */
+ purb_priv->length = size;
+ purb_priv->ed = ed;
+ purb_priv->actual_length = 0;
+
+ /* allocate the TDs */
+ /* note that td[0] was allocated in ep_add_ed */
+ for (i = 0; i < size; i++) {
+ purb_priv->td[i] = td_alloc (dev);
+ if (!purb_priv->td[i]) {
+ purb_priv->length = i;
+ urb_free_priv (purb_priv);
+ err("sohci_submit_job: ENOMEM");
+ return -1;
+ }
+ }
+
+ if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
+ urb_free_priv (purb_priv);
+ err("sohci_submit_job: EINVAL");
+ return -1;
+ }
+
+ /* link the ed into a chain if is not already */
+ if (ed->state != ED_OPER)
+ ep_link (ohci, ed);
+
+ /* fill the TDs and link it to the ed */
+ td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval);
+
+ return 0;
+}
+
+static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb)
+{
+ struct ohci_regs *regs = hc->regs;
+
+ switch (usb_pipetype (urb->pipe)) {
+ case PIPE_INTERRUPT:
+ /* implicitly requeued */
+ if (urb->dev->irq_handle &&
+ (urb->dev->irq_act_len = urb->actual_length)) {
+ writel (OHCI_INTR_WDH, &regs->intrenable);
+ readl (&regs->intrenable); /* PCI posting flush */
+ urb->dev->irq_handle(urb->dev);
+ writel (OHCI_INTR_WDH, &regs->intrdisable);
+ readl (&regs->intrdisable); /* PCI posting flush */
+ }
+ urb->actual_length = 0;
+ td_submit_job (
+ urb->dev,
+ urb->pipe,
+ urb->transfer_buffer,
+ urb->transfer_buffer_length,
+ NULL,
+ urb,
+ urb->interval);
+ break;
+ case PIPE_CONTROL:
+ case PIPE_BULK:
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+/* tell us the current USB frame number */
+
+static int sohci_get_current_frame_number (struct usb_device *usb_dev)
+{
+ ohci_t *ohci = &gohci;
+
+ return m16_swap (ohci->hcca->frame_no);
+}
+#endif
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* search for the right branch to insert an interrupt ed into the int tree
+ * do some load ballancing;
+ * returns the branch and
+ * sets the interval to interval = 2^integer (ld (interval)) */
+
+static int ep_int_ballance (ohci_t * ohci, int interval, int load)
+{
+ int i, branch = 0;
+
+ /* search for the least loaded interrupt endpoint
+ * branch of all 32 branches
+ */
+ for (i = 0; i < 32; i++)
+ if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i])
+ branch = i;
+
+ branch = branch % interval;
+ for (i = branch; i < 32; i += interval)
+ ohci->ohci_int_load [i] += load;
+
+ return branch;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* 2^int( ld (inter)) */
+
+static int ep_2_n_interval (int inter)
+{
+ int i;
+ for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++);
+ return 1 << i;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* the int tree is a binary tree
+ * in order to process it sequentially the indexes of the branches have to be mapped
+ * the mapping reverses the bits of a word of num_bits length */
+
+static int ep_rev (int num_bits, int word)
+{
+ int i, wout = 0;
+
+ for (i = 0; i < num_bits; i++)
+ wout |= (((word >> i) & 1) << (num_bits - i - 1));
+ return wout;
+}
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link (ohci_t *ohci, ed_t *edi)
+{
+ volatile ed_t *ed = edi;
+ int int_branch;
+ int i;
+ int inter;
+ int interval;
+ int load;
+ __u32 * ed_p;
+
+ ed->state = ED_OPER;
+ ed->int_interval = 0;
+
+ switch (ed->type) {
+ case PIPE_CONTROL:
+ ed->hwNextED = 0;
+ if (ohci->ed_controltail == NULL) {
+ writel (ed, &ohci->regs->ed_controlhead);
+ } else {
+ ohci->ed_controltail->hwNextED = m32_swap ((unsigned long)ed);
+ }
+ ed->ed_prev = ohci->ed_controltail;
+ if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
+ !ohci->ed_rm_list[1] && !ohci->sleeping) {
+ ohci->hc_control |= OHCI_CTRL_CLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ ohci->ed_controltail = edi;
+ break;
+
+ case PIPE_BULK:
+ ed->hwNextED = 0;
+ if (ohci->ed_bulktail == NULL) {
+ writel (ed, &ohci->regs->ed_bulkhead);
+ } else {
+ ohci->ed_bulktail->hwNextED = m32_swap ((unsigned long)ed);
+ }
+ ed->ed_prev = ohci->ed_bulktail;
+ if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
+ !ohci->ed_rm_list[1] && !ohci->sleeping) {
+ ohci->hc_control |= OHCI_CTRL_BLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ ohci->ed_bulktail = edi;
+ break;
+
+ case PIPE_INTERRUPT:
+ load = ed->int_load;
+ interval = ep_2_n_interval (ed->int_period);
+ ed->int_interval = interval;
+ int_branch = ep_int_ballance (ohci, interval, load);
+ ed->int_branch = int_branch;
+
+ for (i = 0; i < ep_rev (6, interval); i += inter) {
+ inter = 1;
+ for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]);
+ (*ed_p != 0) && (((ed_t *)ed_p)->int_interval >= interval);
+ ed_p = &(((ed_t *)ed_p)->hwNextED))
+ inter = ep_rev (6, ((ed_t *)ed_p)->int_interval);
+ ed->hwNextED = *ed_p;
+ *ed_p = m32_swap((unsigned long)ed);
+ }
+ break;
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* scan the periodic table to find and unlink this ED */
+static void periodic_unlink ( struct ohci *ohci, volatile struct ed *ed,
+ unsigned index, unsigned period)
+{
+ for (; index < NUM_INTS; index += period) {
+ __u32 *ed_p = &ohci->hcca->int_table [index];
+
+ /* ED might have been unlinked through another path */
+ while (*ed_p != 0) {
+ if (((struct ed *)m32_swap ((unsigned long)ed_p)) == ed) {
+ *ed_p = ed->hwNextED;
+ break;
+ }
+ ed_p = & (((struct ed *)m32_swap ((unsigned long)ed_p))->hwNextED);
+ }
+ }
+}
+
+/* unlink an ed from one of the HC chains.
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed */
+
+static int ep_unlink (ohci_t *ohci, ed_t *edi)
+{
+ volatile ed_t *ed = edi;
+ int i;
+
+ ed->hwINFO |= m32_swap (OHCI_ED_SKIP);
+
+ switch (ed->type) {
+ case PIPE_CONTROL:
+ if (ed->ed_prev == NULL) {
+ if (!ed->hwNextED) {
+ ohci->hc_control &= ~OHCI_CTRL_CLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead);
+ } else {
+ ed->ed_prev->hwNextED = ed->hwNextED;
+ }
+ if (ohci->ed_controltail == ed) {
+ ohci->ed_controltail = ed->ed_prev;
+ } else {
+ ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+ }
+ break;
+
+ case PIPE_BULK:
+ if (ed->ed_prev == NULL) {
+ if (!ed->hwNextED) {
+ ohci->hc_control &= ~OHCI_CTRL_BLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead);
+ } else {
+ ed->ed_prev->hwNextED = ed->hwNextED;
+ }
+ if (ohci->ed_bulktail == ed) {
+ ohci->ed_bulktail = ed->ed_prev;
+ } else {
+ ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+ }
+ break;
+
+ case PIPE_INTERRUPT:
+ periodic_unlink (ohci, ed, 0, 1);
+ for (i = ed->int_branch; i < 32; i += ed->int_interval)
+ ohci->ohci_int_load[i] -= ed->int_load;
+ break;
+ }
+ ed->state = ED_UNLINK;
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* add/reinit an endpoint; this should be done once at the
+ * usb_set_configuration command, but the USB stack is a little bit
+ * stateless so we do it at every transaction if the state of the ed
+ * is ED_NEW then a dummy td is added and the state is changed to
+ * ED_UNLINK in all other cases the state is left unchanged the ed
+ * info fields are setted anyway even though most of them should not
+ * change
+ */
+static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe,
+ int interval, int load)
+{
+ td_t *td;
+ ed_t *ed_ret;
+ volatile ed_t *ed;
+
+ ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) |
+ (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))];
+
+ if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+ err("ep_add_ed: pending delete");
+ /* pending delete request */
+ return NULL;
+ }
+
+ if (ed->state == ED_NEW) {
+ ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */
+ /* dummy td; end of td list for ed */
+ td = td_alloc (usb_dev);
+ ed->hwTailP = m32_swap ((unsigned long)td);
+ ed->hwHeadP = ed->hwTailP;
+ ed->state = ED_UNLINK;
+ ed->type = usb_pipetype (pipe);
+ ohci_dev.ed_cnt++;
+ }
+
+ ed->hwINFO = m32_swap (usb_pipedevice (pipe)
+ | usb_pipeendpoint (pipe) << 7
+ | (usb_pipeisoc (pipe)? 0x8000: 0)
+ | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
+ | usb_pipeslow (pipe) << 13
+ | usb_maxpacket (usb_dev, pipe) << 16);
+
+ if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
+ ed->int_period = interval;
+ ed->int_load = load;
+ }
+
+ return ed_ret;
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void td_fill (ohci_t *ohci, unsigned int info,
+ void *data, int len,
+ struct usb_device *dev, int index, urb_priv_t *urb_priv)
+{
+ volatile td_t *td, *td_pt;
+#ifdef OHCI_FILL_TRACE
+ int i;
+#endif
+
+ if (index > urb_priv->length) {
+ err("index > length");
+ return;
+ }
+ /* use this td as the next dummy */
+ td_pt = urb_priv->td [index];
+ td_pt->hwNextTD = 0;
+
+ /* fill the old dummy TD */
+ td = urb_priv->td [index] = (td_t *)(m32_swap (urb_priv->ed->hwTailP) & ~0xf);
+
+ td->ed = urb_priv->ed;
+ td->next_dl_td = NULL;
+ td->index = index;
+ td->data = (__u32)data;
+#ifdef OHCI_FILL_TRACE
+ if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe)) {
+ for (i = 0; i < len; i++)
+ printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]);
+ printf("\n");
+ }
+#endif
+ if (!len)
+ data = 0;
+
+ td->hwINFO = m32_swap (info);
+ td->hwCBP = m32_swap ((unsigned long)data);
+ if (data)
+ td->hwBE = m32_swap ((unsigned long)(data + len - 1));
+ else
+ td->hwBE = 0;
+ td->hwNextTD = m32_swap ((unsigned long)td_pt);
+
+ /* append to queue */
+ td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+
+static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval)
+{
+ ohci_t *ohci = &gohci;
+ int data_len = transfer_len;
+ void *data;
+ int cnt = 0;
+ __u32 info = 0;
+ unsigned int toggle = 0;
+
+ /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
+ if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
+ toggle = TD_T_TOGGLE;
+ } else {
+ toggle = TD_T_DATA0;
+ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
+ }
+ urb->td_cnt = 0;
+ if (data_len)
+ data = buffer;
+ else
+ data = 0;
+
+ switch (usb_pipetype (pipe)) {
+ case PIPE_BULK:
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
+ while(data_len > 4096) {
+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb);
+ data += 4096; data_len -= 4096; cnt++;
+ }
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb);
+ cnt++;
+
+ if (!ohci->sleeping)
+ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+ break;
+
+ case PIPE_CONTROL:
+ info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+ td_fill (ohci, info, setup, 8, dev, cnt++, urb);
+ if (data_len > 0) {
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
+ /* NOTE: mishandles transfers >8K, some >4K */
+ td_fill (ohci, info, data, data_len, dev, cnt++, urb);
+ }
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
+ td_fill (ohci, info, data, 0, dev, cnt++, urb);
+ if (!ohci->sleeping)
+ writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+ break;
+
+ case PIPE_INTERRUPT:
+ info = usb_pipeout (urb->pipe)?
+ TD_CC | TD_DP_OUT | toggle:
+ TD_CC | TD_R | TD_DP_IN | toggle;
+ td_fill (ohci, info, data, data_len, dev, cnt++, urb);
+ break;
+ }
+ if (urb->length != cnt)
+ dbg("TD LENGTH %d != CNT %d", urb->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t * td)
+{
+ __u32 tdINFO, tdBE, tdCBP;
+ urb_priv_t *lurb_priv = td->ed->purb;
+
+ tdINFO = m32_swap (td->hwINFO);
+ tdBE = m32_swap (td->hwBE);
+ tdCBP = m32_swap (td->hwCBP);
+
+ if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL &&
+ ((td->index == 0) || (td->index == lurb_priv->length - 1)))) {
+ if (tdBE != 0) {
+ if (td->hwCBP == 0)
+ lurb_priv->actual_length += tdBE - td->data + 1;
+ else
+ lurb_priv->actual_length += tdCBP - td->data;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+
+static td_t * dl_reverse_done_list (ohci_t *ohci)
+{
+ __u32 td_list_hc;
+ td_t *td_rev = NULL;
+ td_t *td_list = NULL;
+ urb_priv_t *lurb_priv = NULL;
+
+ td_list_hc = m32_swap (ohci->hcca->done_head) & 0xfffffff0;
+ ohci->hcca->done_head = 0;
+
+ while (td_list_hc) {
+ td_list = (td_t *)td_list_hc;
+
+ if (TD_CC_GET (m32_swap (td_list->hwINFO))) {
+ lurb_priv = td_list->ed->purb;
+ dbg(" USB-error/status: %x : %p",
+ TD_CC_GET (m32_swap (td_list->hwINFO)), td_list);
+ if (td_list->ed->hwHeadP & m32_swap (0x1)) {
+ if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) {
+ td_list->ed->hwHeadP =
+ (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & m32_swap (0xfffffff0)) |
+ (td_list->ed->hwHeadP & m32_swap (0x2));
+ lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1;
+ } else
+ td_list->ed->hwHeadP &= m32_swap (0xfffffff2);
+ }
+#ifdef CONFIG_MPC5200
+ td_list->hwNextTD = 0;
+#endif
+ }
+
+ td_list->next_dl_td = td_rev;
+ td_rev = td_list;
+ td_list_hc = m32_swap (td_list->hwNextTD) & 0xfffffff0;
+ }
+ return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* td done list */
+static int dl_done_list (ohci_t *ohci, td_t *td_list)
+{
+ td_t *td_list_next = NULL;
+ ed_t *ed;
+ int cc = 0;
+ int stat = 0;
+ /* urb_t *urb; */
+ urb_priv_t *lurb_priv;
+ __u32 tdINFO, edHeadP, edTailP;
+
+ while (td_list) {
+ td_list_next = td_list->next_dl_td;
+
+ tdINFO = m32_swap (td_list->hwINFO);
+
+ ed = td_list->ed;
+ lurb_priv = ed->purb;
+
+ dl_transfer_length(td_list);
+
+ /* error code of transfer */
+ cc = TD_CC_GET (tdINFO);
+ if (cc != 0) {
+ dbg("ConditionCode %#x", cc);
+ stat = cc_to_error[cc];
+ }
+
+ /* see if this done list makes for all TD's of current URB,
+ * and mark the URB finished if so */
+ if (++(lurb_priv->td_cnt) == lurb_priv->length) {
+#if 1
+ if ((ed->state & (ED_OPER | ED_UNLINK)) &&
+ (lurb_priv->state != URB_DEL))
+#else
+ if ((ed->state & (ED_OPER | ED_UNLINK)))
+#endif
+ lurb_priv->finished = sohci_return_job(ohci,
+ lurb_priv);
+ else
+ dbg("dl_done_list: strange.., ED state %x, ed->state\n");
+ } else
+ dbg("dl_done_list: processing TD %x, len %x\n", lurb_priv->td_cnt,
+ lurb_priv->length);
+ if (ed->state != ED_NEW &&
+ (usb_pipetype (lurb_priv->pipe) != PIPE_INTERRUPT)) {
+ edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0;
+ edTailP = m32_swap (ed->hwTailP);
+
+ /* unlink eds if they are not busy */
+ if ((edHeadP == edTailP) && (ed->state == ED_OPER))
+ ep_unlink (ohci, ed);
+ }
+
+ td_list = td_list_next;
+ }
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x01, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+ 28, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'O', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'C', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'I', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+/* Hub class-specific descriptor is constructed dynamically */
+
+/*-------------------------------------------------------------------------*/
+
+#define OK(x) len = (x); break
+#ifdef DEBUG
+#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);}
+#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);}
+#else
+#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status)
+#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1])
+#endif
+#define RD_RH_STAT roothub_status(&gohci)
+#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1)
+
+/* request to virtual root hub */
+
+int rh_check_port_status(ohci_t *controller)
+{
+ __u32 temp, ndp, i;
+ int res;
+
+ res = -1;
+ temp = roothub_a (controller);
+ ndp = (temp & RH_A_NDP);
+#ifdef CONFIG_AT91C_PQFP_UHPBUG
+ ndp = (ndp == 2) ? 1:0;
+#endif
+ for (i = 0; i < ndp; i++) {
+ temp = roothub_portstatus (controller, i);
+ /* check for a device disconnect */
+ if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+ (RH_PS_PESC | RH_PS_CSC)) &&
+ ((temp & RH_PS_CCS) == 0)) {
+ res = i;
+ break;
+ }
+ }
+ return res;
+}
+
+static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len, struct devrequest *cmd)
+{
+ void * data = buffer;
+ int leni = transfer_len;
+ int len = 0;
+ int stat = 0;
+ __u32 datab[4];
+ __u8 *data_buf = (__u8 *)datab;
+ __u16 bmRType_bReq;
+ __u16 wValue;
+ __u16 wIndex;
+ __u16 wLength;
+
+#ifdef DEBUG
+pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
+#else
+ wait_ms(1);
+#endif
+ if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
+ info("Root-Hub submit IRQ: NOT implemented");
+ return 0;
+ }
+
+ bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+ wValue = cpu_to_le16 (cmd->value);
+ wIndex = cpu_to_le16 (cmd->index);
+ wLength = cpu_to_le16 (cmd->length);
+
+ info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
+ dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
+
+ switch (bmRType_bReq) {
+ /* Request Destination:
+ without flags: Device,
+ RH_INTERFACE: interface,
+ RH_ENDPOINT: endpoint,
+ RH_CLASS means HUB here,
+ RH_OTHER | RH_CLASS almost ever means HUB_PORT here
+ */
+
+ case RH_GET_STATUS:
+ *(__u16 *) data_buf = cpu_to_le16 (1); OK (2);
+ case RH_GET_STATUS | RH_INTERFACE:
+ *(__u16 *) data_buf = cpu_to_le16 (0); OK (2);
+ case RH_GET_STATUS | RH_ENDPOINT:
+ *(__u16 *) data_buf = cpu_to_le16 (0); OK (2);
+ case RH_GET_STATUS | RH_CLASS:
+ *(__u32 *) data_buf = cpu_to_le32 (
+ RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
+ OK (4);
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4);
+
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ switch (wValue) {
+ case (RH_ENDPOINT_STALL): OK (0);
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ switch (wValue) {
+ case RH_C_HUB_LOCAL_POWER:
+ OK(0);
+ case (RH_C_HUB_OVER_CURRENT):
+ WR_RH_STAT(RH_HS_OCIC); OK (0);
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_ENABLE):
+ WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
+ case (RH_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
+ case (RH_PORT_POWER):
+ WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
+ case (RH_C_PORT_CONNECTION):
+ WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
+ case (RH_C_PORT_ENABLE):
+ WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
+ case (RH_C_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
+ case (RH_C_PORT_OVER_CURRENT):
+ WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
+ case (RH_C_PORT_RESET):
+ WR_RH_PORTSTAT (RH_PS_PRSC); OK (0);
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_PSS ); OK (0);
+ case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
+ if (RD_RH_PORTSTAT & RH_PS_CCS)
+ WR_RH_PORTSTAT (RH_PS_PRS);
+ OK (0);
+ case (RH_PORT_POWER):
+ WR_RH_PORTSTAT (RH_PS_PPS );
+ wait_ms(100);
+ OK (0);
+ case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
+ if (RD_RH_PORTSTAT & RH_PS_CCS)
+ WR_RH_PORTSTAT (RH_PS_PES );
+ OK (0);
+ }
+ break;
+
+ case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0);
+
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case (0x01): /* device descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_dev_des),
+ wLength));
+ data_buf = root_hub_dev_des; OK(len);
+ case (0x02): /* configuration descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_config_des),
+ wLength));
+ data_buf = root_hub_config_des; OK(len);
+ case (0x03): /* string descriptors */
+ if(wValue==0x0300) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_str_index0),
+ wLength));
+ data_buf = root_hub_str_index0;
+ OK(len);
+ }
+ if(wValue==0x0301) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_str_index1),
+ wLength));
+ data_buf = root_hub_str_index1;
+ OK(len);
+ }
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ {
+ __u32 temp = roothub_a (&gohci);
+
+ data_buf [0] = 9; /* min length; */
+ data_buf [1] = 0x29;
+ data_buf [2] = temp & RH_A_NDP;
+#ifdef CONFIG_AT91C_PQFP_UHPBUG
+ data_buf [2] = (data_buf [2] == 2) ? 1:0;
+#endif
+ data_buf [3] = 0;
+ if (temp & RH_A_PSM) /* per-port power switching? */
+ data_buf [3] |= 0x1;
+ if (temp & RH_A_NOCP) /* no overcurrent reporting? */
+ data_buf [3] |= 0x10;
+ else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */
+ data_buf [3] |= 0x8;
+
+ /* corresponds to data_buf[4-7] */
+ datab [1] = 0;
+ data_buf [5] = (temp & RH_A_POTPGT) >> 24;
+ temp = roothub_b (&gohci);
+ data_buf [7] = temp & RH_B_DR;
+ if (data_buf [2] < 7) {
+ data_buf [8] = 0xff;
+ } else {
+ data_buf [0] += 2;
+ data_buf [8] = (temp & RH_B_DR) >> 8;
+ data_buf [10] = data_buf [9] = 0xff;
+ }
+
+ len = min_t(unsigned int, leni,
+ min_t(unsigned int, data_buf [0], wLength));
+ OK (len);
+ }
+
+ case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1);
+
+ case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0);
+
+ default:
+ dbg ("unsupported root hub command");
+ stat = USB_ST_STALLED;
+ }
+
+#ifdef DEBUG
+ ohci_dump_roothub (&gohci, 1);
+#else
+ wait_ms(1);
+#endif
+
+ len = min_t(int, len, leni);
+ if (data != data_buf)
+ memcpy (data, data_buf, len);
+ dev->act_len = len;
+ dev->status = stat;
+
+#ifdef DEBUG
+ pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
+#else
+ wait_ms(1);
+#endif
+
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* common code for handling submit messages - used for all but root hub */
+/* accesses. */
+int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, int interval)
+{
+ int stat = 0;
+ int maxsize = usb_maxpacket(dev, pipe);
+ int timeout;
+ urb_priv_t *urb;
+
+ urb = malloc(sizeof(urb_priv_t));
+ memset(urb, 0, sizeof(urb_priv_t));
+
+ urb->dev = dev;
+ urb->pipe = pipe;
+ urb->transfer_buffer = buffer;
+ urb->transfer_buffer_length = transfer_len;
+ urb->interval = interval;
+
+ /* device pulled? Shortcut the action. */
+ if (devgone == dev) {
+ dev->status = USB_ST_CRC_ERR;
+ return 0;
+ }
+
+#ifdef DEBUG
+ urb->actual_length = 0;
+ pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#else
+ wait_ms(1);
+#endif
+ if (!maxsize) {
+ err("submit_common_message: pipesize for pipe %lx is zero",
+ pipe);
+ return -1;
+ }
+
+ if (sohci_submit_job(urb, setup) < 0) {
+ err("sohci_submit_job failed");
+ return -1;
+ }
+
+#if 0
+ wait_ms(10);
+ /* ohci_dump_status(&gohci); */
+#endif
+
+ /* allow more time for a BULK device to react - some are slow */
+#define BULK_TO 5000 /* timeout in milliseconds */
+ if (usb_pipetype (pipe) == PIPE_BULK)
+ timeout = BULK_TO;
+ else
+ timeout = 100;
+
+ /* wait for it to complete */
+ for (;;) {
+ /* check whether the controller is done */
+ stat = hc_interrupt();
+ if (stat < 0) {
+ stat = USB_ST_CRC_ERR;
+ break;
+ }
+
+ /* NOTE: since we are not interrupt driven in U-Boot and always
+ * handle only one URB at a time, we cannot assume the
+ * transaction finished on the first successful return from
+ * hc_interrupt().. unless the flag for current URB is set,
+ * meaning that all TD's to/from device got actually
+ * transferred and processed. If the current URB is not
+ * finished we need to re-iterate this loop so as
+ * hc_interrupt() gets called again as there needs to be some
+ * more TD's to process still */
+ if ((stat >= 0) && (stat != 0xff) && (urb->finished)) {
+ /* 0xff is returned for an SF-interrupt */
+ break;
+ }
+
+ if (--timeout) {
+ wait_ms(1);
+ if (!urb->finished)
+ dbg("\%");
+
+ } else {
+ err("CTL:TIMEOUT ");
+ dbg("submit_common_msg: TO status %x\n", stat);
+ urb->finished = 1;
+ stat = USB_ST_CRC_ERR;
+ break;
+ }
+ }
+
+ dev->status = stat;
+ dev->act_len = transfer_len;
+
+#ifdef DEBUG
+ pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
+#else
+ wait_ms(1);
+#endif
+
+ /* free TDs in urb_priv */
+ if (usb_pipetype (pipe) != PIPE_INTERRUPT)
+ urb_free_priv (urb);
+ return 0;
+}
+
+/* submit routines called from usb.c */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len)
+{
+ info("submit_bulk_msg");
+ return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup)
+{
+ int maxsize = usb_maxpacket(dev, pipe);
+
+ info("submit_control_msg");
+#ifdef DEBUG
+ pkt_print(NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#else
+ wait_ms(1);
+#endif
+ if (!maxsize) {
+ err("submit_control_message: pipesize for pipe %lx is zero",
+ pipe);
+ return -1;
+ }
+ if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {
+ gohci.rh.dev = dev;
+ /* root hub - redirect */
+ return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
+ setup);
+ }
+
+ return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, int interval)
+{
+ info("submit_int_msg");
+ return submit_common_msg(dev, pipe, buffer, transfer_len, NULL,
+ interval);
+}
+
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset (ohci_t *ohci)
+{
+ int timeout = 30;
+ int smm_timeout = 50; /* 0,5 sec */
+
+ dbg("%s\n", __FUNCTION__);
+
+ if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
+ writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
+ info("USB HC TakeOver from SMM");
+ while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+ wait_ms (10);
+ if (--smm_timeout == 0) {
+ err("USB HC TakeOver failed!");
+ return -1;
+ }
+ }
+ }
+
+ /* Disable HC interrupts */
+ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+ dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n",
+ ohci->slot_name,
+ readl(&ohci->regs->control));
+
+ /* Reset USB (needed by some controllers) */
+ ohci->hc_control = 0;
+ writel (ohci->hc_control, &ohci->regs->control);
+
+ /* HC Reset requires max 10 us delay */
+ writel (OHCI_HCR, &ohci->regs->cmdstatus);
+ while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+ if (--timeout == 0) {
+ err("USB HC reset timed out!");
+ return -1;
+ }
+ udelay (1);
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts
+ * connect the virtual root hub */
+
+static int hc_start (ohci_t * ohci)
+{
+ __u32 mask;
+ unsigned int fminterval;
+
+ ohci->disabled = 1;
+
+ /* Tell the controller where the control and bulk lists are
+ * The lists are empty now. */
+
+ writel (0, &ohci->regs->ed_controlhead);
+ writel (0, &ohci->regs->ed_bulkhead);
+
+ writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
+
+ fminterval = 0x2edf;
+ writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
+ fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
+ writel (fminterval, &ohci->regs->fminterval);
+ writel (0x628, &ohci->regs->lsthresh);
+
+ /* start controller operations */
+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+ ohci->disabled = 0;
+ writel (ohci->hc_control, &ohci->regs->control);
+
+ /* disable all interrupts */
+ mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
+ OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
+ OHCI_INTR_OC | OHCI_INTR_MIE);
+ writel (mask, &ohci->regs->intrdisable);
+ /* clear all interrupts */
+ mask &= ~OHCI_INTR_MIE;
+ writel (mask, &ohci->regs->intrstatus);
+ /* Choose the interrupts we care about now - but w/o MIE */
+ mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
+ writel (mask, &ohci->regs->intrenable);
+
+#ifdef OHCI_USE_NPS
+ /* required for AMD-756 and some Mac platforms */
+ writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+ &ohci->regs->roothub.a);
+ writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif /* OHCI_USE_NPS */
+
+#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);})
+ /* POTPGT delay is bits 24-31, in 2 ms units. */
+ mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+
+ /* connect the virtual root hub */
+ ohci->rh.devnum = 0;
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Poll USB interrupt. */
+void usb_event_poll(void)
+{
+ hc_interrupt();
+}
+
+/* an interrupt happens */
+
+static int hc_interrupt (void)
+{
+ ohci_t *ohci = &gohci;
+ struct ohci_regs *regs = ohci->regs;
+ int ints;
+ int stat = -1;
+
+ if ((ohci->hcca->done_head != 0) &&
+ !(m32_swap (ohci->hcca->done_head) & 0x01)) {
+ ints = OHCI_INTR_WDH;
+ } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+ ohci->disabled++;
+ err ("%s device removed!", ohci->slot_name);
+ return -1;
+ } else if ((ints &= readl (&regs->intrenable)) == 0) {
+ dbg("hc_interrupt: returning..\n");
+ return 0xff;
+ }
+
+ /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
+
+ if (ints & OHCI_INTR_RHSC) {
+ got_rhsc = 1;
+ stat = 0xff;
+ }
+
+ if (ints & OHCI_INTR_UE) {
+ ohci->disabled++;
+ err ("OHCI Unrecoverable Error, controller usb-%s disabled",
+ ohci->slot_name);
+ /* e.g. due to PCI Master/Target Abort */
+
+#ifdef DEBUG
+ ohci_dump (ohci, 1);
+#else
+ wait_ms(1);
+#endif
+ /* FIXME: be optimistic, hope that bug won't repeat often. */
+ /* Make some non-interrupt context restart the controller. */
+ /* Count and limit the retries though; either hardware or */
+ /* software errors can go forever... */
+ hc_reset (ohci);
+ return -1;
+ }
+
+ if (ints & OHCI_INTR_WDH) {
+ wait_ms(1);
+ writel (OHCI_INTR_WDH, &regs->intrdisable);
+ (void)readl (&regs->intrdisable); /* flush */
+ stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
+ writel (OHCI_INTR_WDH, &regs->intrenable);
+ (void)readl (&regs->intrdisable); /* flush */
+ }
+
+ if (ints & OHCI_INTR_SO) {
+ dbg("USB Schedule overrun\n");
+ writel (OHCI_INTR_SO, &regs->intrenable);
+ stat = -1;
+ }
+
+ /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */
+ if (ints & OHCI_INTR_SF) {
+ unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1;
+ wait_ms(1);
+ writel (OHCI_INTR_SF, &regs->intrdisable);
+ if (ohci->ed_rm_list[frame] != NULL)
+ writel (OHCI_INTR_SF, &regs->intrenable);
+ stat = 0xff;
+ }
+
+ writel (ints, &regs->intrstatus);
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+
+/* De-allocate all resources.. */
+
+static void hc_release_ohci (ohci_t *ohci)
+{
+ dbg ("USB HC release ohci usb-%s", ohci->slot_name);
+
+ if (!ohci->disabled)
+ hc_reset (ohci);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * low level initalisation routine, called from usb.c
+ */
+static char ohci_inited = 0;
+
+int usb_lowlevel_init(void)
+{
+#ifdef CONFIG_PCI_OHCI
+ pci_dev_t pdev;
+#endif
+
+#ifdef CFG_USB_OHCI_CPU_INIT
+ /* cpu dependant init */
+ if(usb_cpu_init())
+ return -1;
+#endif
+
+#ifdef CFG_USB_OHCI_BOARD_INIT
+ /* board dependant init */
+ if(usb_board_init())
+ return -1;
+#endif
+ memset (&gohci, 0, sizeof (ohci_t));
+
+ /* align the storage */
+ if ((__u32)&ghcca[0] & 0xff) {
+ err("HCCA not aligned!!");
+ return -1;
+ }
+ phcca = &ghcca[0];
+ info("aligned ghcca %p", phcca);
+ memset(&ohci_dev, 0, sizeof(struct ohci_device));
+ if ((__u32)&ohci_dev.ed[0] & 0x7) {
+ err("EDs not aligned!!");
+ return -1;
+ }
+ memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));
+ if ((__u32)gtd & 0x7) {
+ err("TDs not aligned!!");
+ return -1;
+ }
+ ptd = gtd;
+ gohci.hcca = phcca;
+ memset (phcca, 0, sizeof (struct ohci_hcca));
+
+ gohci.disabled = 1;
+ gohci.sleeping = 0;
+ gohci.irq = -1;
+#ifdef CONFIG_PCI_OHCI
+ pdev = pci_find_devices(ohci_pci_ids, 0);
+
+ if (pdev != -1) {
+ u16 vid, did;
+ u32 base;
+ pci_read_config_word(pdev, PCI_VENDOR_ID, &vid);
+ pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
+ printf("OHCI pci controller (%04x, %04x) found @(%d:%d:%d)\n",
+ vid, did, (pdev >> 16) & 0xff,
+ (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base);
+ printf("OHCI regs address 0x%08x\n", base);
+ gohci.regs = (struct ohci_regs *)base;
+ } else
+ return -1;
+#else
+ gohci.regs = (struct ohci_regs *)CFG_USB_OHCI_REGS_BASE;
+#endif
+
+ gohci.flags = 0;
+ gohci.slot_name = CFG_USB_OHCI_SLOT_NAME;
+
+ if (hc_reset (&gohci) < 0) {
+ hc_release_ohci (&gohci);
+ err ("can't reset usb-%s", gohci.slot_name);
+#ifdef CFG_USB_OHCI_BOARD_INIT
+ /* board dependant cleanup */
+ usb_board_init_fail();
+#endif
+
+#ifdef CFG_USB_OHCI_CPU_INIT
+ /* cpu dependant cleanup */
+ usb_cpu_init_fail();
+#endif
+ return -1;
+ }
+
+ /* FIXME this is a second HC reset; why?? */
+ /* writel(gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control);
+ wait_ms(10); */
+ if (hc_start (&gohci) < 0) {
+ err ("can't start usb-%s", gohci.slot_name);
+ hc_release_ohci (&gohci);
+ /* Initialization failed */
+#ifdef CFG_USB_OHCI_BOARD_INIT
+ /* board dependant cleanup */
+ usb_board_stop();
+#endif
+
+#ifdef CFG_USB_OHCI_CPU_INIT
+ /* cpu dependant cleanup */
+ usb_cpu_stop();
+#endif
+ return -1;
+ }
+
+#ifdef DEBUG
+ ohci_dump (&gohci, 1);
+#else
+ wait_ms(1);
+#endif
+ ohci_inited = 1;
+ return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+ /* this gets called really early - before the controller has */
+ /* even been initialized! */
+ if (!ohci_inited)
+ return 0;
+ /* TODO release any interrupts, etc. */
+ /* call hc_release_ohci() here ? */
+ hc_reset (&gohci);
+
+#ifdef CFG_USB_OHCI_BOARD_INIT
+ /* board dependant cleanup */
+ if(usb_board_stop())
+ return -1;
+#endif
+
+#ifdef CFG_USB_OHCI_CPU_INIT
+ /* cpu dependant cleanup */
+ if(usb_cpu_stop())
+ return -1;
+#endif
+
+ return 0;
+}
+#endif /* CONFIG_USB_OHCI_NEW */
diff --git a/drivers/usb_ohci.h b/drivers/usb_ohci.h
new file mode 100644
index 0000000000..380cb4c927
--- /dev/null
+++ b/drivers/usb_ohci.h
@@ -0,0 +1,445 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * usb-ohci.h
+ */
+
+/* functions for doing board or CPU specific setup/cleanup */
+extern int usb_board_init(void);
+extern int usb_board_stop(void);
+extern int usb_board_init_fail(void);
+
+extern int usb_cpu_init(void);
+extern int usb_cpu_stop(void);
+extern int usb_cpu_init_fail(void);
+
+
+static int cc_to_error[16] = {
+
+/* mapping of the OHCI CC status to error codes */
+ /* No Error */ 0,
+ /* CRC Error */ USB_ST_CRC_ERR,
+ /* Bit Stuff */ USB_ST_BIT_ERR,
+ /* Data Togg */ USB_ST_CRC_ERR,
+ /* Stall */ USB_ST_STALLED,
+ /* DevNotResp */ -1,
+ /* PIDCheck */ USB_ST_BIT_ERR,
+ /* UnExpPID */ USB_ST_BIT_ERR,
+ /* DataOver */ USB_ST_BUF_ERR,
+ /* DataUnder */ USB_ST_BUF_ERR,
+ /* reservd */ -1,
+ /* reservd */ -1,
+ /* BufferOver */ USB_ST_BUF_ERR,
+ /* BuffUnder */ USB_ST_BUF_ERR,
+ /* Not Access */ -1,
+ /* Not Access */ -1
+};
+
+/* ED States */
+
+#define ED_NEW 0x00
+#define ED_UNLINK 0x01
+#define ED_OPER 0x02
+#define ED_DEL 0x04
+#define ED_URB_DEL 0x08
+
+/* usb_ohci_ed */
+struct ed {
+ __u32 hwINFO;
+ __u32 hwTailP;
+ __u32 hwHeadP;
+ __u32 hwNextED;
+
+ struct ed *ed_prev;
+ __u8 int_period;
+ __u8 int_branch;
+ __u8 int_load;
+ __u8 int_interval;
+ __u8 state;
+ __u8 type;
+ __u16 last_iso;
+ struct ed *ed_rm_list;
+
+ struct usb_device *usb_dev;
+ void *purb;
+ __u32 unused[2];
+} __attribute((aligned(16)));
+typedef struct ed ed_t;
+
+
+/* TD info field */
+#define TD_CC 0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC 0x0C000000
+#define TD_T 0x03000000
+#define TD_T_DATA0 0x02000000
+#define TD_T_DATA1 0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R 0x00040000
+#define TD_DI 0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP 0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN 0x00100000
+#define TD_DP_OUT 0x00080000
+
+#define TD_ISO 0x00010000
+#define TD_DEL 0x00020000
+
+/* CC Codes */
+#define TD_CC_NOERROR 0x00
+#define TD_CC_CRC 0x01
+#define TD_CC_BITSTUFFING 0x02
+#define TD_CC_DATATOGGLEM 0x03
+#define TD_CC_STALL 0x04
+#define TD_DEVNOTRESP 0x05
+#define TD_PIDCHECKFAIL 0x06
+#define TD_UNEXPECTEDPID 0x07
+#define TD_DATAOVERRUN 0x08
+#define TD_DATAUNDERRUN 0x09
+#define TD_BUFFEROVERRUN 0x0C
+#define TD_BUFFERUNDERRUN 0x0D
+#define TD_NOTACCESSED 0x0F
+
+
+#define MAXPSW 1
+
+struct td {
+ __u32 hwINFO;
+ __u32 hwCBP; /* Current Buffer Pointer */
+ __u32 hwNextTD; /* Next TD Pointer */
+ __u32 hwBE; /* Memory Buffer End Pointer */
+
+/* #ifndef CONFIG_MPC5200 /\* this seems wrong *\/ */
+ __u16 hwPSW[MAXPSW];
+/* #endif */
+ __u8 unused;
+ __u8 index;
+ struct ed *ed;
+ struct td *next_dl_td;
+ struct usb_device *usb_dev;
+ int transfer_len;
+ __u32 data;
+
+ __u32 unused2[2];
+} __attribute((aligned(32)));
+typedef struct td td_t;
+
+#define OHCI_ED_SKIP (1 << 14)
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of. It must be 256-byte aligned.
+ */
+
+#define NUM_INTS 32 /* part of the OHCI standard */
+struct ohci_hcca {
+ __u32 int_table[NUM_INTS]; /* Interrupt ED table */
+#if defined(CONFIG_MPC5200)
+ __u16 pad1; /* set to 0 on each frame_no change */
+ __u16 frame_no; /* current frame number */
+#else
+ __u16 frame_no; /* current frame number */
+ __u16 pad1; /* set to 0 on each frame_no change */
+#endif
+ __u32 done_head; /* info returned for an interrupt */
+ u8 reserved_for_hc[116];
+} __attribute((aligned(256)));
+
+
+/*
+ * Maximum number of root hub ports.
+ */
+#ifndef CFG_USB_OHCI_MAX_ROOT_PORTS
+# error "CFG_USB_OHCI_MAX_ROOT_PORTS undefined!"
+#endif
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region. This is Memory Mapped I/O. You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+ /* control and status registers */
+ __u32 revision;
+ __u32 control;
+ __u32 cmdstatus;
+ __u32 intrstatus;
+ __u32 intrenable;
+ __u32 intrdisable;
+ /* memory pointers */
+ __u32 hcca;
+ __u32 ed_periodcurrent;
+ __u32 ed_controlhead;
+ __u32 ed_controlcurrent;
+ __u32 ed_bulkhead;
+ __u32 ed_bulkcurrent;
+ __u32 donehead;
+ /* frame counters */
+ __u32 fminterval;
+ __u32 fmremaining;
+ __u32 fmnumber;
+ __u32 periodicstart;
+ __u32 lsthresh;
+ /* Root hub ports */
+ struct ohci_roothub_regs {
+ __u32 a;
+ __u32 b;
+ __u32 status;
+ __u32 portstatus[CFG_USB_OHCI_MAX_ROOT_PORTS];
+ } roothub;
+} __attribute((aligned(32)));
+
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
+#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
+#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
+#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
+#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
+#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
+#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
+#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
+#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+# define OHCI_USB_RESET (0 << 6)
+# define OHCI_USB_RESUME (1 << 6)
+# define OHCI_USB_OPER (2 << 6)
+# define OHCI_USB_SUSPEND (3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR (1 << 0) /* host controller reset */
+#define OHCI_CLF (1 << 1) /* control list filled */
+#define OHCI_BLF (1 << 2) /* bulk list filled */
+#define OHCI_OCR (1 << 3) /* ownership change request */
+#define OHCI_SOC (3 << 16) /* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
+#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
+#define OHCI_INTR_SF (1 << 2) /* start frame */
+#define OHCI_INTR_RD (1 << 3) /* resume detect */
+#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
+#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
+#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
+#define OHCI_INTR_OC (1 << 30) /* ownership change */
+#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
+
+
+/* Virtual Root HUB */
+struct virt_root_hub {
+ int devnum; /* Address of Root Hub endpoint */
+ void *dev; /* was urb */
+ void *int_addr;
+ int send;
+ int interval;
+};
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
+
+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
+
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS 0x00000001 /* current connect status */
+#define RH_PS_PES 0x00000002 /* port enable status*/
+#define RH_PS_PSS 0x00000004 /* port suspend status */
+#define RH_PS_POCI 0x00000008 /* port over current indicator */
+#define RH_PS_PRS 0x00000010 /* port reset status */
+#define RH_PS_PPS 0x00000100 /* port power status */
+#define RH_PS_LSDA 0x00000200 /* low speed device attached */
+#define RH_PS_CSC 0x00010000 /* connect status change */
+#define RH_PS_PESC 0x00020000 /* port enable status change */
+#define RH_PS_PSSC 0x00040000 /* port suspend status change */
+#define RH_PS_OCIC 0x00080000 /* over current indicator change */
+#define RH_PS_PRSC 0x00100000 /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS 0x00000001 /* local power status */
+#define RH_HS_OCI 0x00000002 /* over current indicator */
+#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
+#define RH_HS_LPSC 0x00010000 /* local power status change */
+#define RH_HS_OCIC 0x00020000 /* over current indicator change */
+#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR 0x0000ffff /* device removable flags */
+#define RH_B_PPCM 0xffff0000 /* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP (0xff << 0) /* number of downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* over current protection mode */
+#define RH_A_NOCP (1 << 12) /* no over current protection */
+#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
+
+/* urb */
+#define N_URB_TD 48
+typedef struct
+{
+ ed_t *ed;
+ __u16 length; /* number of tds associated with this request */
+ __u16 td_cnt; /* number of tds already serviced */
+ struct usb_device *dev;
+ int state;
+ unsigned long pipe;
+ void *transfer_buffer;
+ int transfer_buffer_length;
+ int interval;
+ int actual_length;
+ int finished;
+ td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */
+} urb_priv_t;
+#define URB_DEL 1
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+
+typedef struct ohci {
+ struct ohci_hcca *hcca; /* hcca */
+ /*dma_addr_t hcca_dma;*/
+
+ int irq;
+ int disabled; /* e.g. got a UE, we're hung */
+ int sleeping;
+ unsigned long flags; /* for HC bugs */
+
+ struct ohci_regs *regs; /* OHCI controller's memory */
+
+ int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/
+ ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */
+ ed_t *ed_bulktail; /* last endpoint of bulk list */
+ ed_t *ed_controltail; /* last endpoint of control list */
+ int intrstatus;
+ __u32 hc_control; /* copy of the hc control reg */
+ struct usb_device *dev[32];
+ struct virt_root_hub rh;
+
+ const char *slot_name;
+} ohci_t;
+
+#define NUM_EDS 8 /* num of preallocated endpoint descriptors */
+
+struct ohci_device {
+ ed_t ed[NUM_EDS];
+ int ed_cnt;
+};
+
+/* hcd */
+/* endpoint */
+static int ep_link(ohci_t * ohci, ed_t * ed);
+static int ep_unlink(ohci_t * ohci, ed_t * ed);
+static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe,
+ int interval, int load);
+
+/*-------------------------------------------------------------------------*/
+
+/* we need more TDs than EDs */
+#define NUM_TD 64
+
+/* +1 so we can align the storage */
+td_t gtd[NUM_TD+1];
+/* pointers to aligned storage */
+td_t *ptd;
+
+/* TDs ... */
+static inline struct td *
+td_alloc (struct usb_device *usb_dev)
+{
+ int i;
+ struct td *td;
+
+ td = NULL;
+ for (i = 0; i < NUM_TD; i++)
+ {
+ if (ptd[i].usb_dev == NULL)
+ {
+ td = &ptd[i];
+ td->usb_dev = usb_dev;
+ break;
+ }
+ }
+
+ return td;
+}
+
+static inline void
+ed_free (struct ed *ed)
+{
+ ed->usb_dev = NULL;
+}
diff --git a/drivers/usbdcore_ep0.c b/drivers/usbdcore_ep0.c
index 260befe978..1e44f322a7 100644
--- a/drivers/usbdcore_ep0.c
+++ b/drivers/usbdcore_ep0.c
@@ -2,6 +2,9 @@
* (C) Copyright 2003
* Gerry Hamel, geh@ti.com, Texas Instruments
*
+ * (C) Copyright 2006
+ * Bryan O'Donoghue, deckard@CodeHermit.ie
+ *
* Based on
* linux/drivers/usbd/ep0.c
*
@@ -39,11 +42,17 @@
* function driver. This may need to change.
*
* XXX
+ *
+ * As alluded to above, a simple callback cdc_recv_setup has been implemented
+ * in the usb_device data structure to facilicate passing
+ * Common Device Class packets to a function driver.
+ *
+ * XXX
*/
#include <common.h>
-#if defined(CONFIG_OMAP1510) && defined(CONFIG_USB_DEVICE)
+#if defined(CONFIG_USB_DEVICE)
#include "usbdcore.h"
#if 0
@@ -69,7 +78,7 @@ static int ep0_get_status (struct usb_device_instance *device,
char *cp;
urb->actual_length = 2;
- cp = urb->buffer;
+ cp = (char*)urb->buffer;
cp[0] = cp[1] = 0;
switch (requesttype) {
@@ -115,7 +124,7 @@ static int ep0_get_one (struct usb_device_instance *device, struct urb *urb,
*
* Copy configuration data to urb transfer buffer if there is room for it.
*/
-static void copy_config (struct urb *urb, void *data, int max_length,
+void copy_config (struct urb *urb, void *data, int max_length,
int max_buf)
{
int available;
@@ -128,10 +137,7 @@ static void copy_config (struct urb *urb, void *data, int max_length,
dbg_ep0 (1, "data is NULL");
return;
}
- if (!(length = *(unsigned char *) data)) {
- dbg_ep0 (1, "length is zero");
- return;
- }
+ length = max_length;
if (length > max_length) {
dbg_ep0 (1, "length: %d >= max_length: %d", length,
@@ -192,7 +198,7 @@ static int ep0_get_descriptor (struct usb_device_instance *device,
/* setup tx urb */
urb->actual_length = 0;
- cp = urb->buffer;
+ cp = (char*)urb->buffer;
dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type));
@@ -200,7 +206,6 @@ static int ep0_get_descriptor (struct usb_device_instance *device,
case USB_DESCRIPTOR_TYPE_DEVICE:
{
struct usb_device_descriptor *device_descriptor;
-
if (!
(device_descriptor =
usbd_device_device_descriptor (device, port))) {
@@ -214,20 +219,16 @@ static int ep0_get_descriptor (struct usb_device_instance *device,
/* correct the correct control endpoint 0 max packet size into the descriptor */
device_descriptor =
(struct usb_device_descriptor *) urb->buffer;
- device_descriptor->bMaxPacketSize0 =
- urb->device->bus->maxpacketsize;
}
- /*dbg_ep0(3, "copied device configuration, actual_length: %x", urb->actual_length); */
+ dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length);
break;
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
{
- int bNumInterface;
struct usb_configuration_descriptor
*configuration_descriptor;
struct usb_device_descriptor *device_descriptor;
-
if (!
(device_descriptor =
usbd_device_device_descriptor (device, port))) {
@@ -251,130 +252,35 @@ static int ep0_get_descriptor (struct usb_device_instance *device,
index);
return -1;
}
+ dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength));
copy_config (urb, configuration_descriptor,
- sizeof (struct
- usb_configuration_descriptor),
- max);
-
-
- /* iterate across interfaces for specified configuration */
- dbg_ep0 (0, "bNumInterfaces: %d",
- configuration_descriptor->bNumInterfaces);
- for (bNumInterface = 0;
- bNumInterface <
- configuration_descriptor->bNumInterfaces;
- bNumInterface++) {
- int bAlternateSetting;
- struct usb_interface_instance
- *interface_instance;
-
- dbg_ep0 (3, "[%d] bNumInterfaces: %d",
- bNumInterface,
- configuration_descriptor->bNumInterfaces);
-
- if (! (interface_instance = usbd_device_interface_instance (device,
- port, index, bNumInterface)))
- {
- dbg_ep0 (3, "[%d] interface_instance NULL",
- bNumInterface);
- return -1;
- }
- /* iterate across interface alternates */
- for (bAlternateSetting = 0;
- bAlternateSetting < interface_instance->alternates;
- bAlternateSetting++) {
- /*int class; */
- int bNumEndpoint;
- struct usb_interface_descriptor *interface_descriptor;
-
- struct usb_alternate_instance *alternate_instance;
-
- dbg_ep0 (3, "[%d:%d] alternates: %d",
- bNumInterface,
- bAlternateSetting,
- interface_instance->alternates);
-
- if (! (alternate_instance = usbd_device_alternate_instance (device, port, index, bNumInterface, bAlternateSetting))) {
- dbg_ep0 (3, "[%d] alternate_instance NULL",
- bNumInterface);
- return -1;
- }
- /* copy descriptor for this interface */
- copy_config (urb, alternate_instance->interface_descriptor,
- sizeof (struct usb_interface_descriptor),
- max);
-
- /*dbg_ep0(3, "[%d:%d] classes: %d endpoints: %d", bNumInterface, bAlternateSetting, */
- /* alternate_instance->classes, alternate_instance->endpoints); */
-
- /* iterate across classes for this alternate interface */
-#if 0
- for (class = 0;
- class < alternate_instance->classes;
- class++) {
- struct usb_class_descriptor *class_descriptor;
- /*dbg_ep0(3, "[%d:%d:%d] classes: %d", bNumInterface, bAlternateSetting, */
- /* class, alternate_instance->classes); */
- if (!(class_descriptor = usbd_device_class_descriptor_index (device, port, index, bNumInterface, bAlternateSetting, class))) {
- dbg_ep0 (3, "[%d] class NULL",
- class);
- return -1;
- }
- /* copy descriptor for this class */
- copy_config (urb, class_descriptor,
- sizeof (struct usb_class_descriptor),
- max);
- }
-#endif
-
- /* iterate across endpoints for this alternate interface */
- interface_descriptor = alternate_instance->interface_descriptor;
- for (bNumEndpoint = 0;
- bNumEndpoint < alternate_instance->endpoints;
- bNumEndpoint++) {
- struct usb_endpoint_descriptor *endpoint_descriptor;
- dbg_ep0 (3, "[%d:%d:%d] endpoint: %d",
- bNumInterface,
- bAlternateSetting,
- bNumEndpoint,
- interface_descriptor->
- bNumEndpoints);
- if (!(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, index, bNumInterface, bAlternateSetting, bNumEndpoint))) {
- dbg_ep0 (3, "[%d] endpoint NULL",
- bNumEndpoint);
- return -1;
- }
- /* copy descriptor for this endpoint */
- copy_config (urb, endpoint_descriptor,
- sizeof (struct usb_endpoint_descriptor),
- max);
- }
- }
- }
- dbg_ep0 (3, "lengths: %d %d",
- le16_to_cpu (configuration_descriptor->wTotalLength),
- urb->actual_length);
+ cpu_to_le16(configuration_descriptor->wTotalLength),
+ max);
}
+
break;
case USB_DESCRIPTOR_TYPE_STRING:
{
struct usb_string_descriptor *string_descriptor;
-
if (!(string_descriptor = usbd_get_string (index))) {
+ serial_printf("Invalid string index %d\n", index);
return -1;
}
- /*dbg_ep0(3, "string_descriptor: %p", string_descriptor); */
+ dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength);
copy_config (urb, string_descriptor, string_descriptor->bLength, max);
}
break;
case USB_DESCRIPTOR_TYPE_INTERFACE:
+ serial_printf("USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n");
return -1;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
+ serial_printf("USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n");
return -1;
case USB_DESCRIPTOR_TYPE_HID:
{
+ serial_printf("USB_DESCRIPTOR_TYPE_HID - error not implemented\n");
return -1; /* unsupported at this time */
#if 0
int bNumInterface =
@@ -403,6 +309,7 @@ static int ep0_get_descriptor (struct usb_device_instance *device,
break;
case USB_DESCRIPTOR_TYPE_REPORT:
{
+ serial_printf("USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n");
return -1; /* unsupported at this time */
#if 0
int bNumInterface =
@@ -434,12 +341,19 @@ static int ep0_get_descriptor (struct usb_device_instance *device,
#endif
}
break;
+ case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
+ {
+ /* If a USB device supports both a full speed and low speed operation
+ * we must send a Device_Qualifier descriptor here
+ */
+ return -1;
+ }
default:
return -1;
}
- dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d packet size: %2d",
+ dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %2d",
urb->buffer, urb->buffer_length, urb->actual_length,
device->bus->endpoint_array[0].tx_packetSize);
/*
@@ -495,6 +409,12 @@ int ep0_recv_setup (struct urb *urb)
/* handle USB Standard Request (c.f. USB Spec table 9-2) */
if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) {
+ if(device->device_state <= STATE_CONFIGURED){
+ /* Attempt to handle a CDC specific request if we are
+ * in the configured state.
+ */
+ return device->cdc_recv_setup(request,urb);
+ }
dbg_ep0 (1, "non standard request: %x",
request->bmRequestType & USB_REQ_TYPE_MASK);
return -1; /* Stall here */
@@ -567,6 +487,7 @@ int ep0_recv_setup (struct urb *urb)
le16_to_cpu (request->wValue) & 0xff);
case USB_REQ_GET_CONFIGURATION:
+ serial_printf("get config %d\n", device->configuration);
return ep0_get_one (device, urb,
device->configuration);
@@ -642,7 +563,6 @@ int ep0_recv_setup (struct urb *urb)
/*dbg_ep0(2, "address: %d %d %d", */
/* request->wValue, le16_to_cpu(request->wValue), device->address); */
- serial_printf ("DEVICE_ADDRESS_ASSIGNED.. event?\n");
return 0;
case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */
@@ -653,9 +573,10 @@ int ep0_recv_setup (struct urb *urb)
/* c.f. 9.4.7 - the top half of wValue is reserved */
/* */
if ((device->configuration =
- le16_to_cpu (request->wValue) & 0x7f) != 0) {
+ le16_to_cpu (request->wValue) & 0xFF80) != 0) {
/* c.f. 9.4.7 - zero is the default or addressed state, in our case this */
/* is the same is configuration zero */
+ serial_printf("error setting dev->config to zero!\n");
device->configuration = 0; /* TBR - ?????? */
}
/* reset interface and alternate settings */
diff --git a/drivers/usbdcore_mpc8xx.c b/drivers/usbdcore_mpc8xx.c
new file mode 100644
index 0000000000..d4c4096565
--- /dev/null
+++ b/drivers/usbdcore_mpc8xx.c
@@ -0,0 +1,1401 @@
+/*
+ * Copyright (C) 2006 by Bryan O'Donoghue, CodeHermit
+ * bodonoghue@CodeHermit.ie
+ *
+ * References
+ * DasUBoot/drivers/usbdcore_omap1510.c, for design and implementation ideas.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Notes :
+ * 1. #define __SIMULATE_ERROR__ to inject a CRC error into every 2nd TX
+ * packet to force the USB re-transmit protocol.
+ *
+ * 2. #define __DEBUG_UDC__ to switch on debug tracing to serial console
+ * be careful that tracing doesn't create Hiesen-bugs with respect to
+ * response timeouts to control requests.
+ *
+ * 3. This driver should be able to support any higher level driver that
+ * that wants to do either of the two standard UDC implementations
+ * Control-Bulk-Interrupt or Bulk-IN/Bulk-Out standards. Hence
+ * gserial and cdc_acm should work with this code.
+ *
+ * 4. NAK events never actually get raised at all, the documentation
+ * is just wrong !
+ *
+ * 5. For some reason, cbd_datlen is *always* +2 the value it should be.
+ * this means that having an RX cbd of 16 bytes is not possible, since
+ * the same size is reported for 14 bytes received as 16 bytes received
+ * until we can find out why this happens, RX cbds must be limited to 8
+ * bytes. TODO: check errata for this behaviour.
+ *
+ * 6. Right now this code doesn't support properly powering up with the USB
+ * cable attached to the USB host my development board the Adder87x doesn't
+ * have a pull-up fitted to allow this, so it is necessary to power the
+ * board and *then* attached the USB cable to the host. However somebody
+ * with a different design in their board may be able to keep the cable
+ * constantly connected and simply enable/disable a pull-up re
+ * figure 31.1 in MPC885RM.pdf instead of having to power up the board and
+ * then attach the cable !
+ *
+ */
+#include <common.h>
+#include <config.h>
+
+#if defined(CONFIG_MPC885_FAMILY) && defined(CONFIG_USB_DEVICE)
+#include <commproc.h>
+#include "usbdcore.h"
+#include "usbdcore_mpc8xx.h"
+#include "usbdcore_ep0.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ERR(fmt, args...)\
+ serial_printf("ERROR : [%s] %s:%d: "fmt,\
+ __FILE__,__FUNCTION__,__LINE__, ##args)
+#ifdef __DEBUG_UDC__
+#define DBG(fmt,args...)\
+ serial_printf("[%s] %s:%d: "fmt,\
+ __FILE__,__FUNCTION__,__LINE__, ##args)
+#else
+#define DBG(fmt,args...)
+#endif
+
+/* Static Data */
+#ifdef __SIMULATE_ERROR__
+static char err_poison_test = 0;
+#endif
+static struct mpc8xx_ep ep_ref[MAX_ENDPOINTS];
+static u32 address_base = STATE_NOT_READY;
+static mpc8xx_udc_state_t udc_state = 0;
+static struct usb_device_instance *udc_device = 0;
+static volatile usb_epb_t *endpoints[MAX_ENDPOINTS];
+static volatile cbd_t *tx_cbd[TX_RING_SIZE];
+static volatile cbd_t *rx_cbd[RX_RING_SIZE];
+static volatile immap_t *immr = 0;
+static volatile cpm8xx_t *cp = 0;
+static volatile usb_pram_t *usb_paramp = 0;
+static volatile usb_t *usbp = 0;
+static int rx_ct = 0;
+static int tx_ct = 0;
+
+/* Static Function Declarations */
+static void mpc8xx_udc_state_transition_up (usb_device_state_t initial,
+ usb_device_state_t final);
+static void mpc8xx_udc_state_transition_down (usb_device_state_t initial,
+ usb_device_state_t final);
+static void mpc8xx_udc_stall (unsigned int ep);
+static void mpc8xx_udc_flush_tx_fifo (int epid);
+static void mpc8xx_udc_flush_rx_fifo (void);
+static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp);
+static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,
+ struct urb *tx_urb);
+static void mpc8xx_udc_dump_request (struct usb_device_request *request);
+static void mpc8xx_udc_clock_init (volatile immap_t * immr,
+ volatile cpm8xx_t * cp);
+static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi);
+static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp);
+static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp);
+static void mpc8xx_udc_cbd_init (void);
+static void mpc8xx_udc_endpoint_init (void);
+static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size);
+static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment);
+static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp);
+static void mpc8xx_udc_set_nak (unsigned int ep);
+static short mpc8xx_udc_handle_txerr (void);
+static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid);
+
+/******************************************************************************
+ Global Linkage
+ *****************************************************************************/
+
+/* udc_init
+ *
+ * Do initial bus gluing
+ */
+int udc_init (void)
+{
+ /* Init various pointers */
+ immr = (immap_t *) CFG_IMMR;
+ cp = (cpm8xx_t *) & (immr->im_cpm);
+ usb_paramp = (usb_pram_t *) & (cp->cp_dparam[PROFF_USB]);
+ usbp = (usb_t *) & (cp->cp_scc[0]);
+
+ memset (ep_ref, 0x00, (sizeof (struct mpc8xx_ep) * MAX_ENDPOINTS));
+
+ udc_device = 0;
+ udc_state = STATE_NOT_READY;
+
+ usbp->usmod = 0x00;
+ usbp->uscom = 0;
+
+ /* Set USB Frame #0, Respond at Address & Get a clock source */
+ usbp->usaddr = 0x00;
+ mpc8xx_udc_clock_init (immr, cp);
+
+ /* PA15, PA14 as perhiperal USBRXD and USBOE */
+ immr->im_ioport.iop_padir &= ~0x0003;
+ immr->im_ioport.iop_papar |= 0x0003;
+
+ /* PC11/PC10 as peripheral USBRXP USBRXN */
+ immr->im_ioport.iop_pcso |= 0x0030;
+
+ /* PC7/PC6 as perhiperal USBTXP and USBTXN */
+ immr->im_ioport.iop_pcdir |= 0x0300;
+ immr->im_ioport.iop_pcpar |= 0x0300;
+
+ /* Set the base address */
+ address_base = (u32) (cp->cp_dpmem + CPM_USB_BASE);
+
+ /* Initialise endpoints and circular buffers */
+ mpc8xx_udc_endpoint_init ();
+ mpc8xx_udc_cbd_init ();
+
+ /* Assign allocated Dual Port Endpoint descriptors */
+ usb_paramp->ep0ptr = (u32) endpoints[0];
+ usb_paramp->ep1ptr = (u32) endpoints[1];
+ usb_paramp->ep2ptr = (u32) endpoints[2];
+ usb_paramp->ep3ptr = (u32) endpoints[3];
+ usb_paramp->frame_n = 0;
+
+ DBG ("ep0ptr=0x%08x ep1ptr=0x%08x ep2ptr=0x%08x ep3ptr=0x%08x\n",
+ usb_paramp->ep0ptr, usb_paramp->ep1ptr, usb_paramp->ep2ptr,
+ usb_paramp->ep3ptr);
+
+ return 0;
+}
+
+/* udc_irq
+ *
+ * Poll for whatever events may have occured
+ */
+void udc_irq (void)
+{
+ int epid = 0;
+ volatile cbd_t *rx_cbdp = 0;
+ volatile cbd_t *rx_cbdp_base = 0;
+
+ if (udc_state != STATE_READY) {
+ return;
+ }
+
+ if (usbp->usber & USB_E_BSY) {
+ /* This shouldn't happen. If it does then it's a bug ! */
+ usbp->usber |= USB_E_BSY;
+ mpc8xx_udc_flush_rx_fifo ();
+ }
+
+ /* Scan all RX/Bidirectional Endpoints for RX data. */
+ for (epid = 0; epid < MAX_ENDPOINTS; epid++) {
+ if (!ep_ref[epid].prx) {
+ continue;
+ }
+ rx_cbdp = rx_cbdp_base = ep_ref[epid].prx;
+
+ do {
+ if (!(rx_cbdp->cbd_sc & RX_BD_E)) {
+
+ if (rx_cbdp->cbd_sc & 0x1F) {
+ /* Corrupt data discard it.
+ * Controller has NAK'd this packet.
+ */
+ mpc8xx_udc_clear_rxbd (rx_cbdp);
+
+ } else {
+ if (!epid) {
+ mpc8xx_udc_ep0_rx (rx_cbdp);
+
+ } else {
+ /* Process data */
+ mpc8xx_udc_set_nak (epid);
+ mpc8xx_udc_epn_rx (epid, rx_cbdp);
+ mpc8xx_udc_clear_rxbd (rx_cbdp);
+ }
+ }
+
+ /* Advance RX CBD pointer */
+ mpc8xx_udc_advance_rx (&rx_cbdp, epid);
+ ep_ref[epid].prx = rx_cbdp;
+ } else {
+ /* Advance RX CBD pointer */
+ mpc8xx_udc_advance_rx (&rx_cbdp, epid);
+ }
+
+ } while (rx_cbdp != rx_cbdp_base);
+ }
+
+ /* Handle TX events as appropiate, the correct place to do this is
+ * in a tx routine. Perhaps TX on epn was pre-empted by ep0
+ */
+
+ if (usbp->usber & USB_E_TXB) {
+ usbp->usber |= USB_E_TXB;
+ }
+
+ if (usbp->usber & (USB_TX_ERRMASK)) {
+ mpc8xx_udc_handle_txerr ();
+ }
+
+ /* Switch to the default state, respond at the default address */
+ if (usbp->usber & USB_E_RESET) {
+ usbp->usber |= USB_E_RESET;
+ usbp->usaddr = 0x00;
+ udc_device->device_state = STATE_DEFAULT;
+ }
+
+ /* if(usbp->usber&USB_E_IDLE){
+ We could suspend here !
+ usbp->usber|=USB_E_IDLE;
+ DBG("idle state change\n");
+ }
+ if(usbp->usbs){
+ We could resume here when IDLE is deasserted !
+ Not worth doing, so long as we are self powered though.
+ }
+ */
+
+ return;
+}
+
+/* udc_endpoint_write
+ *
+ * Write some data to an endpoint
+ */
+int udc_endpoint_write (struct usb_endpoint_instance *epi)
+{
+ int ep = 0;
+ short epid = 1, unnak = 0, ret = 0;
+
+ if (udc_state != STATE_READY) {
+ ERR ("invalid udc_state != STATE_READY!\n");
+ return -1;
+ }
+
+ if (!udc_device || !epi) {
+ return -1;
+ }
+
+ if (udc_device->device_state != STATE_CONFIGURED) {
+ return -1;
+ }
+
+ ep = epi->endpoint_address & 0x03;
+ if (ep >= MAX_ENDPOINTS) {
+ return -1;
+ }
+
+ /* Set NAK for all RX endpoints during TX */
+ for (epid = 1; epid < MAX_ENDPOINTS; epid++) {
+
+ /* Don't set NAK on DATA IN/CONTROL endpoints */
+ if (ep_ref[epid].sc & USB_DIR_IN) {
+ continue;
+ }
+
+ if (!(usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK))) {
+ unnak |= 1 << epid;
+ }
+
+ mpc8xx_udc_set_nak (epid);
+ }
+
+ mpc8xx_udc_init_tx (&udc_device->bus->endpoint_array[ep],
+ epi->tx_urb);
+ ret = mpc8xx_udc_ep_tx (&udc_device->bus->endpoint_array[ep]);
+
+ /* Remove temporary NAK */
+ for (epid = 1; epid < MAX_ENDPOINTS; epid++) {
+ if (unnak & (1 << epid)) {
+ udc_unset_nak (epid);
+ }
+ }
+
+ return ret;
+}
+
+/* mpc8xx_udc_assign_urb
+ *
+ * Associate a given urb to an endpoint TX or RX transmit/receive buffers
+ */
+static int mpc8xx_udc_assign_urb (int ep, char direction)
+{
+ struct usb_endpoint_instance *epi = 0;
+
+ if (ep >= MAX_ENDPOINTS) {
+ goto err;
+ }
+ epi = &udc_device->bus->endpoint_array[ep];
+ if (!epi) {
+ goto err;
+ }
+
+ if (!ep_ref[ep].urb) {
+ ep_ref[ep].urb = usbd_alloc_urb (udc_device, udc_device->bus->endpoint_array);
+ if (!ep_ref[ep].urb) {
+ goto err;
+ }
+ } else {
+ ep_ref[ep].urb->actual_length = 0;
+ }
+
+ switch (direction) {
+ case USB_DIR_IN:
+ epi->tx_urb = ep_ref[ep].urb;
+ break;
+ case USB_DIR_OUT:
+ epi->rcv_urb = ep_ref[ep].urb;
+ break;
+ default:
+ goto err;
+ }
+ return 0;
+
+ err:
+ udc_state = STATE_ERROR;
+ return -1;
+}
+
+/* udc_setup_ep
+ *
+ * Associate U-Boot software endpoints to mpc8xx endpoint parameter ram
+ * Isochronous endpoints aren't yet supported!
+ */
+void udc_setup_ep (struct usb_device_instance *device, unsigned int ep,
+ struct usb_endpoint_instance *epi)
+{
+ uchar direction = 0;
+ int ep_attrib = 0;
+
+ if (epi && (ep < MAX_ENDPOINTS)) {
+
+ if (ep == 0) {
+ if (epi->rcv_attributes != USB_ENDPOINT_XFER_CONTROL
+ || epi->tx_attributes !=
+ USB_ENDPOINT_XFER_CONTROL) {
+
+ /* ep0 must be a control endpoint */
+ udc_state = STATE_ERROR;
+ return;
+
+ }
+ if (!(ep_ref[ep].sc & EP_ATTACHED)) {
+ mpc8xx_udc_cbd_attach (ep, epi->tx_packetSize,
+ epi->rcv_packetSize);
+ }
+ usbp->usep[ep] = 0x0000;
+ return;
+ }
+
+ if ((epi->endpoint_address & USB_ENDPOINT_DIR_MASK)
+ == USB_DIR_IN) {
+
+ direction = 1;
+ ep_attrib = epi->tx_attributes;
+ epi->rcv_packetSize = 0;
+ ep_ref[ep].sc |= USB_DIR_IN;
+ } else {
+
+ direction = 0;
+ ep_attrib = epi->rcv_attributes;
+ epi->tx_packetSize = 0;
+ ep_ref[ep].sc &= ~USB_DIR_IN;
+ }
+
+ if (mpc8xx_udc_assign_urb (ep, epi->endpoint_address
+ & USB_ENDPOINT_DIR_MASK)) {
+ return;
+ }
+
+ switch (ep_attrib) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ if (!(ep_ref[ep].sc & EP_ATTACHED)) {
+ mpc8xx_udc_cbd_attach (ep,
+ epi->tx_packetSize,
+ epi->rcv_packetSize);
+ }
+ usbp->usep[ep] = ep << 12;
+ epi->rcv_urb = epi->tx_urb = ep_ref[ep].urb;
+
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ if (!(ep_ref[ep].sc & EP_ATTACHED)) {
+ if (direction) {
+ mpc8xx_udc_cbd_attach (ep,
+ epi->tx_packetSize,
+ 0);
+ } else {
+ mpc8xx_udc_cbd_attach (ep,
+ 0,
+ epi->rcv_packetSize);
+ }
+ }
+ usbp->usep[ep] = (ep << 12) | ((ep_attrib) << 8);
+
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ default:
+ serial_printf ("Error endpoint attrib %d>3\n", ep_attrib);
+ udc_state = STATE_ERROR;
+ break;
+ }
+ }
+
+}
+
+/* udc_connect
+ *
+ * Move state, switch on the USB
+ */
+void udc_connect (void)
+{
+ /* Enable pull-up resistor on D+
+ * TODO: fit a pull-up resistor to drive SE0 for > 2.5us
+ */
+
+ if (udc_state != STATE_ERROR) {
+ udc_state = STATE_READY;
+ usbp->usmod |= USMOD_EN;
+ }
+}
+
+/* udc_disconnect
+ *
+ * Disconnect is not used but, is included for completeness
+ */
+void udc_disconnect (void)
+{
+ /* Disable pull-up resistor on D-
+ * TODO: fix a pullup resistor to control this
+ */
+
+ if (udc_state != STATE_ERROR) {
+ udc_state = STATE_NOT_READY;
+ }
+ usbp->usmod &= ~USMOD_EN;
+}
+
+/* udc_enable
+ *
+ * Grab an EP0 URB, register interest in a subset of USB events
+ */
+void udc_enable (struct usb_device_instance *device)
+{
+ if (udc_state == STATE_ERROR) {
+ return;
+ }
+
+ udc_device = device;
+
+ if (!ep_ref[0].urb) {
+ ep_ref[0].urb = usbd_alloc_urb (device, device->bus->endpoint_array);
+ }
+
+ /* Register interest in all events except SOF, enable transceiver */
+ usbp->usber = 0x03FF;
+ usbp->usbmr = 0x02F7;
+
+ return;
+}
+
+/* udc_disable
+ *
+ * disable the currently hooked device
+ */
+void udc_disable (void)
+{
+ int i = 0;
+
+ if (udc_state == STATE_ERROR) {
+ DBG ("Won't disable UDC. udc_state==STATE_ERROR !\n");
+ return;
+ }
+
+ udc_device = 0;
+
+ for (; i < MAX_ENDPOINTS; i++) {
+ if (ep_ref[i].urb) {
+ usbd_dealloc_urb (ep_ref[i].urb);
+ ep_ref[i].urb = 0;
+ }
+ }
+
+ usbp->usbmr = 0x00;
+ usbp->usmod = ~USMOD_EN;
+ udc_state = STATE_NOT_READY;
+}
+
+/* udc_startup_events
+ *
+ * Enable the specified device
+ */
+void udc_startup_events (struct usb_device_instance *device)
+{
+ udc_enable (device);
+ if (udc_state == STATE_READY) {
+ usbd_device_event_irq (device, DEVICE_CREATE, 0);
+ }
+}
+
+/* udc_set_nak
+ *
+ * Allow upper layers to signal lower layers should not accept more RX data
+ *
+ */
+void udc_set_nak (int epid)
+{
+ if (epid) {
+ mpc8xx_udc_set_nak (epid);
+ }
+}
+
+/* udc_unset_nak
+ *
+ * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint.
+ * Switch off NAKing on this endpoint to accept more data output from host.
+ *
+ */
+void udc_unset_nak (int epid)
+{
+ if (epid > MAX_ENDPOINTS) {
+ return;
+ }
+
+ if (usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK)) {
+ usbp->usep[epid] &= ~(USEP_THS_NAK | USEP_RHS_NAK);
+ __asm__ ("eieio");
+ }
+}
+
+/******************************************************************************
+ Static Linkage
+******************************************************************************/
+
+/* udc_state_transition_up
+ * udc_state_transition_down
+ *
+ * Helper functions to implement device state changes. The device states and
+ * the events that transition between them are:
+ *
+ * STATE_ATTACHED
+ * || /\
+ * \/ ||
+ * DEVICE_HUB_CONFIGURED DEVICE_HUB_RESET
+ * || /\
+ * \/ ||
+ * STATE_POWERED
+ * || /\
+ * \/ ||
+ * DEVICE_RESET DEVICE_POWER_INTERRUPTION
+ * || /\
+ * \/ ||
+ * STATE_DEFAULT
+ * || /\
+ * \/ ||
+ * DEVICE_ADDRESS_ASSIGNED DEVICE_RESET
+ * || /\
+ * \/ ||
+ * STATE_ADDRESSED
+ * || /\
+ * \/ ||
+ * DEVICE_CONFIGURED DEVICE_DE_CONFIGURED
+ * || /\
+ * \/ ||
+ * STATE_CONFIGURED
+ *
+ * udc_state_transition_up transitions up (in the direction from STATE_ATTACHED
+ * to STATE_CONFIGURED) from the specified initial state to the specified final
+ * state, passing through each intermediate state on the way. If the initial
+ * state is at or above (i.e. nearer to STATE_CONFIGURED) the final state, then
+ * no state transitions will take place.
+ *
+ * udc_state_transition_down transitions down (in the direction from
+ * STATE_CONFIGURED to STATE_ATTACHED) from the specified initial state to the
+ * specified final state, passing through each intermediate state on the way.
+ * If the initial state is at or below (i.e. nearer to STATE_ATTACHED) the final
+ * state, then no state transitions will take place.
+ *
+ */
+
+static void mpc8xx_udc_state_transition_up (usb_device_state_t initial,
+ usb_device_state_t final)
+{
+ if (initial < final) {
+ switch (initial) {
+ case STATE_ATTACHED:
+ usbd_device_event_irq (udc_device,
+ DEVICE_HUB_CONFIGURED, 0);
+ if (final == STATE_POWERED)
+ break;
+ case STATE_POWERED:
+ usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
+ if (final == STATE_DEFAULT)
+ break;
+ case STATE_DEFAULT:
+ usbd_device_event_irq (udc_device,
+ DEVICE_ADDRESS_ASSIGNED, 0);
+ if (final == STATE_ADDRESSED)
+ break;
+ case STATE_ADDRESSED:
+ usbd_device_event_irq (udc_device, DEVICE_CONFIGURED,
+ 0);
+ case STATE_CONFIGURED:
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void mpc8xx_udc_state_transition_down (usb_device_state_t initial,
+ usb_device_state_t final)
+{
+ if (initial > final) {
+ switch (initial) {
+ case STATE_CONFIGURED:
+ usbd_device_event_irq (udc_device,
+ DEVICE_DE_CONFIGURED, 0);
+ if (final == STATE_ADDRESSED)
+ break;
+ case STATE_ADDRESSED:
+ usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
+ if (final == STATE_DEFAULT)
+ break;
+ case STATE_DEFAULT:
+ usbd_device_event_irq (udc_device,
+ DEVICE_POWER_INTERRUPTION, 0);
+ if (final == STATE_POWERED)
+ break;
+ case STATE_POWERED:
+ usbd_device_event_irq (udc_device, DEVICE_HUB_RESET,
+ 0);
+ case STATE_ATTACHED:
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/* mpc8xx_udc_stall
+ *
+ * Force returning of STALL tokens on the given endpoint. Protocol or function
+ * STALL conditions are permissable here
+ */
+static void mpc8xx_udc_stall (unsigned int ep)
+{
+ usbp->usep[ep] |= STALL_BITMASK;
+}
+
+/* mpc8xx_udc_set_nak
+ *
+ * Force returning of NAK responses for the given endpoint as a kind of very
+ * simple flow control
+ */
+static void mpc8xx_udc_set_nak (unsigned int ep)
+{
+ usbp->usep[ep] |= NAK_BITMASK;
+ __asm__ ("eieio");
+}
+
+/* mpc8xx_udc_handle_txerr
+ *
+ * Handle errors relevant to TX. Return a status code to allow calling
+ * indicative of what if anything happened
+ */
+static short mpc8xx_udc_handle_txerr ()
+{
+ short ep = 0, ret = 0;
+
+ for (; ep < TX_RING_SIZE; ep++) {
+ if (usbp->usber & (0x10 << ep)) {
+
+ /* Timeout or underrun */
+ if (tx_cbd[ep]->cbd_sc & 0x06) {
+ ret = 1;
+ mpc8xx_udc_flush_tx_fifo (ep);
+
+ } else {
+ if (usbp->usep[ep] & STALL_BITMASK) {
+ if (!ep) {
+ usbp->usep[ep] &= ~STALL_BITMASK;
+ }
+ } /* else NAK */
+ }
+ usbp->usber |= (0x10 << ep);
+ }
+ }
+ return ret;
+}
+
+/* mpc8xx_udc_advance_rx
+ *
+ * Advance cbd rx
+ */
+static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid)
+{
+ if ((*rx_cbdp)->cbd_sc & RX_BD_W) {
+ *rx_cbdp = (volatile cbd_t *) (endpoints[epid]->rbase + CFG_IMMR);
+
+ } else {
+ (*rx_cbdp)++;
+ }
+}
+
+
+/* mpc8xx_udc_flush_tx_fifo
+ *
+ * Flush a given TX fifo. Assumes one tx cbd per endpoint
+ */
+static void mpc8xx_udc_flush_tx_fifo (int epid)
+{
+ volatile cbd_t *tx_cbdp = 0;
+
+ if (epid > MAX_ENDPOINTS) {
+ return;
+ }
+
+ /* TX stop */
+ immr->im_cpm.cp_cpcr = ((epid << 2) | 0x1D01);
+ __asm__ ("eieio");
+ while (immr->im_cpm.cp_cpcr & 0x01);
+
+ usbp->uscom = 0x40 | 0;
+
+ /* reset ring */
+ tx_cbdp = (cbd_t *) (endpoints[epid]->tbptr + CFG_IMMR);
+ tx_cbdp->cbd_sc = (TX_BD_I | TX_BD_W);
+
+
+ endpoints[epid]->tptr = endpoints[epid]->tbase;
+ endpoints[epid]->tstate = 0x00;
+ endpoints[epid]->tbcnt = 0x00;
+
+ /* TX start */
+ immr->im_cpm.cp_cpcr = ((epid << 2) | 0x2D01);
+ __asm__ ("eieio");
+ while (immr->im_cpm.cp_cpcr & 0x01);
+
+ return;
+}
+
+/* mpc8xx_udc_flush_rx_fifo
+ *
+ * For the sake of completeness of the namespace, it seems like
+ * a good-design-decision (tm) to include mpc8xx_udc_flush_rx_fifo();
+ * If RX_BD_E is true => a driver bug either here or in an upper layer
+ * not polling frequently enough. If RX_BD_E is true we have told the host
+ * we have accepted data but, the CPM found it had no-where to put that data
+ * which needless to say would be a bad thing.
+ */
+static void mpc8xx_udc_flush_rx_fifo ()
+{
+ int i = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) {
+ ERR ("buf %p used rx data len = 0x%x sc=0x%x!\n",
+ rx_cbd[i], rx_cbd[i]->cbd_datlen,
+ rx_cbd[i]->cbd_sc);
+
+ }
+ }
+ ERR ("BUG : Input over-run\n");
+}
+
+/* mpc8xx_udc_clear_rxbd
+ *
+ * Release control of RX CBD to CP.
+ */
+static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp)
+{
+ rx_cbdp->cbd_datlen = 0x0000;
+ rx_cbdp->cbd_sc = ((rx_cbdp->cbd_sc & RX_BD_W) | (RX_BD_E | RX_BD_I));
+ __asm__ ("eieio");
+}
+
+/* mpc8xx_udc_tx_irq
+ *
+ * Parse for tx timeout, control RX or USB reset/busy conditions
+ * Return -1 on timeout, -2 on fatal error, else return zero
+ */
+static int mpc8xx_udc_tx_irq (int ep)
+{
+ int i = 0;
+
+ if (usbp->usber & (USB_TX_ERRMASK)) {
+ if (mpc8xx_udc_handle_txerr ()) {
+ /* Timeout, controlling function must retry send */
+ return -1;
+ }
+ }
+
+ if (usbp->usber & (USB_E_RESET | USB_E_BSY)) {
+ /* Fatal, abandon TX transaction */
+ return -2;
+ }
+
+ if (usbp->usber & USB_E_RXB) {
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) {
+ if ((rx_cbd[i] == ep_ref[0].prx) || ep) {
+ return -2;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* mpc8xx_udc_ep_tx
+ *
+ * Transmit in a re-entrant fashion outbound USB packets.
+ * Implement retry/timeout mechanism described in USB specification
+ * Toggle DATA0/DATA1 pids as necessary
+ * Introduces non-standard tx_retry. The USB standard has no scope for slave
+ * devices to give up TX, however tx_retry stops us getting stuck in an endless
+ * TX loop.
+ */
+static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi)
+{
+ struct urb *urb = epi->tx_urb;
+ volatile cbd_t *tx_cbdp = 0;
+ unsigned int ep = 0, pkt_len = 0, x = 0, tx_retry = 0;
+ int ret = 0;
+
+ if (!epi || (epi->endpoint_address & 0x03) >= MAX_ENDPOINTS || !urb) {
+ return -1;
+ }
+
+ ep = epi->endpoint_address & 0x03;
+ tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CFG_IMMR);
+
+ if (tx_cbdp->cbd_sc & TX_BD_R || usbp->usber & USB_E_TXB) {
+ mpc8xx_udc_flush_tx_fifo (ep);
+ usbp->usber |= USB_E_TXB;
+ };
+
+ while (tx_retry++ < 100) {
+ ret = mpc8xx_udc_tx_irq (ep);
+ if (ret == -1) {
+ /* ignore timeout here */
+ } else if (ret == -2) {
+ /* Abandon TX */
+ mpc8xx_udc_flush_tx_fifo (ep);
+ return -1;
+ }
+
+ tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CFG_IMMR);
+ while (tx_cbdp->cbd_sc & TX_BD_R) {
+ };
+ tx_cbdp->cbd_sc = (tx_cbdp->cbd_sc & TX_BD_W);
+
+ pkt_len = urb->actual_length - epi->sent;
+
+ if (pkt_len > epi->tx_packetSize || pkt_len > EP_MAX_PKT) {
+ pkt_len = MIN (epi->tx_packetSize, EP_MAX_PKT);
+ }
+
+ for (x = 0; x < pkt_len; x++) {
+ *((unsigned char *) (tx_cbdp->cbd_bufaddr + x)) =
+ urb->buffer[epi->sent + x];
+ }
+ tx_cbdp->cbd_datlen = pkt_len;
+ tx_cbdp->cbd_sc |= (CBD_TX_BITMASK | ep_ref[ep].pid);
+ __asm__ ("eieio");
+
+#ifdef __SIMULATE_ERROR__
+ if (++err_poison_test == 2) {
+ err_poison_test = 0;
+ tx_cbdp->cbd_sc &= ~TX_BD_TC;
+ }
+#endif
+
+ usbp->uscom = (USCOM_STR | ep);
+
+ while (!(usbp->usber & USB_E_TXB)) {
+ ret = mpc8xx_udc_tx_irq (ep);
+ if (ret == -1) {
+ /* TX timeout */
+ break;
+ } else if (ret == -2) {
+ if (usbp->usber & USB_E_TXB) {
+ usbp->usber |= USB_E_TXB;
+ }
+ mpc8xx_udc_flush_tx_fifo (ep);
+ return -1;
+ }
+ };
+
+ if (usbp->usber & USB_E_TXB) {
+ usbp->usber |= USB_E_TXB;
+ }
+
+ /* ACK must be present <= 18bit times from TX */
+ if (ret == -1) {
+ continue;
+ }
+
+ /* TX ACK : USB 2.0 8.7.2, Toggle PID, Advance TX */
+ epi->sent += pkt_len;
+ epi->last = MIN (urb->actual_length - epi->sent, epi->tx_packetSize);
+ TOGGLE_TX_PID (ep_ref[ep].pid);
+
+ if (epi->sent >= epi->tx_urb->actual_length) {
+
+ epi->tx_urb->actual_length = 0;
+ epi->sent = 0;
+
+ if (ep_ref[ep].sc & EP_SEND_ZLP) {
+ ep_ref[ep].sc &= ~EP_SEND_ZLP;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ ERR ("TX fail, endpoint 0x%x tx bytes 0x%x/0x%x\n", ep, epi->sent,
+ epi->tx_urb->actual_length);
+
+ return -1;
+}
+
+/* mpc8xx_udc_dump_request
+ *
+ * Dump a control request to console
+ */
+static void mpc8xx_udc_dump_request (struct usb_device_request *request)
+{
+ DBG ("bmRequestType:%02x bRequest:%02x wValue:%04x "
+ "wIndex:%04x wLength:%04x ?\n",
+ request->bmRequestType,
+ request->bRequest,
+ request->wValue, request->wIndex, request->wLength);
+
+ return;
+}
+
+/* mpc8xx_udc_ep0_rx_setup
+ *
+ * Decode received ep0 SETUP packet. return non-zero on error
+ */
+static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp)
+{
+ unsigned int x = 0;
+ struct urb *purb = ep_ref[0].urb;
+ struct usb_endpoint_instance *epi =
+ &udc_device->bus->endpoint_array[0];
+
+ for (; x < rx_cbdp->cbd_datlen; x++) {
+ *(((unsigned char *) &ep_ref[0].urb->device_request) + x) =
+ *((unsigned char *) (rx_cbdp->cbd_bufaddr + x));
+ }
+
+ mpc8xx_udc_clear_rxbd (rx_cbdp);
+
+ if (ep0_recv_setup (purb)) {
+ mpc8xx_udc_dump_request (&purb->device_request);
+ return -1;
+ }
+
+ if ((purb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)
+ == USB_REQ_HOST2DEVICE) {
+
+ switch (purb->device_request.bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ /* Send the Status OUT ZLP */
+ ep_ref[0].pid = TX_BD_PID_DATA1;
+ purb->actual_length = 0;
+ mpc8xx_udc_init_tx (epi, purb);
+ mpc8xx_udc_ep_tx (epi);
+
+ /* Move to the addressed state */
+ usbp->usaddr = udc_device->address;
+ mpc8xx_udc_state_transition_up (udc_device->device_state,
+ STATE_ADDRESSED);
+ return 0;
+
+ case USB_REQ_SET_CONFIGURATION:
+ if (!purb->device_request.wValue) {
+ /* Respond at default address */
+ usbp->usaddr = 0x00;
+ mpc8xx_udc_state_transition_down (udc_device->device_state,
+ STATE_ADDRESSED);
+ } else {
+ /* TODO: Support multiple configurations */
+ mpc8xx_udc_state_transition_up (udc_device->device_state,
+ STATE_CONFIGURED);
+ for (x = 1; x < MAX_ENDPOINTS; x++) {
+ if ((udc_device->bus->endpoint_array[x].endpoint_address & USB_ENDPOINT_DIR_MASK)
+ == USB_DIR_IN) {
+ ep_ref[x].pid = TX_BD_PID_DATA0;
+ } else {
+ ep_ref[x].pid = RX_BD_PID_DATA0;
+ }
+ /* Set configuration must unstall endpoints */
+ usbp->usep[x] &= ~STALL_BITMASK;
+ }
+ }
+ break;
+ default:
+ /* CDC/Vendor specific */
+ break;
+ }
+
+ /* Send ZLP as ACK in Status OUT phase */
+ ep_ref[0].pid = TX_BD_PID_DATA1;
+ purb->actual_length = 0;
+ mpc8xx_udc_init_tx (epi, purb);
+ mpc8xx_udc_ep_tx (epi);
+
+ } else {
+
+ if (purb->actual_length) {
+ ep_ref[0].pid = TX_BD_PID_DATA1;
+ mpc8xx_udc_init_tx (epi, purb);
+
+ if (!(purb->actual_length % EP0_MAX_PACKET_SIZE)) {
+ ep_ref[0].sc |= EP_SEND_ZLP;
+ }
+
+ if (purb->device_request.wValue ==
+ USB_DESCRIPTOR_TYPE_DEVICE) {
+ if (le16_to_cpu (purb->device_request.wLength)
+ > purb->actual_length) {
+ /* Send EP0_MAX_PACKET_SIZE bytes
+ * unless correct size requested.
+ */
+ if (purb->actual_length > epi->tx_packetSize) {
+ purb->actual_length = epi->tx_packetSize;
+ }
+ }
+ }
+ mpc8xx_udc_ep_tx (epi);
+
+ } else {
+ /* Corrupt SETUP packet? */
+ ERR ("Zero length data or SETUP with DATA-IN phase ?\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* mpc8xx_udc_init_tx
+ *
+ * Setup some basic parameters for a TX transaction
+ */
+static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,
+ struct urb *tx_urb)
+{
+ epi->sent = 0;
+ epi->last = 0;
+ epi->tx_urb = tx_urb;
+}
+
+/* mpc8xx_udc_ep0_rx
+ *
+ * Receive ep0/control USB data. Parse and possibly send a response.
+ */
+static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp)
+{
+ if (rx_cbdp->cbd_sc & RX_BD_PID_SETUP) {
+
+ /* Unconditionally accept SETUP packets */
+ if (mpc8xx_udc_ep0_rx_setup (rx_cbdp)) {
+ mpc8xx_udc_stall (0);
+ }
+
+ } else {
+
+ mpc8xx_udc_clear_rxbd (rx_cbdp);
+
+ if ((rx_cbdp->cbd_datlen - 2)) {
+ /* SETUP with a DATA phase
+ * outside of SETUP packet.
+ * Reply with STALL.
+ */
+ mpc8xx_udc_stall (0);
+ }
+ }
+}
+
+/* mpc8xx_udc_epn_rx
+ *
+ * Receive some data from cbd into USB system urb data abstraction
+ * Upper layers should NAK if there is insufficient RX data space
+ */
+static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp)
+{
+ struct usb_endpoint_instance *epi = 0;
+ struct urb *urb = 0;
+ unsigned int x = 0;
+
+ if (epid >= MAX_ENDPOINTS || !rx_cbdp->cbd_datlen) {
+ return 0;
+ }
+
+ /* USB 2.0 PDF section 8.6.4
+ * Discard data with invalid PID it is a resend.
+ */
+ if (ep_ref[epid].pid != (rx_cbdp->cbd_sc & 0xC0)) {
+ return 1;
+ }
+ TOGGLE_RX_PID (ep_ref[epid].pid);
+
+ epi = &udc_device->bus->endpoint_array[epid];
+ urb = epi->rcv_urb;
+
+ for (; x < (rx_cbdp->cbd_datlen - 2); x++) {
+ *((unsigned char *) (urb->buffer + urb->actual_length + x)) =
+ *((unsigned char *) (rx_cbdp->cbd_bufaddr + x));
+ }
+
+ if (x) {
+ usbd_rcv_complete (epi, x, 0);
+ if (ep_ref[epid].urb->status == RECV_ERROR) {
+ DBG ("RX error unset NAK\n");
+ udc_unset_nak (epid);
+ }
+ }
+ return x;
+}
+
+/* mpc8xx_udc_clock_init
+ *
+ * Obtain a clock reference for Full Speed Signaling
+ */
+static void mpc8xx_udc_clock_init (volatile immap_t * immr,
+ volatile cpm8xx_t * cp)
+{
+
+#if defined(CFG_USB_EXTC_CLK)
+
+ /* This has been tested with a 48MHz crystal on CLK6 */
+ switch (CFG_USB_EXTC_CLK) {
+ case 1:
+ immr->im_ioport.iop_papar |= 0x0100;
+ immr->im_ioport.iop_padir &= ~0x0100;
+ cp->cp_sicr |= 0x24;
+ break;
+ case 2:
+ immr->im_ioport.iop_papar |= 0x0200;
+ immr->im_ioport.iop_padir &= ~0x0200;
+ cp->cp_sicr |= 0x2D;
+ break;
+ case 3:
+ immr->im_ioport.iop_papar |= 0x0400;
+ immr->im_ioport.iop_padir &= ~0x0400;
+ cp->cp_sicr |= 0x36;
+ break;
+ case 4:
+ immr->im_ioport.iop_papar |= 0x0800;
+ immr->im_ioport.iop_padir &= ~0x0800;
+ cp->cp_sicr |= 0x3F;
+ break;
+ default:
+ udc_state = STATE_ERROR;
+ break;
+ }
+
+#elif defined(CFG_USB_BRGCLK)
+
+ /* This has been tested with brgclk == 50MHz */
+ int divisor = 0;
+
+ if (gd->cpu_clk < 48000000L) {
+ ERR ("brgclk is too slow for full-speed USB!\n");
+ udc_state = STATE_ERROR;
+ return;
+ }
+
+ /* Assume the brgclk is 'good enough', we want !(gd->cpu_clk%48Mhz)
+ * but, can /probably/ live with close-ish alternative rates.
+ */
+ divisor = (gd->cpu_clk / 48000000L) - 1;
+ cp->cp_sicr &= ~0x0000003F;
+
+ switch (CFG_USB_BRGCLK) {
+ case 1:
+ cp->cp_brgc1 |= (divisor | CPM_BRG_EN);
+ cp->cp_sicr &= ~0x2F;
+ break;
+ case 2:
+ cp->cp_brgc2 |= (divisor | CPM_BRG_EN);
+ cp->cp_sicr |= 0x00000009;
+ break;
+ case 3:
+ cp->cp_brgc3 |= (divisor | CPM_BRG_EN);
+ cp->cp_sicr |= 0x00000012;
+ break;
+ case 4:
+ cp->cp_brgc4 = (divisor | CPM_BRG_EN);
+ cp->cp_sicr |= 0x0000001B;
+ break;
+ default:
+ udc_state = STATE_ERROR;
+ break;
+ }
+
+#else
+#error "CFG_USB_EXTC_CLK or CFG_USB_BRGCLK must be defined"
+#endif
+
+}
+
+/* mpc8xx_udc_cbd_attach
+ *
+ * attach a cbd to and endpoint
+ */
+static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size)
+{
+
+ if (!tx_cbd[ep] || !rx_cbd[ep] || ep >= MAX_ENDPOINTS) {
+ udc_state = STATE_ERROR;
+ return;
+ }
+
+ if (tx_size > USB_MAX_PKT || rx_size > USB_MAX_PKT ||
+ (!tx_size && !rx_size)) {
+ udc_state = STATE_ERROR;
+ return;
+ }
+
+ /* Attach CBD to appropiate Parameter RAM Endpoint data structure */
+ if (rx_size) {
+ endpoints[ep]->rbase = (u32) rx_cbd[rx_ct];
+ endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
+ rx_ct++;
+
+ if (!ep) {
+
+ endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
+ rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;
+ rx_ct++;
+
+ } else {
+ rx_ct += 2;
+ endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];
+ rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;
+ rx_ct++;
+ }
+
+ /* Where we expect to RX data on this endpoint */
+ ep_ref[ep].prx = rx_cbd[rx_ct - 1];
+ } else {
+
+ ep_ref[ep].prx = 0;
+ endpoints[ep]->rbase = 0;
+ endpoints[ep]->rbptr = 0;
+ }
+
+ if (tx_size) {
+ endpoints[ep]->tbase = (u32) tx_cbd[tx_ct];
+ endpoints[ep]->tbptr = (u32) tx_cbd[tx_ct];
+ tx_ct++;
+ } else {
+ endpoints[ep]->tbase = 0;
+ endpoints[ep]->tbptr = 0;
+ }
+
+ endpoints[ep]->tstate = 0;
+ endpoints[ep]->tbcnt = 0;
+ endpoints[ep]->mrblr = EP_MAX_PKT;
+ endpoints[ep]->rfcr = 0x18;
+ endpoints[ep]->tfcr = 0x18;
+ ep_ref[ep].sc |= EP_ATTACHED;
+
+ DBG ("ep %d rbase 0x%08x rbptr 0x%08x tbase 0x%08x tbptr 0x%08x prx = %p\n",
+ ep, endpoints[ep]->rbase, endpoints[ep]->rbptr,
+ endpoints[ep]->tbase, endpoints[ep]->tbptr,
+ ep_ref[ep].prx);
+
+ return;
+}
+
+/* mpc8xx_udc_cbd_init
+ *
+ * Allocate space for a cbd and allocate TX/RX data space
+ */
+static void mpc8xx_udc_cbd_init (void)
+{
+ int i = 0;
+
+ for (; i < TX_RING_SIZE; i++) {
+ tx_cbd[i] = (cbd_t *)
+ mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));
+ }
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_cbd[i] = (cbd_t *)
+ mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));
+ }
+
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ tx_cbd[i]->cbd_bufaddr =
+ mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));
+
+ tx_cbd[i]->cbd_sc = (TX_BD_I | TX_BD_W);
+ tx_cbd[i]->cbd_datlen = 0x0000;
+ }
+
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_cbd[i]->cbd_bufaddr =
+ mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));
+ rx_cbd[i]->cbd_sc = (RX_BD_I | RX_BD_E);
+ rx_cbd[i]->cbd_datlen = 0x0000;
+
+ }
+
+ return;
+}
+
+/* mpc8xx_udc_endpoint_init
+ *
+ * Attach an endpoint to some dpram
+ */
+static void mpc8xx_udc_endpoint_init (void)
+{
+ int i = 0;
+
+ for (; i < MAX_ENDPOINTS; i++) {
+ endpoints[i] = (usb_epb_t *)
+ mpc8xx_udc_alloc (sizeof (usb_epb_t), 32);
+ }
+}
+
+/* mpc8xx_udc_alloc
+ *
+ * Grab the address of some dpram
+ */
+static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment)
+{
+ u32 retaddr = address_base;
+
+ while (retaddr % alignment) {
+ retaddr++;
+ }
+ address_base += data_size;
+
+ return retaddr;
+}
+
+#endif /* CONFIG_MPC885_FAMILY && CONFIG_USB_DEVICE) */
diff --git a/drivers/usbdcore_omap1510.c b/drivers/usbdcore_omap1510.c
index 1d54a63575..84bb936d86 100644
--- a/drivers/usbdcore_omap1510.c
+++ b/drivers/usbdcore_omap1510.c
@@ -1517,4 +1517,31 @@ void udc_startup_events (struct usb_device_instance *device)
udc_enable (device);
}
+/**
+ * udc_irq - do pseudo interrupts
+ */
+void udc_irq(void)
+{
+ /* Loop while we have interrupts.
+ * If we don't do this, the input chain
+ * polling delay is likely to miss
+ * host requests.
+ */
+ while (inw (UDC_IRQ_SRC) & ~UDC_SOF_Flg) {
+ /* Handle any new IRQs */
+ omap1510_udc_irq ();
+ omap1510_udc_noniso_irq ();
+ }
+}
+
+/* Flow control */
+void udc_set_nak(int epid)
+{
+ /* TODO: implement this functionality in omap1510 */
+}
+
+void udc_unset_nak (int epid)
+{
+ /* TODO: implement this functionality in omap1510 */
+}
#endif
diff --git a/drivers/usbtty.c b/drivers/usbtty.c
index ce4a12e16e..a3b50131df 100644
--- a/drivers/usbtty.c
+++ b/drivers/usbtty.c
@@ -2,6 +2,9 @@
* (C) Copyright 2003
* Gerry Hamel, geh@ti.com, Texas Instruments
*
+ * (C) Copyright 2006
+ * Bryan O'Donoghue, bodonoghue@codehermit.ie
+ *
* 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
@@ -25,20 +28,42 @@
#include <circbuf.h>
#include <devices.h>
#include "usbtty.h"
+#include "usb_cdc_acm.h"
+#include "usbdescriptors.h"
+#include <config.h> /* If defined, override Linux identifiers with
+ * vendor specific ones */
#if 0
-#define TTYDBG(fmt,args...) serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)
+#define TTYDBG(fmt,args...)\
+ serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)
#else
#define TTYDBG(fmt,args...) do{}while(0)
#endif
-#if 0
-#define TTYERR(fmt,args...) serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)
+#if 1
+#define TTYERR(fmt,args...)\
+ serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\
+ __LINE__,##args)
#else
#define TTYERR(fmt,args...) do{}while(0)
#endif
/*
+ * Defines
+ */
+#define NUM_CONFIGS 1
+#define MAX_INTERFACES 2
+#define NUM_ENDPOINTS 3
+#define ACM_TX_ENDPOINT 3
+#define ACM_RX_ENDPOINT 2
+#define GSERIAL_TX_ENDPOINT 2
+#define GSERIAL_RX_ENDPOINT 1
+#define NUM_ACM_INTERFACES 2
+#define NUM_GSERIAL_INTERFACES 1
+#define CONFIG_USBD_DATA_INTERFACE_STR "Bulk Data Interface"
+#define CONFIG_USBD_CTRL_INTERFACE_STR "Control Interface"
+
+/*
* Buffers to hold input and output data
*/
#define USBTTY_BUFFER_SIZE 256
@@ -50,157 +75,336 @@ static circbuf_t usbtty_output;
* Instance variables
*/
static device_t usbttydev;
-static struct usb_device_instance device_instance[1];
-static struct usb_bus_instance bus_instance[1];
+static struct usb_device_instance device_instance[1];
+static struct usb_bus_instance bus_instance[1];
static struct usb_configuration_instance config_instance[NUM_CONFIGS];
-static struct usb_interface_instance interface_instance[NUM_INTERFACES];
-static struct usb_alternate_instance alternate_instance[NUM_INTERFACES];
-static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1]; /* one extra for control endpoint */
-
-/*
- * Static allocation of urbs
- */
-#define RECV_ENDPOINT 1
-#define TX_ENDPOINT 2
+static struct usb_interface_instance interface_instance[MAX_INTERFACES];
+static struct usb_alternate_instance alternate_instance[MAX_INTERFACES];
+/* one extra for control endpoint */
+static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1];
/*
* Global flag
*/
int usbtty_configured_flag = 0;
-
/*
* Serial number
*/
static char serial_number[16];
+
/*
- * Descriptors
+ * Descriptors, Strings, Local variables.
*/
+
+/* defined and used by usbdcore_ep0.c */
+extern struct usb_string_descriptor **usb_strings;
+
+/* Indicies, References */
+static unsigned short rx_endpoint = 0;
+static unsigned short tx_endpoint = 0;
+static unsigned short interface_count = 0;
+static struct usb_string_descriptor *usbtty_string_table[STR_COUNT];
+
+/* USB Descriptor Strings */
static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4};
static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)];
static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)];
static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)];
static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)];
-static u8 wstrInterface[2 + 2*(sizeof(CONFIG_USBD_INTERFACE_STR)-1)];
-
-static struct usb_string_descriptor *usbtty_string_table[] = {
- (struct usb_string_descriptor*)wstrLang,
- (struct usb_string_descriptor*)wstrManufacturer,
- (struct usb_string_descriptor*)wstrProduct,
- (struct usb_string_descriptor*)wstrSerial,
- (struct usb_string_descriptor*)wstrConfiguration,
- (struct usb_string_descriptor*)wstrInterface
-};
-extern struct usb_string_descriptor **usb_strings; /* defined and used by omap1510_ep0.c */
+static u8 wstrDataInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
+static u8 wstrCtrlInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
+/* Standard USB Data Structures */
+static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES];
+static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS];
+static struct usb_configuration_descriptor *configuration_descriptor = 0;
static struct usb_device_descriptor device_descriptor = {
- bLength: sizeof(struct usb_device_descriptor),
- bDescriptorType: USB_DT_DEVICE,
- bcdUSB: USB_BCD_VERSION,
- bDeviceClass: USBTTY_DEVICE_CLASS,
- bDeviceSubClass: USBTTY_DEVICE_SUBCLASS,
- bDeviceProtocol: USBTTY_DEVICE_PROTOCOL,
- bMaxPacketSize0: EP0_MAX_PACKET_SIZE,
- idVendor: CONFIG_USBD_VENDORID,
- idProduct: CONFIG_USBD_PRODUCTID,
- bcdDevice: USBTTY_BCD_DEVICE,
- iManufacturer: STR_MANUFACTURER,
- iProduct: STR_PRODUCT,
- iSerialNumber: STR_SERIAL,
- bNumConfigurations: NUM_CONFIGS
- };
-static struct usb_configuration_descriptor config_descriptors[NUM_CONFIGS] = {
- {
- bLength: sizeof(struct usb_configuration_descriptor),
- bDescriptorType: USB_DT_CONFIG,
- wTotalLength: (sizeof(struct usb_configuration_descriptor)*NUM_CONFIGS) +
- (sizeof(struct usb_interface_descriptor)*NUM_INTERFACES) +
- (sizeof(struct usb_endpoint_descriptor)*NUM_ENDPOINTS),
- bNumInterfaces: NUM_INTERFACES,
- bConfigurationValue: 1,
- iConfiguration: STR_CONFIG,
- bmAttributes: BMATTRIBUTE_SELF_POWERED | BMATTRIBUTE_RESERVED,
- bMaxPower: USBTTY_MAXPOWER
- },
-};
-static struct usb_interface_descriptor interface_descriptors[NUM_INTERFACES] = {
- {
- bLength: sizeof(struct usb_interface_descriptor),
- bDescriptorType: USB_DT_INTERFACE,
- bInterfaceNumber: 0,
- bAlternateSetting: 0,
- bNumEndpoints: NUM_ENDPOINTS,
- bInterfaceClass: USBTTY_INTERFACE_CLASS,
- bInterfaceSubClass: USBTTY_INTERFACE_SUBCLASS,
- bInterfaceProtocol: USBTTY_INTERFACE_PROTOCOL,
- iInterface: STR_INTERFACE
- },
+ .bLength = sizeof(struct usb_device_descriptor),
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = cpu_to_le16(USB_BCD_VERSION),
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+ .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE,
+ .idVendor = cpu_to_le16(CONFIG_USBD_VENDORID),
+ .bcdDevice = cpu_to_le16(USBTTY_BCD_DEVICE),
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT,
+ .iSerialNumber = STR_SERIAL,
+ .bNumConfigurations = NUM_CONFIGS
};
-static struct usb_endpoint_descriptor ep_descriptors[NUM_ENDPOINTS] = {
- {
- bLength: sizeof(struct usb_endpoint_descriptor),
- bDescriptorType: USB_DT_ENDPOINT,
- bEndpointAddress: CONFIG_USBD_SERIAL_OUT_ENDPOINT | USB_DIR_OUT,
- bmAttributes: USB_ENDPOINT_XFER_BULK,
- wMaxPacketSize: CONFIG_USBD_SERIAL_OUT_PKTSIZE,
- bInterval: 0
- },
- {
- bLength: sizeof(struct usb_endpoint_descriptor),
- bDescriptorType: USB_DT_ENDPOINT,
- bEndpointAddress: CONFIG_USBD_SERIAL_IN_ENDPOINT | USB_DIR_IN,
- bmAttributes: USB_ENDPOINT_XFER_BULK,
- wMaxPacketSize: CONFIG_USBD_SERIAL_IN_PKTSIZE,
- bInterval: 0
- },
- {
- bLength: sizeof(struct usb_endpoint_descriptor),
- bDescriptorType: USB_DT_ENDPOINT,
- bEndpointAddress: CONFIG_USBD_SERIAL_INT_ENDPOINT | USB_DIR_IN,
- bmAttributes: USB_ENDPOINT_XFER_INT,
- wMaxPacketSize: CONFIG_USBD_SERIAL_INT_PKTSIZE,
- bInterval: 0
- },
+
+
+/*
+ * Static CDC ACM specific descriptors
+ */
+
+struct acm_config_desc {
+ struct usb_configuration_descriptor configuration_desc;
+
+ /* Master Interface */
+ struct usb_interface_descriptor interface_desc;
+
+ struct usb_class_header_function_descriptor usb_class_header;
+ struct usb_class_call_management_descriptor usb_class_call_mgt;
+ struct usb_class_abstract_control_descriptor usb_class_acm;
+ struct usb_class_union_function_descriptor usb_class_union;
+ struct usb_endpoint_descriptor notification_endpoint;
+
+ /* Slave Interface */
+ struct usb_interface_descriptor data_class_interface;
+ struct usb_endpoint_descriptor
+ data_endpoints[NUM_ENDPOINTS-1] __attribute__((packed));
+} __attribute__((packed));
+
+static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = {
+ {
+ .configuration_desc ={
+ .bLength =
+ sizeof(struct usb_configuration_descriptor),
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength =
+ cpu_to_le16(sizeof(struct acm_config_desc)),
+ .bNumInterfaces = NUM_ACM_INTERFACES,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG,
+ .bmAttributes =
+ BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED,
+ .bMaxPower = USBTTY_MAXPOWER
+ },
+ /* Interface 1 */
+ .interface_desc = {
+ .bLength = sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0x01,
+ .bInterfaceClass =
+ COMMUNICATIONS_INTERFACE_CLASS_CONTROL,
+ .bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS,
+ .bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL,
+ .iInterface = STR_CTRL_INTERFACE,
+ },
+ .usb_class_header = {
+ .bFunctionLength =
+ sizeof(struct usb_class_header_function_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_ST_HEADER,
+ .bcdCDC = cpu_to_le16(110),
+ },
+ .usb_class_call_mgt = {
+ .bFunctionLength =
+ sizeof(struct usb_class_call_management_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_ST_CMF,
+ .bmCapabilities = 0x00,
+ .bDataInterface = 0x01,
+ },
+ .usb_class_acm = {
+ .bFunctionLength =
+ sizeof(struct usb_class_abstract_control_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_ST_ACMF,
+ .bmCapabilities = 0x00,
+ },
+ .usb_class_union = {
+ .bFunctionLength =
+ sizeof(struct usb_class_union_function_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_ST_UF,
+ .bMasterInterface = 0x00,
+ .bSlaveInterface0 = 0x01,
+ },
+ .notification_endpoint = {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x01 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize
+ = cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+
+ /* Interface 2 */
+ .data_class_interface = {
+ .bLength =
+ sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0x01,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 0x02,
+ .bInterfaceClass =
+ COMMUNICATIONS_INTERFACE_CLASS_DATA,
+ .bInterfaceSubClass = DATA_INTERFACE_SUBCLASS_NONE,
+ .bInterfaceProtocol = DATA_INTERFACE_PROTOCOL_NONE,
+ .iInterface = STR_DATA_INTERFACE,
+ },
+ .data_endpoints = {
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x02 | USB_DIR_OUT,
+ .bmAttributes =
+ USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x03 | USB_DIR_IN,
+ .bmAttributes =
+ USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+ },
+ },
};
-static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS] = {
- &(ep_descriptors[0]),
- &(ep_descriptors[1]),
- &(ep_descriptors[2]),
+
+static struct rs232_emu rs232_desc={
+ .dter = 115200,
+ .stop_bits = 0x00,
+ .parity = 0x00,
+ .data_bits = 0x08
};
-/* utility function for converting char* to wide string used by USB */
-static void str2wide (char *str, u16 * wide)
-{
- int i;
- for (i = 0; i < strlen (str) && str[i]; i++)
- wide[i] = (u16) str[i];
-}
+/*
+ * Static Generic Serial specific data
+ */
+
+
+struct gserial_config_desc {
+
+ struct usb_configuration_descriptor configuration_desc;
+ struct usb_interface_descriptor
+ interface_desc[NUM_GSERIAL_INTERFACES] __attribute__((packed));
+ struct usb_endpoint_descriptor
+ data_endpoints[NUM_ENDPOINTS] __attribute__((packed));
+
+} __attribute__((packed));
+
+static struct gserial_config_desc
+gserial_configuration_descriptors[NUM_CONFIGS] ={
+ {
+ .configuration_desc ={
+ .bLength = sizeof(struct usb_configuration_descriptor),
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength =
+ cpu_to_le16(sizeof(struct gserial_config_desc)),
+ .bNumInterfaces = NUM_GSERIAL_INTERFACES,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG,
+ .bmAttributes =
+ BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED,
+ .bMaxPower = USBTTY_MAXPOWER
+ },
+ .interface_desc = {
+ {
+ .bLength =
+ sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = NUM_ENDPOINTS,
+ .bInterfaceClass =
+ COMMUNICATIONS_INTERFACE_CLASS_VENDOR,
+ .bInterfaceSubClass =
+ COMMUNICATIONS_NO_SUBCLASS,
+ .bInterfaceProtocol =
+ COMMUNICATIONS_NO_PROTOCOL,
+ .iInterface = STR_DATA_INTERFACE
+ },
+ },
+ .data_endpoints = {
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x01 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_OUT_PKTSIZE),
+ .bInterval= 0xFF,
+ },
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x02 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_IN_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x03 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+ },
+ },
+};
/*
- * Prototypes
+ * Static Function Prototypes
*/
+
static void usbtty_init_strings (void);
static void usbtty_init_instances (void);
static void usbtty_init_endpoints (void);
-
+static void usbtty_init_terminal_type(short type);
static void usbtty_event_handler (struct usb_device_instance *device,
- usb_device_event_t event, int data);
+ usb_device_event_t event, int data);
+static int usbtty_cdc_setup(struct usb_device_request *request,
+ struct urb *urb);
static int usbtty_configured (void);
-
static int write_buffer (circbuf_t * buf);
static int fill_buffer (circbuf_t * buf);
void usbtty_poll (void);
-static void pretend_interrupts (void);
+/* utility function for converting char* to wide string used by USB */
+static void str2wide (char *str, u16 * wide)
+{
+ int i;
+ for (i = 0; i < strlen (str) && str[i]; i++){
+ #if defined(__LITTLE_ENDIAN)
+ wide[i] = (u16) str[i];
+ #elif defined(__BIG_ENDIAN)
+ wide[i] = ((u16)(str[i])<<8);
+ #else
+ #error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined"
+ #endif
+ }
+}
/*
* Test whether a character is in the RX buffer
*/
+
int usbtty_tstc (void)
{
+ struct usb_endpoint_instance *endpoint =
+ &endpoint_instance[rx_endpoint];
+
+ /* If no input data exists, allow more RX to be accepted */
+ if(usbtty_input.size <= 0){
+ udc_unset_nak(endpoint->endpoint_address&0x03);
+ }
+
usbtty_poll ();
return (usbtty_input.size > 0);
}
@@ -210,15 +414,21 @@ int usbtty_tstc (void)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
+
int usbtty_getc (void)
{
char c;
+ struct usb_endpoint_instance *endpoint =
+ &endpoint_instance[rx_endpoint];
while (usbtty_input.size <= 0) {
+ udc_unset_nak(endpoint->endpoint_address&0x03);
usbtty_poll ();
}
buf_pop (&usbtty_input, &c, 1);
+ udc_set_nak(endpoint->endpoint_address&0x03);
+
return c;
}
@@ -238,7 +448,6 @@ void usbtty_putc (const char c)
}
}
-
/* usbtty_puts() helper function for finding the next '\n' in a string */
static int next_nl_pos (const char *s)
{
@@ -252,8 +461,9 @@ static int next_nl_pos (const char *s)
}
/*
- * Output a string to the usb client port.
+ * Output a string to the usb client port - implementing flow control
*/
+
static void __usbtty_puts (const char *str, int len)
{
int maxlen = usbtty_output.totalsize;
@@ -261,22 +471,19 @@ static void __usbtty_puts (const char *str, int len)
/* break str into chunks < buffer size, if needed */
while (len > 0) {
- space = maxlen - usbtty_output.size;
+ usbtty_poll ();
+ space = maxlen - usbtty_output.size;
/* Empty buffer here, if needed, to ensure space... */
- if (space <= 0) {
+ if (space) {
write_buffer (&usbtty_output);
- space = maxlen - usbtty_output.size;
- if (space <= 0) {
- space = len; /* allow old data to be overwritten. */
- }
- }
- n = MIN (space, MIN (len, maxlen));
- buf_push (&usbtty_output, str, n);
+ n = MIN (space, MIN (len, maxlen));
+ buf_push (&usbtty_output, str, n);
- str += n;
- len -= n;
+ str += n;
+ len -= n;
+ }
}
}
@@ -313,8 +520,10 @@ int drv_usbtty_init (void)
{
int rc;
char * sn;
+ char * tt;
int snlen;
+ /* Ger seiral number */
if (!(sn = getenv("serial#"))) {
sn = "000000000000";
}
@@ -327,6 +536,14 @@ int drv_usbtty_init (void)
memcpy (serial_number, sn, snlen);
serial_number[snlen] = '\0';
+ /* Decide on which type of UDC device to be.
+ */
+
+ if(!(tt = getenv("usbtty"))) {
+ tt = "generic";
+ }
+ usbtty_init_terminal_type(strcmp(tt,"cdc_acm"));
+
/* prepare buffers... */
buf_init (&usbtty_input, USBTTY_BUFFER_SIZE);
buf_init (&usbtty_output, USBTTY_BUFFER_SIZE);
@@ -337,7 +554,7 @@ int drv_usbtty_init (void)
usbtty_init_strings ();
usbtty_init_instances ();
- udc_startup_events (device_instance); /* Enable our device, initialize udc pointers */
+ udc_startup_events (device_instance);/* Enable dev, init udc pointers */
udc_connect (); /* Enable pullup for host detection */
usbtty_init_endpoints ();
@@ -362,30 +579,48 @@ static void usbtty_init_strings (void)
{
struct usb_string_descriptor *string;
+ usbtty_string_table[STR_LANG] =
+ (struct usb_string_descriptor*)wstrLang;
+
string = (struct usb_string_descriptor *) wstrManufacturer;
- string->bLength = sizeof (wstrManufacturer);
+ string->bLength = sizeof(wstrManufacturer);
string->bDescriptorType = USB_DT_STRING;
str2wide (CONFIG_USBD_MANUFACTURER, string->wData);
+ usbtty_string_table[STR_MANUFACTURER]=string;
+
string = (struct usb_string_descriptor *) wstrProduct;
- string->bLength = sizeof (wstrProduct);
+ string->bLength = sizeof(wstrProduct);
string->bDescriptorType = USB_DT_STRING;
str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData);
+ usbtty_string_table[STR_PRODUCT]=string;
+
string = (struct usb_string_descriptor *) wstrSerial;
- string->bLength = 2 + 2*strlen(serial_number);
+ string->bLength = sizeof(serial_number);
string->bDescriptorType = USB_DT_STRING;
str2wide (serial_number, string->wData);
+ usbtty_string_table[STR_SERIAL]=string;
+
string = (struct usb_string_descriptor *) wstrConfiguration;
- string->bLength = sizeof (wstrConfiguration);
+ string->bLength = sizeof(wstrConfiguration);
string->bDescriptorType = USB_DT_STRING;
str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData);
+ usbtty_string_table[STR_CONFIG]=string;
- string = (struct usb_string_descriptor *) wstrInterface;
- string->bLength = sizeof (wstrInterface);
+
+ string = (struct usb_string_descriptor *) wstrDataInterface;
+ string->bLength = sizeof(wstrDataInterface);
string->bDescriptorType = USB_DT_STRING;
- str2wide (CONFIG_USBD_INTERFACE_STR, string->wData);
+ str2wide (CONFIG_USBD_DATA_INTERFACE_STR, string->wData);
+ usbtty_string_table[STR_DATA_INTERFACE]=string;
+
+ string = (struct usb_string_descriptor *) wstrCtrlInterface;
+ string->bLength = sizeof(wstrCtrlInterface);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_CTRL_INTERFACE_STR, string->wData);
+ usbtty_string_table[STR_CTRL_INTERFACE]=string;
/* Now, initialize the string table for ep0 handling */
usb_strings = usbtty_string_table;
@@ -400,6 +635,7 @@ static void usbtty_init_instances (void)
device_instance->device_state = STATE_INIT;
device_instance->device_descriptor = &device_descriptor;
device_instance->event = usbtty_event_handler;
+ device_instance->cdc_recv_setup = usbtty_cdc_setup;
device_instance->bus = bus_instance;
device_instance->configurations = NUM_CONFIGS;
device_instance->configuration_instance_array = config_instance;
@@ -415,8 +651,8 @@ static void usbtty_init_instances (void)
/* configuration instance */
memset (config_instance, 0,
sizeof (struct usb_configuration_instance));
- config_instance->interfaces = NUM_INTERFACES;
- config_instance->configuration_descriptor = config_descriptors;
+ config_instance->interfaces = interface_count;
+ config_instance->configuration_descriptor = configuration_descriptor;
config_instance->interface_instance_array = interface_instance;
/* interface instance */
@@ -447,17 +683,22 @@ static void usbtty_init_instances (void)
sizeof (struct usb_endpoint_instance));
endpoint_instance[i].endpoint_address =
- ep_descriptors[i - 1].bEndpointAddress;
+ ep_descriptor_ptrs[i - 1]->bEndpointAddress;
- endpoint_instance[i].rcv_packetSize =
- ep_descriptors[i - 1].wMaxPacketSize;
endpoint_instance[i].rcv_attributes =
- ep_descriptors[i - 1].bmAttributes;
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+ endpoint_instance[i].rcv_packetSize =
+ le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
+
+ endpoint_instance[i].tx_attributes =
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
endpoint_instance[i].tx_packetSize =
- ep_descriptors[i - 1].wMaxPacketSize;
+ le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
+
endpoint_instance[i].tx_attributes =
- ep_descriptors[i - 1].bmAttributes;
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
urb_link_init (&endpoint_instance[i].rcv);
urb_link_init (&endpoint_instance[i].rdy);
@@ -480,13 +721,79 @@ static void usbtty_init_endpoints (void)
int i;
bus_instance->max_endpoints = NUM_ENDPOINTS + 1;
- for (i = 0; i <= NUM_ENDPOINTS; i++) {
+ for (i = 1; i <= NUM_ENDPOINTS; i++) {
udc_setup_ep (device_instance, i, &endpoint_instance[i]);
}
}
+/* usbtty_init_terminal_type
+ *
+ * Do some late binding for our device type.
+ */
+static void usbtty_init_terminal_type(short type)
+{
+ switch(type){
+ /* CDC ACM */
+ case 0:
+ /* Assign endpoint descriptors */
+ ep_descriptor_ptrs[0] =
+ &acm_configuration_descriptors[0].notification_endpoint;
+ ep_descriptor_ptrs[1] =
+ &acm_configuration_descriptors[0].data_endpoints[0];
+ ep_descriptor_ptrs[2] =
+ &acm_configuration_descriptors[0].data_endpoints[1];
+
+ /* Enumerate Device Descriptor */
+ device_descriptor.bDeviceClass =
+ COMMUNICATIONS_DEVICE_CLASS;
+ device_descriptor.idProduct =
+ cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM);
+
+ /* Assign endpoint indices */
+ tx_endpoint = ACM_TX_ENDPOINT;
+ rx_endpoint = ACM_RX_ENDPOINT;
+
+ /* Configuration Descriptor */
+ configuration_descriptor =
+ (struct usb_configuration_descriptor*)
+ &acm_configuration_descriptors;
+
+ /* Interface count */
+ interface_count = NUM_ACM_INTERFACES;
+ break;
+
+ /* BULK IN/OUT & Default */
+ case 1:
+ default:
+ /* Assign endpoint descriptors */
+ ep_descriptor_ptrs[0] =
+ &gserial_configuration_descriptors[0].data_endpoints[0];
+ ep_descriptor_ptrs[1] =
+ &gserial_configuration_descriptors[0].data_endpoints[1];
+ ep_descriptor_ptrs[2] =
+ &gserial_configuration_descriptors[0].data_endpoints[2];
+
+ /* Enumerate Device Descriptor */
+ device_descriptor.bDeviceClass = 0xFF;
+ device_descriptor.idProduct =
+ cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL);
+
+ /* Assign endpoint indices */
+ tx_endpoint = GSERIAL_TX_ENDPOINT;
+ rx_endpoint = GSERIAL_RX_ENDPOINT;
+
+ /* Configuration Descriptor */
+ configuration_descriptor =
+ (struct usb_configuration_descriptor*)
+ &gserial_configuration_descriptors;
+
+ /* Interface count */
+ interface_count = NUM_GSERIAL_INTERFACES;
+ break;
+ }
+}
-/*********************************************************************************/
+/******************************************************************************/
static struct urb *next_urb (struct usb_device_instance *device,
struct usb_endpoint_instance *endpoint)
@@ -526,27 +833,39 @@ static int write_buffer (circbuf_t * buf)
return 0;
}
- if (buf->size) {
+ struct usb_endpoint_instance *endpoint =
+ &endpoint_instance[tx_endpoint];
+ struct urb *current_urb = NULL;
- struct usb_endpoint_instance *endpoint =
- &endpoint_instance[TX_ENDPOINT];
- struct urb *current_urb = NULL;
+ current_urb = next_urb (device_instance, endpoint);
+ /* TX data still exists - send it now
+ */
+ if(endpoint->sent < current_urb->actual_length){
+ if(udc_endpoint_write (endpoint)){
+ /* Write pre-empted by RX */
+ return -1;
+ }
+ }
+
+ if (buf->size) {
char *dest;
int space_avail;
int popnum, popped;
int total = 0;
- /* Break buffer into urb sized pieces, and link each to the endpoint */
+ /* Break buffer into urb sized pieces,
+ * and link each to the endpoint
+ */
while (buf->size > 0) {
- current_urb = next_urb (device_instance, endpoint);
+
if (!current_urb) {
TTYERR ("current_urb is NULL, buf->size %d\n",
buf->size);
return total;
}
- dest = current_urb->buffer +
+ dest = (char*)current_urb->buffer +
current_urb->actual_length;
space_avail =
@@ -562,14 +881,19 @@ static int write_buffer (circbuf_t * buf)
current_urb->actual_length += popped;
total += popped;
- /* If endpoint->last == 0, then transfers have not started on this endpoint */
+ /* If endpoint->last == 0, then transfers have
+ * not started on this endpoint
+ */
if (endpoint->last == 0) {
- udc_endpoint_write (endpoint);
+ if(udc_endpoint_write (endpoint)){
+ /* Write pre-empted by RX */
+ return -1;
+ }
}
- } /* end while */
+ }/* end while */
return total;
- } /* end if tx_urb */
+ }
return 0;
}
@@ -577,18 +901,22 @@ static int write_buffer (circbuf_t * buf)
static int fill_buffer (circbuf_t * buf)
{
struct usb_endpoint_instance *endpoint =
- &endpoint_instance[RECV_ENDPOINT];
+ &endpoint_instance[rx_endpoint];
if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) {
- unsigned int nb = endpoint->rcv_urb->actual_length;
+ unsigned int nb = 0;
char *src = (char *) endpoint->rcv_urb->buffer;
+ unsigned int rx_avail = buf->totalsize - buf->size;
+
+ if(rx_avail >= endpoint->rcv_urb->actual_length){
- buf_push (buf, src, nb);
- endpoint->rcv_urb->actual_length = 0;
+ nb = endpoint->rcv_urb->actual_length;
+ buf_push (buf, src, nb);
+ endpoint->rcv_urb->actual_length = 0;
+ }
return nb;
}
-
return 0;
}
@@ -597,7 +925,7 @@ static int usbtty_configured (void)
return usbtty_configured_flag;
}
-/*********************************************************************************/
+/******************************************************************************/
static void usbtty_event_handler (struct usb_device_instance *device,
usb_device_event_t event, int data)
@@ -619,8 +947,34 @@ static void usbtty_event_handler (struct usb_device_instance *device,
}
}
-/*********************************************************************************/
+/******************************************************************************/
+
+int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb)
+{
+ switch (request->bRequest){
+
+ case ACM_SET_CONTROL_LINE_STATE: /* Implies DTE ready */
+ break;
+ case ACM_SEND_ENCAPSULATED_COMMAND : /* Required */
+ break;
+ case ACM_SET_LINE_ENCODING : /* DTE stop/parity bits
+ * per character */
+ break;
+ case ACM_GET_ENCAPSULATED_RESPONSE : /* request response */
+ break;
+ case ACM_GET_LINE_ENCODING : /* request DTE rate,
+ * stop/parity bits */
+ memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc));
+ urb->actual_length = sizeof(rs232_desc);
+
+ break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+/******************************************************************************/
/*
* Since interrupt handling has not yet been implemented, we use this function
@@ -630,36 +984,29 @@ static void usbtty_event_handler (struct usb_device_instance *device,
void usbtty_poll (void)
{
/* New interrupts? */
- pretend_interrupts ();
+ udc_irq();
- /* Write any output data to host buffer (do this before checking interrupts to avoid missing one) */
+ /* Write any output data to host buffer
+ * (do this before checking interrupts to avoid missing one)
+ */
if (usbtty_configured ()) {
write_buffer (&usbtty_output);
}
/* New interrupts? */
- pretend_interrupts ();
+ udc_irq();
- /* Check for new data from host.. (do this after checking interrupts to get latest data) */
+ /* Check for new data from host..
+ * (do this after checking interrupts to get latest data)
+ */
if (usbtty_configured ()) {
fill_buffer (&usbtty_input);
}
/* New interrupts? */
- pretend_interrupts ();
-}
+ udc_irq();
-static void pretend_interrupts (void)
-{
- /* Loop while we have interrupts.
- * If we don't do this, the input chain
- * polling delay is likely to miss
- * host requests.
- */
- while (inw (UDC_IRQ_SRC) & ~UDC_SOF_Flg) {
- /* Handle any new IRQs */
- omap1510_udc_irq ();
- omap1510_udc_noniso_irq ();
- }
}
+
+
#endif
diff --git a/drivers/usbtty.h b/drivers/usbtty.h
index 79c2fe57d7..8154e3072e 100644
--- a/drivers/usbtty.h
+++ b/drivers/usbtty.h
@@ -2,6 +2,9 @@
* (C) Copyright 2003
* Gerry Hamel, geh@ti.com, Texas Instruments
*
+ * (C) Copyright 2006
+ * Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit
+ *
* 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
@@ -21,44 +24,47 @@
#ifndef __USB_TTY_H__
#define __USB_TTY_H__
-
#include "usbdcore.h"
+#if defined(CONFIG_PPC)
+#include "usbdcore_mpc8xx.h"
+#elif defined(CONFIG_ARM)
#include "usbdcore_omap1510.h"
+#endif
+#include <version_autogenerated.h>
-#define NUM_CONFIGS 1
-#define NUM_INTERFACES 1
-#define NUM_ENDPOINTS 3
+/* If no VendorID/ProductID is defined in config.h, pretend to be Linux
+ * DO NOT Reuse this Vendor/Product setup with protocol incompatible devices */
-#define EP0_MAX_PACKET_SIZE 64
+#define CONFIG_USBD_VENDORID 0x0525 /* Linux/NetChip */
+#define CONFIG_USBD_PRODUCTID_GSERIAL 0xa4a6 /* gserial */
+#define CONFIG_USBD_PRODUCTID_CDCACM 0xa4a7 /* CDC ACM */
+#define CONFIG_USBD_MANUFACTURER "Das U-Boot"
+#define CONFIG_USBD_PRODUCT_NAME U_BOOT_VERSION
-#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB"
-#define CONFIG_USBD_INTERFACE_STR "Simple Serial Data Interface - Bulk Mode"
+#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB"
-#define CONFIG_USBD_SERIAL_OUT_ENDPOINT 2
-#define CONFIG_USBD_SERIAL_OUT_PKTSIZE 64
-#define CONFIG_USBD_SERIAL_IN_ENDPOINT 1
-#define CONFIG_USBD_SERIAL_IN_PKTSIZE 64
-#define CONFIG_USBD_SERIAL_INT_ENDPOINT 5
-#define CONFIG_USBD_SERIAL_INT_PKTSIZE 16
-
+#define CONFIG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT
+#define CONFIG_USBD_SERIAL_OUT_PKTSIZE UDC_OUT_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_IN_ENDPOINT UDC_IN_ENDPOINT
+#define CONFIG_USBD_SERIAL_IN_PKTSIZE UDC_IN_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT
+#define CONFIG_USBD_SERIAL_INT_PKTSIZE UDC_INT_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_BULK_PKTSIZE UDC_BULK_PACKET_SIZE
#define USBTTY_DEVICE_CLASS COMMUNICATIONS_DEVICE_CLASS
-#define USBTTY_DEVICE_SUBCLASS COMMUNICATIONS_NO_SUBCLASS
-#define USBTTY_DEVICE_PROTOCOL COMMUNICATIONS_NO_PROTOCOL
-
-#define USBTTY_INTERFACE_CLASS 0xFF /* Vendor Specific */
-#define USBTTY_INTERFACE_SUBCLASS 0x02
-#define USBTTY_INTERFACE_PROTOCOL 0x01
-#define USBTTY_BCD_DEVICE 0x0
-#define USBTTY_MAXPOWER 0x0
+#define USBTTY_BCD_DEVICE 0x00
+#define USBTTY_MAXPOWER 0x00
-#define STR_MANUFACTURER 1
-#define STR_PRODUCT 2
-#define STR_SERIAL 3
-#define STR_CONFIG 4
-#define STR_INTERFACE 5
+#define STR_LANG 0x00
+#define STR_MANUFACTURER 0x01
+#define STR_PRODUCT 0x02
+#define STR_SERIAL 0x03
+#define STR_CONFIG 0x04
+#define STR_DATA_INTERFACE 0x05
+#define STR_CTRL_INTERFACE 0x06
+#define STR_COUNT 0x07
#endif
OpenPOWER on IntegriCloud