/*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
*
* ########################################################################
*
* This program is free software; you can distribute 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 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.
*
* ########################################################################
*
* SAA9730 ethernet driver.
*
* Changes:
* Angelo Dell'Aera <buffer@antifork.org> : Conversion to the new PCI API (pci_driver).
* Conversion to spinlocks.
* Error handling fixes.
*
*/
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <asm/addrspace.h>
#include <asm/mips-boards/prom.h>
#include "saa9730.h"
#ifdef LAN_SAA9730_DEBUG
int lan_saa9730_debug = LAN_SAA9730_DEBUG;
#else
int lan_saa9730_debug;
#endif
#define DRV_MODULE_NAME "saa9730"
static struct pci_device_id saa9730_pci_tbl[] = {
{ PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9370,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, saa9730_pci_tbl);
/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
static unsigned int pci_irq_line;
#define INL(a) inl((unsigned long)a)
#define OUTL(x,a) outl(x,(unsigned long)a)
static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp)
{
OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptBlock1);
OUTL(INL(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptStatus1);
OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT |
EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1);
}
static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp)
{
OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptBlock1);
OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptEnable1);
}
static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp)
{
OUTL(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1);
}
static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp)
{
OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptBlock1);
}
static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp)
{
OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptBlock1);
}
static void show_saa9730_regs(struct lan_saa9730_private *lp)
{
int i, j;
printk("TxmBufferA = %x\n", lp->TxmBuffer[0][0]);
printk("TxmBufferB = %x\n", lp->TxmBuffer[1][0]);
printk("RcvBufferA = %x\n", lp->RcvBuffer[0][0]);
printk("RcvBufferB = %x\n", lp->RcvBuffer[1][0]);
for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE;