Commit 605cafbe authored by Osamu Tomita's avatar Osamu Tomita Committed by Jeff Garzik

[PATCH] Support PC-9800 subarchitecture (9/14) NIC

This is the patch to support NEC PC-9800 subarchitecture
against 2.5.65-ac1. (9/14)

C-bus(PC98's legacy bus like ISA) network cards support.
Change IO port and IRQ assign.
Add NE2000 compatible driver for PC-9800.
  PCI netwwork card works fine without patch.

Regards,
Osamu Tomita
parent b65f28be
......@@ -56,6 +56,10 @@
v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
- Introduce driver model for EISA cards.
*/
/*
FIXES for PC-9800:
Shu Iwanaga: 3c569B(PC-9801 C-bus) support
*/
#define DRV_NAME "3c509"
#define DRV_VERSION "1.19b"
......@@ -257,7 +261,7 @@ static struct mca_driver el3_mca_driver = {
};
#endif /* CONFIG_MCA */
#ifdef __ISAPNP__
#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
......@@ -350,7 +354,7 @@ static void el3_common_remove (struct net_device *dev)
if (lp->pmdev)
pm_unregister(lp->pmdev);
#endif
#ifdef __ISAPNP__
#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (lp->type == EL3_PNP)
pnp_device_detach(to_pnp_dev(lp->dev));
#endif
......@@ -368,12 +372,12 @@ static int __init el3_probe(int card_idx)
int ioaddr, irq, if_port;
u16 phys_addr[3];
static int current_tag;
#ifdef __ISAPNP__
#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
static int pnp_cards;
struct pnp_dev *idev = NULL;
#endif /* __ISAPNP__ */
#ifdef __ISAPNP__
#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (nopnp == 1)
goto no_pnp;
......@@ -421,6 +425,9 @@ static int __init el3_probe(int card_idx)
no_pnp:
#endif /* __ISAPNP__ */
#ifdef CONFIG_X86_PC9800
id_port = 0x71d0;
#else
/* Select an open I/O location at 0x1*0 to do contention select. */
for ( ; id_port < 0x200; id_port += 0x10) {
if (check_region(id_port, 1))
......@@ -435,6 +442,7 @@ static int __init el3_probe(int card_idx)
printk(" WARNING: No I/O port available for 3c509 activation.\n");
return -ENODEV;
}
#endif /* CONFIG_X86_PC9800 */
/* Next check for all ISA bus boards by sending the ID sequence to the
ID_PORT. We find cards past the first by setting the 'current_tag'
on cards as they are found. Cards with their tag set will not
......@@ -465,7 +473,7 @@ static int __init el3_probe(int card_idx)
phys_addr[i] = htons(id_read_eeprom(i));
}
#ifdef __ISAPNP__
#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (nopnp == 0) {
/* The ISA PnP 3c509 cards respond to the ID sequence.
This check is needed in order not to register them twice. */
......@@ -490,9 +498,19 @@ static int __init el3_probe(int card_idx)
{
unsigned int iobase = id_read_eeprom(8);
if_port = iobase >> 14;
#ifdef CONFIG_X86_PC9800
ioaddr = 0x40d0 + ((iobase & 0x1f) << 8);
#else
ioaddr = 0x200 + ((iobase & 0x1f) << 4);
#endif
}
irq = id_read_eeprom(9) >> 12;
#ifdef CONFIG_X86_PC9800
if (irq == 7)
irq = 6;
else if (irq == 15)
irq = 13;
#endif
if (!(dev = init_etherdev(NULL, sizeof(struct el3_private))))
return -ENOMEM;
......@@ -522,7 +540,11 @@ static int __init el3_probe(int card_idx)
outb(0xd0 + ++current_tag, id_port);
/* Activate the adaptor at the EEPROM location. */
#ifdef CONFIG_X86_PC9800
outb((ioaddr >> 8) | 0xe0, id_port);
#else
outb((ioaddr >> 4) | 0xe0, id_port);
#endif
EL3WINDOW(0);
if (inw(ioaddr) != 0x6d50) {
......@@ -534,7 +556,7 @@ static int __init el3_probe(int card_idx)
/* Free the interrupt so that some other card can use it. */
outw(0x0f00, ioaddr + WN0_IRQ);
#ifdef __ISAPNP__
#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
found: /* PNP jumps here... */
#endif /* __ISAPNP__ */
......@@ -543,7 +565,7 @@ static int __init el3_probe(int card_idx)
dev->irq = irq;
dev->if_port = if_port;
lp = dev->priv;
#ifdef __ISAPNP__
#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
lp->dev = &idev->dev;
#endif
......@@ -1388,6 +1410,12 @@ el3_up(struct net_device *dev)
outw(0x0001, ioaddr + 4);
/* Set the IRQ line. */
#ifdef CONFIG_X86_PC9800
if (dev->irq == 6)
dev->irq = 7;
else if (dev->irq == 13)
dev->irq = 15;
#endif
outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
/* Set the station address in window 2 each time opened. */
......@@ -1550,7 +1578,7 @@ MODULE_PARM_DESC(debug, "debug level (0-6)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
#ifdef __ISAPNP__
#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
MODULE_PARM(nopnp, "i");
MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
......
......@@ -123,7 +123,8 @@ struct ei_device {
#define inb_p(port) in_8(port)
#define outb_p(val,port) out_8(port,val)
#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE)
#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) || \
defined(CONFIG_NET_CBUS)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
#else
#define EI_SHIFT(x) (x)
......
......@@ -663,7 +663,7 @@ config EL16
as <file:Documentation/networking/net-modules.txt>.
config EL3
tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
tristate "3c509/3c529 (MCA)/3c569B (98)/3c579 \"EtherLink III\" support"
depends on NET_VENDOR_3COM && (ISA || EISA || MCA)
---help---
If you have a network (Ethernet) card belonging to the 3Com
......@@ -932,7 +932,7 @@ config NI65
source "drivers/net/tulip/Kconfig"
config AT1700
tristate "AT1700/1720 support (EXPERIMENTAL)"
tristate "AT1700/1720/RE1000Plus(C-Bus) support (EXPERIMENTAL)"
depends on NET_ETHERNET && (ISA || MCA) && EXPERIMENTAL
---help---
If you have a network (Ethernet) card of this type, say Y and read
......@@ -978,7 +978,7 @@ config HP100
config NET_ISA
bool "Other ISA cards"
depends on NET_ETHERNET && ISA
depends on NET_ETHERNET && ISA && !X86_PC9800
---help---
If your network (Ethernet) card hasn't been mentioned yet and its
bus system (that's the way the cards talks to the other components
......@@ -1176,6 +1176,55 @@ config SK_G16
the Ethernet-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>.
config NET_CBUS
bool "NEC PC-9800 C-bus cards"
depends on NET_ETHERNET && ISA && X86_PC9800
---help---
If your network (Ethernet) card hasn't been mentioned yet and its
bus system (that's the way the cards talks to the other components
of your computer) is NEC PC-9800 C-Bus, say Y.
config NE2K_CBUS
tristate "Most NE2000-based Ethernet support"
depends on NET_CBUS
config NE2K_CBUS_EGY98
bool "Melco EGY-98 support"
depends on NE2K_CBUS
config NE2K_CBUS_LGY98
bool "Melco LGY-98 support"
depends on NE2K_CBUS
config NE2K_CBUS_ICM
bool "ICM IF-27xxET support"
depends on NE2K_CBUS
config NE2K_CBUS_IOLA98
bool "I-O DATA LA-98 support"
depends on NE2K_CBUS
config NE2K_CBUS_CNET98EL
bool "Contec C-NET(98)E/L support"
depends on NE2K_CBUS
config NE2K_CBUS_CNET98EL_IO_BASE
hex "C-NET(98)E/L I/O base address (0xaaed or 0x55ed)"
depends on NE2K_CBUS_CNET98EL
default "0xaaed"
config NE2K_CBUS_ATLA98
bool "Allied Telesis LA-98 Support"
depends on NE2K_CBUS
config NE2K_CBUS_BDN
bool "ELECOM Laneed LD-BDN[123]A Support"
depends on NE2K_CBUS
config NE2K_CBUS_NEC108
bool "NEC PC-9801-108 Support"
depends on NE2K_CBUS
config SKMC
tristate "SKnet MCA support"
depends on NET_ETHERNET && MCA
......
......@@ -81,6 +81,7 @@ obj-$(CONFIG_ARM_ETHERH) += 8390.o
obj-$(CONFIG_WD80x3) += wd.o 8390.o
obj-$(CONFIG_EL2) += 3c503.o 8390.o
obj-$(CONFIG_NE2000) += ne.o 8390.o
obj-$(CONFIG_NE2K_CBUS) += ne2k_cbus.o 8390.o
obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
obj-$(CONFIG_HPLAN) += hp.o 8390.o
obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
......
......@@ -19,6 +19,7 @@ obj-$(CONFIG_MACE) += crc32.o
obj-$(CONFIG_MACMACE) += crc32.o
obj-$(CONFIG_MIPS_AU1000_ENET) += crc32.o
obj-$(CONFIG_NATSEMI) += crc32.o
obj-$(CONFIG_NE2K_CBUS) += crc32.o
obj-$(CONFIG_PCMCIA_FMVJ18X) += crc32.o
obj-$(CONFIG_PCMCIA_SMC91C92) += crc32.o
obj-$(CONFIG_PCMCIA_XIRTULIP) += crc32.o
......
......@@ -233,7 +233,7 @@ static struct devprobe isa_probes[] __initdata = {
#ifdef CONFIG_E2100 /* Cabletron E21xx series. */
{e2100_probe, 0},
#endif
#ifdef CONFIG_NE2000 /* ISA (use ne2k-pci for PCI cards) */
#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */
{ne_probe, 0},
#endif
#ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */
......
......@@ -34,6 +34,10 @@
only is it difficult to detect, it also moves around in I/O space in
response to inb()s from other device probes!
*/
/*
99/03/03 Allied Telesis RE1000 Plus support by T.Hagawa
99/12/30 port to 2.3.35 by K.Takai
*/
#include <linux/config.h>
#include <linux/errno.h>
......@@ -76,10 +80,17 @@ static int fmv18x_probe_list[] __initdata = {
* ISA
*/
#ifndef CONFIG_X86_PC9800
static int at1700_probe_list[] __initdata = {
0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
};
#else /* CONFIG_X86_PC9800 */
static int at1700_probe_list[] __initdata = {
0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0
};
#endif /* CONFIG_X86_PC9800 */
/*
* MCA
*/
......@@ -122,6 +133,7 @@ struct net_local {
/* Offsets from the base address. */
#ifndef CONFIG_X86_PC9800
#define STATUS 0
#define TX_STATUS 0
#define RX_STATUS 1
......@@ -136,6 +148,7 @@ struct net_local {
#define TX_START 10
#define COL16CNTL 11 /* Controll Reg for 16 collisions */
#define MODE13 13
#define RX_CTRL 14
/* Configuration registers only on the '865A/B chips. */
#define EEPROM_Ctrl 16
#define EEPROM_Data 17
......@@ -144,8 +157,39 @@ struct net_local {
#define IOCONFIG 18 /* Either read the jumper, or move the I/O. */
#define IOCONFIG1 19
#define SAPROM 20 /* The station address PROM, if no EEPROM. */
#define MODE24 24
#define RESET 31 /* Write to reset some parts of the chip. */
#define AT1700_IO_EXTENT 32
#define PORT_OFFSET(o) (o)
#else /* CONFIG_X86_PC9800 */
#define STATUS (0x0000)
#define TX_STATUS (0x0000)
#define RX_STATUS (0x0001)
#define TX_INTR (0x0200)/* Bit-mapped interrupt enable registers. */
#define RX_INTR (0x0201)
#define TX_MODE (0x0400)
#define RX_MODE (0x0401)
#define CONFIG_0 (0x0600)/* Misc. configuration settings. */
#define CONFIG_1 (0x0601)
/* Run-time register bank 2 definitions. */
#define DATAPORT (0x0800)/* Word-wide DMA or programmed-I/O dataport. */
#define TX_START (0x0a00)
#define COL16CNTL (0x0a01)/* Controll Reg for 16 collisions */
#define MODE13 (0x0c01)
#define RX_CTRL (0x0e00)
/* Configuration registers only on the '865A/B chips. */
#define EEPROM_Ctrl (0x1000)
#define EEPROM_Data (0x1200)
#define CARDSTATUS 16 /* FMV-18x Card Status */
#define CARDSTATUS1 17 /* FMV-18x Card Status */
#define IOCONFIG (0x1400)/* Either read the jumper, or move the I/O. */
#define IOCONFIG1 (0x1600)
#define SAPROM 20 /* The station address PROM, if no EEPROM. */
#define MODE24 (0x1800)/* The station address PROM, if no EEPROM. */
#define RESET (0x1e01)/* Write to reset some parts of the chip. */
#define PORT_OFFSET(o) ({ int _o_ = (o); (_o_ & ~1) * 0x100 + (_o_ & 1); })
#endif /* CONFIG_X86_PC9800 */
#define TX_TIMEOUT 10
......@@ -225,8 +269,20 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
int slot, ret = -ENODEV;
struct net_local *lp;
#ifndef CONFIG_X86_PC9800
if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name))
return -EBUSY;
#else
for (i = 0; i < 0x2000; i += 0x0200) {
if (!request_region(ioaddr + i, 2, dev->name)) {
while (i > 0) {
i -= 0x0200;
release_region(ioaddr + i, 2);
}
return -EBUSY;
}
}
#endif
/* Resetting the chip doesn't reset the ISA interface, so don't bother.
That means we have to be careful with the register values we probe for.
......@@ -317,10 +373,17 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
/* Reset the internal state machines. */
outb(0, ioaddr + RESET);
if (is_at1700)
if (is_at1700) {
#ifndef CONFIG_X86_PC9800
irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
| (read_eeprom(ioaddr, 0)>>14)];
else {
#else
{
char re1000plus_irqmap[4] = {3, 5, 6, 12};
irq = re1000plus_irqmap[inb(ioaddr + IOCONFIG1) >> 6];
}
#endif
} else {
/* Check PnP mode for FMV-183/184/183A/184A. */
/* This PnP routine is very poor. IO and IRQ should be known. */
if (inb(ioaddr + CARDSTATUS1) & 0x20) {
......@@ -392,18 +455,22 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
/* Set the station address in bank zero. */
outb(0x00, ioaddr + CONFIG_1);
for (i = 0; i < 6; i++)
outb(dev->dev_addr[i], ioaddr + 8 + i);
outb(dev->dev_addr[i], ioaddr + PORT_OFFSET(8 + i));
/* Switch to bank 1 and set the multicast table to accept none. */
outb(0x04, ioaddr + CONFIG_1);
for (i = 0; i < 8; i++)
outb(0x00, ioaddr + 8 + i);
outb(0x00, ioaddr + PORT_OFFSET(8 + i));
/* Switch to bank 2 */
/* Lock our I/O address, and set manual processing mode for 16 collisions. */
outb(0x08, ioaddr + CONFIG_1);
#ifndef CONFIG_X86_PC9800
outb(dev->if_port, ioaddr + MODE13);
#else
outb(0, ioaddr + MODE13);
#endif
outb(0x00, ioaddr + COL16CNTL);
if (net_debug)
......@@ -447,7 +514,12 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
kfree(dev->priv);
dev->priv = NULL;
err_out:
#ifndef CONFIG_X86_PC9800
release_region(ioaddr, AT1700_IO_EXTENT);
#else
for (i = 0; i < 0x2000; i += 0x0200)
release_region(ioaddr + i, 2);
#endif
return ret;
}
......@@ -459,7 +531,11 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
#define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */
/* Delay between EEPROM clock transitions. */
#ifndef CONFIG_X86_PC9800
#define eeprom_delay() do { } while (0)
#else
#define eeprom_delay() __asm__ ("out%B0 %%al,%0" :: "N"(0x5f))
#endif
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6)
......@@ -542,12 +618,12 @@ static void net_tx_timeout (struct net_device *dev)
inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80
? "IRQ conflict" : "network cable problem");
printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
dev->name, inw (ioaddr + 0), inw (ioaddr + 2), inw (ioaddr + 4),
inw (ioaddr + 6), inw (ioaddr + 8), inw (ioaddr + 10),
inw (ioaddr + 12), inw (ioaddr + 14));
dev->name, inw(ioaddr + TX_STATUS), inw(ioaddr + TX_INTR), inw(ioaddr + TX_MODE),
inw(ioaddr + CONFIG_0), inw(ioaddr + DATAPORT), inw(ioaddr + TX_START),
inw(ioaddr + MODE13 - 1), inw(ioaddr + RX_CTRL));
lp->stats.tx_errors++;
/* ToDo: We should try to restart the adaptor... */
outw (0xffff, ioaddr + 24);
outw(0xffff, ioaddr + MODE24);
outw (0xffff, ioaddr + TX_STATUS);
outb (0x5a, ioaddr + CONFIG_0);
outb (0xe8, ioaddr + CONFIG_1);
......@@ -704,7 +780,7 @@ net_rx(struct net_device *dev)
dev->name, inb(ioaddr + RX_MODE), status);
#ifndef final_version
if (status == 0) {
outb(0x05, ioaddr + 14);
outb(0x05, ioaddr + RX_CTRL);
break;
}
#endif
......@@ -724,7 +800,7 @@ net_rx(struct net_device *dev)
dev->name, pkt_len);
/* Prime the FIFO and then flush the packet. */
inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
outb(0x05, ioaddr + 14);
outb(0x05, ioaddr + RX_CTRL);
lp->stats.rx_errors++;
break;
}
......@@ -734,7 +810,7 @@ net_rx(struct net_device *dev)
dev->name, pkt_len);
/* Prime the FIFO and then flush the packet. */
inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
outb(0x05, ioaddr + 14);
outb(0x05, ioaddr + RX_CTRL);
lp->stats.rx_dropped++;
break;
}
......@@ -761,7 +837,7 @@ net_rx(struct net_device *dev)
if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
break;
inw(ioaddr + DATAPORT); /* dummy status read */
outb(0x05, ioaddr + 14);
outb(0x05, ioaddr + RX_CTRL);
}
if (net_debug > 5)
......@@ -844,24 +920,28 @@ set_rx_mode(struct net_device *dev)
outb(0x02, ioaddr + RX_MODE); /* Use normal mode. */
}
save_flags(flags);
cli();
spin_lock_irqsave (&lp->lock, flags);
if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
int saved_bank = inw(ioaddr + CONFIG_0);
/* Switch to bank 1 and set the multicast table. */
outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0);
for (i = 0; i < 8; i++)
outb(mc_filter[i], ioaddr + 8 + i);
outb(mc_filter[i], ioaddr + PORT_OFFSET(8 + i));
memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
outw(saved_bank, ioaddr + CONFIG_0);
}
restore_flags(flags);
spin_unlock_irqrestore (&lp->lock, flags);
return;
}
#ifdef MODULE
static struct net_device dev_at1700;
#ifndef CONFIG_X86_PC9800
static int io = 0x260;
#else
static int io = 0xd0;
#endif
static int irq;
MODULE_PARM(io, "i");
......@@ -901,7 +981,15 @@ cleanup_module(void)
/* If we don't do this, we can't re-insmod it later. */
free_irq(dev_at1700.irq, NULL);
#ifndef CONFIG_X86_PC9800
release_region(dev_at1700.base_addr, AT1700_IO_EXTENT);
#else
{
int i;
for (i = 0; i < 0x2000; i += 0x200)
release_region(dev_at1700.base_addr + i, 2);
}
#endif
}
#endif /* MODULE */
MODULE_LICENSE("GPL");
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment